خطأ قاتل في برمجة Back End وحله الاحترافي

x32x01
  • بواسطة x32x01 ||
  • #1
كتير من مطوري Back-End بيقعوا في نفس الغلطة أثناء كتابة Business Logic، خصوصًا لما بيكون عندهم شوية شروط لازم تتحقق قبل تنفيذ عملية معينة.

خلينا نفترض مثال بسيط في نظام بنكي:
1️⃣ لو الشخص عنده حساب في البنك
2️⃣ لو الحساب Active
3️⃣ لو نوع الحساب جاري أو توفير
4️⃣ لو الحساب فيه رصيد كافي
لو كل الشروط دي اتحققت… نقدر نبدأ عملية السحب.

السيناريو ده طبيعي جدًا في أي نظام فيه Validation أو Business Rules.
لكن المشكلة بتبدأ من طريقة كتابة الكود 👀

المشكلة: استخدام Nested If Conditions بكثرة ⚠️​

كتير من المبرمجين بيكتبوا الكود بالشكل ده:
Java:
if (hasBankAccount(user)) {
    if (isAccountActive(account)) {
        if (isAccountTypeValid(account)) {
            if (hasBalance(account)) {
                withdraw(account);
            }
        }
    }
}
في البداية الكود ممكن يبان بسيط…
لكن مع الوقت ومع زيادة الشروط، الكود بيتحول لشكل السهم 👇
⚠️ وده اللي معروف باسم Arrow Anti-Pattern

المشكلة هنا إن:
  • الكود بيبقى صعب القراءة
  • Flow البرنامج معقد
  • أي مطور يجي يشتغل بعدك هيعاني معاه 😅
  • بيكسر مبادئ SOLID Principles
خصوصًا مبدأين مهمين:
Single Responsibility Principle (SRP)
الفانكشن بقت مسؤولة عن كل حاجة.
Open/Closed Principle (OCP)
لو البنك طلب شرط جديد… لازم تعدل الكود الأساسي.
وده ممكن يكسر Unit Tests الموجودة.



الحل الأول: تقسيم الكود إلى Methods​

بعض المطورين بيحاولوا يحلوا المشكلة عن طريق Refactoring.
يعني يعملوا Methods منفصلة:
Java:
if (!hasBankAccount(user)) return;
if (!isAccountActive(account)) return;
if (!isAccountTypeValid(account)) return;
if (!hasBalance(account)) return;

withdraw(account);
ده حل أفضل شوية 👌
لكن المشكلة لسه موجودة.

لأن الكلاسات مازالت معتمدة على بعض.
وده اسمه: ⚠ Tight Coupling



الحل الاحترافي: استخدام Chain of Responsibility Pattern 🔗​

الحل الأقوى في الحالة دي هو استخدام Design Pattern مشهور اسمه: Chain of Responsibility
الفكرة ببساطة إنك بتقسم كل شرط في Class مستقل.
وكل Class بيكون مسؤول عن خطوة واحدة فقط.
كل Handler بعد ما يخلص شغله يسلم المهمة للـ Handler اللي بعده.



مثال عملي على Chain of Responsibility 💻​

أولاً: تعريف الـ Interface​

Java:
public interface Handler {
    void setNext(Handler next);
    void handle(Account account);
}

Handler لفحص الحساب​

Java:
public class AccountExistsHandler implements Handler {

    private Handler next;

    public void setNext(Handler next) {
        this.next = next;
    }

    public void handle(Account account) {
        if(account == null) {
            throw new RuntimeException("Account not found");
        }

        if(next != null) {
            next.handle(account);
        }
    }
}

Handler لفحص الرصيد​

Java:
public class BalanceCheckHandler implements Handler {

    private Handler next;

    public void setNext(Handler next) {
        this.next = next;
    }

    public void handle(Account account) {

        if(account.getBalance() <= 0) {
            throw new RuntimeException("No balance");
        }

        if(next != null) {
            next.handle(account);
        }
    }
}

تشغيل السلسلة​

Java:
Handler h1 = new AccountExistsHandler();
Handler h2 = new BalanceCheckHandler();

h1.setNext(h2);

h1.handle(account);
هنا كل Handler بيعمل مهمة واحدة بس
وبعدها يسلم المهمة للي بعده.



يعني إيه Loose Coupling؟ 🤔​

المفهوم ببساطة: إن الكلاسات متبقاش لازقة في بعض.
خلينا نشرحها بمثال بسيط 👇
تخيل المشترك الكهربائي.
المشترك مش فارق معاه:
  • تلاجة
  • شاحن موبايل
  • كمبيوتر
المهم إن الفيشة متوافقة مع المدخل.
لو غيرت الجهاز… المشترك مش هيكسر.

نفس الفكرة لازم تكون في تصميم الكود.
كل Class يبقى مستقل.



دمج Chain of Responsibility مع Strategy Pattern 🧠​

في بعض الحالات بنستخدم معاه Pattern تاني اسمه: Strategy Pattern
مثلاً:
لو الحساب:
  • جاري
  • توفير
كل نوع ممكن يكون ليه طريقة مختلفة لحساب رسوم السحب.
بدل ما نعمل If Condition تاني…
نخلي النظام يختار Strategy المناسبة وقت التشغيل.



هل ده Over-Engineering؟ 🤨​

الإجابة تعتمد على حجم المشروع.
لو المشروع:
✔ صغير
✔ Prototype
✔ مش هيكبر​
ممكن الحل البسيط يكفي.
لكن لو النظام:
  • نظام بنكي
  • Enterprise System
  • Business Logic بيتغير كتير
فلازم تستخدم Design Patterns زي:
  • Chain of Responsibility
  • Strategy Pattern
علشان الكود يفضل قابل للتطوير والصيانة.



الخلاصة 💡​

أكبر مشكلة بتقع فيها مشاريع Back-End هي:
Nested If Conditions
Arrow Anti-Pattern
Tight Coupling
والحل الاحترافي بيكون باستخدام:
Chain of Responsibility Pattern
Strategy Pattern
Loose Coupling Design
وده بيخلي الكود:
  • أسهل في القراءة
  • أسهل في الصيانة
  • قابل للتوسع بسهولة
وده الفرق الحقيقي بين Junior Developer و Senior Engineer 😉
 

المواضيع ذات الصلة

x32x01
الردود
0
المشاهدات
838
x32x01
x32x01
x32x01
الردود
0
المشاهدات
838
x32x01
x32x01
x32x01
الردود
0
المشاهدات
876
x32x01
x32x01
x32x01
الردود
0
المشاهدات
1K
x32x01
x32x01
x32x01
الردود
0
المشاهدات
941
x32x01
x32x01
الوسوم : الوسوم
back end business logic chain of responsibility clean code design patterns loose coupling refactoring الكود solid principles strategy pattern برمجة الخادم
الدخول أو التسجيل السريع
نسيت كلمة مرورك؟

آخر المشاركات

إحصائيات المنتدى
المواضيع
2,379
المشاركات
2,592
أعضاء أكتب كود
573
أخر عضو
x365
عودة
أعلى