2

スパゲッティ VBA コードを使用して数年前の MS Access アプリを C# および OOP に移植しようとしていますが、ドメイン ロジックをドメイン クラスに配置する最善の方法を見つけるのに苦労しています。

Country簡単な例としてクラスを使用します。ビジネス ルールが異なる 3 つのプロパティがあります。

  • CountryCode国が作成されると、国を使用するサードパーティのアプリで問題が発生するため、変更できなくなります
  • CountryName基礎となるロジックやビジネス ルールなしで、いつでも変更できます。
  • IsoCodeいつでも変更できますが、正確に 2 文字の長さでなければなりません
    (IsoCode実際にはもっと多くの規則がありますが、この例では、単純にするために「正確に 2 文字でなければならない」が唯一の規則であると仮定します)

クラスのわずかに異なる 2 つのバージョンを作成しました。
私はオブジェクト指向プログラミングの経験がまったくないので、次のことを決めるのに助けが必要です:

  • どのアプローチを使用するかは重要ですか?
  • それらの 1 つ (または両方) に、私が見ていない問題がありますか?
  • さらに良い別の方法はありますか?

私のアプローチは両方とも今は良さそうに見えますが、後で問題が発生するかどうかはわかりません (問題のアプリは 10 年前のものであり、おそらく長い間存続するでしょう)。


バージョン 1:

public class Country1
{
    public string CountryCode { get; private set; }
    public string CountryName { get; set; }
    public string IsoCode { get; private set; }

    public Country1(string countryCode, string countryName, string isoCode)
    {
        this.CountryCode = countryCode;
        this.CountryName = countryName;
        SetIsoCode(isoCode);
    }

    public void SetIsoCode(string isoCode)
    {
        if (isoCode.Length != 2)
        {
            throw new ArgumentException("must be exactly 2 characters!");
        }

        this.IsoCode = isoCode;
    }
}

バージョン 2:

public class Country2
{
    public Country2(string countryCode, string countryName, string isoCode)
    {
        this.countrycode = countryCode;
        this.CountryName = countryName;
        this.isocode = isoCode;
    }

    private readonly string countrycode;
    private string isocode;

    public string CountryCode
    {
        get { return this.countrycode; }
    }

    public string CountryName { get; set; }

    public string IsoCode
    {
        get { return this.isocode; }
        set
        {
            if (value.Length != 2)
            {
                throw new ArgumentException("must be exactly 2 characters!");
            }

            this.isocode = value;
        }
    }
}

なぜ私がこれを求めているのか、そして私が知りたいことについて、もう少し背景を説明します。

「正しい OOP の方法」について、さまざまな意見を読みました。
ゲッターとセッターをまったく公開すべきではないと言う人もいます。これがセッターの悪い考えである理由を理解していCountryCodeます。そのため、コンストラクターからのみ設定できます。

getter と setter を使用する代わりに、GetXXXandSetXXXメソッドを使用する必要があると言う人もいます。場合によっては、これが理にかなっていることがわかります (たとえば、SetXXX一緒に設定する必要がある複数の値がある場合に、複数のパラメーターを持つメソッド)。
しかし、多くの場合CountryName、私の例のような単純な値があります。これは、ロジックのない「ダム」値です。1 つのクラスにこれらのものが 10 個ある場合、それぞれのメソッドを作成GetXXXしたくありません。SetXXX

次に、 のようなものがありIsoCodeますが、これは他のどのプロパティにも接続されていません (そのため、SetXXXメソッドを使用して別のプロパティと一緒に設定する必要はありません)。ただし、いくつかの検証が含まれているため、メソッドを作成SetXXXするか、setter で検証を実行する (何か問題がある場合は例外をスローする) ことができます。

例外をスローすることは、呼び出し元にエラーを通知する最良の方法ですか? 大丈夫だと言う人もいれば、「例外的な」場合にのみ例外をスローするべきだと言う人もいます
IMO 誰かが無効な ISO コードを入力しても例外ではありませんが、エラーが発生したという情報 (人間が読めるエラー メッセージを含む!!) をクライアントに取得するにはどうすればよいですか? ErrorMessageエラー コードと文字列プロパティを持つ応答オブジェクトを使用する方がよいでしょうか?

4

2 に答える 2

2

個人的には、プロパティとメソッドの実装に大きな違いはないと思います。値を個別に設定できる場合は、プロパティを使用することを好みます。値が何らかの形で相互に依存している場合 (たとえば、整数 x と y を設定し、y を x より大きくすることはできません) に、セッター メソッドを使用して、モデルに同時に複数の値を強制的に提供します。

ビューモデルに単純な検証ロジック (必須フィールド、フィールド長など) を含めることは非常に理にかなっている記入されていました)。

例外をスロー/キャッチするのに適した条件については、Eric Lippert による次の記事を強くお勧めします。

http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx

于 2013-02-24T13:50:49.267 に答える
1

一度に設定する必要がある複数の値を含むルールがある場合は、単一の値の変更とメソッドにプロパティを使用することはSetXXXめったにありません (Andy Skirrow が言ったように)。

SetXXXすべてのメソッドは、一般的な "Javaish" 規則です (ただし、C# のようなセッターとゲッターを持たない多くの言語で使用されています)。

人々は、ある言語で学んだ良い実践を、可能な限りすべての言語に適用しようとします。

「OOP マニア」にならないようにしてください。これでは頭が痛くなるだけです。OOP は宗教ではありません (そして、宗教でさえ狂信者がいるべきではありませんが、これは別の話です)。

ポイントに戻る

2 つのアプローチは、機能的な違いはなく、将来的に害を及ぼすことはありません。より読みやすく、コーディングしやすい方法で記入してください。これは、「正しい OOP の方法」よりもはるかに多くのことを意味します。なぜなら、多くの人が物事を行う「より良い方法」について独自の定義を持っているからです。

検証

MVC のような構造またはアーキテクチャ パターンを使用している場合は、データ注釈属性を使用して検証を実施し、フレームワークによっては、それを使用してクライアント側の検証を実施することもできます。

リンクについては、@Andy Skirows の回答を参照してください。

于 2013-02-24T14:11:31.667 に答える