読みやすくするためだけに、単純なクラスでコレクションをラップするのはやり過ぎですか?


15

次のマップがあります。

Map<Double, List<SoundEvent>> soundEventCells = new HashMap<Double, List<SoundEvent>>();

これHashMapは、double値(ある時点)を対応するSoundEvent「セル」にマップします。各「セル」には、多数のSoundEventsを含めることができます。それがaとして実装されているList<SoundEvent>理由です。それがまさにそれだからです。

コードを読みやすくするために、次のような非常に単純な静的内部クラスを実装することを考えました。

private static class SoundEventCell {
    private List<SoundEvent> soundEvents = new ArrayList<SoundEvent>();
    public void addEvent(SoundEvent event){
        soundEvents.add(event);
    }
    public int getSize(){
        return soundEvents.size();
    }
    public SoundEvent getEvent(int index){
        return soundEvents.get(index);
    }
    // .. remove() method unneeded
}

また、マップ宣言(および他の多くのコード)の方が見栄えがよくなります。たとえば、次のようになります。

Map<Double, SoundEventCell> soundEventCells = new HashMap<Double, SoundEventCell>();

これはやり過ぎですか?あなたのプロジェクトでこれをしますか?


概念的には、読み取り可能で保守が容易なコードを記述したかどうかをどのように知っていますか?仲間は物事のあなたの方法に文句続けるならば、それは一つの方法またはそれらに気分を良くするために別の、あなたより良い変化で
ブヨ

1
サウンドイベントのリストをリストではなく「セル」にするのは何ですか?この単語の選択は、セルがリストとは異なる動作をする、または最終的に異なる動作を持つことを意味しますか?
xコード14

@DocBrownなんで?このクラスはprivate static、外部クラスでのみ使用されるため、外部クラスの特定のインスタンスとは関係がないためです。それは正確に正しい使い方ではありませんprivate staticか?
アビブコーン14

2
@Doc Brown、Aviv Cohn:言語を指定するタグはありません。そのため、同時に正しいことも間違っていることもあります。
エミリオガラヴァリア14

@EmilioGaravaglia:Java(構文によって判断すると、JavaまたはC#である可能性があり、使用される規則によりJavaに絞り込まれているため、かなり明確だと思います;))。
アビブコーン14

回答:


12

決して過剰ではありません。「HashMapを使用できます」から始めるのではなく、必要な操作から始めます。HashMapは必要なものだけである場合があります。
あなたの場合、そうではないと思います。おそらくあなたがしたいことは次のようなものです:

public class EventsByTime {
    public EventsByTime addEvent(double time, SoundEvent e);
    public List<SoundEvent> getEvents(double time);
    // ... more methods specific to your use ...
}

あなたは間違いなくこれを言っているたくさんのコードを持ちたくありません:

List<SoundEvent> events = eventMap.get(time);
if (events == null) {
   events = new ArrayList<SoundEvent>();
   eventMap.put(time, events);
}

または、Guava Multimap実装のいずれかを使用することもできます。


本質的に情報隠蔽メカニズムであるクラスを、情報隠蔽メカニズムとして使用することを提唱しますか?ホラー。
ロバートハーヴェイ14

1
実際TimeLine、そういうものにぴったりのクラスがあります:)それはHashMap<Double, SoundEventCell>(最終的にはアイデアのSoundEventCell代わりに行った)の薄いラッパーList<SoundEvent>です。だから、私はやることができtimeline.addEvent(4.5, new SoundEvent(..))、低レベルのものをカプセル化することができます:)
アビブコーン14

14

一部の領域では読みやすさを高めることができますが、事態を複雑にする可能性もあります。私は個人的には流readingさのためにコレクションをラップしたり拡張したりすることを避けています。新しいラッパーは、最初に読んだときに、注意すべき動作があるかもしれないことを示唆しています。それを最小サプライズの原則の陰と考えてください。

インターフェースの実装に固執するということは、インターフェースについてだけ心配する必要があるということです。もちろん、具体的な実装には追加の動作が含まれますが、心配する必要はありません。だから、誰かのコードを通して自分の道を見つけようとするとき、読みやすさのためにプレーンなインターフェースを好む。

一方、追加された動作の恩恵を受けるユースケースを見つけている場合、本格的なクラスを作成してコードを改善するという議論があります。


11
ラッパーは、不要な動作を削除(または非表示)するためにも使用できます。
ローマンライナー14

4
@RomanReiner-そのようなことには注意したい。今日の不要な行動は、多くの場合、明日あなたの名前を呪うプログラマーです。誰もが何がListできるかを知っています、そして、それは正当な理由でそれらすべてをします。
テラスティン14

機能性を維持したいという願いに感謝しますが、ソリューションは機能性と抽象化の慎重なバランスだと思います。 SoundEventCell実装できるIterableためSoundEventのイテレータを提供思われる、S soundEventsあなたが任意のリストとして読む(書き込みは不可)することができるだろうので、メンバーを。List将来的にもっとダイナミックな何かが必要になるかもしれないときに使うのをalmostするのとほぼ同じくらい複雑さを隠すのをためらいます。
ニール14

2

それをラップすると、機能を、書くことに決めたメソッドだけに制限し、基本的には利益をもたらさないようにコードを増やします。少なくとも、次のことを試してみます。

private static class SoundEventCell : List<SoundEvent>
{
}

サンプルからコードを作成することもできます。

Map<Double, SoundEventCell> soundEventCells = new HashMap<Double, SoundEventCell>();

つまり、リスト自体に必要な機能がある場合にのみ、これを実行したことがあります。しかし、あなたの方法はこれには行き過ぎだと思います。リストのほとんどのメソッドへのアクセスを制限する理由がない限り。


-1

別の解決策は、リストを公開する単一のメソッドでラッパークラスを定義することです。

private static class SoundEventCell
{
    private List<SoundEvent> events;

    public SoundEventCell(List<SoundEvent> events)
    {
        this.events = events;
    }

    public List<SoundEvent> getEvents()
    {
        return events;
    }
}

これにより、最小限のコードで適切な名前のクラスが得られますが、カプセル化が可能になり、たとえば、コンストラクターでディフェンシブコピーをCollections.unmodifiableList行い、アクセサーで使用することでクラスを不変にすることができます。

(ただし、これらのリストが実際にこのクラスでのみ使用されている場合、多くのnullチェックロジックとエラーを節約できるため、Map<Double, List<SoundEvent>>Multimap<Double, SoundEvent>docs)に置き換える方が良いと思います。)

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