web-dev-qa-db-ja.com

ボイラープレートの防御?

私には、定型コードは明らかに悪いです。しかし、ボイラープレートを減らすために抵抗を示す開発者に会いました。私は、私が長年にわたって開発してきた嫌悪を超えて、すぐに形成され、よく考えられた議論を持っていなかったことに気づきました。

ボイラープレートを少なくすることを支持する説得力のある議論を形成できるように、いくつかの反論は何ですか?言い換えれば、ボイラープレートを支持する議論(ある場合)は何ですか?

(つまり、私が一般的にボイラープレートによって意味されると思いますが、Javaのゲッターとセッターが良い例です。)

16
abstracted

覚えておくべき重要なことの1つは、コードは通常、不要なコンテキストを削除することによって小さくなっていることです。 コンパイラが何かを理解できる場合、引数が使用されますそれを明示的に書き込む必要はありません。

そして、コンパイラだけがそれを読むつもりであったなら、それは素晴らしいことです。しかし、「プログラムは、人々が読むために、そして偶然にマシンが実行するためだけに書かれるべきである」ことを覚えておいてください。 (皮肉なことに、この引用は 普通の人間が読むのが最も難しいすべての言語の1つに捧げられた教科書から 主にその過度の簡潔さによるものです。)

あなたが書いているときに退屈で反復的な定型文のように見えるものは、1年後(または5年後)に来てコードを保守する必要がある他の人にとって貴重なコンテキストになる場合があります。

WRT Javaの例、具体的には、それが悪いボイラープレートの良い例であることに同意します。これは、短い読みやすく、柔軟性も高い:プロパティ。ただし、これは、すべての言語のすべての定型構文要素がJavaのゲッターおよびセッターと同じくらい無駄であるという意味ではありません。 =およびC++。

15
Mason Wheeler

ボイラープレートコードを支持する1つの議論は、1か所で変更した場合、コードの1つのフローのみに影響するということです。これは、多くの場合、実際に変更を使用して、それを使用するすべてのコードに影響を与えることが望ましいという事実とバランスを取る必要があります。しかし、私は議論を支持するまれな例を見てきました。

たとえば、次のようなコードがあるとします。

public ForTheBar(Foo foo)
{
    Bar bar = foo.bar();
    return bar.BeFooed();
}

これは、コードの約2箇所で使用されます。

ある日、誰かがやって来て、「わかりました、この道だけで、フーする前にバーをグロミットして欲しいです。」

そして、あなたは「まあこれは簡単です」と思います。

public ForTheBar(Foo foo, bool shouldIGrommit)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    return bar.BeFooed();
}

次に、ユーザーがいくつかの新しい機能を追加し、FooTheBarにうまく適合すると考えます。そして、あなたはそれをフーする前にそのバーをグロミットするべきかどうか彼らに忠実に尋ね、彼らは「いいえ、今回は違います」と言います。

したがって、上記のメソッドを呼び出すだけです。

しかし、その後、ユーザーは「OK、ちょっと待ってください。3つ目のケースでは、BeFooedを呼び出す前にDoodle the Barを用意してほしい」と言います。

問題ないと思います、私はそれができます。

public ForTheBar(Foo foo, bool shouldIGrommit, bool shouldIDoodle)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    if (shouldIDoodle)
    {
        bar.BeDoodled();
    }

    return bar.BeFooed();
}

突然、コードが定型文でなくなります。おそらく、2行のコードの繰り返しを受け入れたはずです。これで、3〜3行のコードができ、それぞれ2〜3行が長くなり、繰り返しのようには見えなくなりました。

これはすべて言ったが、私は「これは一般的なケースではなく、それが起こったときにリファクタリングできる」と反論します。

私が最近聞いたもう1つの主張は、ボイラープレートコードがコードのナビゲートに役立つことがあることです。私たちが話し合った例は、大量のボイラープレートマッピングコードを削除してAutoMapperで置き換えたところです。現在、すべてが慣例に基づいているため、IDEにこのプロパティセットはどこにあるかと言うことはできません。

私は、IoCコンテナーについて同様のことを主張する人を見てきました。

私が彼らに同意することは言うまでもありませんが、それでもそれは公正な議論です。

7
pdr

効率の進化

あなたはこれから始めます:

_<p>
    <label for="field">My field</label>
    <input type="text" id="field">
</p>
_

次に、迷惑な定型文をすべて削除し、関数に入れます。

  1. createFieldHtml( id, label )

    これはいいです、たくさんの行を保存しています!

  2. createFieldHtml( id, label, defaultValue )

    ええ、私もデフォルト値が必要です。それは簡単に追加できました。

  3. createFieldHtml( id, label, defaultValue, type )

    かっこいい、チェックボックスにも使えるようになりました

  4. createFieldHtml( id, label, defaultValue, type, labelFirst )

    UXデザイナーは、ラベルはチェックボックスの後にある必要があると述べました。

  5. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate )

    必要に応じて日付ピッカーをレンダリングするようになりました。うーん、パラメータは少し手に負えなくなってきています

  6. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses )

    cSSクラスを追加する必要があるこの1つのケースがありました

  7. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses, fieldCssClasses, disabled, clearAfter, helpText, uploadPath )

    aaaaaaaaaaaaaaaaaaaaa

ボイラープレートの防御

