Enum มีคุณสมบัติบูลีนมากมาย


11

ขณะนี้ฉันกำลังทำงานกับ webapp ซึ่งเรามักจะต้องกำหนดเงื่อนไขของเซิร์ฟเวอร์บางอย่างโดยอิงจากหน้าเว็บที่จะถูกส่งคืนให้กับผู้ใช้

แต่ละหน้าจะได้รับรหัสหน้า 4 ตัวอักษรและรหัสหน้าเหล่านี้มีการระบุไว้ในชั้นเรียนเป็นสตริงคงที่:

public class PageCodes {
    public static final String FOFP = "FOFP";
    public static final String FOMS = "FOMS";
    public static final String BKGD = "BKGD";
    public static final String ITCO = "ITCO";
    public static final String PURF = "PURF";
    // etc..
}

และบ่อยครั้งที่ในโค้ดเราเห็นโค้ดลักษณะนี้ ( รูปแบบที่ 1 ):

if (PageCode.PURF.equals(destinationPageCode) || PageCodes.ITCO.equals(destinationPageCode)) {
    // some code with no obvious intent
} 
if (PageCode.FOFP.equals(destinationPageCode) || PageCodes.FOMS.equals(destinationPageCode)) {
    // some other code with no obvious intent either
} 

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

ทางออกปัจจุบัน

ส่วนเหล่านี้ifได้รับการทำให้ง่ายขึ้นโดยใช้รายการหน้าซึ่งประกาศโดยคนต่าง ๆ ในชั้นเรียนที่แตกต่างกัน ทำให้โค้ดดูเหมือน ( แบบที่ 2 ):

private static final List<String> pagesWithShoppingCart = Collections.unmodifiableList(Arrays.asList(PageCodes.ITCO, PageCodes.PURF));
private static final List<String> flightAvailabilityPages = Collections.unmodifiableList(Arrays.asList(PageCodes.FOMS, PageCodes.FOFP));

// later in the same class
if (pagesWithShoppingCart.contains(destinationPageCode)) {
    // some code with no obvious intent
} 
if (flightAvailabilityPages.contains(destinationPageCode)) {
    // some other code with no obvious intent either
} 

... ซึ่งเป็นการแสดงออกถึงเจตนาที่ดีกว่ามาก แต่...

ปัญหาปัจจุบัน

ปัญหาที่นี่คือถ้าเราเพิ่มหน้าเราในทางทฤษฎีจะต้องผ่านฐานรหัสทั้งหมดเพื่อค้นหาว่าเราจำเป็นต้องเพิ่มหน้าของเราไปยังรายการif()หรือรายการแบบนั้น

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

โซลูชั่นใหม่

โซลูชันของฉันคือการสร้าง enum (เนื่องจากมีรายการรหัสหน้าเว็บที่รู้จักกันดี) ซึ่งแต่ละหน้ามีคุณสมบัติบางอย่างที่เราต้องตั้งค่า:

public enum Page {
    FOFP(true, false),
    FOMS(true, false),
    BKGD(false, false),
    PURF(false, true),
    ITCO(false, true),
    // and so on

    private final boolean isAvailabilityPage;
    private final boolean hasShoppingCart;

    PageCode(boolean isAvailabilityPage, boolean hasShoppingCart) {
        // field initialization
    }

    // getters
}

จากนั้นรหัสเงื่อนไขนี้จะมีลักษณะดังนี้ ( รูปแบบที่ 3 ):

if (destinationPage.hasShoppingCart()) {
    // add some shopping-cart-related data to the response
}
if (destinationPage.isAvailabilityPage()) {
    // add some info related to flight availability
}

ซึ่งอ่านง่ายมาก นอกจากนี้หากมีคนต้องการเพิ่มหน้าเขา / เธอถูกบังคับให้คิดเกี่ยวกับบูลีนแต่ละครั้งและไม่ว่าจะเป็นเรื่องจริงหรือเท็จสำหรับหน้าใหม่ของเขา

ปัญหาใหม่

ปัญหาหนึ่งที่ฉันเห็นคืออาจจะมี 10 booleans เช่นนี้ซึ่งทำให้ตัวสร้างใหญ่จริงๆและมันอาจจะยากที่จะได้รับการประกาศเมื่อคุณเพิ่มหน้า ไม่มีใครมีทางออกที่ดีกว่า?

คำตอบ:


13

คุณสามารถนำแนวคิดนี้ไปอีกขั้นหนึ่งและกำหนดคุณสมบัติ enum สำหรับหน้าเพจของคุณแทนที่จะใช้บูลีน

สิ่งนี้ทำให้ง่ายต่อการเพิ่ม / ลบคุณลักษณะไปยังหน้าและทำให้คำจำกัดความของหน้าสามารถอ่านได้ทันทีแม้ว่าจะมีคุณสมบัติที่เป็นไปได้ 30-40 ข้อ

public enum PageFeature {
    AVAIL_PAGE,
    SHOPPING_CART;
}

public enum Page {
    FOFP(AVAIL_PAGE),
    FOMS(AVAIL_PAGE),
    BKGD(),
    PURF(SHOPPING_CART, AVAIL_PAGE),

    private final EnumSet<PageFeature> features;

    PageCode(PageFeature ... features) {
       this.features = EnumSet.copyOf(Arrays.asList(features));
    }

    public boolean hasFeature(PageFeature feature) {
       return features.contains(feature);
    }
 }

ฉันคิดเกี่ยวกับเรื่องนี้ แต่ที่นี่นักพัฒนาไม่ได้ถูกบังคับให้ตอบคำถามทั้งหมด "มันเป็นหน้าประโยชน์หรือไม่", "มันมีตะกร้าสินค้าหรือไม่" ฯลฯ เมื่อมีจำนวนมากคุณลืมได้ง่าย
Joffrey

5
@Joffrey เมื่อคุณคิดเกี่ยวกับการมีสิบ booleans ไม่ได้บังคับให้พวกเขาให้คำตอบอย่างน้อยก็ไม่ใช่คำตอบที่พวกเขาคิด สถานการณ์ที่เป็นไปได้มากที่สุดคือพวกเขาจะคัดลอกคำจำกัดความของหน้าอื่นหรือปล่อยให้ IDE เติมพารามิเตอร์ทั้งหมดด้วยfalseจากนั้นแก้ไขหนึ่งหรือสองรายการ (อาจเป็นสิ่งที่ผิดเนื่องจากเป็นเรื่องยากที่จะติดตาม) ไม่มีการป้องกันที่สมบูรณ์แบบจากความโง่และมาถึงจุดที่คุณต้องเชื่อถือนักพัฒนาซอฟต์แวร์ของคุณให้ทำสิ่งที่ถูกต้อง
biziclop

ใช่ฉันไม่ได้คิดแบบนี้ :) และฉันไม่คิดว่า "การพิสูจน์คนโง่" ที่ได้รับจากบูลีนขนาดเล็กพิเศษนั้นคุ้มค่ากับความเสื่อมในการมองเห็นดังนั้นฉันอาจจะไปหาคำตอบ vararg ขอบคุณสำหรับความเข้าใจของคุณ!
Joffrey

1
ทางออกที่ดี upvoted แม้ว่าส่วนหนึ่งของฉันที่เขียนใน 6502s ต้องการอัดทุกอย่างเป็นบิต :-)
user949300

@ user949300 vararg เหมือนการแก้ปัญหาแรกที่ผมคิดเกี่ยวกับการถูกกัดจริงหน้ากาก :) แต่ vararg จริงกับประเภท enum สะอาด
Joffrey
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.