tcp/ip4階層モデル

TCP/IPとは

はじめに

この記事は下記の参考資料を元にした筆者の解釈の記述です。

正確さについては保証されませんので詳しくは下記の参考元をご参照ください。

基礎からわかるTCP/IP ネットワークコンピューティング入門 第3版

TCP/IP 4階層モデルとは?

TCP/IPという言葉

TCP/IPはインターネットワーキングを実現するための仕組みのことだが、TCP/IPという言葉が使われる時は以下の三つのうちのどれかを意味していることが多い。

プロトコルの名前

  • TCP
    • Transmission Control Protocol
  • IP
    • Internet Protocol

インターネットを動かす通信技術をまとめた呼称

TCP/IP Protocol Suiteの意味。

前述のTCPとIPに加え下記のプロトコル群が含まれる。 TCP/IPの意味として最も一般的。

  • UDP
    • User Datagram Protocol
  • ICMP
    • Internet Control Message Protocol
  • ARP
    • Address Resolution Protocol

Protocol Stack としてのTCP/IP

プロトコル群の機能を実現するための実装のことをプロトコルスタックと呼ぶ。

TCP/IPの機能を実現するプロトコルスタックを単にTCP/IPと呼ぶこともある。

以下はこの意味でTCP/IPという言葉を使用する。

TCP/IP 4階層モデル

OSI参照モデルとの違い

osi参照モデルは7階層に別れたインターネットワーキングのためのモデルである。

ISOが定めた。

TCP/IPOSI参照モデルよりも2年ほど早く使われ始め、広く普及されていたためOSI参照モデルが実際に使われる機会が少なくなってしまった。

アプリケーション層

データを利用するアプリケーションの間でのデータのプロトコルを定める。

HTTPなど。

トランスポート層

UDPTCPがこの階層に相当する。

ここではポート番号などの情報を読み取って正しくアプリケーション層へデータを渡すなどの役割がある。

インターネット層

IPはこの階層のプロトコル

複数のネットワークが互いに接続された環境でデバイス間のデータ送信を実現している。

ネットワークインターフェイス

ハードウェアが通信を実現するための層。

イーサネットwifiなどがこの層のプロトコルを利用している。

通信の階層化とプロトコルスタック

4階層で別れているそれぞれのプロトコルはそれを扱うそれぞれのソフトウェアによって対応されるようになっている。

これらのうちアプリケーション層はアプリケーションソフトウェアによって実現され、ネットワークインターフェイス層はそれを扱うハードウェア内に実装されている。

トランスポート層TCPとIPについては現在利用されているほとんどのOS内にそれを扱うためのソフトウェアが実装されている。

TCP/IPの利用

TCP/IPはインターネットだけで利用されている訳ではない。

企業や学校などある特定の範囲のみを結ぶネットワークのことをイントラネットと呼ぶがこれにみTCP/IPが使用されている。

また、限定されたコンピューター同士をつなぐネットワークはエクストラネットと呼ばれこれはVPN(Virtual Private Network)として排他的に構築されるがこのようなネットワークにもTCP/IPが利用されている。

そのほかにもネットワークとして機能している様々な分野の技術でTCP/IPが応用されている。

TCP/IPを定める人

TCP/IPはIETE(Internet Engineering Task Force)と呼ばれる標準化団体によって策定されている。IETEは特定の企業等ではなく、全世界の様々な企業や学校などが参加している。

また、その情報はRFC(Request For Comments)として公開されている。

ソフトウェアとしてのTCP/IP

ネットワークを利用するためには言うまでもなくパソコンなどのハードウェアが必要になるが、それがあるだけでは不十分である。

パソコン自体にネットワークに繋がる仕組みがあったとしてもそれを実現するためにはソフトウェアが必要になる。

そのソフトウェアがTCP/IPであると言うこともできる。

物理的な接続/論理的な接続

コンピュータ同士をケーブルで物理的に接続すれば物理的な接続を実現することができる。

