docker 概念整理

dockerとは

dockerとはホストマシン(macのローカル)に依存せず、開発環境を構築出来るツール linuxカーネルの仮想技術を用いているため、オーバーヘッドが少ない。

コンテナ技術を用いて、実行環境を他のプロセスから隔離してアプリを起動させます。 カーネルを直接使用しているから楽になります。 Vagrantだとメモリ割当やらCPUコア数やら設定しなくてはいけないんですが、 dockerは必要ありません。 もちろん、virtualboxでのメモリ割当は必要です。

カーネルとは

ぐぐってみると、アプリケーションとハードウェアの連携を司るシステムだそうです。

コンテナ技術とは

1つのOS上に隔離された区画を用意してアプリケーションを実行する技術です。 よく docker pull centos をしてcentosのイメージなどを構築するケースがありますが、これはdocker(linux環境)上にcentos環境を構築する形となります。

dockerホストマシン作成方法

通常はvirtualboxなどを用いて仮想マシンを作成します。 macwindowsではdocker-machineを用いて、docker virtualbox上にdockerホストマシンを構築します。

コマンドは以下の通りの感じで作成出来ます。

$ docker-machine create --driver virtualbox vbox

これで仮想マシンを作成します。

Google Maps Direction API を使ってみる。

概要

最近、mapsAPIを調べた所、Direction APIというのがあったのを知った のでまとめておきます。(昔からあったかも??)

Direction APIとは

2つの地点の距離、移動時間を計測するAPIです。

公式HPにそのまま書いてある通りです。

移動時間については、徒歩、自転車、電車、車など様々なモードが選んで計算してくれるところが 良いところではないでしょうあk。

使い方

APIを用いる際に必要なのは以下の2点となります。

  • APIキー取得、DirectionAPI有効化
  • リクエストパラメータ設定

リクエストパラメータについて

必須パラメータ

  • origin #出発地: 指定方法は 住所、緯度・経度
  • destination # 目的地を示す。 指定方法はoriginと同じ
  • APIKEY # 取得したGoogle maps api key

※ 場所指定(origin destination)は多少アバウトでも拾ってくれます。

オプションパラメータ(抜粋)

  • mode #移動時間を計算する際の交通手段を選択
  • units #移動距離の単位を選択。
  • arrival_time # 到着時刻を指定  UNIXTIMEからの経過時間で指定することに注意
  • departure_time # 出発時刻を指定 

実行してみる

request

$curl -s "https://maps.googleapis.com/maps/api/distancematrix/json?\
mode=walking&origins=渋谷www&destinations=恵比寿リキッドルーム\
&key=[API_KEY]" 

response

{
   "destination_addresses" : [ "Japan, 〒150-0011 Tokyo, Shibuya, Higashi, 3−16−6" ],
   "origin_addresses" : [
      "Japan, 〒150-0042 Tokyo, Shibuya, Udagawacho, 13−17 ライズビル 地下"
   ],
   "rows" : [
      {
         "elements" : [
            {
               "distance" : {
                  "text" : "2.0 km",
                  "value" : 2005
               },
               "duration" : {
                  "text" : "24 mins",
                  "value" : 1460
               },
               "status" : "OK"
            }
         ]
      }
   ],
   "status" : "OK"
}

次はjsonを抜き出したケース

request

$curl -s "https://maps.googleapis.com/maps/api/distancematrix/json?\
mode=walking&origins=渋谷www&destinations=恵比寿リキッドルーム\
&key=[API_KEY]"\
 | jq '({ destination: .destination_addresses[] },{ origin: .origin_addresses[] }) ,{distance: .rows[].elements[].distance.text } ,  {distance: .rows[].elements[].duration.text }'\
 | jq 'keys[],.[]' | xargs echo

response

destination Japan, 〒150-0011 Tokyo, Shibuya, Higashi, 3−16−6 origin Japan, 〒150-0042 Tokyo, Shibuya, Udagawacho, 13−17 ライズビル 地下 distance 2.0 km duration 24 mins

感想

有益な点

事前に登録してある場所の検索には非常に有益ではないでしょうか。

例えば、緯度・経度を事前に登録してある場合のケース(不動産サービスやホテルに対して駅からの距離) においては非常に強力だと思います。

やや残念な点

フリーキーワードで位置検索する場合の認識が甘いです。

例をあげます。

出発地=渋谷駅 到着地=代々木駅 でリクエストした場合は以下の通りとなります。

request

