「エンジニアのための時間管理術」を読んだ

エンジニアのための時間管理術

エンジニアのための時間管理術

この本を読もうと思った背景は2つある。1つは、前回のエントリーでも書いた通り、最近は仕事を効率的に終わらせてプライベートの時間をちゃんと確保しようとしていることだ。もう1つは、7月から新卒のメンターを担当しており、作業の割り込みが増えたことだ。新人には分からないことがあればどんどん割り込んでほしいと伝えているため、メンターが割り込みを処理しつつ普段の業務もそつなくこなす必要がある。

この本は「エンジニアのための」と書いてあるが実際はシステム管理者をターゲットとしており、プログラマーである僕とは少し事情が異なるかもしれない。それでも、割り込みへの対処法やタイムマネジメントなど、その他の職業にとっても有用なノウハウがたくさん書いてある。

本書を通して感じたことは「考えることを減らして、目の前の作業に集中しよう」というメッセージだ。良い習慣を身につけたり、外部記憶装置やカレンダーのようなツールを使ったり、単純で頻繁に行う作業を自動化したりすることで、考えることを減らすことができ、割り込みやタイトスケジュールによって作業効率が落ちるのを避けられるという話が多かったように思う。

その中で特に印象に残ったのは、とにかく外部記憶装置を多用しようという話だ。本書ではPDAがその例として出てくるが、若者はPDAなんて使わないと思うので、仕事でよく使うツールに置き換えて読んでいた。本書で言われていた通り、頭のなかで覚えておく作業が増えてくるとだんだん目の前の作業に集中できなくなってくる気がする。

僕の場合、会社ではメール、スケジュールはすべてOutlookで管理されているので、やるべき作業もすべてOutlookで管理するようにしてみた。その日のTODOリストは自作のtodo管理ツール*1で管理しているが、1日の始まりにOutlookからやるべきことを棚卸ししてTODOリストに追加している。逆に、すべてのTODOをTODOリストで管理してしまうと、TODOリストがいつになっても空にならず達成感がもてなくなってしまう。すべてのタスクを記録する外部記憶装置と短いTODOリストに分けることでうまく機能しそうだ。

その他にも今すぐ実践できそうなノウハウがたくさんあったので試行錯誤して効率的に仕事をこなせるようになりたい。

「すごいHaskell たのしく学ぼう!」を読んだ

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

本書は一度は8章あたりで挫折したが、今回13章あたりまで読みファンクタ―、アプリカティブファンクタ―、モノイド、モナドといった概念がなんなのか理解とまでは言えないけど知ることができた。

一度は挫折したが今回またリベンジしようと思った理由は、今後モバイルアプリを開発していくにあたって関数型プログラミングの概念を理解して採り入れていくことが必要になってくると思ったからだ。Swiftletによる不変型の宣言やOptional型などの文脈付きの型など関数型プログラミング言語としての側面をもっていると思う。また、データバインディングSwiftBond/Bondなど)やJSONのパース(thoughtbot/Argoなど)といった場面で関数型プログラミングの概念が登場してきている。Swiftのポテンシャルを最大限に発揮して、堅牢で生産性の高いコードを書くには関数型プログラミングの知識が必要になってきていると最近感じている。

本書を読んだ結果として、データの構造について新しい視点を得ることができた。MaybeEitherといった概念を"文脈"と呼んでいるのが自分の中にはなかった発想だった。例えば、MaybeMaybe Intを区別して考えるのはとても抽象的だけど強力な考え方と思った。Maybeは「あるかもしれないし、ないかもしれない」という文脈を表し、Maybe Intは「Int型かもしれないし、何もないかもしれない」型を表している。これらを分けることで、文脈を保ったまま計算するという発想が出てくるのだと思う。文脈を保ったまま計算する段階として、本書ではFunctorApplicative、そしてMonadが登場してきた。

Swiftでは、Haskellにおける型コンストラクタにあたる概念がない。Genericsを使うことでMaybeのような型を表現することはできるが、ある型が型引数をとるのかとらないのか、とるとしたらいくつとるのかを知る術はない(はず)。Haskellではそれらは種類という概念で説明されている。Maybeの種類はMaybe :: * -> *だし、Eitherの種類はEither: * -> * -> *となっているので、それぞれ型引数を1つと2つとることがわかる。HaskellFunctorは種類が* -> *の型コンストラクタしかインスタンスにできないのだけど、こういう概念をSwiftで表現できない。