ただし、物理的に接続しただけではそこを通るデータに意味を持たせることはできない。それらを解釈することができて初めて意味があり、論理的な接続が実現できたことになる。

パケット

TCP/IPはパケット(packet)と呼ばれるものを交換するためのプロトコルである。

パケットはpackage(郵便物)に例えることができる。

パケットにはヘッダとペイロードに分けることができ、ヘッダには届け先が書かれたものであり、ペイロードには実際の荷物に相当する。

元が大きなデータであったとしても、パケットの単位で区切られて小分けにされて届け先まで届けることができる。

パケット交換方式

データをパケットの単位で送信する方法はパケット交換方式と呼ばれている。

パケット交換方式の利点は限られた回線を複数のコンピュータで共有できる点である。

一つ一つのパケットが独立して意味を持つためそれらがバラバラに一斉に回線を流れていっても破綻することがなく送信先で意味をなすことができる。

これにより少ない回線を有効利用することができ、物理的なインフラのコストを抑えることができる優れた方式であった。

アドレス

ネットワークに接続できる端末はアドレスを持っている。

これらの識別子は機器を特定し送り先を特定するために使用される。

ネットワーク技術を支えるコンピュータの基礎

TCP/IPでのハードウェアとソフトウェア

ネットワークに使用されるハードウェアには接続のためのケーブルやNIC(ネットワークカード)などがある。あるいは接続に使用するコンピュータそのものも含まれる。

対してネットワークソフトウェアは大まかに下記の三つに分けられる。

  • ネットワークアプリケーション
  • ネットワークOS
  • ネットワークハードウェア

ネットワークOSとはネットワークに使用する機器を制御する機能を備えたOSのことである。

現在のほとんどのOSはこの機能を持っている。

ネットワークアプリケーションはwebブラウザメーラーなどネットワークを使用するプログラムのことである。

このようにネットワークの技術は階層に別れていてそれらが組み合わされることで実現されているが、それらの部分部分のことをモジュールと呼ぶ。

それぞれのモジュールは交換可能になっており目的によって最適なモジュールを使い分けることができるようになっている。

コンピュータ内のネットワーク

コンピュータ内ではCPUを中心に周辺機器がバスと呼ばれる通り道で繋がれている。

CPUからそれぞれのデバイスにアクセスするためにそれらに固有のアドレスが割り振られている。

外のネットワークに接続するためのNICのそれらのデバイスのうちの一つである。

DynamoDB開発者ガイド要約

DynamoDB開発者ガイド要約

参考資料

Amazon DynamoDB 開発者ガイド API バージョン 2012-08-10

DynamoDBとは

AWSのプロダクトの一つ。

DynamoDBなのでデータベースである。

リレーショナルデータベースではなくNoSQLである。

NoSQLとは

NoSQLは Not only SQL の略と解釈されるのが一般的である。

NoSQLはRDBではないため共通する特徴として非構造のデータを扱うことができるというものがある。

NoSQLには大きく下記の四つに分類されることが多い。

  • キーバリューデータストア
  • 列ファミリーデータストア
  • 文書データストア
  • グラフデータストア

DynamoDBはこれらのうちのキーバリューデータストアに分類される

キーバリューデータストアとは

この構造の原型がAmazonDynamoであると言われている。

高い可用性とスケーラビリティが特徴である。

主キーに対してBLOBの値を持つのみという極めてシンプルな構造を持っている。

複雑なクエリを発行することはできない。

DynamoDBのしくみ

テーブル

各データはテーブルに保存される。

項目(Items)

項目(item)はRDBに置ける行(record)に相当する。

項目はプライマリキーによって一意に識別可能であることが前提となる。

テーブルごとの項目数の制限はない。

属性(Attributes)

属性はRDBにおける列に相当する。

属性にはそれ以上分割できない単位のデータを格納する。

属性を入れ子にすることもできる。 最大32階層までの入れ子属性をサポートしている。

