web-dev-qa-db-ja.com

C#3で流暢なインターフェイスを作成するためのヒント

私はC#の流暢なインターフェースのためのいくつかの良いヒントを求めています。私は自分でそれについて学んでいますが、私が読んでいる記事の外で他の人がどう思うかを聞きたがっています。特に私が求めているのは:

  1. 流暢すぎるのはいつですか?
  2. 流暢なパターンはありますか?
  3. 流暢なインターフェイスをより流暢にするC#の機能(拡張メソッドなど)
  4. 複雑な流暢なインターフェースはまだ流暢なものですか?
  5. 流暢なインターフェースに到達するためのリファクタリングまたは既存の流暢なインターフェースのリファクタリング
  6. 一緒に仕事をした、またはお勧めできる良い例はありますか?

1つのヒントや考え、または投稿ごとに何でも投稿できるかどうか。彼らがどのように投票されるのかも見てみたいです。

前もって感謝します。

43
Scott McKenzie

あなたの4番目のポイントで;

はい、複雑で流暢なインターフェースでも流暢に話せると思います。

流暢なインターフェースは妥協点だと思います。 (良いものですが!)プログラミングに自然言語を使用することについては多くの研究があり、一般的に自然言語はプログラムを表現するのに十分正確ではありません。

流暢なインターフェースは、プログラミング言語のように書くように構築されており、自然言語で表現できるもののごく一部しか許可されていませんが、自然言語のように読めます。

たとえば、サイのモックを見ると、通常のライブラリに比べて書き込み部分が複雑になっています。インターフェースが流暢であるため、学習に時間がかかりましたが、コードがはるかに読みやすくなります。プログラムは通常1回作成され、複数回読み取られるため、これは適切なトレードオフです。

だから私のポイントを少し修飾する。書くのは複雑ですが、読みやすい流暢なインターフェースでも流暢に話すことができます。

18
Mendelt

流暢なインターフェースの消費者として私が経験した唯一の最大の課題は、それらのほとんどが実際には流暢なインターフェースではないということです。代わりに、それらは私が「読みやすいインターフェース」と呼ぶ傾向のあるもののインスタンスです。

流暢なインターフェースは、その主な目標がそれを読みやすくすることであることを意味しますが、読みやすいインターフェースは、その主な目標がそれを読みやすくすることであることを意味します。ほとんどの流暢なインターフェースは、コーディングが途方もなく難しい傾向がありますが、逆に、後で他の人が読むのは信じられないほど簡単です。

Assert().That().This(actual).Is().Equal().To(expected).
    Except().If(x => x.GreaterThan(10));

...実際にコードで作成するよりも、後で読む方がはるかに簡単です。

27
sbohlen

ポリモーフィックメソッドを使用すると呼び出しチェーンが壊れ、必要のない場所で醜いキャストとパランセシスを使用してインターフェイスを非流暢にしたくないため、継承と流暢なインターフェイスを使用すると問題が発生します。ジェネリックビルダーとジェネリック制約付きのジェネリック拡張メソッドを使用した回避策を提供するパターンに関する記事を書きました: http://liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-コンパイル時の制約/

11
jhonny

Moqは、equals、ToStringなどの関連のないメソッドを非表示にして、流暢なインターフェイスをさらに使いやすくします。

システムオブジェクトの非表示 は、これを行うことの利点を説明する記事です。

8
Finglas

そして、2番目と3番目の質問について。

私が気づいた3つの流暢なパターン

1つ目は、usingステートメント(C#2.0)を使用して、次のような特定のコンテキストでコードを実行します。

using(var transaction = new Transaction())
{
  // ..
  // ..
}

これは、Transactionのコンストラクターとディスポーザーを使用してトランザクションをセットアップし、このコンテキストでコードを実行します。

2つ目はほぼ同じですが、ラムダの場合、これはたとえばRhinoMocksでよく使用されます。

(new Transaction()).Run( () => mycode(); );

最もよく知られている流暢なインターフェースは、戻り値の型を使用してメソッド呼び出しを連鎖させることです。ほとんどの場合、メソッドはこれを返すため、同じオブジェクトで呼び出しを連鎖させることができます。ただし、呼び出されたメソッドに応じて、さまざまなオブジェクトを返してコンテキストを変更することもできます。トランザクションでのみ実行できるオブジェクトがある場合(申し訳ありませんが、別の例を考えることはできません)、擬似コードで、呼び出しrunとstoptransactionを実行できる初期化されたトランザクションを返すStartTransactionメソッドを指定できます。

class Runner
{
  Transaction StartTransaction()
  {
    return new Transaction(this);
  }
}

class Transaction
{
  Transaction Run()
  Transaction StopTransaction()
}

通話は次のようになります

var runner = new Runner();
runner
  .StartTransaction()
  .Run()
  .StopTransaction();

もちろん、あらゆる種類のエラー処理などを追加する必要があります。

7
Mendelt

私も、仕事で小さなアプリのための流暢なインターフェースを書く方法を学ぶことに飛びついています。私は周りに尋ねて少し調べたところ、流暢なインターフェースを書くための良いアプローチは「ビルダーパターン」を使用することであることがわかりました。それについてもっと読む ここ

本質的に、これは私が私の始めた方法です:

public class Coffee
{
    private bool _cream;
    private int _ounces;

    public Coffee Make { get new Coffee(); }

    public Coffee WithCream()
    {
        _cream = true;
        return this;
    }

    public Coffee WithOuncesToServe(int ounces)
    {
        _ounces = ounces;
        return this;
    }
}

これは、流暢なインターフェースでクロージャを実装するために持っている 同様の質問 へのクロスポストです。

7
sam

1つは、英語の構文の形態を説明し、その下に文書化されていない順次結合を導入していないことを確認する必要があるということです。

// Snarky employees get a raise.
employees.WhereSnarky().GiveRaise();

vs.

// Depending on implementation, everyone may get a raise.
employees.GiveRaise().WhereSnarky();
4
An00bus

しばらく前、私はあなたが今持っているのと同じ疑問を持っていました。私はいくつかの調査を行い、現在、それらのトピックに役立ついくつかの投稿を書いています。

私のブログでそれをチェックしてください:

C#パート1の流暢なインターフェイス設計のガイドライン

そして、次の投稿では、あなたが言及したすべてのポイントをカバーします。

よろしくアンドレヴィアンナ

2
Andre Vianna