というわけで、Swift関数型プログラミングをするにはHaskellほどうまくはできないことがなんとなくわかった。Genericsなどで擬似的に表現するしかない。Functorfmapを以下のように実装してみた。

extension Optional {
    func fmap<U>(f: T -> U) -> U? {
        switch self {
        case .Some(let value):
            return f(value)
        case .None:
            return .None
        }
    }
}

let maybeOne: Int? = 1
let maybeTen = maybeOne.fmap({ x in x * 10 })

SwiftOptional<T>型はつまりT?型のことなのだけど、Optional型を拡張してfmapを追加している。return f(value)のところは暗黙的にU?型にラップしている。このように実装することで、Optional型のもつ「あるかもしれないし、ないかもしれない」という文脈を保ちつつ、中身の1というIntを計算している。

ここではFunctorだけを簡単に実装してみたが、これに加えてApplicativeMonadを実装するとより抽象的な計算が可能になってくる。JSONのパースなどを実装する際にはApplicativeの操作が必要になってきそうな感じがする。自分はまだ関数型プログラミングの実装を実際にしたわけではないので、理解したとは到底いえない。パーサーの実装をしてみたり、上で紹介したライブラリのコードを読んでみることで関数型プログラミングを実践的に理解していきたい。

「UMLモデリングの本質」を読んだ

UMLモデリングの本質 第2版

UMLモデリングの本質 第2版

UMLモデリングの本質」という本を読んだ。最近、ソフトウェアの設計について興味があって、いろいろ調べてみたところ各所でこの本がオススメされていたので手にとってみた。以前のエントリー(「達人に学ぶDB設計徹底指南書」を読んだ - naoty.to_s)でデータベースの設計について理解できたんだけど、結局のところ、そのシステムが扱う業務内容をいかにして実装可能なモデルに落とし込むか(=モデリング)が重要になってくると思う。この本で理解したかったのはそこだった。タイトルからUMLの書き方についての本のようにも思えるが、そうではなく、むしろまったくUMLの書き方は書いてない。UMLを使って、複雑な業務用件をいかにモデリングするかを説いている。本書は300ページに満たないものの、密度が非常にあり2, 3週間でゆっくり読んでも第3章までしか読めていない。それでも、十分に学びがあったので忘れてしまう前にエントリーとして残しておきたいと思う。

モデリングとは

モデリングとは「仕組みや概念を理解するために概念的な要素とそれらの関係を記述すること」とあった。これは普段の業務で多かれ少なかれ必ず行っていると思う。ただ、それをモデリングという工程として認識してはいなかった。そして、モデリングの手法についても特に考えることはなかった。いつも漫然とノートに四角形と線を書いて整理してた(以下、イメージ)。

f:id:naoty_k:20150228013509j:plain:h400

こういう自己流ではなくて、標準的な概念の表記法がある。その1つがUMLだ。UMLを習得することで、他人とのコミュニケーションの手段として使えるようになるし、UMLを通して標準的なモデリングの手法も学べるようになる。

本書によると、モデリングは大まかに以下の順番に行っていくようだ。

  1. 業務フロー図を書いて業務フローを整理する。
  2. 業務フローからユースケース図を書いてユースケースを洗い出す。
  3. ユースケースから概念となる名詞を抜き出し、初期の型図を作成する。型図というのは実際はクラス図のことで、クラスと言っちゃうとクラスとして実装されることを含意してしまうが、実際にはクラスとは限らないため型図という言い方をしている。
  4. ユースケースごとにシーケンス図を書く。これによって各アクターの責務が明確になり、初期の型図を機能的側面から修正することができる。

UMLはけっこうな種類があるような気がするけど、とりあえず上に出てきた図だけ覚えておけばよさそうだ。各ステップの具体的な方法については本書を参照してほしい。読んだだけではあまり意味がないと思うので、近いうちに簡単な例で実践してみたいと思っている。

分類の実装

モデリングの手法の次はより実装に近い話が続く。その中でも分類の実装の話がよかった。例えば、ユーザーに「有料会員」と「無料会員」という分類がある場合に、それをフラグとして実装するのか「Stateクラス」として実装するのかという議論がある。

# フラグで実装

class User < ActiveRecord::Base
  enum plan: %i(free premium)
end
# Stateクラスで実装