属性のうち一つ必ずプライマリキーとなる要素が含まれている必要がある。

非構造

テーブルの項目はスキーマレスであることが許容されている。

プライマリキー以外の属性やデータ型を定義する必要がない。

テーブル内の各項目がそれぞれバラバラな属性や構造を持っていても良い。

プライマリキー

前述のようにテーブルにはそれぞれ一つ以上のプライマリキーが定められていなければならない。

プライマリキー属性の値はスカラー値(文字列・数値・バイナリのいずれか)である必要がある。

プライマリキーは二種類のものがある。

パーティションキー

シンプルなプライマリキー。 DynamoDBの内部でパーティションキーの値をハッシュ関数にかけその出力に基づいて項目が保存される物理ストレージのアドレスが決まる。 ハッシュ属性とも呼ばれる。

パーティションキーの値にアクセスすることで物理ストレージの目的の項目のアドレスに直接アクセスすることができる。

プライマリキーがパーティションキーのみである場合はキーの値が項目間で一意である必要がある。

パーティションキーとソートキーの複合

複合プライマリキーと呼ばれる。

第一のプライマリキーはパーティションキーであり第二のプライマリキーがソートキーとなる。

複合プライマリキーの場合は複数の項目のパーティションキーに同じ値を用いることもできる。 ただしソートキーは異なる値である必要がある。 ソートキーは範囲属性とも呼ばれる。

同じパーティションキー値を持つ項目は物理ストレージの同じ領域にソートキーの値によって分類されて物理的に近い場所に格納される。

複合プライマリキーのメリット

データのクエリを実行する際の柔軟性を高める。

パーティションキーとソートキーの組み合わせでクエリの範囲を調整することができるためである。

セカンダリインデックス

DynamoDBではプライマリキー属性に対してインデックスを作成している。 基本的にはプライマリキーを指定することでデータへのアクセスを迅速に行うことができる。

プライマリキー以外の属性を指定した場合でも効率的なデータへのアクセスを実現したい場合はセカンダリインデックスを使用することができる。

テーブルにグローバルセカンダリインデックスを作成することでテーブルから直接データを読み込むのとほぼ同様の方法でインデックスからデータを読み取ることができる。

読み込み/書き込みキャパシティモード

テーブルでの読み込みと書き込みについてキャパシティモードが2つ設けられている。

キャパシティモードは1秒あたりにどれだけのリクエストを許容するかの指標である。

  • オンデマンド
  • プロビジョンド

プロビジョンドはデフォルトであり無料枠である。

オンデマンドモード

オンデマンドモードではリクエスト数に制限がない柔軟なオプションである。

リクエスト数に応じて支払い料金が発生する。

リクエスト数が事前に予測できない場合は有効なオプションと言える。

プロビジョニングモード

1秒あたりの読み込みと書き込みの回数を指定する必要がある。

Auto Scaling が有効である場合トラフィックに応じてテーブルのプロビジョンドキャパシティーを自動的に調整することができる。

リクエスト数が予測可能である場合はプロビジョニングモードが有効である。

読み込みキャパシティーユニット/書き込みキャパシティーユニット

プロビジョニングモードのテーブルでは読み込みキャパシティユニットと書き込みキャパシティーユニットの二つの基準に基づいてスループットを調整することができる。

読み込みキャパシティーユニット

読み込みキャパシティユニット一つにつき最大サイズ4KBの項目について1秒あたり1回の強力な整合性のある読み込み、あるいは1秒あたり2回の結果整合 のある読み込みを行うことができる。

必要な読み込みキャパシティユニットの数は項目のサイズと読み込みの種類によって変動する。

例として項目サイズが8KBの場合は4KBの場合に比べて倍の数の読み込みキャパシティユニットが必要になる。 このように項目のサイズが大きければ大きいほど必要な読み込みキャパシティユニットの数は増える。

書き込みキャパシティーユニット

