# クリーンコード 第14章~第16章 ## 第14章 継続的改良~コマンドライン引数のパーサを用いたケーススタディ~ ### リファクタリング済のクラス内のコードの流れ ```java= public class args { //1:フィールド(private) private Map<Character, ArgumentMarshaler> marshalers; //・・・以下必要なフィールドを記述・・・ //2:他クラスからの呼び出しを受ける関数(public) public Args(String schema, String[] args) throws ArgsException{ //・・・下のprivateメソッドの呼び出し・・・ } //3:2のpublic関数から呼び出される関数(private) private void parseSchema(String schema) throws ArgsException{ //・・・処理を記述。次の関数に引き継ぐ場合は最後に次の関数を呼び出す・・・ } //4:3のprivate関数からの呼び出しを受ける関数(あれば記述。private) //3・4共通:全処理を終えるまで繰り返し。呼び出しを受ける順に上から下へと配置すること。 //5:getter及び他クラスからの部分的な処理の呼び出し(public) public String getString(char arg){ return StringArgumentMarshaler.getValue(marshalers.get(arg)); } //・・・以下必要な関数を記述・・・ } ``` ### 継続的改良 クリーンコードを書くためには、まず汚いコードで始めて、それをきれいにしていくべきである。 作文が下書き→推敲→清書の順で行うように、まずは動く下書きを作り、それをリファクタリングで推敲を重ね、 最終的な清書がクリーンコードになる。 #### Argsクラスの場合 当初は1つの引数タイプの場合のみで下書きレベルのコードを書いていた。 そこに2つ、3つと引数タイプを追加していくと、途端に雑然さが増していき、手に負えなくなっていった。 そこでいったん中断して、引数タイプごとに受け取り窓口を作り、型変換して共通の処理を行い、最後に 適切な型に再度変換する形に変更された。 #### インクリメンタル主義で テスト駆動開発は、システムを常に動かし続けられることを保証する改善方法である。 変更時のシステム破壊のリスクを最小限に抑えられる。 小さな変更を行い、壊れたコードに小さな修正を加える。 また、テストコードの変更も同時に行う。 これを繰り返すことで、少しずつ確実に変更を行っていく。 ## 第15章 JUnitの内部 ### JUnitフレームワーク JUnitフレームワークは、代表的なJavaテスティングフレームワークである。 現在の最新版はJUnit5(jupiter)である。 初代JUnitは、ケント・ベックとエリック・ガンマが、飛行機の中で開発したとされる。 このフレームワークのコードをもとに、リファクタリング練習を行う。 ### リファクタリングメニュー * fプレフィックス(関数の名前にfをつける習慣):削除 * 長い条件式:関数の抽出→privateでカプセル化 * 同一名の複数責務、あいまいな変数名:変数名の変更 * 否定の条件式:肯定文への書き換え→if/elseの逆転 * 関数の複数責務:関数名の変更、関数の抽出→privateでカプセル化 * 関数内の呼び出しの戻り値の有無が揃っていない:戻り値の有無の統一 * 時系列的依存関係:関数の呼び出し位置の変更、関数名の変更 * インデックス値と大きさ(length(), size()等)のズレ:値の調整回数の最小化、不等号の変更→**潜在的なバグ発見** ### 結論 リファクタリングが元に戻っている箇所もあるが、トライ&エラーを重ねて、プロとしてふさわしい価値が感じられる状態へと必然的に収束していく。 **コードを見たら、より良い状態にする!** ## 第16章 SerealDateのリファクタリング JCommonのorg.jfree.date.SerialDateクラスを取り上げ、リファクタリング練習を行う。 同クラスはデビッド・ギルバートが書いた、高いプロフェッショナル精神と規律のある、日付を扱うコードである。彼はコードを公開する勇気と善意を持ったプログラマでもある。彼の意思に敬意を表明しつつ、リファクタリングを行っていく。 ### まずは動作させる #### 単体テストを書く 単体テストのカバレッジ率が5割程度と低く、テストの通らなかった部分のコメントアウトが散見される状態であった。 そこで、単体テスト書き上げカバレッジを9割まで引き上げた。また、筆者が意図を汲んで独自にコードを書きあげている。 #### 日付の境界値の修正 コードのいくつかの部分において、境界値エラーが発見された。誤ったアルゴリズムや境界値判定を修正した。 ### そして正しく直した(以下リファクタリングメニュー) * 複数書式の混合:HTMLコードの削除 * 日付の通し番号SerialDate:DayDateへの変更 * publicな内部実装:カプセル化 * 定数を宣言したクラスの継承:関数への置き換え * 直列化の制御変数serialVersionUID:削除 * 冗長なコメント、不要になった記述、デフォルトコンストラクタ等:削除 * 日付の通し番号の最初が2:スプレッドシート関連クラスに移動 * 抽象クラスが実装を必要とする:抽象ファクトリパターンによる委譲 * 変数宣言のfinal:削除 * 複数の同一名称や同一処理:統合 * 関数の位置や抽象関係の不一致:適切な位置に引き上げor押し下げ * 変数を操作するstaticメソッド:インスタンスメソッドに変更 * 複雑なアルゴリズム:一時変数による意味の解説 * 誤解を招く関数名:より意図が明確な関数名へと変更 * テストからしか呼び出されない関数:関数及びテストの削除 * 抽象クラス内:抽象メソッドの作成 最終的にカバレッジは85%程度に減少した。これはクラスの長さが短くなり、カバーされていない部分が相対的に増えただけである。 ###### tags: `読書`