自己参照メソッドチェーンに実際の欠点はありますか?


14

私は最近、特定のプロジェクトの特定のクラスにチェーンのメソッドを実装して、コードの可読性を向上させることを提案しました。「便利なだけでなく、セマンティクスのために流fluentなインターフェイスを実装すべきではない」という回答を得て、提案を打ち切りました。私は、流interfaceなインターフェースを提案しているのではなく、読みやすさとコーディングの快適さを改善するためにメソッド自体を連鎖させる(両方とも混同される可能性があります)と回答しました。

とにかく、これは、おそらく何も返さないはずのメソッド(セッターなど)で常に「this」を返すことで、悪い習慣を負わされる可能性があると考えさせられました。

私の質問は、前の慣習を適用することを悪い習慣や虐待とみなすことができるのか、なぜなのか、ということです。パフォーマンス上の欠点はないと思いますか?



@KeesDijkありがとう、同じクラスのメソッドをチェーンする場合に興味があるので、質問を少し編集したので、質問に似ていません
-dukeofgaming

1
SOで、彼らは私に、チェーンはC ++ではない、と言った-stackoverflow.com/questions/5760551/…-あなたはどう思いますか?
カガリさん

1
@mhambraメソッドチェーンを実装し、そのための明確な標準を定義するときだけ注意する必要があるようです。
dukeofgaming

回答:


10

番号

ケント・ベックが指摘し、コードがはるかに多くの場合、それが書かれているよりも、読まれます。

メソッドチェーンによりコードが読みやすくなる場合は、メソッドチェーンを使用します。


1
素晴らしい本.. +1
ラインヘンリヒス

5
しかし、もしあなたがメソッドチェーンをより読みやすくする唯一の方法だとしたらどうでしょう?これがスタイルの問題である場合、一連のコーディング規約に従う必要があります。つまり、一貫性を保つために、既存のコードと同じ方法で記述します。
2014年

OPはすでにそれをやるように言われているようですね@coredumpが、私はスティーブンがちょうどのためにこれを言っていたと考えている場合、メソッドチェーンは、それが読みやすくなります。
パンツァークライシス14