一つの書き込みキャパシティユニットはサイズが1KBまでの項目について1秒あたり1回の書き込みを行うことができる。

1KBを超えて書き込みを行う場合、項目のサイズに比例して追加のキャパシティユニットが必要になる。

また、トランザクション書き込みリクエストの場合は通常のリクエストの倍のキャパシティユニットが必要になる。

ProvisionedThroughputExceededException

意図せず大量のキャパシティーユニットが消費されるのを防ぐためにスロットリングも動作するようになっている。

ロットリングはテーブルがサポートできるよりも高いレートで読み込みや書き込みが試みられた場合に発生する。

ロットリングが発動するとリクエストはHTTP Bad Request となり ProvisionedThroughputExceededException が返る。

AWS SDKにはスロットリングされたリクエストを再試行するためのサポートもある。

CloudWatchではスロットリングされた書き込み/読み込みリクエストをモニタリングすることができる。

スループットについて検討する際に考慮すべきこと

項目のサイズ

項目のサイズが十分に小さければリクエストが大量に発生しない限り消費ユニットを少なく収めることができる。

項目のサイズは予測できる範囲に収められるように設計すべきで、かつできる限り小さなものになるように努力すべきである。

リクエストのレート

リクエスト数についても可能な限り見積もりがなされるべきである。

ただし、項目のサイズを小さく保つことができればこの見積もりも難しいものではなくなるはずである。

Auto Scaling

DynamoDB Auto Scaling ではテーブルのスループットキャパシティが自動的に管理される。キャパシティユニットの上限と下限が自動で定義される。

トラフィックが増加した場合、リクエストのスロットリングが発生しないためにキャパシティの増加を行う。

また、意図的にスループットを低下させるような処置も行う。

https://aws.amazon.com/jp/dynamodb/pricing/

『Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』第5章[前編]

第5章 メモリ

はじめに

参考文献

武内 覚 著『Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』をテキストとして学習した記録です。

本書を読んで筆者が解釈した内容について記述しています。

なので本書の内容の間違った解釈やあるいは単純に間違った記述がある可能性があります。

概要

Linuxのメモリの扱い方

誰がメモリを管理しているか

メモリの使用状況はカーネルのメモリ管理システムが管理している。

メモリを管理しているのはカーネルだが、メモリを使用するのはプロセスだけではなくカーネル自身もまたメモリを使用している。また、カーネルが使用しているメモリ領域のデータは捨てても良いものか捨てることができない重要なものかはカーネル自身が知っているが、プロセスのそれはカーネルからは判断することができない。

メモリが足りなくなってくるとカーネルはメモリ領域のうちで捨てても大丈夫だとわかっているカーネル由来のデータを破棄するが、それでもメモリが足りなくなってきた場合OOMと呼ばれる状態になる。

こうなるとシステムは何もできない状態になってしまうため、メモリを使用しているプロセスをランダムにkillすることでメモリを解放するOOM killerを発動する。

サーバで勝手にこのようなことをされると困るのでOOM発生時はシステム全体を強制終了させる設定を行う場合もある。

どうやってメモリを割り当てるか

これまででわかっているところ

  • メモリを管理するのはカーネルのメモリ管理システム
  • メモリを使うのはプロセスとカーネル
  • メモリは有限
  • メモリは皆で同時に分け合って使われている

プロセスはカーネルに自分の分のメモリの割り当てを要求する。

プロセスの割り当ては下記のように行う

  1. カーネルがプロセスにとって必要な分のサイズのメモリを確保する
  2. その先頭のアドレスをプロセスに渡す

プロセスは生成された時点で一旦メモリをもらうが、そのあとでメモリが足りなくなったら追加の分を要求する。

プロセスがメモリ上の自分用の領域を使いたい場合にはカーネルにもらったアドレスを基準にメモリの参照や書き換えなどを行う。