class User < ActiveRecord::Base
  has_one :plan
end

class Plan < ActiveRecord::Base
end

class Free < Plan
end

class Premium < Plan
end

個人的にはStateクラスという手法を知らなかったので、いつも前者のフラグとして実装していた。この実装の問題点は、状態が増えた場合にコードを修正する必要がある点と、if文の分岐を多用することになりコードが複雑になってしまう点がある。特に後者は、状態フラグの種類(例えば、「公開アカウント」or「非公開アカウント」)が増えたときに組み合わせが倍になり指数関数的に複雑になってしまうため、重大な問題点だと思う。

Stateクラスであれば、サブクラスを追加するだけでよく既存のコードを修正する必要がない。if文による分岐もダックタイピングによって解決する。状態フラグが複数になった場合は、直交する状態をサブクラスとして定義する(PublicFree, PrivatePremiumなど)のがよいと本書では書かれていた。状態によって振る舞いが異なる場合や状態が増える可能性がある場合は、フラグではなくStateクラスで実装する方がいいのかもしれない。

ファサード

モデリングによって整理された概念をクラスとして実装する際、層別化アーキテクチャを使うのがいいという話が出てくる。よく知られた4層モデルの話で、システムを「ユーザーインターフェイス層」「アプリケーション層」「ドメイン層」「永続層」に分離し、層間の参照を一方向にすることで結合度を抑えるというアプローチだ。このとき、モデリングによって整理された概念はそのままドメイン層に配置することになる。そして、アプリケーション層には業務フローで定義された手続きや処理の手順を定義していくことになる。

アプリケーション層を実装していくなかで、ドメイン層に定義された概念が高度に抽象化されていて扱いづらいときがある。とは言え、これまでのモデリングで練り上げてきた概念をアプリケーション層の都合でねじまげるわけにはいかないだろう。そこで登場するのがファサードというオブジェクトだ。ファサードはアプリケーション層からは冗長に見えるドメインを1つにまとめて扱いやすくする。さらに、複数ドメインにまたがった排他制御も扱う。

ファサードという概念はなんとなく耳にしたことがあったが、モデリング→実装という流れの文脈で捉えるとその必要性を実感することができた。普段RailsMVCだけを書いていると、こうした視点が持てずにドメインをねじ曲げてしまうことがある。なので、ファサードの実装方法について調べて実践していきたいと思った。

「達人に学ぶDB設計徹底指南書」を読んだ

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

「達人に学ぶDB設計徹底指南書」を読んだ。最近、Webアプリケーションを開発する中で設計に問題意識を感じるようになった。ただ、具体的にどこが問題なのかうまく言語化できなくて、というか設計という言葉が何を指しているのかイマイチ分かってなかったので、データベースの設計について本を読んでみた。

内容

  • データベースの設計は「論理設計」→「物理設計」の順に行う。論理設計はデータの要素やデータ間の関係を定める工程を指す。物理設計はデータを格納する物理的な領域や格納方法を定める工程を指す。
  • 論理設計は「エンティティの抽出」→「エンティティの定義」→「正規化」→「ER図の作成」の順に行う。エンティティというのは業務内容に現れるデータの集合体を指す。
  • 物理設計は「テーブル定義」→「インデックス定義」→「ハードウェアのサイジング」→「ストレージの冗長構成決定」→「ファイルの物理配置決定」の順に行う。
  • 正規化というのはデータの形式を正規形にすることであり、正規形というのはデータの冗長性が排除され一貫性と効率性が保持されるデータ形式のこと。異なるエンティティを異なるテーブルに分離することによって第3正規形までは実現できる。
  • 正規化の目的はデータの冗長性を排除して不整合な更新を避けることにある。ただし、正規化はテーブルを分離するため、SQLでjoinを使うことになる。joinはパフォーマンスが悪化するため、正規化とパフォーマンスはトレードオフの関係にある。
  • 「非正規化は最後の手段」というのが筆者の意見である。

感想

  • データベース設計で最初に行うのは「エンティティの抽出」であるということがとても重要なポイントに感じた。
  • いつもRailsでアプリケーションを開発するとき、正規化を意識することはない。Modelを定義することはテーブルを定義することと同義だ。なので、適切にエンティティを定義できていれば、意識せずとも第2正規形、第3正規形を実現できると思う。筆者の「非正規化は最後の手段」という立場にたつと、いつもどおりModelを定義することで正規化を行い、非正規化以外の手段でパフォーマンスを向上させていけばいいということになる。つまり、今まで通りでいいってことか。
  • 結局、「いかにしてエンティティを抽出・定義するか」という問題を考える必要がありそうだ。