1
@Panzercrisis OPは、利便性とセマンティクスのために、メソッドチェーンの使用を控えるように指示されています。Stevenの答えは基本的に「とにかくやる」と言っており、チームの意見や一貫性を考慮せずに、OPのコードの可読性のみを考慮します。OPがコードの読みやすさに関する好みに合うように、プロジェクト内の既存のクラスをすべて書き直したい場合はどうなりますか?それが私が便利/セマンティクスの議論を理解する方法です:メソッドチェーンを持つ「技術的な」理由があるはずです(ところで、その議論は、他の人が自分の好みの言い訳をしているように聞こえ
ます

9

はい、欠点があります

読みやすいコードは優れていますが、コードが通信する内容にも注意してください。オブジェクトのメソッドが常にオブジェクトを返すとき、それはいくつかのことを伝えます:

  1. 高度な設定が必要です。これは、どの順序で設定または設定する必要があるかが必ずしも明らかではありません
  2. 後続の各メソッド呼び出しは、最後に構築されます

有効なユースケース:アドホックデータベースクエリ

クラスライブラリはほとんどすべての言語に存在するため、ハードコードされたSQLを使用せずにデータベースを照会できます。例としてEntity Framework for .NETを取り上げます。

DBContext db = new DBContext();
List<Post> posts = db.Posts
    .Where(post => post.Title.Contains("Test"))
    .OrderBy(post => post.DateCreated)
    .ToList();

これは、後続の各メソッド呼び出しが前のメソッドに基づいて構築される、流fluentなインターフェイスです。これらの呼び出しを論理的に読み取ることは、データベースのクエリのコンテキストで意味があります。

無効なユースケース:プロパティを設定するための構文シュガー

次に、Postクラスで同じパターンを使用してみましょう。

public class Post
{
    public string Title { get; set; }
    public DateTime DateCreated { get; set; }
    public string Body { get; set; }

    public Post SetTitle(string title)
    {
        Title = title;

        return this;
    }

    public Post SetDateCreated(DateTime created)
    {
        DateCreated = created;

        return this;
    }

    public Post SetBody(string body)
    {
        Body = body;

        return this;
    }
}

次に、このクラスの使用方法を見てみましょう。

Post post = new Post()
    .SetTitle("Test")
    .SetDateCreated(DateTime.Now)
    .SetBody("Just a test");

このコードが表示されたら、すぐに次の質問をします。「呼び出した後SetBody、データベースにクエリを実行しますか。「完了」と言うために別のメソッドを呼び出す必要がありますか?」

チェーンされたメソッド呼び出しは、クラスを使用してコードと何を通信Postますか?

  1. 複雑な設定があります
  2. 各メソッド呼び出しは前の呼び出しに基づいています

これ本当ですか?いいえ。Postクラスには複雑な設定はありませ。タイトル、作成日、および本文の設定は、より複雑な最終目標に向かって互いに構築されませ。正方形のペグを丸い穴にマッシュしました。

自己参照メソッドチェーンの欠点は、何かを行うために複数のメソッド呼び出しが必要であり、各呼び出しが最後から構築されることを伝えることです。これが当てはまらない場合、メソッドチェーンは他のプログラマに間違ったことを伝えている可能性があります。

同僚が言ったとき:

流interfacesなインターフェイスは、便宜上だけでなく、セマンティクスのために実装されるべきです

彼らは絶対に正しいです。流なインターフェイス、またはメソッドチェーンは、それ自体ではない可能性のある何かを伝えます。


これは、メソッドチェーンと複雑な設定が常に連動することを前提としています。それらは別個のエンティティであり、一方が存在しても他方を仮定することはできません。
ジャック

それは単に「複雑な構成」ではなく、「前のメソッドからビルドされた後続のメソッド呼び出し」でもあります。メソッドチェーンには、クラスの目的に必ずしも当てはまるとは限らないメタ通信があります。
グレッグブルクハート

1
以前のものから構築された後続のメソッド呼び出しもメソッドチェーンとは異なり、メソッドチェーンの構文を、順序に依存する一連の副作用操作のセマンティクスに対する強力なコミュニケーションとして扱うことは、信頼性があり有用ではないと思います。これは構文上の速記であり、それ以上のものではありません。物事を短くして読みやすくする場所で使用します。
ジャック

1
私はあなたのメソッドチェーンは別のだと思います理解し、私は言っていること、あなたの頭の中ではなかったし、他のクラスライブラリを使用する他のプログラマーない真実ですあなたのコードについての仮定を作るに終わる可能性がこれらの理由のために、メソッドチェーンを実装します。メソッドチェーンは、コード作成者であるあなたが意図していなかったことを暗示する可能性があることに注意してください。明確に通信するコードは、読みやすいコードと同じくらい重要です。一方を他方のために犠牲にしないでください。
グレッグブルクハート

1
When an object's methods always return the object, it communicates a couple of things-これは個人的な意見だと思います。チェーンされたメソッドを見るすべての人が同じことを想定していると主張するのは困難です。
サムデュフェル14

1

主な欠点は、明瞭さが失われることです。例えば:

x.foo();
x.bar();
x.baz();

これらのステートメントはいずれも値を返さないため(値が返された場合は無視されます)、副作用を引き起こす場合にのみ有用です。それとは対照的に:

x.foo()
 .bar()
 .baz();

まず、のクラスがこれらのメソッドを持つ唯一のクラスであるという事実を知っている場合を除き、と同じタイプのオブジェクトを操作していることは明らかではbarありません。その場合でも、メソッドがで動作するか、新しいオブジェクトであるかは明確ではありません。bazxxx

副作用があるコードの部分を強調表示すると、プログラムについて推論するためにそれらの副作用を追跡する必要があるため便利です。明快さの損失の可能性とコードの書きやすさの潜在的な利益を比較検討する必要がありますが、コードは書かれている以上に読み取られることも考慮してください。


0

プログラミング言語のすべての文体的要素(ハンドコーディングマシン言語とは対照的に)を検討すると、「セマンティクスではなくセマンティクス」引数が弱まります。

エンジニアとして私たちが行うことの多くは、セマンティクスに関する利便性を提供しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.