web-dev-qa-db-ja.com

「クリーンコード」ルールセットでforループは許可されますか?

「クリーンコード」で説明されている一連のルールを考えると、forループを実際に使用できますか?私の混乱は、forループ自体が低レベルの構成体であるという事実から生じます。したがって、それは本によって、非常に低い抽象化レベルでのみ使用できます。しかし、それは、抽象化のより高いレベルに属するコードの一部、つまり関数が呼び出されているコードの一部でループの使用が禁止されていることを意味しますか?

この本のように、「低レベルと高レベルを混ぜないでください」という観点からコードを調べようとしたところ、forループを作成することすらできないことに気づいたので、私は尋ねています。これは私をクロールまで遅くしました(いつものカメの遅いコーディングよりも遅い)。

5
iksemyonov

Clean Codeの「関数ごとに1レベルの抽象化」の原則を参照していると思います。

この一般的な原則は完全に理にかなっています。 抽象化のレベル は、複雑さを習得するために、より低いレベルの詳細を隠すことです。したがって、異なるレベルの抽象化を混在させることは、より高いレベルの複雑さを非表示/カプセル化しようとする試みが、より低いレベルを同時に使用することによって破られることを意味します。したがって、カプセル化の利点が失われます。

これは、さまざまな指示に与える価値判断とは関係ありません。 forが低レベルであると考える場合、ifwhilereturn、関数呼び出しなどについても同様に考えることができます。

したがって、ルールに違反することなく、forをデザインで使用できます。

備考:forループを使用して非表示にする必要がある詳細レベルにアクセスする場合、ルールに違反する可能性があります。たとえば、高レベルの関数でforを使用して配列を反復処理する場合、検索を実行するための高レベルの関数がすでにある場合です。

9
Christophe

まず、本Clean Codeがルールではなくguidelinesを提案していることを覚えておく価値があります。ここで参照されている特定のガイドラインは、抽象化のレベルを混在させない推奨事項であるようです

このアドバイスは、具体的にはクラスインターフェイスの設計に言及していることを覚えておく価値があります。 (つまり、パブリック/保護されたメソッド、パブリックプロパティ-クラスを使用する何かに公開されるものすべて)

高レベルの抽象クラスAnimalを考えてみましょう。そこから低レベルの具象クラスDogが派生します。 Dogには、Dogの抽象化レベルに適していると思われるBark()というメソッドを含めることができます。

ただし、Bark()メソッドがabstractAnimalクラスのインターフェースに含まれるのを止めるものは何もありません。しかし、Animalから派生した他のクラスがBark()メソッドを使用できない場合、これはコードの匂いになります。 Animalから派生したものは、Bark()メソッドが具象クラスに完全に不適切であっても、Bark()メソッドを継承(さらにはオーバーライド)する必要があります。

つまり.

public abstract class Animal
{
     public abstract void Bark();
}

public class Elephant : Animal
{
     public override void Bark()
     {
         // HUH?!
     }
}

このアドバイスは一般的に、高水準の抽象化/インターフェースで提供するメソッドについて慎重に検討することを奨励しています。派生( "下位レベル")クラスに、下位レベルクラスに論理的に属さないメソッドまたは動作を継承、オーバーライド、または実装させることを回避するため。

forキーワードなどの言語構造は、クラスインターフェイスとは無関係です。 「混合レベルの抽象化」に関するアドバイスは、メソッドの実装に関してはまったく意味がありません。

6
Ben Cottrell

質問のタイトルは少し挑発的です。それは、テキストから明らかであるため、「Are for loops allowed in the "Clean Code" set of rules、except for low-level components) "。これが私があなたの質問を解釈する方法です。

私はこれが私にとって非常に興味深い質問だと思います。一見するとそれほど簡単ではありません。ボブマーティンの「クリーンコード」に照らしてこれを解釈するのではなく、ラルフウエストファール(ドイツ語のリファレンス: http:// clean- code-developer.de/ 、Google翻訳をお試しください)。彼が何と呼ぶか​​についての彼の提案 [〜#〜] ioda [〜#〜] アーキテクチャは、「低レベルと高レベルを混在させない」という原則を極端にします。そして実際、このアーキテクチャでは、「上位のコンポーネント」では「for」ループは見つかりません(条件文のような他の制御構造はありません)-下位レベルでのみです。このアーキテクチャの上位レベルのコンポーネントの目的は、下位レベルのコンポーネントを一緒に「プラグイン」することのみです。

これを本当に極端にすると、すべての関数の構造を次のように変更する必要があります

_  function HighLevelfunction()
      sum=0
      for i = 1 to upperLimit  logic
           sum+=LowLevelFunction1(i)
      return sum
_

_  function LowLevelfunction2( func funcAsParameter)
      sum=0
      ' just for demonstration purposes, think not of reusage here
      for i = 1 to upperLimit
           sum+=funcAsParameter(i)
      return sum
_

最初のバージョンではHighLevelfunctionLowLevelFunctionに依存し、2番目のバージョンでは_LowLevelfunction2_は他の関数に依存しなくなりました。 2つ目では、LowLevelfunction2(LowLevelFunction1)の呼び出しが行われる「より高いレベル」の関数が必要になりますが、これは単なる統合手順であり、必要なより高いレベルでの「for」ループはありません。

ただし、これを実際のプログラムのすべての機能に対して実行することは、おそらく非常に実用的ではなくなります。私(そして他のほとんどのプログラマーもそうだと思います)は、高レベルと低レベルの関数、クラス、またはコンポーネントの間に、より粗い粒度で線を引きます。正しいバランスを見つける必要があり、清潔さのためだけにクリーンなコードを書かないようにしてください。または、ラルフウェストファルの言葉でそれを言うには、 "クリーンアップを船外に持ち出さないでください" です。

3
Doc Brown