前回は「右に長いコードは書かない」というお話をしました。では右に長いコードになってしまうときはどのように対処していけばいいのか,というお話を今回はしていきたいと思います。
改行しても右に長いコードには変わりない
改行した場合
まず最初に考えられる対処法は,改行するということですね。前回の右に長いコードを改行してみましょう。
//改行しても右に長いコードには変わりない ProductSqlServer.GetProducts() .Where(x => x.Price > 100) .ToList().ForEach(x => dtos.Add(new ProductDto(x)));
ただ,改行しても左から右に読んでいく量は同じなので,読んでいく量,脳みそに覚えておかないといけない量は特に変化がなく,大した改善にはなっていませんね。まぁ改行しないよりは,している方がマシ程度です。ですので,改行したから右に長いコードではなくなったということにはなりません。
どこかで切る
対処法としては,どこかで切る必要があります。例えば,ToList()まででいったん切ります。次のように,ToList()までの結果をproducts1に受けて,その後,products1.ForEach・・・とします。
var products1 = ProductSqlServer.GetProducts().Where(x => x.Price > 100).ToList(); products1.ForEach(x => dtos.Add(new ProductDto(x)));
こうすると,いったんToList()が終わった段階で思考を切ることができますね。いままでは,ProductSqlServerをGetProducts()して,Whereで100より大きいやつをListにして,それを回してProductDtoにする・・・とすべてを脳みその中に放り込んでいたものを,「Priceが100より大きいリストがproducts1」ということで,ここで思考を切ることができ,脳みそは,いったん忘れて,次のForEachに移ることができます。こういった感じで,思考をいったん切ることで,読みやすさは大きく変わります。
ToListが冗長
先ほどはToListの部分で切ることで,思考を切ることができて,右に長いコードがある程度改善しました。ただ,この例でいうと,このToList()自体が,冗長なので,その部分も解説しておきます。
//ListのForEachをするためにToListするのは冗長 var products1 = ProductSqlServer.GetProducts().Where(x => x.Price > 100).ToList(); products1.ForEach(x => dtos.Add(new ProductDto(x)));
このToListがForEachするために変換しているとすれば,非常に冗長です。要するに,products1.ForEachのForEachは,List<T>にだけ存在するメソッドなので,Whereを取得されたIEnumerable<T>をList<T>に変換していますが,ListのForEachではなく,通常のforeach文を使えば,Listに変換する必要がなくなるので,ToListをする必要がありません。ですので,List<T>のForEachをするためだけにToListを呼び出しているのであれば,これも無駄に右に長くしているコードの元凶になっているので,あえてToListする必要はありません。
隣のとなりまでしか訪ねない
①のようにToListをやめて,Whereの結果をproduct2に受けていったん切ります。
//GOOD:隣のとなりまでしか訪ねない var products2 = ProductSqlServer.GetProducts().Where(x => x.Price > 100);//① foreach (var product in products2) //② { dtos.Add(new ProductDto(product)); }
次に②のように通常のforeach文を使用してproduct2をぐるぐる回してdtos.Add・・・の部分を実施すれば,結果は同じになります。こうすることで,ProductSqlServerから始まる文は,GetProductsのWhereの部分でいったん完結しているので,ProductSqlServerの隣の隣に収まっているといえます。そこまで完結させておいて,次はそれをぐるぐる回す,②の部分に移るので,脳みそで覚えておくことは,格段に少なくなっているといえます。隣のとなりまでしか訪ねないということを目安にして,うまく文を切っていくことを検討してみてください。
ラムダを覚えても右に長くしない
今回解説した通り,右に長いコードになる場合は,どこかで切れないかを考えてみてください。ラムダ式等を覚えたり,新しい書き方を覚えたりすると,使いたくなって,つい右に長いコードを書きがちです。新しい書き方がすべてにおいて正義ではないし,最初に言った通り,何秒で理解できるかが大事なので,新しい書き方だからOKという感じではなく,総合的に判断して使っていただいた方がいいと思います。
右に長くなるという事はクラスをうまく分割できていない
最後に余談ですが,本書はオブジェクト指向に関しては触れずに,シンプルに書き方を解説することを目的としていますが,右に長くなるコードの原因の1つとして,うまくクラスが分割できていないという可能性があります。例えば今回の例でいえば,ProductSqlServerのGetProductsでPriceの引数を受ける関数があれば,
ProductSqlServer.GetProducts().Where(x => x.Price > 100)
の部分を,
ProductSqlServer.GetProductsByPrice(100);
とすることもできます。これだとお隣さんに尋ねるだけなので,大変シンプルに読むことができます。今回はオブジェクト指向やデザインパターンの話はしないので,クラス分割にはあまり言及しませんが,そういった部分も原因としてはあると思うので,本書以外にも,そういった部分を勉強していただいてもいいかと思います。
#02_プロジェクトの作成
#03_右に長いコードを書かない_隣のとなりまでしか訪ねない
#04_隣のとなりまで_右スクロールより縦スクロールの方がいい
#05_IFとELSEがある時は肯定系をIF否定形をELSEにする
#06_比較する時は変数を左_定数を右にする
#07_複数の比較を1回のif文でやらない
#08_booの比較でTrueやFalseを書かない
#09_否定の否定はしない
#10_型チェックはasを使う
#11_メソッドはできるだけ早く抜ける_返却する値を無駄に変数に入れない
#12_対象外の時はすぐに抜ける
#13_都合が悪いケースはガードする
#14_必ずやりたい処理はfinallyを使う
#15_比較演算子はできるだけクラスにさせる
#16_ifの中括弧の省略はしない
#17_if文のリーダブルコードまとめ
#18_名前の付け方
#19_意図が明確な名前を付ける
#20_名前は素直に付ける_連想ゲーム的な名前を付けない
#21_1つの事しかしていなければ短い名前でも理解できる
#22_長いクラス名の扱い方
#23_単数形と複数形で表現する
#24_対になる言葉の組み合わせを決めておく
#25_業務で使う名前は統一する
#26_名前を統一するための辞書ツール作成
#27_メンバー変数にアンダーバーを付ける
#28_ハンガリアン記法を使わない
#29_メソッド内の変数をメソッド最初に全部宣言しない
#30_メソッド内の変数は直前に宣言する
#31_ループの変数はループ内で宣言する
#32_変数を使いまわさない
#33_boolの戻り値はどちらがTrueかをわかるようにする
#34_解放が必要なオブジェクトにはusingを使う
#35_varを推奨する場合
#36_メソッド名の付け方
#37_voidとFunctionを意識する
#38_インテリセンスを意識した名前にする
#39_生成メソッドはCreate_型変換はToを使う
#40_無駄に変数に入れて返却しない
#41_重複をなくす
#42_リージョンで区切らない
#43_アクセス修飾子とsealedを付ける
#44_クラス名はソリューションエクスプローラーで並べることを意識する
#45_クラス名は名詞か名詞句で命名する
#46_クラス名で継承元や特性を表現する
#47_メソッド内にコメントを書かない
#48_分かりづらい部分はメソッド化をしてメソッド名で想いを伝える
#49_コードを読んだ人が「えっ?」と思うことが予想される場所にだけコメントを付ける
#50_コメントで悪いコードを取り繕うことはできない
#51_未実装機能はTODOコメントを書く
#52_リーダブルコードまとめ