$curl -s "https://maps.googleapis.com/maps/api/distancematrix/json?\
mode=walking&origins=JR渋谷駅&destinations=代々木駅\
&language=ja&key=[API_KEY]"\
 | jq '({ destination: .destination_addresses[] },{ origin: .origin_addresses[] }) ,{distance: .rows[].elements[].distance.text } ,  {distance: .rows[].elements[].duration.text }'\
 | jq 'keys[],.[]' | xargs echo

response

destination 日本 origin 日本、東京都渋谷区道玄坂
 distance 3.5 km duration 11分

というように一般的に使われそうなキーワードでも引っかからないことがあります。

【Rubyメモ】Struct

Structとは

Structは構造体を表現するクラスです。 構造体とは1つ以上のフィールドを持つクラスです。 これを用いることで複数のフィールドをもたせることが出来ます。

少し特殊なのはStruct.newを行なうと、Sturctクラスの サブクラスを返すことです。

通常はクラスに対して newを行なうとそのクラスのインスタンスが返るので 最初は不思議な気がしました。

コード

# subject、gpaのフィールドを定義
SchoolRecord = Struct.new(:subject,:gpa)

# スーパークラスはStructクラス(=Struct.newはStructのサブクラス)
p SchoolRecord.superclass #Struct 

record = SchoolRecord.new("english",3.2)
#recordオブジェクトでフィールドへアクセス
p record.subject #english
p record.gpa #3.2

#ハッシュっぽい使い方
p record[:subject] #english
p record.members #[:subject, :gpa]

hashとの比較

hashとどこが違うのという話がありますが、hashの場合は新たにシンボルを 定義することが出来ます。が、Structはnewした際に定義したメンバーしか使えません。

SchoolRecord = Struct.new(:subject,:gpa)
SchoolRecord[:test] = "test" #error
SchoolRecord.test = "test" #error

参考文献

パーフェクトruby

【デザインパターン勉強】Proxyメソッド

ざっくり概要

ある処理を肩代わりする代わりに出来ない処理が着た場合、 処理を他のクラスに肩代わさせるメソッドです。

生徒と先生の関係を考えてみます。

先生といえども、生徒の質問に全て答えられるわけではないですね。 数学の先生が英語の質問をされたときは、英語の先生(クラス)を呼び出して回答する そんなパターンです。

コード

import abc

class Teacher(metaclass=abc.ABCMeta):
    def __init__(self):
        self.subject = "Math"
    
    @abc.abstractmethod
    def question_1(self):
        pass
        
    @abc.abstractmethod
    def question_2(self):
        pass
    
class MathTeacher(Teacher):
    def question_1(self,question):
        print(question,"two")
        
    def question_2(self,question):
        EnglishTeacher().question_2(question)

class EnglishTeacher(Teacher):
    def question_1(self,question):
        MathTeacher().question_1(self,question)
    
    def question_2(self,question):
        print(question,"緑茶です。")

    
if __name__ == '__main__':
    # 生徒役
    MathTeacher().question_1("1+1 equal?") #1+1 equal ? two
    MathTeacher().question_2("what does mean green tea?") #what does mean green tea? 緑茶です。
        

ざっくり解説

今回の例では、生徒の質問(if name以下)はデフォルトで数学の先生(MathTeacherクラス) としておきます。question_2では、英語の質問なので、数学の先生は英語の先生に答えてもらってます。

状況としては数学の先生が同学年の英語の先生が病気のため代理で授業しているとシチューエーションをイメージして下さい。

mainにある処理のイメージを書き下すと、 question_1は数学の先生なんで余裕ですが、question_2は少しむずかしいかもしれません。そこで、1学年下の英語の先生に頼み込んで 回答している状況を示しています。

現実的な利用シーン(個人的感想)

代理で行なうメリットとしては、重いクラスの代理を軽いクラスで肩代わりすることが可能です。 例えば、

  • (あまり実感はないですが)クラスの初期化に呼び出されるコンストラクタが重い
  • DBをロードしなくてはいけない処理がある

といったケースでは代理を立てることで動きの遅いクラスを軽いクラスに肩代わりさせられます。

参考にしたもの

http://www.techscore.com/tech/DesignPattern/Proxy.html/

【デザインパターン勉強】Decoratorメソッド

ざっくり概要

decoratorとは 装飾 の意味です。 あるコアクラスを元にして機能をかぶせていく手法です。

今回は簡略化のために1つのコア、一つの機能をかぶせた例を用いて説明します。

コード

class PlainNumber():
    def __init__(self,num):
        self._num = num
    
class MultiplicationNumber(PlainNumber):
    def __init__(self,num):
        self._number = num
    
    def render(self,num):
        return self._number.render() * num

    
