15

私のソフトウェア開発プログラミングのクラスでは、RSS フィード用の「フィード マネージャー」タイプのプログラムを作成することになっていました。FeedItems の実装をどのように処理したかを次に示します。

素晴らしくシンプル:

struct FeedItem {
    string title;
    string description;
    string url;
}

そのためにマークダウンしました。「正しい」回答例は次のとおりです。

class FeedItem
{
public:
    FeedItem(string title, string description, string url);

    inline string getTitle() const { return this->title; }
    inline string getDescription() const { return this->description; }
    inline string getURL() const { return this->url; }

    inline void setTitle(string title) { this->title = title; }
    inline void setDescription(string description){ this->description = description; }
    inline void setURL(string url) { this->url = url; }

private:
    string title;
    string description;
    string url;
};

私には、これはばかげているように思えます。正直なところ、これが私のものとまったく同じことをより多くのオーバーヘッドで行うとき、私がマークダウンしたとは信じられません。


C# で人々が常にこれを行う方法を思い出します。

public class Example
{
    private int _myint;

    public int MyInt
    {
        get
        {
            return this._myint;
        }
        set
        {
            this._myint = value;
        }
    }
}

私は彼らがそれを行う理由を取得することを意味ます。おそらく、後でセッターでデータを検証するか、ゲッターでデータをインクリメントしたいと考えています。しかし、その状況が発生するまで、なぜあなたはこれをやらないのですか?

public class Example
{
    public int MyInt;
}

申し訳ありませんが、これは一種の暴言であり、実際には質問ではありませんが、冗長性は私にとって腹立たしいです. ゲッターとセッターが必要ないのに、なぜそれほど愛されているのでしょうか?

4

13 に答える 13

14

それは「ベスト プラクティス」とスタイルの問題です。

  • データ メンバーを直接公開する必要はありません。それらへのアクセス方法を常に制御できるようにしたいと考えています。この例では、少しばかげているように思えますが、慣れるようにそのスタイルを教えることを目的としています.
  • クラスの一貫したインターフェースを定義するのに役立ちます。何かに到達する方法は常に知っています --> その get メソッドを呼び出します。

次に、再利用性の問題もあります。たとえば、将来、誰かがデータ メンバーにアクセスしたときの動作を変更する必要があるとします。クライアントにコードの再コンパイルを強制することなく、これを行うことができます。クラスのメソッドを変更するだけで、新しいロジックが確実に使用されます。

于 2009-11-11T02:15:44.080 に答える
13

これは、件名に関する素敵な長い SO ディスカッションです: getters と setters を使用する理由

自問したい質問は、「3 か月後に検証FeedItem.url 必要であることに気付いたが、287 の他のクラスからすでに直接参照されている場合はどうなるか?」ということです。

于 2009-11-11T02:14:35.680 に答える
7

必要になる前にこれを行う主な理由は、バージョン管理のためです。

