إدارة تعقيد المنشئين: متى تكون “الكثير من” الوسائط كثيرة جداً؟

في تطوير البرمجيات، وخصوصاً في البرمجة الشيئية، تلعب المنشئات دوراً محورياً في تهيئة الكائنات. ومع ذلك، مع تطور المشاريع ونمو المتطلبات، تظهر مشكلة شائعة: كم عدد وسائط المنشئ هو أكثر من اللازم؟ يمكن أن تصبح الفصول التي تتطلب العديد من معلمات المنشئ معقدة بسرعة، مما يجعل من الصعب الحفاظ عليها واستخدامها بشكل فعّال. في هذه المدونة، سنناقش هذه التحديات واستكشاف نمطين تصميميين يمكنهما تبسيط استخدام المنشئين وجعل الشيفرة أكثر نظافة وسهولة في الإدارة.

المشكلة: المنشئات المرهقة

اعتبر فصلاً يسمى Customer. يحتوي على عدة حقول أساسية تتماشى مع منطق عملك:

  • اسم المستخدم
  • البريد الإلكتروني
  • الاسم الأول
  • الاسم الأخير

بينما قد يبدو من السهل فرض هذه الحقول الأربعة في المنشئ، فإن الوضع يمكن أن يصبح مرهقًا كلما تزايدت الحقول المطلوبة. عندما يجمع الفصل 20 معلمة أو أكثر، يصبح استخدام هذا المنشئ صداعًا للمطورين.

مخاطر وجود العديد من وسائط المنشئ

  • زيادة التعقيد: يمكن أن يكون المنشئ الذي يحتوي على العديد من المعلمات صعب القراءة والفهم.
  • عرضة للأخطاء: يمكن أن تنشأ أخطاء المطور من ترتيب المعلمات بشكل خاطئ أو نسيان توفير حقل مطلوب.
  • تحديات الصيانة: يتطلب تعديل فصل يحتوي على منشئ مبالغ فيه غالبًا تعديلات كبيرة في عدة أماكن في قاعدة الشفرات الخاصة بك.

بينما تفكر في كيفية مواجهة هذا التعقيد، قد تتساءل عما إذا كانت هناك طرق تصميم بديلة لتقليل وسائط المنشئ أو تبسيط استخدامها.

الحلول: نمط البناء ونمط الواجهة السلسة

  1. نمط البناء: يوفر طريقة أكثر مرونة وقابلية للقراءة لإنشاء الكائنات من خلال استخدام حقول منفصلة وبناء الكائن خطوة بخطوة.
  2. نمط الواجهة السلسة: يعزز هذا النمط الشيفرة التي تقرأ مثل اللغة الطبيعية، مما يعزز الوضوح.

مثال على واجهة سلسة في العمل

في المثال أدناه، سنوضح كيفية تنفيذ 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; }    
}

استخدام بناء الكود

ستبدو عملية إنشاء الكائن الفعلية باستخدام CustomerBuilder كما يلي:

import static com.acme.CustomerBuilder.customer;

public class Client {
    public void doSomething() {
        Customer customer = customer()
            .withSurname("Smith")
            .withFirstName("Fred")
            .withSsn("123XS1")
            .build();
    }
}

الخاتمة: تحقيق التوازن

إدارة وسائط المنشئين بحكمة أمر بالغ الأهمية لبناء شفرة قابلة للصيانة وسهلة القراءة. من خلال استخدام أنماط مثل البناء والواجهة السلسة، يمكن للمطورين تقليل التعقيد في منشئيهم وتجنب مخاطر وجود العديد من المعلمات.

في المرة القادمة، عندما تواجه حقولاً مطلوبة متعددة، اعتبر تنفيذ أحد هذه الأنماط. ستكون شيفرتك أكثر نظافة وستكون أكثر متعة في العمل بها.