上記のようにプロセスが直接本物のメモリにアクセスできるような設計には問題がある。

  • 離ればなれのアドレスにあるメモリを一つのプロセスが扱うのは困難
  • 自分の領域ではないアドレスにアクセスすることが可能
  • マルチプロセスを実行したいときにアクセスすべきアドレスがわからなくなる

仮想記憶

プロセスにメモリへ直接アクセスさせる際の問題点を解決するための仕組みが仮想記憶。

Linuxではプロセスには直接本物のメモリ上のアドレスにアクセスさせる代わりに仮想記憶を介してアクセスさせるようにしている。

メモリ上の本物のアドレスのことを物理アドレスとよび、プロセスが認識するアドレスを論理アドレスと呼ぶ。

プロセスは論理アドレスを指定してメモリを読み書きするが、実際に扱うアドレスは論理アドレスに対応する別のアドレスということになる。

ページテーブル

どの仮想アドレスがどの物理アドレスに対応しているかはカーネルが使用・管理しているメモリ領域の「ページテーブル」というテーブルに記録されている。

プロセスが論理アドレスを指定するとCPUがそのプロセスのページテーブルを見て対応する物理アドレスを探し、そこにアクセスするようにする。

またページテーブルにはそのプロセスに割り当てられているだけの領域しか記録されていないはずなのでプロセスがその領域外の論理アドレスを指定した場合はページフォールトという割り込み処理が発生し、そのプロセスの処理を不正な処理とみなした上で強制終了するようになっている。

『Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』第4章[後編]

第4章 プロセススケジューラ[後編]

はじめに

参考文献

武内 覚 著『Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』をテキストとして学習した記録です。

本書を読んで筆者が解釈した内容について記述しています。

なので本書の内容の間違った解釈やあるいは単純に間違った記述がある可能性があります。

概要

プロセスにはいくつかの状態がある。

それらのなかには実行待ち状態やスリープ状態などプロセスが進捗しない状態も含まれる。

プロセスはその一生で状態をいくつか遷移し、一生を終える。

CPUは場合によって何もしていないように見える時があるが、そういう時はアイドルプロセスと呼ばれる「何もしない」ためのプロセスが動いている。

性能の指標にはスループットとレイテンシがある。 スループットは時間あたりにこなした仕事量。レイテンシは処理にかかった時間。両者ともに値が高いほど性能も高いと言える。

性能を高めるためにはプロセスが進捗しない時間を減らしたり、CPUが暇になるアイドル状態が生じないようにCPUにプロセスを割り当てることが重要になりそうである。

そのためにプロセススケジューラが担う役割はどんなものか?

論理CPUが複数の場合のスケジューリング

論理CPUが複数ある場合はロードバランサがプロセスを公平に分配する役割を果たす。

マルチコアCPU環境(論理CPUが複数ある環境)であっても複数プロセスを同時に実行できない場合はスループットは上がらない。例えば各プロセスを直列で処理する必要がある場合はそのようになる。

プロセス数が論理CPUの合計よりも多い場合はスループットが論理CPUの数によって向上することは無い。

経過時間と使用時間

timeコマンドでプロセスを作成するとプロセスの経過時間使用時間の二つの値を得ることができる。それぞれの意味は下記の通り。

  • 経過時間
    • プロセスを開始してから完了するまでにかかった時間
  • 使用時間
    • そのプロセスが論理CPUを使用した時間

プロセスの状態と経過時間・使用時間

中編で学んだようにプロセスにはいくつかの状態がある。実行状態のみそのプロセスが実際に進捗している状態である。 また、実行状態が唯一論理CPUの時間を使っている状態となり、使用時間が増えている状態となる。

下記のような状態の場合は経過時間のみが増えている状態となる。

  • 複数のプロセスが存在していて他のプロセスが実行中の実行待ち状態。
  • そのプロセスが何らかのイベントを待っているスリープ状態。

論理CPUの数と経過時間・使用時間

論理CPUが複数の場合のスケジューリングで見たように複数の論理CPUがあれば複数のプロセスがあってもそれぞれのCPUになるべく公平になるように割り振られる。

