この度「プリンシプルオブプログラミング」という書籍を読みましたので勉強のためまとめます。
この記事は前編の続きです。
第4章 視点 プログラマの観る角度
凝集度
凝集度とはモジュールに含まれる機能の純粋度を表す尺度でモジュールの強さを測るもの。
強度レベルは7まであり、レベルが高いほど結合度が低く良いモジュールとなる。
レベル1:暗合的強度
暗合とは「偶然に物事が一致する」という意味で、暗合的強度モジュールはモジュール内の要素間に特別の関係が認められてない。
たまたまモジュールの中に重複している命令群のパターンがあったので統合して1つのモジュールにしたようなケース。
暗合的強度のモジュール内の各要素は、自モジュール内の他の要素との関連性が弱い反面、他モジュールで変更を行うと大きな影響を受けることが多いので保守が難しい。
レベル2:論理的強度
論理的強度モジュールとはある機能を抽象的に捉えてまとめたもの。
機能を抽象的に捉えるとは全ての入出力操作をまとめてモジュールにしたり、色々なデータを編集するものためのモジュールを作成したような場合のこと。
このような場合はモジュール内の論理は条件によって実行パスが異なるようなものになる。
つまり、論理的強度のモジュールは関連したいくつかの機能を含んでいて、そのうちの1つだけが呼び出しモジュールによって識別され実行されるモジュールのことを言う。
よってモジュールが呼び出されたときに実行される命令は一部だけで、モジュール内の全ての命令が実行されるわけではない。内包される命令郡の関連性は弱くてモジュール強度は弱くなる。
論理的強度にも以下の良い面もある
- 機能的には共通するものを複数個含んでいるので一部の論理は共有できる
- 関連した機能を1つのモジュールにまとめることでプログラマの指向を集中させる効果がある
- 特定データの処理を1つのモジュールに局所化させる効果がある
レベル3:時間的強度
時間的強度モジュールは、特定の時点(時間)に連続して実行する複数の機能を1つのモジュールにまとめたもの。
機能間に強い関連性はなく特定の時点に連続して実行しているだけ。
代表的なものに「初期処理モジュール」などがある。
レベル4:手順的強度
手順的強度モジュールは、問題を処理するために関係している複数個の機能のうちのいくつかを順番に実行する。
基本的に時間的強度の特性を持つが、機能間に手順的な関連性がある分、強度が強い。
この手順的強度モジュールは複数機能の中の1つだけ必要といったときに使えなくなるので、使えるようにするには機能選択が必要だが、それをすると論理的強度となり強度を落とすことになる。
レベル5:連絡的強度
連絡的強度モジュールとは基本的に手順的強度の特性を持っていて、手順的強度と異なるのはモジュール内機能間でデータの受け渡しをしたり同じデータを参照する点。
モジュール内機能がデータに関してつながっている分、手順的強度より凝集度が高くなる。
レベル6:情報的強度
情報的強度モジュールは、特定のデータ構造を扱う複数の機能を1つのモジュールにまとめたもの。
同一データ構造は、できるだけ特定のモジュールだけでアクセスしようという発想でデータの修正時の影響をこのモジュールだけに限定できる。
レベル7:機能的強度
機能的強度モジュールはモジュール内のすべての命令が1つの役割を実行するために関連しあっているモジュールで純粋度が一番高いモジュールになる。
単一の機能を遂行するため、すべての命令がお互いに関連を持っている。
結合度
結合度とはモジュール同士の関係の密接さを表す尺度で、ある結合の「太さ」を測るもの。
結合度のレベルは6つでレベルが高いほど関係が薄く、良いモジュールであると判断される。
レベル1:内容結合
内容結合とは、あるモジュールが他のモジュールと一部を共有するようなモジュールの結合。
他モジュール内の外部宣言していないデータを直接参照したり、命令の一部を共有したりする場合が内部結合にあたる。
一方のモジュール変更が他のモジュールに変更を及ぼす問題がある。
レベル2:共通結合
共通結合とは共通域に定義したデータをいくつかのモジュールが共同使用するような結合形式。
共通域の定義データとは「グローバル変数」のこと。
共通結合は結合度が高いため以下のデメリットがある。
- 共通域のデータはモジュール間のインターフェース上に現れないのでコードの解読を非常に難しくする。
- 共通域のデータは、もともとコードの安定性が低くなる。
- 共通結合しているモジュールは共通域のデータを通じて色々なモジュールとつながっているため再利用性が阻害される。
レベル3:外部結合
外部結合とは、外部宣言したデータを共有したモジュール間の結合形式で、外部宣言した定義とはpublic宣言された変数などのこと。
データの共有という意味では共通結合と似ているが、必要なデータだけを外部に宣言するので不必要なデータまで共有することがない。
レベル4:制御結合
制御結合とは、呼び出し側のモジュールが呼び出しされるモジュールの制御を指示するデータをパラメータとして渡す結合形式。
制御結合ではパラメータの1つとしてスイッチ変数を渡して呼び出されるモジュールがそのときに行う機能を指示。
呼び出し側は呼び出すモジュールの論理を知っている必要があるので、相手をブラックボックス扱いできず結合度が強くなる。
呼び出されるモジュールの凝集度は論理的な強度になってしまうデメリットはあるが、データの共有ということはないので共通結合や外部結合と比べて結合度は弱い。
レベル5:スタンプ結合
スタンプ結合とは共通域にないデータ構造を2つのモジュールで受け渡すような結合形態。
データ構造の受け渡しは、パラメータを介して行われる。
スタンプ結合では受け渡すデータ構造の一部を使用しないことがあり不必要なデータまで受け渡しする点が結合度を少し強めてしまう。
レベル6:データ結合
データ結合とは、モジュール間のインターフェースとしてスカラ型のデータ要素だけを、パラメータとして受け渡す結合形式。
相手モジュールをブラックボックス化できるので結合度が弱くなる。
低結合モジュールを作成するための方法
- データの受け渡しはできるだけ引数でおこなう
- データの置き場所はできるだけグローバル変数に置かない
- 動作について渡す値に応じて変わるようなコードを書かないようにする
直交性
コードは直交性を満たすようにする。
直行しているコードとは2つ以上のコードの塊があったときに、片方を変更しても他方に影響を与えないようなコード。
直交性のあるコードを記述することで以下の2つのメリットを享受できる。
-
生産性の向上
- 変更が局所化されるため、開発期間とテスト期間を短縮できる。
- コードが疎結合になるのでコードが再利用しやすい。
-
リスクの軽減
- コードに問題があったときに、その部分を隔離できる
- 依存が少ないのでテストを簡単に行うことができる。
コードに直交性を持たせるためにはモジュール間の結合度を最小化することが大事。
不要な情報を他のモジュールに公開せず他のモジュールの実装を当てにしないコード記述を心がける。
結合度を最小化するためにもレイヤー化のアプローチが有効。
ソフトウェアはそれぞれが独立した機能を持ったモジュールの協調動作からなるべきで、それらのモジュールはレイヤーごとに整理し、各レイヤーごとに抽象化する。
各レイヤーでは、その直下レイヤーが提供している抽象化された機能のみを使用する。
可逆性
プログラミングにおいて可逆性をもたせるとは元に戻せないような決定をしてはいけないということ。
実世界の状況は常に変化しているのでその影響をうけるソフトウェアは柔軟で適応性のある可逆的なコードを書いておき、何か問題があったときにやり直しができるようにする。
変更に耐えるためにも特定の技術に依存せず、コードを独立して変更しやすい状態にする。
コードの臭い
「コードの臭い」とは、コードの中で理解しにくい、修正しにくい、拡張しにくい、と感じられる部分のこと。
プログラマはその臭いを嗅ぎ分け、適切なコードに改善していく必要がある。
コードの臭いには、以下のようないくつかの傾向がある。
-
よく見る
- そっくりなコードが色々な場所に散らばっている状態。重複しているコードは、修正しにくくなる。
-
長すぎる
- 関数が長すぎてスクロールを何回も繰り返して終わらないケース。
- 関数が長いと理解するのが難しくなる。
-
大きすぎる
- モジュールが大きすぎて管理不能な状態。
- モジュールが大きいということはモジュールが担う責務が大きすぎるということ。
-
多すぎる
- モジュールが多すぎて管理不能な状態。
- モジュールが大きいからといって、分解しすぎてはいけない。
-
名前が合わない
- 名前と実際のコードが合っていない状態。
- 名前はコードの読み手に適切な情報を伝える役目があるので慎重につける。
技術的負債
問題コードは借金
時間がかかってもきれいなコードを書くか、すばやく汚いコードを書くかの選択は、時間があるなら常に時間がかかってもきれいなコードを書くべき。
時間がないときはすばやく汚いコードを書くこともあるが、汚いコードは負債になる。
技術的負債はコードにおける「修正しにくい」「理解しにくい」といった、問題のあるコードのことを表す。
プログラミングには「技術的負債」の考え方を取り入れ、問題コードを管理する。
緊急事態や時間がないときに汚いコードを書いてしまったら、すぐにその後リファクタリングをすることが大事。
問題コードが広がってしまう原因
- 経験不足のプログラマ
- 締切のプレッシャー
- 読みにくいコード
- 特殊化されたコード
- 不要に複雑なコード
- 単に悪い設計
チームの文化的な要因に以下のようなものもある
- きれいなコードを書かない
- 不明瞭なリファクタリングに時間を割かない
- リリース直前になって回帰テストを実行する
- 膨大な依存性を抱えた古いシステムのリプレースを躊躇する
- 安易にコードをブランチさせる
これらの誘因を意識して、汚いコードの蔓延を前もって防ぐ。
プログラマの3大美徳
プログラマの3大美徳とは「怠慢」「短期」「傲慢」であること。
-
怠慢
- 全体の労力を減らすために手間を惜しまない気質で、後々皆が楽できるように、今役立つコードを書いてしまう。
-
短期
- コンピュータがサボっているときにときに怒りを感じる気質で、コンピュータが効率的に動いていなかったら直ちにコードを直す。
- 今ある問題に留まらず、今後起こりうる問題を想定したコードを書いておく。
-
傲慢
- 神罰が下るほどの過剰な自尊心を持つ気質で、高いプライドを持ち、人様に見られても恥ずかしくないコードを書く。
ボーイスカウトの規則
ボーイスカウトにはシンプルな規則があり、その内容は「自分がいた場所はそこを出ていくときに、来たときよりも綺麗にしないといけない」というもの。
この規則をプログラミングに当てはめると、コードは自分がそこに来たときよりも綺麗にしてからその場を去る。
つまり、コードをリポジトリから取得したときよりも綺麗にしてからコミットする。
これを心がけて習慣化する。
パフォーマンスチューニングの箴言
パフォーマンスチューニングとは速いコードを書くことで、コードの「最適化」とも言われる。
コードを速くすることはよいことのように思われるが、早すぎるタイミングでの最適化は諸悪の根源。
そのため最適化には2つのルールがある。
- 行ってはならない
- (エキスパート専用)まだ行ってはならない
パフォーマンスチューニングはプログラミングの中で最初に考えるものではなく、まずは「正しい」「読みやすい」ことを主眼に置いたコードを作成する。
コードの最適化は以下のものを失うことになりがち。
- 可読性の低下
- 品質の低下
- 複雑性の増大
- 保守の阻害
- 環境間の競合
- 作業量の増大
なのでまず良いコードを作成して、その後必要に応じてパフォーマンスチューニングを行うべき。
エゴレスプログラミング
プログラミングにおいてはエゴを捨てることが重要。
「うぬぼれ」や「プライド」を捨てて、仲間に協力を求めたり、自分の書いたコードを積極的に仲間に見せて改善点を指摘してもらう。
コードを見る側も見せる側も「自分の方が優れている」という自尊心を捨てて、「より良いものを作る」ということに価値を置くべき。
以下の10個の「エゴレスプログラミングの十戒」を念頭においてコードを書くようにする。
- 自分自信も間違いを犯すということを理解し、受け入れる。
- 書いたコードは自分自信ではない。
- どれほど極めたと思っても、上には上がいる。
- 相談なしに、コードを書き直さない。
- 自分よりもスキルが劣る人にも、尊敬と敬意と忍耐を持って接する。
- 世界で唯一変わらないものは、変わるということだけ。
- 信じるもののために戦う。ただし負けは潔く受け入れる。
- 部屋に籠りきりはいけない。
- 「人に優しく、コードに厳しく」して人ではなく、コードを批評する。
1歩ずつ少しずつ
プログラミングは一度に小さな1つのことを行う。
決して複数を相手にせずに1つずつ対処していく。
小さくても確実な1歩を繰り返して進むほうが結果的に品質も時間効率も上がる。
一方で、複数の作業を一度に行うと、それらの作業が混戦して、どれも失敗する可能性が高くなったり時間が無駄にかかったりする。
例えばリファクタリングのときにモジュール間で関数を移動するときに、関数名の不備に気づいたとしても移動と名前変更を同時に行ってはいけない。
関数を移動して、いったん動作確認をしてから名前を変更する。
TMTOWTDI(やり方は1つではない)
ツールの多様性は善
他の人に使用してもらうツール(プログラミング言語やDSLやAPI)を設計するときは、達成したいことの手段を複数用意しておく。
それによってツール側は複雑になるが、使う側は多様な場面でシンプルなコードを書くことができる。
やり方の選択肢を多く用意するにあたって目指すのは「簡単なことは簡単に、難しいことは可能に」というところを目指す。
ツールは作る時間よりも使われる時間のほうが圧倒的に多くなるので、ツールをより良いものにするための投資はレバレッジがかかる。
じっくり時間をかけて設計しても良いものができればリターンは計り知れない。
6章 手法 プログラマの道具箱
曳光弾
「曳光弾」とは発光することで飛んだ軌跡がわかるようになっている弾丸のこと。
曳光弾を発射すると銃口から着弾するまでの弾道が花火のように書き出されるので撃ちながら狙いを修正できる。
通常弾も同一の環境で発射するので曳光弾が当たれば通常弾も同様に当たる。
プログラミングにおける「曳光弾」とは優先的に検証したい部分を、先行的にプログラミングすること。
簡易でも良いので実際の環境下で動作して確認できるエンド・ツー・エンドのソフトウェアを作成する。
ここで作成するコードは土台になり、プロジェクトを通じて肉付けされて最終的な成果物になる。
土台のコードは最小限に留めるが、ちゃんと動作するものであり、ソフトウェア最終型の骨格をなすものとして作成する。
土台コードに付け足していくときは、目標とのズレをチェックして必要に応じて軌道修正していく。
曳光弾とプロトタイプの違い
曳光弾とプロトタイプはアプローチが似ているが、明確に異なる点がある。
-
プロトタイプ
- プロトタイプはソフトウェアのコンセプトや最終形態についての「理解を検証する」ためのものでコンセプトの確認を終えた後は作成したものを全て捨て去り、得られた情報を使ってもう一度正しい形で再構築する。
- 使い捨てのハリボテなコード
-
曳光弾
- 曳光弾はソフトウェア全体がどのように連携するのかを明らかにする。プログラマに対して、今後も使い続けるアーキテクチャ上の骨格を提供し、ユーザーに対してどのような使い勝手になるのかを提示する。
- 最小限とはいえ、動作する本物のコード。
契約による設計
関数は、それぞれ「何らかの作業」を行うもの。
その「何か」を開始する前に、その世界の状態について何らかの「想定」を置き、終了時にその世界の状態についての何らかの「確約」を行うことができるはず。
この「想定」を「事前条件」と呼び、これは関数を呼び出す側が守るべき契約となる。
一方「確約」を「事後条件」と呼び、これは関数が守るべき契約となる。
関数と関数を呼び出す側で互いに守るべき契約を結んでいるとしてプログラミングすることを「契約による設計」という。
契約を意識して守ることで以下のメリットを受けることができる。
- コードの正しさを保証できる。
- コードをシンプルにできる。
- 問題の早期発見が容易になる。
契約の内容はあらかじめ関数のコメントで伝えることが重要。
契約履行のチェックのためのコードは、アサーション(表明)を使用して、契約が履行されなかったらソフトウェアを停止するようにする。
防御的プログラミング
「こうなるはずだ」と決めつけてプログラミングをしてはいけない。
自動車の「かもしれない運転」と同じでプログラミングでも「かもしれない」プログラミングを心がける。
関数に不正な値が入るかもしれないなどを想像し、防御的なコードを書いておく。
「防御的なプログラミング」によってプログラミングが安全に安全になり、安全には2つの側面がある。
-
開発中の安全運転
- 不正なデータを早めに見つけるようにすると、デバッグの効率が上がる。
-
運用中の安全運転
- 不正なデータに早めに対処することで、運用中の問題が大きくなることを防ぐ。
防御的プログラミングをするために「バリケード戦略」と取る。
コードにバリケードを築くためには投句亭のインターフェースを「安全地域への境界」として使用する。
「安全地帯への境界」を通過するデータを検証して、不正なデータには適切な措置を取るようにする。
手術室のシステムと同様ですべてのものは「消毒」してからでないと手術室に持ち込めないようにする。
ドッグフーディング
自分で開発したソフトウェアは、自ら使用するようにする。
自らが率先して味見をして、その梅塩を確かめる必要がある。
ユーザーが使うように使うことでユーザーの視点が手に入り、不具合が見つかりやすくなる。
リリース前には自らがユーザーになってソフトウェアを使用してみて品質を確認し、リリース後も自らソフトウェアを使い続けることが重要。
ラバーダッキング
「ラバーダッキング」とは、ある種のデバッグ手法。
プログラミングにおいて、発生している問題や、問題を抱えているコードを「誰か」に説明することで、問題の原因に自ら気付き自己解決できることがある。
説明される側は適度にうなずくだけで特になにも言う必要はない。
ラバーダッキングは「簡単」で「安い」のに効果の高いデバッグ方法。
問題解決が停止したときは、「誰か」に説明をしてみると良い。人ではなく物に説明しても良い。
コンテキスト
コンテキストとは周りの状況や背景のことで文脈とも言う。
プログラミングのときにはこのコンテキストという概念を2つの側面から上手く使うと良い。
-
コードの読み書きに利用
- コードの読み書きはコードを書く人とコードを読む人のコミュニケーション。
- コードを書くときにはコードを読む人のコンテクストを醸成する必要があり、コードを書くときにその内容をトップダウン型で伝えるようにする。
- 具体的にはモジュール名などの名前で「何」についての責任を持っているのかを明確にする
-
思考のツールとして利用
- プログラミングは問題解決の作業で、問題は単独の要素を見ているだけでは解決ができず、物事がつながっている周囲の状況や背景のようなコンテクストを考慮に入れることで正確に問題を解くことができる。
読み手が「何についてのコードなのか」を把握できるようにするためにもコードを書くときにはコンテクストを先に示すようにする。
逆にコードを読むときにはコンテキストとを汲んでから、その内側のコードを理解するようにする。
コードの共通化はコンテキスト志向でする
コードの共通部分を関数化するときには以下の2点に気をつける。
-
共通化した部分に別々の変更が必要になるケースがある。
- 同じことを行っている共通部分があったとしても、それぞれの成り立ちがまったく異なればそれは一時的にそうなっているだけで依存関係は全く無い。
- そういったコードを共通化しても、その後ニーズが変われば、共通化した部分を元に戻してそれぞれ必要な変更をする作業が生じる可能性が高い。
-
共通化したコード部分に修正が入った場合の影響度が上がる
- コードを共通化したら、共通化した部分とそれを利用する各部分に依存関係が生じる。
- コードを共通化するということはソフトウェアを構成するコードの行数を減らすことができるが、共通化した部分を修正したときに影響が大きいのでテストの手間が増える。
- コードを共通化するときにはコンテキストを確認してどこを共通化すべきかを見極める必要がある。
第7章 法則 プログラミングのアンチパターン
ブルックスの法則
スケジュールが遅れているソフトウェアの開発に遅れを取り戻すために人を追加すると逆にさらに遅延が生じ、火に油を注ぐことになる。
これは人月換算において「人」と「月」が交換できないことが要因。
プロジェクトの工数は人月換算され、「何人が、何ヶ月従事するか」で「人×月」の掛け算になる。
12月人のプロジェクトを6ヶ月で開発するなら2名の人員を追加することになる。
もし「人」と「月」が交換可能ならば開発期間が2ヶ月になったとしても6人投入すれば良いことになるが、現実には「2×6」と「6×2」は同じにはならない。
理由は以下の通り
-
依存関係によるオーバーヘッドが発生する
- 仕事が完全に独立分割できるのであれば人数が3倍なら生産性は3倍に上げることができるが、たいていの仕事は分割するとそれぞれの作業や担当部分間で依存関係が発生するので、オーバーヘッドが発生する。
-
教育に時間がかかる
- 人を追加した場合、追加した人が戦力になるにはそのプロジェクト固有の色々な知識や情報、技術を学習する必要があって教育に時間を取られることになる。
以上の理由から無条件でスケジュールの遅れを人員の投入で取り戻すのではなく、リスケジュールすることで解決する。
ユーザーと調整しながら、機能に優先度をつけて段階的にリリースする。
コンウェイの法則
ソフトウェアの構造、つまり「アーキテクチャ」は、それを作った「組織」を反映する。
コンパイラを3チーム編成で作れば、3パスのコンパイラができあがるし4チーム編成で作れば、4パスのコンパイラが作成される。
自然に任せた場合アーキテクチャは組織に従うが理想としては、良いアーキテクチャを設計してそのアーキテクチャに組織を合わせるようにするべき。
組織の都合でできたアーキテクチャは完成品の品質に悪影響を及ぼすし、組織がそのままでアーキテクチャ側を最適なものに使用としてもコミュニケーションパスにズレが生じる。
まずは良いアーキテクチャを作り、組織をそれに従属させるべき。
割れた窓の法則
割れ窓理論とは、1枚の割られた窓ガラスをそのままにしていると、さらに割られる窓ガラスが増え、いずれ街全体が荒廃してしまうという、アメリカの犯罪学者ジョージ・ケリング博士が提唱した理論。
ソフトウェアでもこれと同じ現象が発生し、ソフトウェアの「悪い設計」「間違った意思決定」「悪いコード」を放置すると、それがどんなに小さなものであってもソフトウェア全体を短期感で腐敗させてしまう。
ソフトウェアに「割れた窓」が存在すると、修正するプログラマに「きっと残りのすべてのコードもガラクタだから適当に修正してしまえ」という考えが出てくる。
なのでコードの「割れた窓」はそのまま放置せずに発見と同時に修復することが重要。
正しく修復する時間がない場合は、このコードがよくないという旨を、わかりやすいように明示しておく。
エントロピーの法則
エントロピーは物理学の用語で、「無秩序な度合い」を表すもので、熱力学の法則によれば全宇宙のエントロピーは増加していくことが証明されている。
ソフトウェアの開発はこのエントロピーの法則に強く縛られ、自然に任せるとコードは限界を超えるまで無秩序が増大していき腐ったコードになる。
コードの腐敗にはいくつかの「兆候」が存在する。それらを見逃さないように迅速に対応する。
-
硬さ
- 「硬さ」とは変更の難しさのこと。
- 1つの変更で依存関係にあるモジュールを連鎖的に変更しなければならないような場合は「硬い」設計のコードだと言える。
-
脆さ
- 「脆さ」とは、1つの変更で他の多くの部分が壊れてしまう度合いのこと。
-
移植性のなさ
- 「移植性のなさ」とは他の環境への移植のしにくさのこと。
-
扱いにくさ
- 「扱いにくさ」はコードの扱いにくさと開発環境の扱いにくさがある。
- コードの扱いにくさとは、設計構造の柔軟性のなさのこと。
- 環境の扱いにくさとは、開発環境が遅くて非効率なときに生じる。
-
複雑さ
- 「複雑さ」とは「不必要な」要素の多さのこと。
- 将来を見越して入れた不必要なコードは複雑さが増す原因になる。
-
不透明さ
- 「不透明さ」とは、コードのわかりにくさのこと。
これらの「兆候」を見逃さないことが大事。
80-10-10の法則
ユーザーの求める80%は短時間で実現が可能であるが、残りの20%のうち10%は実現は可能だが相当な努力が必要で、残りの10%は完全に実現が不可能ということ。
ソフトウェア開発において、万能薬は存在しないことを認識する。
ツールの使用は適材適所で、事前に疑似開発を行い、適用範囲と効果を確かめて導入する。
ジョシュアツリーの法則
人は名前を知った途端にそれが見えるようになるという法則。
デザインパターンの最大の成果は、すでにそこにあった設計ノウハウに名前をつけることで再利用可能にしたこと。
チームで名前をつけ、言葉をつくるには「ユビキタス言語」を使用すると良い。
ユビキタス言語とは、その問題領域の各要素を正確に表現するチームの共通言語のこと。
ユビキタス言語がないと皆勝手にバラバラな言葉を使用し、コミュニケーションにコストがかかってしまう。
チームが一体になるには「糊」のような役割を果たすユビキタス言語が必要不可欠。
セカンドシステム症候群
ファーストバージョンをリリースしたエンジニアが設計するセカンドバージョンのソフトウェアは、そのエンジニアが設計するもっとも危険なバージョンになる。
セカンドバージョンには機能を盛り込みすぎて品質が悪く、機能の使い勝手も悪い。
自尊心を働かせて「多機能主義」にならないようにし、プログラミング中は以下の問いを考える。
- ユーザーは誰なのか?
- ユーザーは何を必要としているのか?
- ユーザーは何が必要だと考えているか?
- ユーザーは、何を望んでいるか?
車輪の再発明
ある機能をすでに実現しているコードやライブラリがあるのに自分で改めて1から作ることがある。
使えるものがあるのに、わざわざ作るのは工数の浪費となる。
車輪を再発明してしまうパターンは大きく2つある。
-
車輪を知らないパターン
- プログラマが車輪を知らなかったゆえに意図しない再発明をしてしまうパターン。
- プログラマの知識不足、勉強不足によるもの。
-
車輪を作りたい。
- プログラマの車輪を作りたいという欲求によるもの。
- プログラマが自分自身で作ったもの以外を拒み、自分自身で何でも作りたがるという場合に当てはまる。
車輪の再発明は避け、本来やるべき作業に注力する。
そのためにコードを書く前に同じ機能が標準ライブラリにないか、OSSライブラリにないかを必ずチェックするようにする。
ヤクの毛刈り
ヤクという家畜は毛が多く、毛を刈って本体に到達するにはたくさんの毛を刈らないといけない。
問題に取り組んでいる時、ヤクの毛刈りのようにある問題を解こうとしたら別の問題が出てきてなかなか問題の解決に到達できないことがある。
ヤクの毛を刈っているような状態に陥ったら立ち止まり、そもそも何が目的だったかを思い出す。目的からズレていたり時間やコストと見合わないと判断した場合はすぐに作業を止めて別の道を探したほうが良い。
また、他の人が同じ状況に陥らないためにも、その顛末をメンバーに共有する。