เรากำลังใช้วิธีการคงที่หรือไม่?


13

สองสามเดือนที่ผ่านมาฉันเริ่มทำงานในโครงการใหม่และเมื่อผ่านรหัสมันทำให้ฉันจำนวนคงที่วิธีการแบบคงที่ ไม่เพียง แต่วิธีการใช้งานยูทิลิตี้collectionToCsvString(Collection<E> elements)แต่ยังมีตรรกะทางธุรกิจมากมาย

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

@Service
public class CustomerReceiptCreationService {

    public CustomerReceipt createReceipt(Object... args) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        return receipt;
    }
}

ตอนนี้ผู้ชายคนนั้นบอกว่าเขาไม่ชอบที่จะมีคลาสที่จัดการโดยสปริงโดยไม่จำเป็นเพราะมันมีข้อ จำกัด ว่าคลาสไคลเอนต์จะต้องเป็นสปริงบีนเอง เราจบลงด้วยการจัดการทุกอย่างในฤดูใบไม้ผลิซึ่งบังคับให้เราทำงานกับวัตถุไร้สัญชาติอย่างเป็นขั้นตอน มากหรือน้อยที่ระบุไว้ที่นี่https://www.javacodegeeks.com/2011/02/domain-driven-design-spring-aspectj.html

ดังนั้นแทนที่จะเป็นรหัสข้างต้นเขามี

public class CustomerReceiptCreator {

    public static CustomerReceipt createReceipt(Object... args) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        return receipt;
    }
}

ฉันสามารถโต้เถียงกับจุดที่หลีกเลี่ยง Spring จัดการชั้นเรียนของเราเมื่อเป็นไปได้ แต่สิ่งที่ฉันไม่เห็นคือประโยชน์ของการมีทุกอย่างคงที่ วิธีการคงที่เหล่านี้ยังไร้สัญชาติดังนั้นจึงไม่มากเกินไป ฉันจะรู้สึกสะดวกสบายกับบางสิ่งบางอย่างมากขึ้น

new CustomerReceiptCreator().createReceipt()

เขาอ้างว่าวิธีการคงที่มีประโยชน์พิเศษบางอย่าง กล่าวคือ:

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

แต่ฉันแค่รู้สึกว่ามีบางอย่างไม่ถูกต้องกับสิ่งนี้ดังนั้นฉันอยากได้ยินความคิดของนักพัฒนาที่มีประสบการณ์มากกว่านี้

ดังนั้นคำถามของฉันคืออะไรผิดพลาดที่อาจเกิดขึ้นของวิธีการเขียนโปรแกรมนี้




4
staticวิธีการที่คุณกำลังแสดงข้างต้นเป็นเพียงวิธีการที่โรงงานสามัญ การทำให้วิธีการของโรงงานคงที่คือการประชุมที่ยอมรับกันโดยทั่วไปด้วยเหตุผลหลายประการที่น่าสนใจ ไม่ว่าวิธีการของโรงงานที่เหมาะสมที่นี่เป็นเรื่องที่แตกต่าง
Robert Harvey

คำตอบ:


23

ความแตกต่างระหว่างnew CustomerReceiptCreator().createReceipt()และCustomerReceiptCreator.createReceipt()คืออะไร? ค่อนข้างไม่มีเลย ข้อแตกต่างที่สำคัญคือกรณีแรกมีไวยากรณ์ที่น่าอึดอัดใจมากกว่ามาก หากคุณปฏิบัติตามข้อแรกในความเชื่อที่ว่าการหลีกเลี่ยงวิธีการแบบคงที่จะทำให้โค้ดของคุณดีขึ้น OO คุณจะเข้าใจผิดอย่างมาก การสร้างวัตถุเพียงเพื่อเรียกวิธีการเดียวในมันเป็นวิธีการคงที่โดยป้านไวยากรณ์

สิ่งที่จะได้รับที่แตกต่างกันคือเมื่อคุณฉีดCustomerReceiptCreatorแทนของnewไอเอ็นจีมัน ลองพิจารณาตัวอย่าง:

class OrderProcessor {
    @Inject CustomerReceiptCreator customerReceiptCreator;

    void processOrder(Order order) {
        ...
        CustomerReceipt receipt = customerReceiptCreator.createReceipt(order);
        ...
    }
}

ลองเปรียบเทียบนี่เป็นรุ่นวิธีการคงที่:

void processOrder(Order order) {
    ...
    CustomerReceipt receipt = CustomerReceiptCreator.createReceipt(order);
    ...
}

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

CustomerReceiptCreatorฉันไม่สามารถทำให้การค้ำประกันเดียวกันถ้าเราได้ฉีด มันอาจมีสถานะภายในที่เปลี่ยนแปลงโดยการโทรฉันอาจได้รับผลกระทบจากหรือเปลี่ยนสถานะอื่น อาจมีความสัมพันธ์ที่ไม่สามารถคาดเดาได้ระหว่างคำสั่งในฟังก์ชั่นของฉันเช่นการเปลี่ยนลำดับจะแนะนำข้อบกพร่องที่น่าแปลกใจ

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

public class CustomerReceiptCreator {
    @Injected FeatureFlags featureFlags;

    public CustomerReceipt createReceipt(Order order) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        if (featureFlags.isFlagSet(Flags::FOOBAR)) {
           ...
        }
        return receipt;
    }
}

แล้วเราจะทำเพราะรหัสโทรจะถูกฉีดด้วยซึ่งจะได้รับการฉีดโดยอัตโนมัติCustomerReceiptCreatorFeatureFlags

ถ้าเราใช้วิธีการคงที่

public class CustomerReceiptCreator {
    public static CustomerReceipt createReceipt(Order order, FeatureFlags featureFlags) {
        CustomerReceipt receipt = new CustomerReceipt();
        // creation logic
        if (featureFlags.isFlagSet(Flags::FOOBAR)) {
           ...
        }
        return receipt;
    }
}

แต่เดี๋ยวก่อน! รหัสการโทรต้องได้รับการอัพเดตด้วย:

void processOrder(Order order) {
    ...
    CustomerReceipt receipt = CustomerReceiptCreator.createReceipt(order, featureFlags);
    ...
}

ของหลักสูตรนี้ยังคงทิ้งคำถามของที่processOrderได้รับของFeatureFlagsจาก หากเราโชคดีเส้นทางสิ้นสุดลงที่นี่หากไม่จำเป็นต้องผ่าน FeatureFlags จะถูกผลักขึ้นไปบนกองซ้อนอีกครั้ง

มีการแลกเปลี่ยนที่นี่ วิธีการแบบคงที่ต้องผ่านการอ้างอิงอย่างชัดเจนซึ่งส่งผลในการทำงานมากขึ้น วิธีการฉีดลดงาน แต่ทำให้การอ้างอิงโดยนัยและทำให้การซ่อนรหัสทำให้เหตุผลยากขึ้น

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