担当するプロセスをそれぞれのCPUが時間を使って実行していくので使用時間の合計が経過時間よりも多くなるということも起きる。

動いているCPUの数だけ使用時間があると考えられる。

これは人工の考え方と同じ。 二人の人がある一日を使ってある作業をしたとすると一日しか経っていなくても二人日分の仕事ができる。

この場合経過日数は一日で使用日数は二日と言える。

優先度

プロセスはCPUの時間を平等に与えられるが、これに優先順位を持たせることもできる。

nice()コマンドを使うことでそれが実現することができプロセスに使用されるCPU時間の割合を-19から20の段階に応じて調整することができる。

『Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』第4章[中篇]

第4章 プロセススケジューラ[中篇]

はじめに

参考文献

武内 覚 著『Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』をテキストとして学習した記録です。

本書を読んで筆者が解釈した内容について記述しています。

なので本書の内容の間違った解釈やあるいは単純に間違った記述がある可能性があります。

概要

プロセスにはいくつかの状態がある。

それらのなかには実行待ち状態やスリープ状態などプロセスが進捗しない状態も含まれる。

プロセスはその一生で状態をいくつか遷移し、一生を終える。

CPUは場合によって何もしていないように見える時があるが、そういう時はアイドルプロセスと呼ばれる「何もしない」ためのプロセスが動いている。

性能の指標にはスループットとレイテンシがある。 スループットは時間あたりにこなした仕事量。レイテンシは処理にかかった時間。両者ともに値が高いほど性能も高いと言える。

性能を高めるためにはプロセスが進捗しない時間を減らしたり、CPUが暇になるアイドル状態が生じないようにCPUにプロセスを割り当てることが重要になりそうである。

そのためにプロセススケジューラが担う役割はどんなものか?

プロセスの状態

プロセスにはいくつかの状態がある。

  • 実行状態: 論理CPUの時間を使用している
  • 実行待ち状態: CPUの時間が空くのを待っている
  • スリープ状態: イベントの発生を待っている。CPUが空くのを待っている訳ではない。
  • ゾンビ状態: プロセスは終了したが、親のプロセスがまだ終わっていなくてその終了を待っている。

通常多くのプロセスがいくつも同時に発生しているが、論理CPUの数はそのプロセスよりも少数である。そしてCPUが一度にできる仕事は一つだけ。 なので論理CPUが順番に色々な仕事をこなしていく中で、プロセスはたとえスリープ状態でなかったとしても自分の出番を待つ実行待ち状態が生じる。

アイドル状態

逆にCPUに仕事が来なくなる場合もある。 プロセスがないかあっても全てスリープ状態であればCPUが暇になってしまう。 sarコマンドで確認してみると実際にほとんどのプロセスはスリープ状態であるためCPU時間のほとんどがアイドル状態となっている。

性能指標 スループットとレイテンシ

  • スループット: 時間あたりにこなした仕事の量
  • レイテンシ: 仕事を完了するのにかかった時間

これらはCPUに限らず別のデバイスでも同様に用いられる指標である。 今回の話はCPUについて。

スループットはCPUが一定時間内にどれだけ多くのプロセスを完了させられるかに焦点が当てられている。なのでCPUが暇している状態(アイドル状態)が多いほどスループットは下がるということが言える。

レイテンシは一つのプロセスに焦点を当ててそのプロセスが開始されてからいかに短時間で完了されるかを測るものである。前篇で学んだようにプロセスはスケジューラに(ラウンドロビン方式の場合)均等なローテーションで実行される。CPU時間がスケジューラによって他のプロセスに使われている場合は実行待ち状態となっている。当然待っている時間が長いほどレイテンシは大きくなるので、プロセスの数は少ないほどレイテンシが小さくなると言えそうである。

