The King's Museum

ソフトウェアエンジニアのブログ。

Introduction and Background: The Twelve-Factor App

サーバーアプリケーションの開発において The Twelve-Factor App という考え方があるのをつい最近知った(いまさら感がすごい)。

勉強がてら記事にしておこうと思う。

まずは Twelve-Factor App の Introduction と Background から・・・

The Twelve-Factor App

12factor.net

INTRODUCTION

The Twelve-Factor app は「サービスとしてのソフトウェア(software-as-a-service)」を構築するための方法論です。

サービスとしてのソフトウェアは次のような特徴を持ちます。

  • プロジェクトに新たに参加する開発者のコストを最小化するため、セットアップ自動化には宣言的なフォーマットを使う
  • OS への依存関係を明確化し、実行環境に関して最大限のポータビリティを提供する
  • サーバーやシステム管理の必要性を事前に省くために、モダンなクラウドプラットフォームへのデプロイを最適化する
  • 最大限の機敏性をもつ CI のために、開発環境とプロダクション環境の差違を最小化する
  • ツール、アーキテクチャ、開発プラクティスに大きな変更を加えることなしにスケールできる

どのような言語で書かれていても、どのようなバックエンドサービスとの組み合わせでも問題ありません。

BACKGROUND

このドキュメントの起草者は直接的、または間接的にさまざまなアプリケーションの開発やオペレーションを目にしてきました。

そこで目にした問題を提起し議論するために共通の語彙を与え、問題を解決するための概念的な解決策を提示するることがこのドキュメントの目的です。

感想

Introduction と Background はそんなに大したこと書いてないと思った。

じゃあ、どうやってこれらを実現していくか、っていうのが大事なわけで、それを説明したこのあとの12個の Practice がこのドキュメントの面白いところだと思う。

ここ数ヶ月 Docker 関連でサーバーサイドをいじっているが、自分なりに「こういう方法論で作るのがベストなんじゃないかな」と思っていることが、そのまま出てきたりしたので、もっと早くに出会っていれば、、、と思った。

Coursera: Improving Deep Neural Networks を修了したよ

Coursera: Deep Learning SpecializationCourse 2: Improving Deep Neural Networks を修了しました。

f:id:hjm333:20180323230238p:plain

学んだ内容は次の通り。

  • Train/Dev/Test set
  • Bias/Variance
  • L2 Regularization
  • Dropout
  • Normalizing
  • Mini-Batch Gradient Descendant
  • Momentum, RMSprop, Adam Optimization
  • Tuning hyper parameter
  • Batch Normalization
  • Soft-max
  • Tensorflow

Course1 は Deep Neural Network のイメージを掴むための基礎講義だったけど、Course 2 は学習時に使われている最適化アルゴリズムの紹介がメインだった。

DNN はパラメータ Wb で定義されるわけだけど、学習でそれらを決めるためには、

  • ネットワークの深さ
  • 各層のユニット数
  • 学習率
  • 減衰率
  • バッチサイズ
  • 学習回数
  • 最適化アルゴリズムとそのパラメータ

という、パラメータ Wb を決定するハイパーパラメータを決定する必要がある。

結局、これらのハイパーパラメータを「どうやって、どの値にするか」が勝敗を決める、という感じですね。

Course1 で DNN の全体像をきちんと掴んでいたおかげで、それぞれのアルゴリズムやテクニックがどこに効いてくるかがとても分かりやすかった。 やはり Andrew 先生の講義で間違いなかった…(比較対象はないけど)。

Coursera: Neural Networks and Deep Learning を修了したよ

Coursera: Deep Learning SpecializationCourse 1: Neural Networks and Deep Learning を修了しました。

f:id:hjm333:20180226214601p:plain

内容は次の通り。

  1. Logistic Regression as Neural Network
  2. Vectorization
  3. Shallow Neural Network
  4. Deep Neural Network