Web API: The Good Partsを読んだ

Web API: The Good Parts

Web API: The Good Parts

業務ではiOSアプリとバックエンドの開発を両方担当しているので、APIの設計を何回かやってきた。しかし、自分なりのやり方でやってきた部分が多かったので、最近発売されたWeb API: The Good Partsを読んでちゃんとした設計について学ぶことにした。

得られた学びをメモとして残す。

HATEOAS

HATEOAS(Hypermedia As The Engine Of Application State)という設計方法を初めて知った。HATEOASではまず、サーバー側はレスポンスに関連するエンドポイントを含め次にアクセスするAPIを簡単に辿れるようにする。クライアント側は最初のエンドポイント以外はハードコーディングせずにレスポンスに含まれるエンドポイントだけにアクセスを制限する。このようにすることで、アプリケーションのワークフローをクライアント側で制御するのではなく、サーバーサイドで制御できるようになる。

HATEOASのメリットとしては、特にモバイルアプリケーション開発の文脈で重要なこととして、最初にアクセスするものを除いてエンドポイントをハードコーディングせずに済むということだと思う。一度リリースしてしまったアプリにハードコーディングされたエンドポイントは互換性を死守しなければならないが、レスポンス中に含まれるものを使うのであれば柔軟にエンドポイントを変更することが可能になる。

例として、配列を返すレスポンスに前後のページへのリンクを含める場合はこのようになる。

{
  friends: [
    {
      id: 12345,
      name: "Alice"
    },
    {
      id: 12346,
      name: "Bob"
    }
  ],
  hasNext: true,
  links: [
    {
      uri: "http://api.example.com/v1/users?page=3&per_page=20",
      rel: "next"
    },
    {
      uri: "http://api.example.com/v1/users?page=1&per_page=20",
      rel: "prev"
    }
  }
}

エラー時のレスポンス

エラーが発生した場合は適切なHTTPステータスコードを返すのは当然としてエラーの詳細情報を返す必要がある。それらはレスポンスボディに含めることが多い。複数のエラーが同時に発生する場合を考慮して、詳細情報を配列で返す方が親切だと思う。詳細情報には、エラーメッセージだけでなく、API提供側で独自に定義した詳細コードが含まれることがある。詳細コードはステータスコードと混同しないように4桁にして、1000番台は汎用的なエラー、2000番台はユーザー情報に関連するエラーというようにカテゴリー分けすると便利。

{
  errors: [
    {
      message: "Not Found",
      code: 1013
    }
  ]
}

クライアント側の実装としては、HTTPステータスコードではなく詳細コードごとにエラーメッセージを出し分ける方がユーザーにとってフレンドリーなUIになるだろう。

キャッシュ

HTTPのキャッシュの仕様には2種類あり、期限切れモデルと検証モデルがある。

期限切れモデルでは、キャッシュの保存期限をサーバー側で指定し、クライアントはその期限中は通信を行わなくなり期限が切れたらアクセスを再開する。期限の指定方法はCache-ControlヘッダーとExpiresヘッダーの2種類ある。Cache-ControlDateヘッダーの日時からの経過時間を指定する。Expiresは期限を表す日時を指定する。Cache-Controlは頻繁には更新されないデータに使われ、Expiresは天気情報など決まった時間に更新されることがわかっている場合に使われることが多い。

検証モデルでは、クライアントは今持っているキャッシュが有効かどうかを問い合わせて無効だったときだけ取得する。サーバー側はデータを返す際Last-ModifiedヘッダーとETagヘッダーを返し、クライアントに保持してもらう。そして、クライアントが問い合わせるときに送られたIf-Modified-SinceIf-None-Matchと比較して変化しているかどうかを判定する。変化していればキャッシュは無効とみなし再取得させる。期限切れモデルとは異なり、毎回アクセスは発生しているため、データ自体がそこまで大きくないとあまり効果はない。

使い分けとしては、頻繁に更新されないものや定期的に更新されるようなデータは期限切れモデルを使い、頻繁に更新される可能性があるものは検証モデルを利用するのがよさそうだ。