スループットはCPUのアイドル状態が短いほど高くなる。プロセスが少数の場合それらのプロセスがスリープ状態になって暇になるリスクが高いので、スループット的な観点からみるとプロセスの数は多いほど良い。 しかしすでに見たようにレイテンシを考えるとプロセス数は少ないほど良いと言える。

このように同時に実行されるプロセス数を巡ってスループットとレイテンシはトレードオフの関係にある。

レビューについて

コードレビューについて

目的

  1. 実装にかかる時間を減らすこと。
  2. 品質を高めること。

前提

  • 基本的にコーディングにかかる時間は一定。
  • 方法を決めるのに時間がかかる。
  • 不確定要素によって方法を決める時間が変動する。

狙い

前提によると以下のように言える。

  • 不確定要素は少なければ少ないほど良い。
  • 方法を決める時間が少ないほど実装時間が短くなる。

ただし、後者については以下のようにも言える

  • 正しい方法を採用しないと、品質が低下する。
  • 品質が低下するとプロダクト内の不確定要素が増加する。

ここにはジレンマがある。
方法を決める時間を0にするには例えば何らかのロジックを実装しようとしていてそれについてメソッドに抽出を行なったりクラスの設計を行なったりすることをしなければ良い。

ただし、それをすると品質が低下し、未来の不確定要素が増えることになる。総合的にみて、良い方法であるとは言えない。

下記のような状態を目指す必要がある。

  • 正しい設計を行い品質を高めつつそれにかける時間を減らす。
  • 不確定要素を減らす。

これらを実現するためにレビューを活用したい。

期待する効果

  • 自分では気がつかなかった課題に気づく(不確定要素を減らす)。
  • メンバーの知恵を借りて、正しい設計に辿り着くまでの時間を減らす。

注意点

レビューはお墨付きをもらうためのものではない。

なので効果の裏返しで、以下のような点が注意点としてあげられる。

  • レビューによって不確定要素がなくなるとは限らない。減らすだけ。
  • レビューによって正しい答えが得られるとは限らない。確率を高めるだけ。

これらの注意点を考慮に入れると、レビューの回数は多いほど良いということになる。

タイミング

レビューは定期的に行うのが良いと思われる。

自分の認識できていない課題を早期発見するという目的を考慮すると、順調に思われる時にもレビューが必要であるからである。

また、レビューは先延ばしにされる傾向がある。前述のようにレビューの回数は多いほど良い。 他のメンバーの時間を使うのにその準備が整っていないと感じられるからである。 また、順調に進んでいるように思われるときは必要のないものと思われるし、順調でない時にはそれを隠したいという心理も働くかもしれない。

なのでレビューのタイミングは予めスケジュールに組み込んでおくと良いと思われる。

一方で、中途半端な状態でレビューを行うと、本来の効果が期待できず、チームメンバーの時間を浪費ことになりかねない。

スケジュールまでにレビューしてもらえる状態に持っていくための努力が必要になるが短期の締め切り効果を狙えるかもしれない。

形式

実装は外枠から行うというルールを守る。

枠組みを決めるまでその中身の詳細について考えるべきではない。 このルールを守る意味でもレビュー時の実装は回を追うごとに詳細化されるようにする。

またこのようにすることでレビューごとの実装の抽象度のレベルが一定になるためコンテキストも一定になり議論の生産性も向上すると思われる。

あらかじめ行う実装を階層化しておき階層ごとにレビューの日を設けて、それを締め切りとみなして開発していくという方法を試してみたい。

『Clean Coder』を読んで見積もりについて考える

見積もりについて

はじめに

参考文献

ロバート・マーティン 著『Clean Coder』をテキストとして学習した記録です。

本書を読んで私が解釈した内容について記述しています。

なので本書の内容の間違った解釈やあるいは単純に間違った記述がある可能性があります。

遅れ

何をしてはいけないか

してはいけないことは締め切り間際になって間に合わないことが明らかになってからその報告をすることだ。

このようなことが起こる原因は遅れの管理ができていない事による。

遅れ自体は見積もりの間違いや不確定要素によっていつでも起こる可能性はある。