これは最近気づいていたので、言葉で表すのは難しいので、リストを作成します。

  1. 少し伸びる線が重複する恐れがあるようです。ほんの数行であれば問題ないかもしれません。一部の事柄は本質的に「ほぼ反復的」です(上記の例のように)。長期的に見れば、そこを最適化する可能性はほとんどありません。
  2. 機能はどこかにカプセル化するのが大好きです。あなたが客観的に見ると、それが単に「混乱を隠している」ように見える場合、疑わしいです!古き良き定型文の時期かもしれない
  3. あなたがますます強力になる機能を持っているとき;これは、入力に応じて多くの異なる実行パスを受け取り、最終的にはほとんど何もしません-それは定型的な時間かもしれません!
  4. 抽象化の層を別の抽象化の層の上に追加するが、コードを短くする場合(基礎となる層は変更することを意図していない)-ボイラープレート時間!
  5. 非常に多くのパラメーターを受け取る関数がある場合、名前付きパラメーターを本当に(= /// =)する必要があります-多分それは定型の時間です。

私が最近いつも自問していることの1つは、これです。
何も変更せずに別のプロジェクトにコピー&ペーストできますか?はいの場合は、カプセル化またはライブラリに入れても問題ありません。いいえの場合は、定型の時間です。

これは、ボイラープレートがコードのコピーと貼り付けであるという一般的な認識とはかなり反対です。私にとって、ボイラープレートはコピーと貼り付けに関するものですが、常に微調整する必要があります。


更新:実際の名前の上に私の例を挙げた記事を見つけました: "too DRY anti-パターン"。

関数はより多くのパラメーターを取得し、さまざまなケースでの動作を制御するための内部ロジックがますます複雑になります。あまりにもDRY関数は見つけやすいです。それらには、さまざまな使用法に対処しようとする複雑なif-thenロジックがたくさんあります。[...]また、繰り返しコードは常にコードが小さく、ディスクリート機能を実行する場合は悪いことです。

それは短くて興味深い読み物です、あなたはここで記事を見つけることができます: Too Dry Anti-Pattern

7
kritzikratzi

despiseボイラープレートコードを削除できますが、ボイラープレートコードを削除できるとは限りません。

WPFフレームワークには 依存関係プロパティ があり、非常に多くのボイラープレートコードが含まれています。余暇には 私は解決策を調査しました これにより、記述する必要があるコードの量が大幅に削減されます。 1年以上後 私はまだこのソリューションを改善しています であり、その機能を拡張するか、バグを修正する必要があります。

何が問題なのですか?これは、新しいことを学び、代替ソリューションを探索するのに最適ですが、おそらく最善ではありませんコマーシャルの決定。

WPFフレームワークは十分に文書化されています。それはきちんとあなたのボイラープレートコードを書く方法を文書化します。このボイラープレートコードを削除しようとするのは素晴らしいことであり、検討する価値のあることですが、msdnが提供するのと同じレベルの「ポリッシュ」を達成するには長い時間がかかります。

4
Steven Jeuris

ボイラープレートの問題は、DRYに違反することです。基本的に、ボイラープレートを作成するときは、複数のクラスにわたって同じコード(または非常に類似したコード)を繰り返しています。そのコードを変更する必要がある場合、開発者がコードが繰り返されたすべての場所を覚えているかどうかは、まったく確実ではありません。これにより、古いAPIまたは古いメソッドが使用されるバグが発生します。

ボイラープレートを共通ライブラリまたは親クラスにリファクタリングする場合、APIが変更されたときに1か所でコードを変更するだけで済みます。さらに重要なことに、予期しない変更が発生すると、コードはoneの場所で中断し、すべてを再び機能させるために修正する必要があることを正確に通知します。これは、1つの変更が数十、さらには数百のクラスで失敗を引き起こすシナリオよりもはるかに望ましい方法です。

1
quanticle

私は別のタクトを取るつもりです。開発の一貫性はソフトウェア設計の最も重要な機能の1つであり、アプリケーションを拡張可能かつ保守可能なものにするための重要なツールですが、複数のサイト、言語、タイムゾーンにまたがってチームを管理する場合、達成が難しい場合があります。

達成された場合、一貫性により、「一度見たらすべて見た」コードにアクセスしやすくなり、維持とリファクタリングがはるかに安くなりますが、何よりも拡張がはるかに簡単になります。いくつかのボイラープレートを必要とするライブラリーを作成するときは、ライブラリーの能力とともに、開発者にも与えました。

  • 開始点機能のプリアンブル(定型文)を理解します。通常、ほとんどの主要なクラスとアクセスポイントは定型文の一部として機能します。これにより、開発者はドキュメントへの出発点を得ることができます
  • 期待開発者への配置が明らかになります。たとえば、プリアンブルの一部としてトレースオブジェクトを設定した場合、開発者は例外と情報をどこに記録するかがわかります。
  • 暗黙的な理解開発者にクラスのインスタンス化のプロセスを強制的に実行させると、ライブラリの残りの部分にアクセスするために必要な手法を推論し、それらをあらゆる規則に導入する機会を得ることができますライブラリ全体で使用した
  • 簡単な検証ボイラープレートコードが必要な場合、通常、例外とガード句を使用して非常に簡単にそれ自体を検証できます。
  • 構成ボイラープレートコードを必要とするライブラリの場合、単一の実行パスの機能をカスタマイズする明らかな実装ポイントがすでにあるため、簡単です。これは、必要なボイラープレートコードがFactoryまたはCommandパターンで拡張されている場合に特に役立ちます。

ライブラリのコンシューマがインスタンス化を把握していると、ボイラープレートコードを実装するためのプライベート/拡張メソッド、親クラス、またはテンプレートさえ簡単に作成できます。

1
Dead.Rabit