その他

OAuth2.0のフロー、各HTTPステータスコードの説明、APIにまつわるセキュリティなどAPIを設計する上で必要となる周辺知識がのっている。個人的に気になっていたAPIオーケストレーションの話はそこまで取り上げられていなかった。

「集合知プログラミング」を読んでる

集合知プログラミング」という本を先週から読み始めた。この本は機械学習をテーマとしていて、現実にありそうな問題(例えば、映画の評点から似ているユーザーを推薦するとか、数ある旅行プランの組み合わせから最適なプランを選択するとか)を題材にさまざまなアルゴリズムチュートリアル形式で学んでいける。登場するサンプルコードはすべてPythonで書かれているため、まずこの本を読む前に軽くPythonについて勉強した。機械学習の本というと、むずかしい数式がたくさんでてきて近寄りがたいイメージがあるのだけど、この本についてはほとんど数式は出てこないので、カジュアルに読み進められる。

まだ半分も進んでないけど、その中で一番おもしろかったのが最適化アルゴリズムの話だった。ある最適な値を求めたいとき、「となりあう値と比較して良い方を選択する」というのを繰り返していくとどこか最適な値で落ち着くはずというアルゴリズムヒルクライム)があるのだけど、これだと局所最適に陥ってしまうということを最近勉強した。つまり、全体を見渡すともっと最適な値があるのだけど、近くの値とだけ比較しているとそれを見逃してしまうということだ。また、別のアルゴリズム(模擬アニーリング)は、試行回数が少ないうちは悪い結果を受け入れ、回数を経るにつれてその悪い結果を受け入れ難くしていくことで局所最適を回避する。

これはいろんなところで当てはまりそうな考え方だなと思った。見える範囲、理解できる範囲だけで最適な選択をとろうとするとより適切な解を見落としてしまう。若いうちは結果が悪かろうともそれを受け止めることで局所最適を回避し全体最適に近づくことができるのかもしれない。

この本を読もうと思った理由としては、いろんな領域と機械学習を組み合わせるとなんか面白いものが作れそうな気がしたから。これまで自分が作ってきたソフトウェアの中で自分自身気に入っているものの多くは別の領域のアイデアを持ち込むところから生まれている。だから、組み合わせの可能性が大きい領域を何か新しく学びたいと思ったときに機械学習というものが浮かんでてきてこの本から取り組んでみることにした。今は「iOS x 機械学習」みたいな掛け合わせで何か面白いものが作れないか考えている。

集合知プログラミング

集合知プログラミング

Head First Cの感想

以前参加したmrubyの勉強会でC言語でコードを書く機会があってよくわからなかったので、オススメされた「Head First C」を読んでみた。

Head First C ―頭とからだで覚えるCの基本

Head First C ―頭とからだで覚えるCの基本

500ページ超あるんだけどすごくわかりやすくて10日間で読み終わった。Head FirstシリーズはRailsなどいろいろあるのは知ってたけど読んだことなかった。どうやらこのシリーズは科学的なアプローチで分かりやすく書いているみたいで、確かにわかりやすかった。C言語の入門書というとすごい古い本や固っくるしい本が多いような印象があるけど、この本は今月発売されたばかりでかつカジュアルだったので、とっかかりやすかった。

内容はmain()とかポインタから始まって、最後はマルチプロセスのwebサーバーを作ったりマルチスレッドプログラミングを扱うところまでカバーしてる。やっぱりポインタが鬼門で、何度も読み返したけど80%くらいの理解。文字列ポインタとか配列変数とかで???ってなった。それ以外は本当にわかりやすくてよかった。特にメモリ管理のところはわかりやすかった。普段Rubyとか書いてるとあまりメモリのことは考えないけど、スタックとヒープの区別がついたり、valgrindを使ってメモリリークを調べたりすることでだいぶメモリに対する意識が高まった。また、gccでコンパイルしたりリンクをひとつひとつ丁寧にやることでmakeの有難みを感じた。iOSアプリを開発するとたまに出てくるスタティックリンクライブラリ(lib*.aみたいなの)の正体もわかってよかったし、今後iOSアプリのビルドに失敗しても怯えなくて済みそう。あと、途中のコラムでOpenCVについて簡単な説明があってちょっと興味がわいてきた。Raspberry Piとウェブカメラを買ってOpenCVで遊んでみたいと思った。