web-dev-qa-db-ja.com

Clean Codeの原則を関数型言語に適用する

私は現在 Robert Martin'sClean Code を読んでいます。すばらしいと思います。OOコードを書くとき、私は彼のレッスンを心に留めています。特に、意味のある名前の小さな関数を使用するという彼のアドバイスは、私のコードフローをよりスムーズにすると思います。次の引用で要約するのが最善です。

[W] eプログラムが、TO段落のセットであるかのようにプログラムを読み取ることができるようにしたい。それぞれが現在の抽象化レベルを記述し、次のレベルで後続のTO段落を参照する。

クリーンコード、37ページ:「TO段落」は、不定詞で発声された文で始まる段落です。「Xを実行するには、ステップYおよびZ。 "" Yを行うには、私たちは... "など)例:

RenderPageWithSetupsAndTeardownsを実行するには、ページがテストページであるかどうかを確認し、そうである場合は、セットアップとティアダウンを含めます。どちらの場合も、ページをHTMLでレンダリングします

私はまた、自分の仕事の関数型コードも書きます。本のマーティンの例は間違いなくそれらが段落のセットであるかのように読みますが、それらは非常に明確です-しかし、「段落のセットのように読む」が機能コードに望ましい品質であることは確かではありません。

Haskell標準ライブラリ から例をとります:

maximumBy               :: (a -> a -> Ordering) -> [a] -> a
maximumBy _ []          =  error "List.maximumBy: empty list"
maximumBy cmp xs        =  foldl1 maxBy xs
                        where
                           maxBy x y = case cmp x y of
                                       GT -> x
                                       _  -> y

それは、マーティンのアドバイスから得られる可能性がある限り遠く離れていますが、簡潔で慣用的なHaskellです。彼の本のJavaの例とは異なり、彼が求めるケイデンスのようなものにそれをリファクタリングする方法を想像することはできません。Haskellがクリーンコードは、長々とした不自然なものになります。

関数型プログラミングのベストプラクティスと矛盾する(少なくともいくつか)クリーンコードを検討するのは間違っていますか?彼が別のパラダイムで言っていることを再解釈するための賢明な方法はありますか?

17
Patrick Collins

Clean Codeは何よりもまずスタイルマニュアルです。 Strunk and White は、クリンゴン語で書いている場合は適用されません。アイデアは、コードを読む可能性のあるプログラマーに明確にしたいということです。モジュール化され、簡単に再構築できるコードが必要です。他の言語でこれを行う方法と同じように、Haskellでこれを行う方法がありますが、正確な詳細は異なります。

そうは言っても、Haskellにはいくつかのスタイル ガイドライン があります。 Stack Overflowには、かなり包括的な guide もあります。コーディングロジックをわかりやすく簡潔に保つことは、かなり一定しているようです。モジュール化につながるため、関数の一般化も強調されます。 DRYコードも強調され、クリーンコードと同じです。

結局、Clean CodeとHaskellのコーディングガイドラインは同じことを目指して努力していますが、そこにたどり着くには独自の道をたどる必要があります。

11
World Engineer

私があなたの例であなたが何を意味しているのかはわかりません。パラグラフは、彼がそれらを説明しているように、長い時間を必要としない。彼はコードが英語のように読まれるべきだという意味ではありません。重要な部分は、同じ抽象レベルで機能をグループ化することです。これは、プログラミングパラダイムを超える理論的な構造概念です。

ボブ・マーティンの「TO段落」形式で表現すると、私はあなたの例を次のように読みます。

  • maximumByを計算するには、順序付け関数とリストが必要です。結果はそのリストの要素になります。
  • 空のリストと順序付け関数のmaximumByを計算するとエラーになります。
  • リストmaximumByxsを計算するには、maxBy関数を使用してそのリストを折りたたみます。
  • 2つのリスト要素のmaxByを計算するには、与えられた順序付け関数を使用してそれらを比較します。最初の要素の方が大きい場合は、それを選択します。それ以外の場合は2番目を選択します。

命令型の例と同様に、最も一般的な概念から始めて、より詳細に進みます。 「TO段落」の考え方は、ページを上下に移動することなく、十分な詳細が得られた時点で読みを停止できるということです。確かにそうです。

いくつかの名前はおそらくより良いかもしれませんが、特に一般的な高階関数を書くとき、それらは言語の一般的な慣習です。高次の関数名は、本の例のような命令的な動詞句にもうまく対応しません。動詞間の関係をより詳しく説明するためです。

これを実装するには、「TO段落」のガイドラインに従わない方法があります。明示的な型シグネチャを省略すると、上位レベルの「概要」文が省略されます。エラー処理にif式を使用すると、パターンマッチングの代わりに、別の抽象化レベルを不適切に混乱させる可能性があります。 maxByを、後で詳細に説明できる名前を付ける代わりに、匿名関数としてインライン化することができます。

実際、whereのような構成要素は、実際にはbetter段落形式に適合していると思います。これは、英語での表現方法に近い方法で、より詳細に名前を付けるために使用できるためです。 、同様に、その範囲を「段落」のコンテキストに明確な方法で制限します。

16
Karl Bielefeldt