0

かつて私は大手テクノロジー企業で働いていました。Javaでプログラミングしました。彼らは驚くほど賢く、Java で C/C++ の構造体をシミュレートするのが好きです。明確にするために、彼らは「データホルダー」として機能するクラスを作成することを提唱しています。

public class BookInformation {
    public final List<String> authors;
    public final String bookTitle;
    public BookInformation(List<String> authors, String bookTitle) {
        this.authors = authors;
        this.bookTitle = bookTitle;
    }
    @Override
    public String toString() { ... }

    @Override
    public int hashCode() { ... }

    @Override
    public boolean equals(Object obj) { ... }
}

ご覧のとおり、このクラスの目的は単にデータを保持することです。クラス フィールドを直接公開しない、防御的コピーなど、多くのエンタープライズ プログラミング ルールに違反していますが、この種のクラスには簡潔なコーディングなどの利点があります。ゲッターとセッターを呼び出す代わりに、フィールド名を直接呼び出すことができます。

私を悩ませているのは、この種のクラスは保守と拡張が難しいことです。オブジェクトの状態が合法であることを確認する方法がないため、維持が困難です。ビジネス ロジックでは、書籍にはタイトルと少なくとも 1 人の著者が必要であると言う場合があります。しかし、実際には、オブジェクトのタイトルが空、タイトルが空、著者リストが空、または著者リストが空である可能性があり、それを制御することはできません。伸びにくいです。たとえば、データ ソースを変更して、著者名に姓名を別々に提供するとどうなるでしょうか。1 つではなく 2 つの文字列リストを使用する必要があります。さらに悪いことに、データ構造の変更はインターフェイスに影響を与えます。私は getAuthorNames() インターフェースを持っていないので、多くの場所でコードを変更しなければならない可能性があります。

上記のシナリオが発生していないことを認めなければなりません。クラスを使用するすべてのコードはチームの管理下にあることを認めなければならないため、インターフェイスの変更は、他のチーム/企業が使用するために書くほど悪くはありません。では、純粋な OO 言語である Java を使用してエンタープライズ レベルでコーディングしている場合でも、そのようなコーディング標準を使用しても問題ないのでしょうか?

おそらく「正しい」答えがないことはわかっています。個人的な意見が聞きたいです。あなた自身のために大声で話してください!

編集:

わかった。私の質問の核心を言い換える必要があります: シンプルさを得るために教科書のコーディング規則のいくつかを犠牲にするのは賢明ですか? コードベースが成長し、チームが成長したときに、犠牲は後であなたを苦しめますか? 個人的な意見は重要であり、特に賢明な人からのものであり、多くの場合、正しい質問も間違った質問もありません。私たちは皆、説得力のある意見に従っているだけです。申し訳ありませんが、Stackoverflow は正誤問題専用に設計されています。その場合、この質問はクローズする必要があります。

4

2 に答える 2

4

私は正しい答えがあると思います:それがあなたのために働くなら、それのために行きなさい。あなたを逮捕するのを待っているスタイルの警官はいない。

ルールとその背後にある理由を知っています。それらを壊すとき、結果を理解してください。あなたがしていることを正当化する。何が起こるかと一緒に暮らす。

たとえば、データを公開しないというルールは絶対的なものである必要はないと思います。適切に行う限りです。

あなたはそれが間違っていたことを認識する必要があります。

そのリスト参照をfinalにしたという事実は、参照を変更できないことを意味します。参照が参照するリストには、要素を追加および削除できます。必要なことを達成するには、不変にする必要があります。

不変にしないと、コンストラクターに渡す参照に加えた変更がオブジェクトに反映されます。これは、その参照を非公開にした場合でも当てはまります。オブジェクトの状態を完全に独立させるには、渡したリストのコピーを作成する必要があります。Dateなどの可変型への他の参照と同じです。

不変であるため、Stringで機能します。

もう1つ、それはでequals()はなく、である必要がありEquals()ます。Javaではケースが重要です。

public final class BookInformation {
    public final List<String> authors;
    public final String bookTitle;
    public final Date publicationDate;

    public BookInformation(List<String> authors, String bookTitle, Date publicationDate) {
        this.authors = Collections.unmodifiableList((authors == null) ? new ArrayList<String>() : authors);
        this.bookTitle = (StringUtils.isBlank(bookTitle) ? "" : bookTitle);
        this.publicationDate = ((publicationDate == null) ? new Date() : new Date(publicationDate.getTime()));
    }
    @Override
    public String toString() { ... }

    @Override
    public int hashCode() { ... }

    @Override

   public boolean equals(Object obj) { ... }
}
于 2013-01-09T01:42:06.077 に答える
0

標準のゲッター/セッターが不必要に冗長になることがありますが、これを回避する方法があります。

たとえば、フィールドと同じ名前のゲッターまたはセッターを使用でき、フィールドに直接アクセスするよりも簡潔な操作メソッドを作成できます。

例えば

public class BookInformation {
    private final Set<String> authors = new LinkedHashSet<>();
    private final String bookTitle;

    public BookInformation(List<String> authors, String bookTitle) {
        assert authors != null;
        assert bookTitle != null;

        for(String author: authors) addAuthor(author);
        this.bookTitle = bookTitle;
    }

    public String bookTitle() { return bookTitle; }

    // get all the authors without needing a defensive copy.
    // for(int i = 0, len = bookInfo.authorCount(); i < len; i++) {
    //     String name = bookInfo.author(i);

    public int authorCount() { return authors.size(); }
    public String author(int n) { return authors.get(n); }

    public void addAuthor(String name) {
        assert name != null
        authors.add(name);
    }

class AuthorCounter {
    private final ConcurrentMap<String, AtomicInteger> authorCountMap =
                  new ConcurrentHashMap<>();

    public void addAuthor(String name) {
        authorCountMap.putIfAbsent(name, new AtomicInteger());
    }

    public void incrCountFor(String name) {
        authorCountMap.get(name).incrementAndGet();
    }

    public int countForAuthor(String name) {
        AtomicInteger ai = authorCountMap.get(name);
        return ai == null ? 0 : ai.get();
    }
}
于 2013-01-09T09:02:00.793 に答える