การจัดการความซับซ้อนของตัวสร้าง: เมื่อใดที่ มีมากเกินไป
ถือว่ามากเกินไป?
ในกระบวนการพัฒนาซอฟต์แวร์ โดยเฉพาะอย่างยิ่งในการเขียนโปรแกรมเชิงวัตถุ ตัวสร้างมีบทบาทสำคัญในการเริ่มต้นวัตถุ อย่างไรก็ตาม เมื่อโครงการพัฒนาขึ้นและความต้องการเพิ่มขึ้น ปัญหาที่พบได้บ่อยคือ: จำนวนอาร์กิวเมนต์ของตัวสร้างที่มากเกินไปคือเท่าใด? คลาสที่ต้องการพารามิเตอร์จำนวนมากสำหรับตัวสร้างสามารถกลายเป็นเรื่องยุ่งยากได้อย่างรวดเร็ว ทำให้ยากต่อการบำรุงรักษาและใช้งานอย่างมีประสิทธิภาพ ในโพสต์บล็อกนี้ เราจะพูดคุยเกี่ยวกับความท้าทายนี้และสำรวจสองแพทเทิร์นการออกแบบที่สามารถทำให้การใช้งานตัวสร้างง่ายขึ้นและทำให้โค้ดของคุณสะอาดและจัดการได้ง่ายขึ้น
ปัญหา: ตัวสร้างที่ยุ่งเหยิง
ลองพิจารณาคลาสชื่อว่า Customer
ซึ่งมีฟิลด์หลายฟิลด์ที่จำเป็นต้องสอดคล้องกับตรรกะทางธุรกิจของคุณ:
- ชื่อผู้ใช้
- อีเมล
- ชื่อจริง
- นามสกุล
แม้ว่าจะดูเหมือนว่าเป็นเรื่องง่ายที่จะกำหนดฟิลด์ทั้งสี่นี้ลงในตัวสร้าง แต่สถานการณ์อาจกลายเป็นเรื่องที่ไม่สะดวก เมื่อมีฟิลด์ที่ต้องการเพิ่มขึ้น เมื่อคลาสมีจำนวนพารามิเตอร์ถึง 20 ตัวขึ้นไป การใช้งานตัวสร้างนั้นกลายเป็นความยุ่งยากสำหรับนักพัฒนา
ความเสี่ยงจากจำนวนอาร์กิวเมนต์ของตัวสร้างที่มากเกินไป
- ความซับซ้อนที่เพิ่มขึ้น: ตัวสร้างที่มีพารามิเตอร์มากเกินไปอาจทำให้เข้าใจได้ยากและอ่านยาก
- ความผิดพลาด: ข้อผิดพลาดจากนักพัฒนาสามารถเกิดขึ้นจากการจัดเรียงพารามิเตอร์ผิดหรือการลืมใส่ฟิลด์ที่จำเป็น
- ปัญหาการบำรุงรักษา: การปรับเปลี่ยนคลาสที่มีตัวสร้างที่ใหญ่เกินไปมักจะต้องมีการปรับเปลี่ยนที่สำคัญในหลายจุดในโค้ดของคุณ
ในขณะที่คุณพิจารณาว่าจะต่อสู้กับความซับซ้อนนี้อย่างไร คุณอาจสงสัยว่ามีแนวทางการออกแบบทางเลือกใดบ้างที่สามารถจำกัดพารามิเตอร์ของตัวสร้างหรือทำให้การใช้งานของพวกเขาง่ายขึ้น
ทางออก: แพทเทิร์นบิลเดอร์และฟลูเอนท์อินเตอร์เฟซ
- แพทเทิร์นบิลเดอร์: อนุญาตให้มีวิธีการสร้างวัตถุที่ยืดหยุ่นและอ่านง่ายมากขึ้น โดยใช้ฟิลด์แยกกันและสร้างวัตถทีละขั้นตอน
- แพทเทิร์นฟลูเอนท์อินเตอร์เฟซ: แพทเทิร์นนี้ส่งเสริมโค้ดที่อ่านเหมือนภาษาธรรมชาติ เพิ่มความชัดเจน
ตัวอย่างของฟลูเอนท์อินเตอร์เฟซในทางปฏิบัติ
ในตัวอย่างด้านล่างนี้ เราจะแสดงให้เห็นวิธีการสร้าง CustomerBuilder
สำหรับสร้างวัตถุ Customer
:
public class CustomerBuilder {
String surname;
String firstName;
String ssn;
public static CustomerBuilder customer() {
return new CustomerBuilder();
}
public CustomerBuilder withSurname(String surname) {
this.surname = surname;
return this;
}
public CustomerBuilder withFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public CustomerBuilder withSsn(String ssn) {
this.ssn = ssn;
return this;
}
// ลูกค้าไม่สามารถสร้าง Customer โดยตรงได้
public Customer build() {
return new Customer(this);
}
}
public class Customer {
private final String firstName;
private final String surname;
private final String ssn;
Customer(CustomerBuilder builder) {
if (builder.firstName == null) throw new NullPointerException("firstName");
if (builder.surname == null) throw new NullPointerException("surname");
if (builder.ssn == null) throw new NullPointerException("ssn");
this.firstName = builder.firstName;
this.surname = builder.surname;
this.ssn = builder.ssn;
}
public String getFirstName() { return firstName; }
public String getSurname() { return surname; }
public String getSsn() { return ssn; }
}
การใช้งาน Customer Builder
การสร้างวัตถุจริงด้วย CustomerBuilder
จะมีลักษณะดังนี้:
import static com.acme.CustomerBuilder.customer;
public class Client {
public void doSomething() {
Customer customer = customer()
.withSurname("Smith")
.withFirstName("Fred")
.withSsn("123XS1")
.build();
}
}
สรุป: การสร้างสมดุล
การจัดการอาร์กิวเมนต์ของตัวสร้างอย่างชาญฉลาดมีความสำคัญสำหรับการสร้างโค้ดที่สามารถบำรุงรักษาและอ่านได้ โดยการใช้แพทเทิร์นเช่น บิลเดอร์ และ ฟลูเอนท์อินเตอร์เฟซ นักพัฒนาสามารถลดความซับซ้อนในตัวสร้างของตนและป้องกันข้อเสียของพารามิเตอร์ที่มากเกินไป
เมื่อครั้งหน้าหากคุณเผชิญกับฟิลด์ที่จำเป็นจำนวนมาก ให้พิจารณาการใช้หนึ่งในแพทเทิร์นเหล่านี้ โค้ดของคุณจะไม่เพียงแต่สะอาด แต่ยังสนุกในการทำงานอีกด้วย