มันมากเกินไปที่จะห่อคอลเลกชันในชั้นเรียนที่เรียบง่ายเท่านั้นเพื่อประโยชน์ในการอ่านที่ดีขึ้น?


15

ฉันมีแผนที่ดังต่อไปนี้:

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

นี้HashMapแมdoubleค่า (ซึ่งเป็นคะแนนในเวลา) เพื่อที่สอดคล้องกันSoundEvent'มือถือ': แต่ละเซลล์สามารถมีจำนวนSoundEvents นั่นเป็นสาเหตุที่มันถูกนำมาใช้เป็น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-code

@DocBrown ทำไม คลาสเป็นprivate staticเพราะคลาสภายนอกจะใช้เท่านั้น แต่ไม่เกี่ยวข้องกับอินสแตนซ์เฉพาะของคลาสภายนอก นั่นเป็นการใช้งานที่เหมาะสมprivate staticใช่ไหม
Aviv Cohn

2
@Doc Brown, Aviv Cohn: ไม่มีแท็กระบุภาษาใด ๆ ดังนั้นสิ่งใดก็ตามที่ถูกและผิดในเวลาเดียวกัน!
Emilio Garavaglia

@EmilioGaravaglia: Java (ฉันคิดว่ามันค่อนข้างชัดเจนตั้งแต่พิจารณาจากไวยากรณ์มันอาจเป็น Java หรือ C # และอนุสัญญาที่ใช้แคบลงเพื่อ Java;))
Aviv Cohn

คำตอบ:


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 implementations อย่างใดอย่างหนึ่ง


ดังนั้นคุณจึงสนับสนุนให้ใช้คลาสซึ่งโดยพื้นฐานแล้วคือกลไกการซ่อนข้อมูลเป็นกลไกการซ่อนข้อมูล? สยองขวัญ.
Robert Harvey

1
ที่จริงแล้วฉันมีTimeLineชั้นเรียนอย่างแน่นอนสำหรับสิ่งนั้น :) มันเป็นเสื้อคลุมบาง ๆ รอบ ๆHashMap<Double, SoundEventCell>(ในที่สุดฉันก็ไปด้วยSoundEventCellแทนที่จะเป็นList<SoundEvent>ความคิด) ดังนั้นผมก็สามารถทำtimeline.addEvent(4.5, new SoundEvent(..))และมีสิ่งที่ระดับต่ำกว่าห่อหุ้ม :)
ลอาวีฟ Cohn

14

ในขณะที่มันอาจช่วยในการอ่านในบางพื้นที่ก็ยังสามารถทำให้สิ่งต่าง ๆ ที่ซับซ้อน ฉันเอนตัวออกห่างจากการห่อหรือขยายคอลเลกชันเพื่อความคล่องแคล่วในฐานะที่เป็นเสื้อคลุมตัวใหม่ในการอ่านครั้งแรกหมายถึงฉันว่าอาจมีพฤติกรรมที่ฉันต้องระวัง ถือว่าเป็นเงาของหลักการแห่งความประหลาดใจน้อยที่สุด

การผสานกับการใช้อินเทอร์เฟซหมายความว่าฉันเพียงแค่ต้องกังวลเกี่ยวกับอินเทอร์เฟซ แน่นอนว่าการติดตั้งที่เป็นรูปธรรมอาจทำให้เกิดพฤติกรรมเพิ่มเติม แต่ฉันไม่ควรกังวลเกี่ยวกับมัน ดังนั้นเมื่อฉันพยายามหาทางผ่านรหัสของใครบางคนฉันชอบอินเตอร์เฟซธรรมดาสำหรับการอ่าน

หากในมืออื่น ๆ ที่คุณกำลังหากรณีการใช้งานที่ไม่ได้รับประโยชน์จากพฤติกรรมเพิ่มแล้วคุณมีข้อโต้แย้งสำหรับการปรับปรุงรหัสโดยการสร้างชั้นเต็มเปี่ยม


11
wrapper สามารถใช้เพื่อลบ (หรือซ่อน) พฤติกรรมที่ไม่จำเป็น
Roman Reiner

4
@ RomanReiner - ฉันควรระมัดระวังกับสิ่งเหล่านี้ พฤติกรรมที่ไม่ต้องการในวันนี้มักจะเป็นคำสาปแช่งโปรแกรมเมอร์ของคุณในวันพรุ่งนี้ ทุกคนรู้ว่าListทำอะไรได้บ้างและทำสิ่งเหล่านั้นด้วยเหตุผลที่ดี
Telastyn

ฉันขอขอบคุณความปรารถนาที่จะรักษาฟังก์ชันการทำงานแม้ว่าฉันคิดว่าวิธีแก้ปัญหาคือความสมดุลระหว่างการทำงานและนามธรรม SoundEventCellสามารถใช้IterableสำหรับSoundEvents ซึ่งจะให้ตัววนซ้ำของsoundEventsสมาชิกดังนั้นคุณจะสามารถอ่าน (แต่ไม่เขียน) เป็นรายการใด ๆ ฉันลังเลที่จะปกปิดความซับซ้อนเกือบเท่าที่ฉันลังเลที่จะใช้Listเมื่อฉันต้องการบางสิ่งบางอย่างที่มีพลังมากขึ้นในอนาคต
Neil

2

การตัดมัน จำกัด ฟังก์ชั่นของคุณเฉพาะวิธีที่คุณตัดสินใจที่จะเขียนโดยทั่วไปการเพิ่มโค้ดของคุณโดยไม่มีประโยชน์ อย่างน้อยที่สุดฉันจะลองทำสิ่งต่อไปนี้:

private static class SoundEventCell : List<SoundEvent>
{
}

คุณยังสามารถเขียนรหัสจากตัวอย่างของคุณได้

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

ที่กล่าวว่าฉันเคยทำเมื่อมีฟังก์ชั่นบางอย่างที่รายการต้องการ แต่ฉันคิดว่าวิธีการของคุณจะ overkill นี้ ถ้าคุณไม่มีเหตุผลที่ต้องการ จำกัด การเข้าถึงวิธีการส่วนใหญ่ของรายการ


-1

โซลูชันอื่นอาจกำหนดคลาส wrapper ของคุณด้วยเมธอดเดียวซึ่งแสดงรายการ:

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

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

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

สิ่งนี้จะช่วยให้คุณมีคลาสที่มีชื่อรหัสน้อยที่สุด แต่ยังช่วยให้คุณมีแค็ปซูลช่วยให้คุณสามารถทำให้คลาสนั้นไม่เปลี่ยนรูป (โดยการทำสำเนาการป้องกันในตัวสร้างและการใช้งานCollections.unmodifiableListใน accessor)

( แต่ถ้ารายการเหล่านี้เป็นจริงเพียง แต่ถูกนำมาใช้ในชั้นนี้ผมคิดว่าคุณควรจะทำดีกว่าที่จะมาแทนที่ของคุณMap<Double, List<SoundEvent>>ด้วยMultimap<Double, SoundEvent>( เอกสาร ) เช่นที่มักจะบันทึกจำนวนมากของตรรกะ null การตรวจสอบและข้อผิดพลาด.)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.