if __name__ == '__main__':
    plain_num = PlainNumber(11)
    multiple_output = MultiplicationNumber(plain_num)
    print("11*2=",multiple_output.render(2)) # 11*2= 22
    

ざっくり解説

コードの流れは以下の通りです。

  1. 数字を設定(PlainNumberクラス)を設定
  2. 掛け算(MultiplicationNumber)機能を追加し
  3. 数字×掛け算を実行

MultiplicationNumberはPlainNumberを継承しているので掛け算が実行出来ますね。

現実的な利用シーン(個人的感想)

  • 長所

開発のシーンでは、最初に決めた仕様し、実装し、あとから機能追加といったことがあると思います。 そういった際、設計を変えずに追加することが出来て、便利なんじゃないでしょうか。

  • 短所

デコレートをしすぎると管理しづらい気がします。(意図せず重複した機能を持ったクラスを追加するなど)そこらへんは長所とトレードオフな気がしますが

参考文献

Javaで学ぶデザインパターン入門 https://github.com/faif/python-patterns/blob/master/structural/decorator.py

【デザインパターン勉強】Facadeメソッド

ざっくり概要

Facade(建物の正面)という意味を指しています。 このパターンは内部の処理を簡素化したクラスを一つにすることで、複雑な処理を見せないメソッドです。

自分なりの言葉で言うと、処理を一つのクラスに集約したら見通して良くなって、すぐわかるんじゃね? ということです。

コード

ココのコードを利用して説明します。

import time

class TC1:
    
    def run(self):
        print("test1")
        print("settup")
        print("finish")
        time.sleep(0.1)

class TC2:
    
    def run(self):
        print("test2")
        print("settup")
        print("finish")
        time.sleep(0.1)

        
class TC3:
    
    def run(self):
        print("test3")
        print("settup")
        print("finish")
        time.sleep(0.1)

class TestRunner:
    
    def __init__(self):
        self.tc1 = TC1()
        self.tc2 = TC2()
        self.tc3 = TC3()
        self.tests = [self.tc1,self.tc2,self.tc3]
    
    def runAll(self):
        [i.run() for i in self.tests]

if __name__ == '__main__':
    testrunner = TestRunner()
    testrunner.runAll()

ざっくり解説

TestRunnerクラス

このクラスで処理をまとめています。 具体的にはTC1~3で標準出力するメッドをrunAllに集約しています。

今回はTC1~TC3という3つのクラスのメソッドを用いて集約してますが、 もっと複雑なケースを考えてみます。

  • そのままAクラスはインスタンス化して、
  • Aのメソッドを呼び出し
  • Bクラスメソッドを使って

・・・C、D、E、F、Gの処理へ続く。

といったケースですと、複雑で何しているかわからなくなりますね。

一つのクラス(窓口)に集約化することで見通しが良くなります。 クラス名もわかりやすく(例えば、MakeCSV具体的な作業を明示) とか、わかりやすくすれば初見の人でも通りやすくなるんじゃないでしょうか。

利用方法

個人開発をしている人にはあまり実りのあるメソッドとはいえないと思います(処理の流れをわかっているため)。 しかしながら、何人も関わっている開発プロダクトの場合、は必須のパターンだと思います。

参考文献

Javaで学ぶデザインパターン入門

【デザインパターン勉強】Singletonメソッド

ざっくり概要

このパターンの目的は 一つのクラスに複数のインスタンスを作らないようにすることです。

利用シーン... パスワード管理のメソッドなど管理が厳重にする必要があるメソッドを管理する時に使うんでしょうかね。。

コード

class Singleton:
    initial_class_name = None
    
    # クラスインスタンス化した際、__new__→__init__が呼び出される。
    def __init__(self):
        print("init")
    
    def __new__(self):
        
        if Singleton.initial_class_name is None:
            print("new")
            Singleton.initial_class_name = super().__new__(self)
        
        return Singleton.initial_class_name

if __name__ == '__main__':
    a = Singleton() #こんな感じで出力→<__main__.Singleton object at 0x106614438>
    b = Singleton() #↑と同じ。<__main__.Singleton object at 0x106614438>
    print(a)
    print(b)
    print(a is b)
    

ざっくり解説。

classをインスタンス化した際にクラス変数(initial_class_name)をつけておくことで フラグ(インスタンスを生成したかどうか)として機能させています。

今回は参考URLが非常に秀逸だったのであまり語ることはないです。。

参考URL

http://blanktar.jp/blog/2016/07/python-singleton.html