自走プログラマ
清水川貴之,清原弘貴,tell-k 著,株式会社ビープラウド 監修
Contents-list
コード実装
1.1 関数設計
- [ ] 関数名は処理内容を想像できる名前にする
- [ ] 関数名はより具体的な意味の英単語を使おう
- [ ] 関数名から想像できる型の戻り値を返す
- [ ] 副作用のない関数にまとめる
- [ ] 意味づけをできるまとまりで関数化する
- [ ] リストや辞書をデフォルト引数にしない
- [ ] コレクションを引数にせず、intやstrを受け取る
- [ ] インデックス番号に意味を持たせない
- [ ] 関数の引数に可変長引数を乱用しない
- [ ] コメントには「なぜ」を書く
- [ ] コントローラには処理を書かない
1.2 クラス設計
- [ ] 辞書ではなくクラスを定義する
- [ ] Data classを使う
- [ ] 別メソッドに値を渡すためだけの属性を設定しない
- [ ] インスタンスを作る関数をクラスメソッドにする
1.3 モジュール設計
- [ ] utils.pyのような汎用的な名前を避ける
- [ ] ビジネスロジックをモジュールに分割する
- [ ] モジュール名のおすすめ集
1.4 ユニットテスト
- [ ] テストにテスト対象と同等の実装を書かない
- [ ] 1つのテストメソッドでは1つの項目のみ確認する
- [ ] テストケースは準備、実行、検証に分割しよう
- [ ] 単体テストをする観点から実装の設計を洗練させる
- [ ] テストから外部環境への依存を排除しよう
- [ ] テスト用のデータはテスト後に削除しよう
- [ ] テストユーティリティを活用する
- [ ] テストケースごとにテストデータを用意する
- [ ] テストの実行順序に依存しないテストを書く
- [ ] 戻り値がリストの関数のテストで要素数をテストする
- [ ] テストで確認する内容に関するデータのみ作成する
- [ ] 過剰なmockを避ける
- [ ] カバレッジだけではなく重要な処理は条件網羅する
1.5 実装の進め方
- [ ] 公式ドキュメントを読もう
- [ ] 一度に実装する範囲を小さくしよう
- [ ] 基本的な機能だけ実装してレビューしよう
- [ ] 実装方針を相談しよう
- [ ] 実装予定箇所にコメントを入れた時点でレビューしよう
- [ ] 必要十分なコードにする
- [ ] 開発アーキテクチャドキュメント
1.6 レビュー
- [ ] PRの差分にレビュアー向け説明を書こう
- [ ] PRに不要な差分を持たせないようにしよう
- [ ] レビュアーはレビューの根拠を明示しよう
- [ ] レビューのチェックリストを作ろう
- [ ] レビュー時間を予め見積もりに含めよう
- [ ] ちょっとした修正のつもりでコードを際限なく書き換えてしまう
モデル設計
2.1 データ設計
- [ ] マスターデータとトランザクションデータを分けよう
- [ ] トランザクションデータは正確に記録しよう
- [ ] クエリで使いやすいテーブル設計をする
2.2 テーブル定義
- [ ] NULLをなるべく避ける
- [ ] 一意制約をつける
- [ ] 参照頻度が低いカラムはテーブルを分ける
- [ ] 予備カラムを用意しない
- [ ] ブール値でなく日時にする
- [ ] データはなるべく物理削除する
- [ ] Typeカラムを神格化しない
- [ ] 有意コードをなるべく定義しない
- [ ] カラム名を統一する
2.3 Django ORMとの付き合い方
- [ ] DBのスキーママイグレーションとデータマイグレーションを分ける
- [ ] データマイグレーションはロールバックも実装する
- [ ] Django ORMでどんなSQLが発行されているか気にしよう
- [ ] ORMのN+1問題を回避しよう
- [ ] SQLから逆算してDjango ORMを組み立てる
エラー設計
3.1 エラーハンドリング
- [ ] 臆さずにエラーを発生させる
- [ ] 例外を握りつぶさない
- [ ] Try節は短く書く
- [ ] 専用の例外クラスでエラー原因を明示する
3.2 ロギング
- [ ] トラブル解決に役立つログを出力しよう
- [ ] ログがどこに出ているか確認しよう
- [ ] ログメッセージをフォーマットしてロガーに渡さない
- [ ] 個別の名前でロガーを作らない
- [ ] Info, errorだけでなくログレベルを使い分ける
- [ ] ログにはprintでなくloggerを使う
- [ ] ログには5W1Hを書く
- [ ] ログファイルを管理する
- [ ] Sentryでエラーログを通知・監視する
3.3 トラブルシューティング・デバック
- [ ] シンプルに実装しパフォーマンスを計測して改善しよう
- [ ] トランザクション内はなるべく短い時間で処理する
- [ ] ソースコードの更新が確実に動作に反映させる工夫をしよう
システム設計
4.1 プロジェクト構成
- [ ] 本番環境はシンプルな仕組みで構築する
- [ ] OSが提供するPythonを使う
- [ ] OS標準以外のPythonを使う
- [ ] Docker公式のPythonを使う
- [ ] Pythonの仮想環境を使う
- [ ] リポジトリのルートディレクトリはシンプルに構成する
- [ ] 状況依存の設定を環境変数に分離する
- [ ] 設定ファイルもバージョン管理しよう
4.2 サーバ構成
- [ ] 共有ストレージを用意しよう
- [ ] ファイルをCDNから配信する
- [ ] KVS(Key Value Store)を利用しよう
- [ ] 時間のかかる処理は非同期化しよう
- [ ] タスク非同期処理
4.3 プロセス設計
- [ ] サービスマネージャーでプロセスを管理する
- [ ] デーモンは自動で起動させよう
- [ ] Celeryのタスクにはプリミティブなデータを渡そう
4.4 ライブラリ
- [ ] 要件から適切なライブラリを選ぼう
- [ ] バージョンをいつ上げるのか
- [ ] フレームワークを使おう(巨人の肩に乗ろう)
- [ ] フレームワークの機能を使おう
4.5 リソース設計
- [ ] ファイルパスはプログラムからの相対パスで組み立てよう
- [ ] ファイルを格納するディレクトリを分散させる
- [ ] 一時的な作業ファイルは一時ファイル置き場に作成する
- [ ] 一時的な作業ファイルには絶対に競合しない名前を使う
- [ ] セッションデータの保存にはRDBかKVSを使おう
4.6 ネットワーク
- [ ] 127.0.0.1と0.0.0.0の違い
- [ ] ssh port forwardingによるリモートサーバーアクセス
- [ ] リバースプロキシ
- [ ] Unixドメインソケットによるリバースプロキシ接続
- [ ] 不正なドメイン名でのアクセスを拒否する
- [ ] hostsファイルを変こすいてドメイン登録と異なるIPアドレスにアクセスする
やることの明確化
5.1 要件定義
- [ ] いきなり作り始めてはいけない
- [ ] 作りたい価値から考える
- [ ] 100%の要件定義を目指さない
5.2 画面モックアップ
- [ ] 文字だけでは伝えず、画像や画面で伝える
- [ ] モックアップは完成させよう
- [ ] 遷移、入力、表示に注目しよう
- [ ] コアになる画面から書こう
- [ ] モックアップから実装までをイメージしよう
- [ ] 最小で実用できる部分から作ろう
- [ ] ストーリーが満たせるかレビューしよう