常に遅れの管理を行っていることが大切なことである。

遅れの管理の秘訣は早期発見と透明性である。

定期的に進捗を確認して下の三つの期日を出来るだけ正確にチームのメンバーやリーダーに伝えることで透明性を担保することができる。これは常に見積もりを更新することでもある。 見積りには願望を反映させてはいけない。 というか基本的に願望を持ってはいけない。 他の誰かに期待することもあってはいけない。

  • 最早終了日
  • 通常の終了日
  • 最遅終了日

なぜ三つも必要なのか?

見積もりとは

見積りとコミットメントは分けて考えるべきである。

コミットメントは確実な数値である。 それは絶対に守られなければならないもので残業や休日返上など様々な犠牲を払っても、そのために努力しなければならないものである。 残業が続くとパフォーマンスが落ちて、全体の生産性は大きく低下する確率が高い。コミットメントは避けるべきである。

対して見積もりとは予測である。

そもそも、見積りが必要なのは必要な時間がわからないからである。

見積りとは数値ではなく、確率分布。 本の著者は多くの人が見積もりを間違うのはこの違いを明確に意識できていない場合が多いのだという。

確率分布

通常不確定要素は作業が完了に近づけば近づくほど、少なくなっていく。

見積もりの段階では行う作業の不確定要素が最も多い状態と言える。

不確定要素がある以上は見積もりというのは確率にされるということである(当たり前だけど)。

例えば3日で終わる可能性が高い作業であっても、4日かかる可能性もあるし、5日や6日かかる可能性も多少はある。10日かかる可能性もあるかもしれない。

この場合見積もりの時間を聞かれたらどう答えるべきなのか? 3日で終わる可能性が高いように見えても、10日かかる可能性もある。確実に完了できる日数(数値)を計算できるのは不確定要素が限りなく0に近い場合のみということになる。通常見積もりを行う段階ではそのような状態にはなっていない。

コミットメント

このような理由で確実な日数(数値)の約束(コミットメント)は極力避けるべきである。

コミットメントには暗黙的なものも含まれる。例えば「試してみる」などの対応も控えるべきである。そのような曖昧な表現は期待や願望を生むだけで見通しが不透明になり、誰にとっても良い結果にならない。あくまで、確率の分布を伝えるように努力するべきである。透明性を保てるように注意しなければならない。

3点見積もり

コミットメントができないとしたら、見積もりをどう捉えるべきか? また確率分布はどのように扱うべきなのか?

3点見積もりは下記の三つの見積もりを元に作業期間を予想する方法である。

  • 楽観値(O): 全てがうまくいってこれ以上なくスムーズに進行することを想定した極端に楽観的な値
  • 標準値(N): 最も確率が高いと思われる値
  • 悲観値(P): 考えられる最悪なケースを想定した極端に悲観的な値

これらを元に下記の式で確率分布の計算を行う。 μが予想される作業期間である。

μ = (O + 4N + P) / 6

この方法には確率分布をうまく取り扱い妥当な数値を出すとともに楽観的な予想を防止するという意図もある。傾向として悲観値は楽観値よりも大きく影響することが多いため、計算結果も悲観的な数値がでることが多い。

私の場合見積もりの段階では見栄なのか願望なのかよくわからないが、楽観的な見積もりを出す傾向にある。

このような方法を使うことで、そのような失敗の防止が期待できると思う。

チームメンバーの意見を聞く

また、見積もりは一人で行うよりもなるべく多くの人の意見を聞けた方が精度が上がる。一人では気づくことのできない不確定要素も気付きやすくなり、異なる意見を聞くことで新たな視点も獲得できる可能性もある。ただし、楽観的な意見に影響を受けすぎる危険性に注意しなければならない。

大数の法則

大きい作業をそのまま見積もるよりも、小さい作業に分割してそれぞれについて見積もりを行い、それらを合計した方が正確性が増す。間違いが平準化されるからである。