これらを学習する過程で、

  • Activation function
  • Forward propagation & Back propagation
  • Gradient descend
  • Compute Graph
  • numpy

という Deep Learning の基礎的な知識も得ることができる。

これらの知識を得られたことも価値だけど、時折 Andrew 先生が話してくれる

最近は、 XX という手法が流行っていて結果を出しているよ

とか

YY という手法もあるけどあまり使われてないよ

というアドバイスがすごく価値があるのではないかと思わせる講義だった。

Week 4 の課題のバグ

Week 4 の課題はバグがあって一度で 100% が取れず少し苦労した。

プログラミングの課題は Jupyter Notebook になっていて、

  1. テキストを読む
  2. コードの穴埋め
  3. その場でインタラクティブに実行して結果をチェック(この時点では採点されない)
  4. 最終的にコードを提出し採点

という流れになっている。

ただ、Week 4 の "Building your Deep Neural Network: Step by Step" の "6.3 - L-Model Backward" で提示されているコードは、穴埋め前の状態でバグがある。 加えて、そこに提示されている「期待される実行結果」自体が間違っている。

そのため、

  • 提示されているコードを元にして穴埋めをする
  • その場で実行すると、実行結果が「期待される実行結果」と一致するので、コードがあっているように見える
  • しかし、本当はコードが間違っているので最終的に提出するとスコアが 0 になる

という分かりづらい自体に陥る。

ここで間違った部分のコードを貼って解説しようかと思ったけど、規約上微妙かな、と思ったので役に立ちそうな Discussion Forum のリンクだけ貼っておきます。

本当に困っていたら直接連絡をください。

【Effective Java 3rd】Item 1: Consider static factory methods instead of constructors

オブジェクトを生成するために public コンストラクタの他に static ファクトリーメソッドを用意するとよいでしょう。

static ファクトリーメソッドとは、インスタンスを返す単なる static メソッドのことです。 例えば、Java の Boolean では次のような static ファクトリーメソッドが提供されています。

