Software Development Pattern
一般原則
- 大抵の物事はトレードオフの問題である
- 過ぎたるは猶及ばざるが如し
- 可能であることと最善であることは異なる
- 手段を目的にしてはならない
- 原理主義者にならない
- 思考停止しない
- 奥が深い症候群
プロジェクト・マネジメント
プロジェクト・マネジメントの基本原則
- ソフトウェア開発に銀の弾丸はない
- プロジェクトは放っておけば必ず失敗するものである
- 「誰でも出来る」は幻想である
- 画面や帳票は見積り単位にしてはならない
プロジェクトマネジメントのパターン
- チームメンバーのコミットメント
- 雑用専門員を投入する
- 設計と実装は不可分である
プロジェクト・マネジメントのアンチパターン
- マイクロ・マネジメント
- 現場に任せた症候群
- 大規模開発
- チームを分割すると失敗する
- エクストリーム・ウォーターフォール
- プロジェクトのゴールが曖昧である
- 諦めの境地に入って工夫しない
米国国防総省(DOD)におけるベストプラクティス
- 公式のリスク管理
- 仕様としてのユーザマニュアル
- 審査、レビュー、及びウォークスルー
- メトリックスに基づいたスケジュール管理と追跡
- 小さなマイルストーンでのバイナリ品質ゲート
- プロジェクト計画のプログラム全体の可視性及び進捗と計画の対比
- 品質目標に対する欠陥の追跡
- ハードウェアの仕様とソフトウェアの機能性の分離
- 全員がわきまえている経営責任
米国国防総省(DOD)におけるワーストプラクティス
- 日程に余裕のないプロジェクトでは、新技術の使用を正当化するために日程短縮を使ってはならない
- RFP上でインプリメンテーション技術を想定してはならない
- 立証されていない「銀の弾丸」の使用を擁護してはならない
- 提供すべき機能性を、遅れに対応するより多く減らさない限り、大幅な(10%以上の)日程の遅れから回復することを期待してはならない
- クリティカル・パス上にある作業項目を、プロジェクト・コントロールの外に置いてはならない
- 過去に観測された実績より大きなプラス(10%以上)の改善を達成することを期待してはならない
- プロジェクトの複雑性のすべてを(ハードウェアではなく)ソフトウェアの中に埋め込んではならない
- 重大なシステム工学上のタスク(特に、ハードウェア/ソフトウェア機能分割)を、十分なソフトウェアの専門的技術を持たないで実施してはならない
- 公式レビューがプロジェクトの正確な姿を規程すると信じてはならない。公式レビューの有用性は、5人を超える参加人数の数に反比例することを予期せよ
要件定義
要件定義の原則
- 凝集性を高くする
- 完全性を保つ
- 一貫性を保つ
- 正確さを保つ
- 実現可能性を保つ
- 修正容易容易性を保つ
- 曖昧さを排除する
- 検証可能性を保つ
- ユーザは自身の要求を定義することはできない
- 要件定義作業は可能な限り少人数で行うべきである
超上流から攻めるIT化の原理原則17ヶ条
- ユーザとベンダの想いは相反する
- 取り決めは合意と承認によって成り立つ
- プロジェクトの成否を左右する要件確定の先送りは厳禁である
- ステークホルダ間の合意を得ないまま、次工程に入らない
- 多段階の見積りは双方のリスクを低減する
- システム化実現の費用はソフトウェア開発だけではない
- ライフサイクルコストを重視する
- システム化方針・狙いの周知徹底が成功の鍵となる
- 要件定義は発注者の責任である
- 要件定義書はバイブルであり、事あらばここへ立ち返るもの
- 優れた要件定義書とはシステム開発を精緻にあらわしたもの
- 表現されない要件はシステムとして実現されない
- 数値化されない要件は人によって基準が異なる
- 「今と同じ」という要件定義はありえない
- 要件定義は「使える」業務システムを定義すること
- 機能要求は膨張する。コスト、納期が抑制する
- 要件定義は説明責任を伴う
ソフトウェア構成管理
構成管理パターン
- Main Line
- Task Branch
- Topic Branch
- Release Line
- Release-Prep Code Line
- Third Party Codeline
- Git Flow
- GitHub Flow
- GitLab flow
- Git Feature Flow
- Mono Repository
構成管理におけるベストプラクティス
- 最初からツールを利用する
- 構成管理責任者を決めておく
- ディレクトリ構成はあらかじめ用意しておく
- マージ修正モデルかロックモデルかを決めておく
- コメントのルールを決めておく
- メインラインを1つに保つ
- コードラインポリシーを決めておく
- タグ/ブランチのルールを決めておく
- 個人ワークスペースを設ける
- 必要なものは全てリポジトリに登録しておく
- No Ticket, No Commit
構成管理のアンチパターン
- 統合された資料がない
- バージョン管理システムが使われていない
- 名称 + 日付によるファイル管理
- ブランチを切らない
- ビルド手順が異様に煩雑
- 依存関係地獄
- 修正前のソースコードをコメントアウトして残している
- 変更履歴の管理をエクセルで行っている
アーキテクチャ設計
アーキテクチャ設計の原則
- KISS原則
- DRY原則
- YAGNI原則
- 簡単よりも単純を選択せよ
- 関心の分離
- 問題の分割と抽象化
- 技術は問題解決の手段であり、それ自体を目的としてはならない
- 意思決定は言語化し、記録する
12Factor
- 12Factor(1): コードベース
- 12Factor(2): 依存関係
- 12Factor(3): 設定
- 12Factor(4): バックエンドサービス
- 12Factor(5): ビルド、リリース、実行
- 12Factor(6): プロセス
- 12Factor(7): ポートバインディング
- 12Factor(8): 並行性
- 12Factor(9): 廃棄容易性
- 12Factor(10): 開発/本番一致
- 12Factor(11): ログ
- 12Factor(12): 管理プロセス
アーキテクチャ構成パターン
- Layers
- Model View Controller
- Pipe & Fillter
- Use at Willアーキテクチャ
- REST
- Clean Architecture
- Hexagonal architecture
- Onion Architecture
- Micro Service Architecture
- CQRS (Command Query Responsibility Segregation)
- Saga
- Business Rule Micro Service
WEBアプリケーションのアーキテクチャ
- MVC2
- ADR
- MVC-S
Enterprise Integration Pattern (EIP)
- File Transfer
- Shared Database
- Remote Procedure Invocation
- Messaging
アーキテクチャ設計アンチパターン
- Over Engineering
- Big ball of mud
UNIXという考え方
- スモール・イズ・ビューティフル
- 一つのプログラムは一つのことをうまくやらせる
- できるだけ早く試作を作成する
- 効率より移植性
- 数値データはASCIIフラットファイルに保存する
- ソフトウェアの梃子を有効に活用する
- シェルスクリプトを使うことで梃子の効果と移植性を高める
- 過度の対話的インターフェイスを避ける
- すべてのプログラムをフィルタにする
データベース設計
データベース設計の原則
- One Fact One Place
- 正規化せよ
- データ量が膨大になることが予想される時はパーテショニングを検討せよ
- 正規化を崩す前にビューの利用を検討せよ
データベース設計に関するパターン
- 親子テーブル
- 中間テーブル
- 隣接リスト(Adjacency List)
- 経路列挙 (Path Enumeration)
- 入れ子集合(Nested Set)
- 閉包テーブル(Closure Table)
- イミュータブルデータベース
- 削除データ保管テーブル
- 進行管理テーブル
- 下書き保存テーブル
- 表示順管理テーブル
- JSON保存テーブル
- マスタテーブル
- トランザクションテーブル
- サマリテーブル
- BLACKHOLEエンジン(MySQL)
データベース設計に関するアンチパターン
- 単一参照テーブル
- 列持ちテーブル
- 主キーは3つを超えてはならない
- 概念モデルのリレーションを変更してはならない
- テーブルの属性が多すぎるのはいけない
- ドメインに属さない属性を作ってはならない
- 複数属性を作ってはならない
- 削除フラグは極力避けるべし
- 余計なチューニングを考えてはならない
- 安易に正規化を崩してはならない
データベース設計に関するアンチパターン(命名編)
- 名称は省略しすぎない
- モデリングルールを忘れない
- 変更を恐れない
API設計
プログラム設計
プログラム設計の原則
- 保守性が最優先
- 読みやすいコードを書く
- プログラムをモジュール化する
- モジュールのテスト容易性を高く保つ
- モジュールの凝集度を高く保つ
- モジュール同士は粗結合に保つ
- OAOO原則
- 抽象度統一の原則(SLA原則, SLAP)
- パフォーマンスチューニングは必要になるまでやらない
- 再利用にこだわるほどコードは使いにくくなる
- 配列/連想配列はラップせよ
- バグったプログラムは即座に殺せ
- 無理のあるelse句の省略はしない
- デメテルの法則
- グローバル変数は使うな
- 変数は不変であれ
- 処理は小さく分割せよ
- 重複コードは書くな
- 状態を持つな
- 実装者の手間よりも利用者の手間の方が重要である
- プログラミングは設計である
- 関連するものはまとめろ
- レイヤを越境するな
- 例外を隠蔽するな
- 入力は寛容に、出力は厳密に
コードレビューの原則
- 大きな変更はレビューの効果を低下させる
CLEANなコード
プログラム設計のパターン
良いコードの条件
- 短い
- 覚えることが少ない
- 一貫性がある
- 役割が明確である
- 同じコードが二回以上現れない
GRASP
- Expert
- Creator
- Controller
- Low Coupling
- High Cohesion
- Polymorphism
- Pure Fabrication
- Indirection
- Protected Variations
オブジェクト指向における5つの設計原則
パッケージ設計の6つの原則
- 再利用・リリース等価の原則
- 全再利用の原則
- 閉鎖性共通の原則
- 非循環依存関係の原則
- 安定依存の原則
- 安定度・抽象度等価の原則
オブジェクト・ロール・ステレオタイプ
- 情報保持役 (Information Holder)
- 構造化役 (Structurer)
- サービス提供役 (Service Provider)
- 調整役 (Coordinator)
- 制御役 (Controller)
- インターフェース役 (Interfacer)
オブジェクト指向エクササイズ
- ひとつのメソッドにつきインデントは1段階までにすること
- else句を使用しないこと
- すべてのプリミティブ型と文字列型をラップすること
- ファーストクラスコレクションを使用すること
- 1行につきドットは1つまでにすること
- 名前を省略しないこと
- すべてのエンティティを小さくすること
- 1つのクラスにつきインスタンス変数は2つまでにすること
- Getter、Setter、プロパティを使用しないこと
ドメイン駆動設計に関するパターン
- Entity
- Value Object
- Factory
- Repository
- Domain Service
- Domain Event
- Event Sourcing
- Always Valid Domain Model
生成に関するパターン
- Abstract Factory
- Builder
- Factory Method
- Prototype
- Singleton
- Simple Factory
構造に関するパターン
振る舞いに関するパターン
- BCEパターン
- Before/After
- Chain of Responsibility
- Context Object
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Null Object
- Observer
- Snapshot
- Specification
- State
- Strategy
- Template Method
- Visitor
並行性に関するパターン
- Single Threaded Execution
- Immutable
- Guarded Suspension
- Balking
- Producer-Consumer
- Read-Write Lock
- Thread-Per-Message
- Worker Thread
- Future
- Two-Phase Termination
- Thread-Specific Storage
- Active Object
データベース/データアクセスに関するパターン
- Data Access Object
- Active Record
- Data Transfer Object
- Data Access Method
- Data Mapper
- Unit of Work
- Strategyパターンを用いてリポジトリに認可機能を持たせる
テスト容易性に関するパターン
- Dependency Injection
- Service Locator
- Mock Object
- Don't talk to strangers
- View State
クロージャデザインパターン
- Execute Around Method
- Pluggable Behavior
- Iterator Pattern
- Dynamical Conditional Execution
- Template Method Pattern
- Loan Pattern
- Command Design Pattern
- Strategy Pattern
- Factory Pattern
- Method Combination
その他
- 決定表関数パターン
- Functional Validationパターン
- reduce関数によるパイプライン処理パターン
- 合成関数を用いたSLA原則の実現
- ポリシーパターン
- Parameter Object
- PRG(Post/Redirect/Get)パターン
- Exponential Backoff
TypeScript/JavaScriptに関するパターン
- Option Object
go-langに関するパターン
- Functional Option Pattern
アンチパターン
- グローバル変数が乱用されている
- 巨大ループ
- Fat Controller
- 巨大クラス
- スパゲッティコード
- マジックナンバー
- ハードコード
- 出力パラメータ
- プログラム中で使われる型がInt,String,Booleanしかない
- ひとつのモジュールが複数の責務を兼任している
- コピペプログラミング
- 早まった最適化
- レイヤーの概念がない
- 分割の概念がない
- 気合と根性で実装されている
- ドメインモデル貧血症
- Smart UI
- シングルファイルWEBアプリケーション
- ドメインモデルにビジネスロジックが無い
- 定数インターフェイス
- ループの中からDBアクセス
- 経験が浅い開発者ほどフルスクラッチに走る
コードの不吉な臭い
- 重複したコード
- 長すぎるメソッド
- 巨大なクラス
- 多すぎる引数
- 変更の発散
- 機能の横恋慕
- 不適切な関係
- 相続拒否
- 怠け者クラス
- 重複メソッド
- 不自然な複雑さ
UI設計
- UIデザイン原則
Javaの格言
- インスタンス変数は全てprivateに設定し、読み書きはアクセサ経由で行う
- インスタンス変数に対するアクセサメソッドはfinalにする
- 必ずパッケージを使う
- パッケージ内部でしか使われないクラスは公開しないこと
- staticインナークラスよりもパッケージの利用を優先させること
- インナークラスは包含されるクラス以外から利用できてはいけない
- 継承の階層を深くしないこと
- 継承よりも委譲を積極的に使うこと
- 継承はクラスベースでの is a type of関係である
- 不要なキャストは避ける
- 実装ではなくインターフェイスに対してプログラミングする
- インスタンスを生成する意味の無いクラスは抽象クラスにする
- メソッドシグネチャしか持たない抽象クラスはインターフェイスにする
- 共通のインスタンス変数・具象アクセスメソッドは、クラス階層中のintercfaceと具象クラスの間に位置する抽象クラスへ移す
- 変更可能オブジェクトを変更不能として振舞わせるには、読み取り専用のinterfaceを使う
- 例外ハンドラでは想定される例外を明示的にcatchすること
- 例外は設計段階で見定めておくこと
- 全てのメソッドでtry-catchを使うことは避ける
- finallyブロックよりも外に例外を伝播させないこと
- throws Exception使用禁止
- コンストラクタで例外を投げることは慎重に検討せよ
- 例外を値の返却手段として利用しないこと
- コンストラクタチェーンを利用することによって、コンストラクタの振る舞いやデフォルト値がチェーン中の一箇所だけに表れるようにする
- privateなヘルパーメソッドを設けることによって、コンストラクタチェーンにおけるsuper()とthis()の衝突を避ける
- 具象Singletonクラスでは怠惰なインスタンス化を避ける
- クライアントクラスによって直接・間接に呼びされる場合、怠惰なインスタンス化を使ったメソッドはスレッドセーフにすること
ソフトウェアテスト
ソフトウェアテストの一般原則
- テストは欠陥があることしか示せない
- 全数テストは不可能
- 初期テスト重要
- 欠陥の偏在
- 殺虫剤のパラドクス
- テストは条件次第
- 「バグゼロ」の落とし穴
テスト容易性
- 繰り返し可能であること
- 記述が容易であること
- 理解しやすいこと
- 高速であること
テストコードの原則
- テストコードにはわかりやすいコメントを入れる
- テストの実行は素早く終わるよう工夫する
- テスト同士の依存関係を作らず、独立性を高める
- テストコードでは冗長性の排除よりも分かりやすさを重視する
- テストコードでは処理効率と分かりやすさでは分かりやすさを重視する
- テストコードはテスト対象モジュールと同じ場所に置く
- 自動生成したコードにはテストコードを書かない
- テストに使うデータはきちんと検討する
- テストの名前は後から見ても理解できるようにする
FIRST
- FIRST(1): Fast (迅速)
- FIRST(2): Isorated (隔離)
- FIRST(3): Repeatable (繰り返し可能)
- FIRST(4): Self-validating (自律的検証)
- FIRST(5): Timely (タイムリー)
Right-BICEP
- Right-BICEP(1): Right
- Right-BICEP(2): Boundary
- Right-BICEP(3): Inverse
- Right-BICEP(4): Cross-check
- Right-BICEP(5): Error
- Right-BICEP(6): Performance
CORRECT
- CORRECT(1): Conformance
- CORRECT(2): Ordering
- CORRECT(3): Range
- CORRECT(4): Reference
- CORRECT(5): Existance
- CORRECT(6): Cardinality
- CORRECT(7): Time
Unit Testのパターン
ソフトウェアテストのアンチパターン
- テストが統合されていない
- テストの確認項目に「正しく動作する」的なことが書いてある問題