C#リーダブルコード #04_右に長いコードの対処

当サイトではアフィリエイト広告を利用しています。

リーダブルコード
Subway Station in Munich, Germany. Train coming in. Strong Motion Blur on Train and People, no recognizable Persons.

前回は「右に長いコードは書かない」というお話をしました。では右に長いコードになってしまうときはどのように対処していけばいいのか,というお話を今回はしていきたいと思います。

改行しても右に長いコードには変わりない

改行した場合

まず最初に考えられる対処法は,改行するということですね。前回の右に長いコードを改行してみましょう。

//改行しても右に長いコードには変わりない
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);

とすることもできます。これだとお隣さんに尋ねるだけなので,大変シンプルに読むことができます。今回はオブジェクト指向やデザインパターンの話はしないので,クラス分割にはあまり言及しませんが,そういった部分も原因としてはあると思うので,本書以外にも,そういった部分を勉強していただいてもいいかと思います。