public static Boolean valueOf (boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

なお、GoF のデザインパターンで議論される「ファクトリーメソッド」とは異なるので注意が必要です。

Advantages

通常のコンストラクタと比較して static ファクトリーメソッドには次のようなメリットがあります。

名前がつけられる

コンストラクタの名前は必ずクラス名と一致しなければなりません。

一方、static ファクトリーメソッドではより適切な名前をつけることができます。

インスタンスの生成をコントロールできる

コンストラクタは必ずインスタンスを生成してしまいます。

一方、static ファクトリーメソッドでは必ずしもインスタンスを生成する必要はありません。 これは GoF のデザインパターンの Flyweight パターンに相当します。 さきほどの Boolean.valueOf はまさにこのパターンです。

インスタンスの生成をコントロールできることで、シングルトン(項目3)、インスタンス化不可能(項目4)、不変クラス(項目15)などのパターンに応用することもできます。

サブタイプのインスタンスを生成できる

コンストラクタは必ずそのクラスのインスタンスを生成します。

一方、static ファクトリーメソッドでは必ずしもそのクラスのインスタンスを返す必要がありません。 例えば、実装のためだけの非公開クラスを公開することなく、そのインスタンスを生成することができます。

Java8 以前ではインタフェースが static メソッドを持てませんでした。 そのため、Type というインタフェースを継承した実装クラスを生成するため、インスタンス化不可能な Types という Utility クラスを定義して static ファクトリーメソッドを用意していました。 しかし、Java8 からはインタフェースがインタフェースが static メソッドを持てるようになったのでこのテクニックの必要性はうすれています。

引数の値によって生成するインスタンスを変更できる

コンストラクタは生成する引数によってインスタンスを変更できません。

一方、static ファクトリーメソッドを使うと入力値によって生成するインスタンスを変更可能です。

EnumSet がよい例です。 EnumSet のファクトリーメソッドは enum 型の値の個数によって、生成するインスタンスを変更しています。 具体的には enum 要素が 64 以下なら RegularEnumSet のインスタンスを返しますが、それより大きければ JumboEnumSet のインスタンスを返します。

クラス作成時には存在しないインスタンスを生成できる

当たり前の話ですが、あるクラスのコンストラクタを作成するとき、生成するインスタンスのクラスは必ず定義されています。

一方、static ファクトリーメソッドでは作成時点では、返すクラスの定義は存在していなくてもかまいません。 この柔軟なファクトリーメソッドは Service Provider Framework の基本となります。

Disadvantages

static ファクトリーメソッドにはいくつかのデメリットもあります。

public または protected のコンストラクタを持たないクラスをサブクラスにできない

この制限は不便に感じるかもしれませんが、実際には問題ありません。 なぜなら、そのような場合は継承ではなく、コンポジョンの利用を促すからです。

他の static メソッドと区別がつきづらい

static ファクトリーメソッドのための API ドキュメントが存在しません。そのため、ドキュメント上で通常の static メソッドと static ファクトリーメソッドの区別がつきません。

これに対しては一般的な命名規則に従うことで弱点を克服しています。以下に命名規則の例を示します。

  • from()
    • 一つのパラメータをもらって対応するインスタンスを返します。
  • of()
    • 複数のパラメータをもらってそれらを取り扱うインスタンスを返します。
  • valueOf()
    • from() や of() の代替です。
  • instance() or getInstance()
    • パラメータで指定されたインスタンスを返します。
    • 入力したパラメータと同じ値を持つとは限りません。
  • create() or newInstance()
    • getInstance に似ていますが、必ず新しいインスタンスを生成します。
  • getType()
    • getInstance に似ていますが、ファクトリーメソッドが対象のクラスと異なるクラスにある場合に利用されます。
    • Type は返されるオブジェクトの型の名前です。
  • newType()
    • newInstance に似ていますが、ファクトリーメソッドが対象のクラスと異なるクラスにある場合に利用されます。
    • Type は返されるオブジェクトの型の名前です。
  • type()
    • getType や newType の代替です。

Effective Java

Effective Java

Coursera の "Deep Learning Specialization" をはじめたよ

久しぶりに Coursera を始めてみました。

www.coursera.org

今流行りの Deep Learning です。

流行ってるだけあって、世間にはいろんな教材があるわけで、何を使ってどうやって学ぶかは迷うところ。 その中で自分は Coursera の Andrew Ng 先生の講義を選んだ。他の教材を比較検討したわけじゃないけど、Coursera で Andrew 先生の講義なら間違いないでしょ、という結論。

以前、受講した先生のMachine Learning の講義もすごく良かったからね。

www.thekingsmuseum.info

Deep Learning でキャリアを築くぞ!とはぜんぜん思っていなくて、これからのエンジニア人生を考えるとこの領域を無視するわけにはいかないだろうし…。というくらいの動機。もちろん、とても興味ある領域だしね。

ところで、Coursera は最近けっこう有料の講義が増えてきてると思う。 でも、それはネガティブだとは思わないかな。 そのおかげで講義自体の質とかビデオ・資料まわりの使いやすさがとても向上しているように思う。 そもそも有料化といっても、1コース1万円弱なわけで。 それで世界的に活躍する人たちの講義が受講できる、というのはどう考えてもお得。

AlphaGo

ちょっと話題が逸れるけど、Netflix で AlphaGo のドキュメンタリー見た。

www.netflix.com

イ・セドル棋士が AlphaGo に三連敗したあと、一勝するシーンは鳥肌が立った(AlphaGo が勝利したことは覚えていたけれど、詳細な勝敗は覚えてなかった)。

このシーンを見ながら「人間の脳の力って侮れないなー」と思ったな。

AlphaGo って世界トップの研究者とエンジニアが10人くらい集まって、Google が持ってるとんでもない計算力使って試合に望んでいるわけで。対局してる間もバックヤードでエンジニア数人が常にシステムの状態チェックしたりしてるんだよね。

それに対して、イ・セドル棋士はたった一人で孤独に考え続けなければならないわけですよ。プレッシャーも半端ないし。 そんな状況でたとえ一勝とはいえ AlphaGo を倒しちゃうんだからね。 実況してる解説者たちが「やったー!勝ちましたー!」ってお互いにハイタッチしてたけど、俺も一緒にハイタッチしたい気分になったよw

【Effective Java 3rd Edition】Chapter 1: Introduction

この本は Java の言語とライブラリを効果的に利用するための手引きについて書かれています。 全部で 90 の項目があり、それぞれで一つのルールが示されています。

この本では最近の Java の特徴についてもカバーしています。

Feature Items Release
Lambdas Item 42-44 Java 8
Streams Item 45-48 Java 8
Optionals Item 55 Java 8
Default methods in interfaces Item 21 Java 8
try-with-resources Item 9 Java 7
@SafeVarargs Item 32 Java 7
Modules Item 15 Java 9

この本の規則は、明瞭性(clarity)と簡潔性(simplicity)という原則から導かれています。あらゆる再利用可能なコンポーネント(モジュール)は、その挙動でモジュールの利用者を驚かせてはいけませんし、その規模は小さくあるべきです。また、コードはコピーされないで再利用されるべきです。

エラーはなるべく早い段階で検知できるようにし、実行時ではなく、コンパイラ段階で検知できるように努めるべきです。

この本で提示される規則は常に守らなければならないわけではないですが、まずは規則を学び、ときにそれを破るという姿勢をもつべきです(守破離)。

明瞭で、正しく、再利用可能で、強固で、柔軟性があるようにコードを書いていれば、たいていの場合、必要なパフォーマンスが得られます。 そうしておけばパフォーマンスが本当に必要になったとき、簡単にそれを得ることができるでしょう。

Java の構成要素

Java には4種類の型があります。

  • interfaces(annotations を含む)
  • classes(enums を含む)
  • arrays
  • primitives

最初の3種類は reference types として知られています。また、class instance と array は objects と呼ばれます。

クラスは次の要素を持っています。

  • fields
  • methods
  • member classes
  • member interfaces

メソッドシグネチャは次の要素で構成されます。

  • name
  • the types of its formal parameter

メソッドの戻り値の型が含まれないことに注意してください。

用語

この本では『Java 言語仕様』とは異なる用語の使い方をしているケースがあります。 ただし、大抵のケースはそのまま理解できるものでしょう。

例えば、この本では「サブクラス化(subclassing)」を「継承(inheritance)」と書く場合があります。

API

この本において API とは次の要素を示しています。

  • classes
  • interfaces
  • constructors
  • members
  • serialized forms

プログラマはこれらを通して各種モジュールアクセスするためです。 これらの要素が Javadoc で標準出力されるのは、偶然ではなく意図的にそうなっています。

API を利用するプログラマをユーザーと呼び、API を利用するクラスをクライアントと呼びます。

Java 9 では module system が導入されています。 ライブラリが module system を使っている場合、module で宣言されたパッケージが公開 API となります。

感想

Effective Java 3rd を読むついでに、第二版(日本語)向けに書いた記事をアップデートしてみることにした。

最初に Effective Java の記事書いたのもう2年半前。 読み返してみるとやっぱり間違ってるところあるし、こういう記事書いておいてなんだけど、本気の人はちゃんと本で読んだ方がいいですよ・・・(そして僕に間違いを教えてください)

Effective Java

Effective Java

独自ドメイン化しました

この度、ブログを独自ドメイン化しました。

http://www.thekingsmuseum.info

はてなブログもプロになったので広告やキーワードリンクなどを消しました。 (もしかしたらいつの間にか Google AdSense が入っていたりするかもしれません)

ついでにこっそりアイコンやニックネームを僕自身のものに変更しました :-)

今後ともよろしくお願いします。

(c) The King's Museum