フィールドは、特に左辺値として使用する場合 (特に C# では許可されない場合が多い)、プロパティとは異なる動作をします。また、後でプロパティの get/set ルーチンを追加する必要がある場合、API が壊れます。クラスのユーザーは、新しいバージョンを使用するためにコードを書き直す必要があります。

これを前もって行う方がはるかに安全です。

C#3、ところで、これは簡単になります:

public class Example
{
    public int MyInt { get; set; }
}
于 2009-11-11T02:16:39.260 に答える
6

私はあなたに絶対に同意します。しかし、人生ではおそらく正しいことを行うべきです。学校では、良い成績を取ることです。あなたの職場では、仕様を満たすことです。頑固になりたい場合は、それで問題ありませんが、自分自身を説明してください。コメントで根拠をカバーして、受ける可能性のある被害を最小限に抑えてください。

上記の特定の例では、たとえば URL を検証する必要があることがわかります。タイトルと説明をサニタイズしたいと思うかもしれませんが、いずれにせよ、これはクラス設計の早い段階で伝えられることだと思います。コメントであなたの意図と根拠を述べてください。検証が必要ない場合は、ゲッターとセッターは必要ありません。その通りです。

シンプルさは価値のある機能です。宗教的なことは絶対にしないでください。

于 2009-11-11T02:21:17.383 に答える
4

何かが単純な構造体である場合、それは単なる DATA であるため、ばかげています。

これは、人々がまだクラスの概念をまったく理解していなかった OOP の始まりへの逆戻りです。いつか getId() をハッブル望遠鏡へのリモート呼び出しに変更する可能性がある場合に備えて、何百もの get メソッドと set メソッドを用意する理由はありません。

あなたは本当にトップレベルでその機能を望んでいますが、ボトムでは価値がありません. IE では、純粋な仮想クラスが送信されて動作する複雑なメソッドがあり、以下で何が起こっても動作できることが保証されます。すべての構造体にランダムに配置するのは冗談であり、POD に対しては決して行うべきではありません。

于 2009-11-11T03:50:22.453 に答える
3

コーディングの「ベスト プラクティス」は、プログラミング言語の進歩によって時代遅れになることが多いことに注意してください。

たとえば、C# では、getter/setter の概念がプロパティの形で言語に組み込まれています。C# 3.0 では、コンパイラが getter/setter を自動的に生成する自動プロパティの導入により、これが容易になりました。C# 3.0 では、オブジェクト初期化子も導入されました。これは、ほとんどの場合、単にプロパティを初期化するコンストラクターを宣言する必要がなくなったことを意味します。

したがって、あなたがしていることを行う標準的な C# の方法は次のようになります。

class FeedItem
{
    public string Title { get; set; } // automatic properties
    public string Description { get; set; }
    public string Url { get; set; }
};

使用法は次のようになります (オブジェクト初期化子を使用):

FeedItem fi = new FeedItem() { Title = "Some Title", Description = "Some Description", Url = "Some Url" };

要点は、使用している特定の言語のベスト プラクティスや標準的な方法を試して学ぶべきであり、もはや意味をなさない古い習慣を単純にコピーするのではありません。

于 2009-11-12T02:58:31.590 に答える
3

どちらのバージョンのクラスにも動作がないため、両方のオプションが少し間違っている可能性があります。文脈がなければこれ以上コメントするのは難しいです。

http://www.pragprog.com/articles/tell-dont-askを参照してください。

FeedItemここで、あなたのクラスが非常に人気があり、あらゆる場所のプロジェクトで使用されていると想像してみましょう。(他の回答が示唆しているように)提供されたURLを検証する必要があると判断します。

URL のセッターを作成しました。これを編集し、URL を検証して、無効な場合は例外をスローします。クラスの新しいバージョンをリリースすると、それを使用するすべての人が満足します。(これを軌道に乗せるために、チェックされた例外とチェックされていない例外を無視しましょう)。

ただし、怒っている開発者から電話がかかってきます。アプリケーションの起動時に、ファイルからフィード項目のリストを読み取っていました。そして今、誰かが構成ファイルに小さな間違いを犯した場合、あなたの新しい例外がスローされ、システム全体が起動しません。

メソッドのシグネチャを同じに保っている可能性がありますが、インターフェイスのセマンティクスを変更したため、依存コードが壊れています。今、あなたは高台を取り、彼らにプログラムを正しく書き直すように言うか、謙虚に追加することができsetURLAndValidateます.

于 2009-11-11T02:25:40.510 に答える
1

C++ 開発者として、一貫性を保つためにメンバーを常に非公開にしています。したがって、px ではなく px() と入力する必要があることを常に知っています。

また、私は通常、setter メソッドの実装を避けます。オブジェクトを変更する代わりに、新しいオブジェクトを作成します。

p = Point(p.x(), p.y() + 1);

これにより、カプセル化も保持されます。

于 2009-11-11T02:23:19.883 に答える
1

カプセル化がばかげたものになるポイントは絶対にあります。

コードに抽象化が導入されるほど、事前教育、学習曲線のコストが大きくなります。

C を知っている人なら誰でも、基本言語の C 標準ライブラリだけを使用する、恐ろしく書かれた 1000 行の関数をデバッグできます。あなたが発明したフレームワークを誰もがデバッグできるわけではありません。導入されたすべてのレベルのカプセル化/抽象化は、コストと比較検討する必要があります。それだけの価値がないと言っているわけではありませんが、いつものように、状況に最適なバランスを見つける必要があります.

于 2009-11-11T02:25:37.650 に答える
1

これは非常によくある質問です。理由は簡単です。通常、後で修正/再テスト/再展開するのではなく、最初に正しく実行する方がはるかに安価です。古い見積もりでは、メンテナンス コストは 80% であると言われています。そのメンテナンスの多くは、まさにあなたが示唆していることです。つまり、誰かが問題を抱えた後にのみ正しいことを行うということです。最初から正しく行うことで、より興味深いことに集中し、生産性を高めることができます。

ずさんなコーディングは通常、非常に不利益です。製品の信頼性が低く、使用時に生産性がないため、顧客は不満を抱いています。開発者も満足していません。彼らは 80% の時間をパッチに費やしていますが、これは退屈です。最終的には、顧客と優れた開発者の両方を失うことになります。

于 2010-10-23T16:22:21.860 に答える
1

もちろん、ゲッター/セッターは良い習慣ですが、書くのは面倒で、さらに悪いことに読むのは面倒です。

半ダースのメンバー変数とそれに付随する getter/setter を持つクラスを何回読んだことか。 X'、'Y の値を取得'、'Y の値を設定'、'Z の値を取得'、'Zzzzzzzzzzzzz の値を設定。ドキドキ!

于 2009-11-11T05:28:59.237 に答える
1

ソフトウェア業界が直面している問題の 1 つは、再利用可能なコードの問題です。それは大きな問題です。ハードウェアの世界では、ハードウェア コンポーネントは一度設計され、後でコンポーネントを購入してそれらを組み合わせて新しいものを作成するときに設計が再利用されます。

ソフトウェアの世界では、コンポーネントが必要になるたびに何度も設計を繰り返します。とても無駄です。

カプセル化は、作成されたモジュールが再利用可能であることを保証するための手法として提案されました。つまり、モジュールの詳細を抽象化し、後でそのモジュールを使いやすくする明確に定義されたインターフェイスがあります。このインターフェイスは、オブジェクトの誤用も防ぎます。

class で構築する単純なクラスは、適切に定義されたインターフェイスの必要性を十分に示していません。「でも、その状況が発生するまで、なぜあなたたちはこれをやらないのですか?」と言ってください。実生活では機能しません。あなたがソフトウェア工学コースで学んでいるのは、他のプログラマーが使用できるソフトウェアを設計することです。.net フレームワークや Java API によって提供されるようなライブラリの作成者には、この規律が絶対に必要であると考えてください。カプセル化が難しすぎると判断した場合、これらの環境で作業することはほとんど不可能になります。

これらのガイドラインに従うことで、将来的に高品質のコードが得られます。自分自身だけでなく、それから恩恵を受けるため、フィールドに価値を追加するコード。

最後のポイントとして、カプセル化により、モジュールを適切にテストし、それが機能することを合理的に確認することも可能になります。カプセル化がなければ、コードのテストと検証はさらに困難になります。

于 2009-11-11T02:26:27.497 に答える
0

私はあなたに同意しますが、システムを生き残ることが重要です。学校にいる間、同意するふりをしてください。言い換えれば、評価を下げることはあなたにとって有害で​​あり、あなたの原則、意見、または価値観について評価を下げることは価値がありません.

また、チームや雇用主で働いている間は、同意するふりをしてください。その後、自分のビジネスを始めて、自分のやり方でやってください。他の人のやり方を試すときは、冷静に相手に対して心を開いてください。これらの経験が自分の見方を再形成することに気付くかもしれません。

カプセル化は、内部実装が変更された場合に理論的に役立ちます。たとえば、オブジェクトごとの URL が格納された値ではなく計算結果になった場合、getUrl() カプセル化は引き続き機能します。しかし、あなたはすでにその側面を聞いたことがあると思います。

于 2009-11-11T02:16:58.260 に答える