Table of Contents
وفي مجال البرمجة الموجهة نحو الجسم، فإن نظم البناء التي تتسم بالقوة والقدرة على التكيف هي التحدي الدائم، ومن بين المبادئ الأساسية التي توجه المطورين نحو هذا الهدف مبدأ " ليزكوف " الذي لا يُعتبر " مبدئيا " ، الذي يُعتبر بمثابة " نموذج " لا يُحترم فيه إلا " ، هو المبدأ الذي يُعتبر ضمنا " ، الذي يُعدّ نموذجا " " " " ، الذي يُحترم فيه " ، ويُ " ، ويُ " ، ويُ " ، ويُعتبر " ، ويُعتبر أن " " " " " " " " " " " ، ويُ " ، ويُ " ، ويُعتبر " المبادئ الأساسية " المبادئ الأساسية " المبادئ الأساسية " ، ويُستشفعَ " ، ويُستعانى " ، ويُ " ، ويُستعانى " ، ويُ "
ما هو مبدأ ليسكوف البديل؟
وينص مبدأ ليزكوف البديل على أن الأشياء ذات الدرجة الخارقة ينبغي أن تحل محلها أشياء من أفرقته الفرعية دون أن تؤثر على صحة البرنامج، وبعبارة أخرى، إذا كانت وظيفة أو طريقة مصممة للعمل بنوع أساس، فإنه ينبغي لها أيضا أن تعمل بأي نوع مستمد دون أن تتطلب تعديلا أو تنتج آثارا جانبية غير متوقعة.
أما نظام الأفضليات المعينة فهو أساسي بشأن الاستعاضة عن السلوكيات، إذ لا يكفي أن يكون للفئة الفرعية نفس التوقيعات التي يوقعها والدها (التوافق المنهجي)؛ كما يجب على الفئة الفرعية أن تحترم نوايا وقيود فئة الوالدين، وإذا غيرت الدرجة الفرعية السلوك الأساسي لأسلوب الوالدين - مثلا، عن طريق وضع استثناء لا يلقيه الوالد، أو إعادة قيمة تنتهك عقد الوالد، أو أنها لا تنتهك شروطا بديلة أشد صرامة -
التعريف الرسمي والمعلومات الأساسية
وفيما يلي التعريف الرسمي الأصلي لباربرا ليزكوف:
" إذا كان لكل جسم من المواد o1 من النوع S، هناك موضوع يُطلق عليه: ](2) من النوع T الذي يكون محل سلوك P بالنسبة لجميع البرامج المحددة من حيث T، إذا كان هذا التصرف غير متغير عندما يكون (1))
ويؤكد هذا التعريف أن النموذج الفرعي )س( يجب أن يكون بديلا لنموذجه الأعلى في أي برنامج )م( مكتوب من حيث T.. ولا يمكن الحفاظ على السلوك الذي يمكن ملاحظته في البرنامج، وهذا المفهوم يرتبط ارتباطا وثيقا بمنهجية التصميم حسب العقد، التي يقودها شركة بيرتراند ميير، حيث تكون لكل طريقة شروط مسبقة واضحة )ما يجب أن يكون صحيحا قبل بدء العمل( وما بعده.
For further reading, see the original Liskov and Wing paper] that formalized the concept. Additionally, the ]Wikipedia article on LSP] provides a good overview.
لماذا (لوس أنجلوس) مهم؟
ويجلب الالتزام بنظام الأفضليات المعينة عدة فوائد حاسمة للنظم ذات الوجهة الموضوعية:
- ]Reliability and Correctness:] Code that uses a base type can trust that any subclass will behave according to the base type’s contract. This prevents subtle fines that occur when a subclass introduces expected behavior.
- Polymorphism:] Polymorphism is the ability to treat objects of different classes through a common interface. Without LSP, polymorphism becomes dangerous because substituting a subclass may produce incorrect results. LSP ensures that polymorphic code works as intended.
- Maintainability and Extensibility:] When LSP violations are avoided, added new subclasses does’t require modifying existing code that depends on the base type. This aligns with the Open/Closed Principle (OCP) — software entities should be open for extension but closed for modification.
- testingability:] Unit tests written against a base class can be reused to validate subclasses. If a subclass violates LSP, those tests will fail, revealing the inconsistency early.
وليس نظام الأفضليات المعينة مفهوما أكاديمي فحسب، بل ينطوي على آثار عملية مباشرة، ففي نظام تجهيز المدفوعات مثلا، إذا كان لديك طبقة أساس ] ذات طريقة ، تتوقعون من جميع الفئات الفرعية (مثلا، ]، ) تجهيز المدفوعات دون أخطاء أو آثار جانبية لا يمكن أن تؤديها طبقة الأساس.
الانتهاكات المشتركة لمبدأ ليسكوف
والاعتراف بانتهاكات نظام الأفضليات المعمم هو الخطوة الأولى نحو إصلاحها، وهنا بعض الأنماط النموذجية التي تكسر المبدأ:
تعزيز الشروط المسبقة
وإذا كانت طريقة طبقة الأساس تتوقع أن يكون البارامترات غير المبردة، فإضافة شرط في الدرجة الفرعية بأن يكون الطوروغ إيجابيا (بينما يقبل طبقة القاعدة أي ثلاجة) يعزز الشرط المسبق، فالوكلاء الذين ينتقلون إلى درجة الأساس سيفشلون الآن في الدرجة الفرعية. ]
// Base class
class UserService {
public void assignRole(int userId) { ... }
}
// Subclass violation
class AdminService extends UserService {
@Override
public void assignRole(int userId) {
if (userId <= 0) throw new IllegalArgumentException("Invalid ID");
...
}
}
وضع شروط بريدية محسنة
وإذا كان لفئة الأساس قيمة عائدة معينة أو أثر جانبي، فإن درجة فرعية تقلل من ذلك الضمان تنتهك نظام الأفضليات المعمم، فعلى سبيل المثال، قد تعود دائماً إلى خط غير قائم؛ ودرجة فرعية تعود ] في بعض الحالات تضعف شرط ما بعد الولادة.
إسقاط الاستثناءات الجديدة
وينبغي ألا تُلقي الفئات الفرعية استثناءات من أن فئة القاعدة لا تُلقي بها (ما لم تكن تلك الاستثناءات هي فئات فرعية من الاستثناءات مسموح بها بالفعل) وإذا لم يلحق زبائن فئة القاعدة إلا ، ويرمي طبقة فرعية ]، فإن الإحلال سيتسبب في حدوث تحطمات غير متوقعة.
طرق إزالة أو التغلب على هذه الأساليب التي ينبغي أن تكون مدمجة
وإذا تجاوز طبقة فرعية طريقة لفعل أي شيء (جسد فارغ) أو رمي ، فإن ذلك يشكل انتهاكا واضحا، ولا تتصرف الدرجة الفرعية كما هو مقصود من الدرجة الأساسية.
نموذج كلاسيكي: Rectangle, Square, and the Area Trap
The most cited example of LSP violation involves geometric shapes. Many textbooks start with a class that has and ] methods, and then create a ] subclass that overrides these to enforce width altitude. Here’s the problem:
// Base class
class Rectangle {
protected int width, height;
public void setWidth(int w) { width = w; }
public void setHeight(int h) { height = h; }
public int getArea() { return width * height; }
}
// Subclass violation
class Square extends Rectangle {
@Override
public void setWidth(int w) {
width = height = w;
}
@Override
public void setHeight(int h) {
width = height = h;
}
}
الآن النظر في وظيفة تعمل مع :
void resize(Rectangle r) {
r.setWidth(5);
r.setHeight(10);
assert r.getArea() == 50; // Expect 50
}
وعندما يمر ، تحدد طريقة ] الاستعارة إلى 5 ثم ارتفاعها إلى 10 - ولكن المنطقة المربعة تهيأ على 10 أيضا، وهكذا ينتهي مربع مع الاستعارة = 10، ارتفاع = 10، منطقة = 100.
The fix:] Avoid inheriting from . instead, design an abstract ] with a common ]]] and have both and
النموذج العالمي الحقيقي: تكامل بوابة الدفع
تخيل نظام التجارة الإلكترونية مع طبقة أساس :
abstract class PaymentGateway {
public abstract void charge(double amount);
public void refund(double amount) { /* default implementation */ }
}
وتشمل هذه الفئات الفرعية [[() و.() ويمكن أن تُسمي العمليات المدفوعات ثم .() يحدث انتهاك إذا تجاوز ] لفرض استثناء لأن نظام الإبلاغ الموحد الخاص بمدفوعات المعاشات التقاعدية يتطلب مبلغاً من نوع ID.
How to fix:] either (a) ensure the base class’s contract includes the possibility that might not be supported (e.g. make it return a success boolean or declare a checkfund exception), or (b) redesign the hierarchy so that not all gateways support refunds. For example, introduce an interface
How to follow the Liskov Substitution Principle in Practice
ويتطلب تنفيذ نظام الأفضليات المعمم الانضباط في التصميم والاختبار، وهنا مبادئ توجيهية قابلة للتنفيذ:
- Design by Contract:] clearly specify preconditions, postconditions, and invariants for base class methods. Document what each method expects and guarantees. then ensure every subclass complies. Tools like Contracts in.NET or JML for Java can help enforce these rules.
- Favor Interfaces over Abstract Classes:] Interfaces define a contract without implementation details. They are naturally aligned with LSP because any implementing class must fulfill the entire interface. With abstract classes, it’s easier to introduce accidentally dependencies.
- ]Use Composition Over Inheritance: When a subclass would need to override behavior to the point of breaking the base contract, it’s often better to use composition. For example, instead of inheriting from , have a
- testing for substitutability:] Write parameterized tests that execute the same scenarios against both base and derived types. If a test passes with the base type but fails with a derived type, you have an LSP violation and this practice is especially powerful when using test doubles.
- Check for Covariant Return Types:] Some languages allow covariant return types (e.g., a subclass method can return a more specific type than the base). This is fine as long as it does not change the postcondition. Ensure the returned object still satisfyisfies all expectations of the base type’s return value.
- Avoid Overriding Concrete Methods Indiscriminately:] If you feel the need to override a concrete method in a subclass, question whether inheritance is the right tool. may the base class was too concrete. Make the method abstract or virtual only when you intend for subclasses to change behavior in a controlled way.
LSP and the Other SOLID Principles
ويرتبط نظام الأفضليات المعينة ارتباطاً وثيقاً بالمبادئ الأخرى المتعلقة بمكافحة شغب الأطفال، ولا سيما المبدأ المفتوح/المغلق ومبدأ تحويل المعالين:
- LSP و OCP:] OCP states that classes should be open for extension but closed for modification. LSP ensures that extensions (subclasses) do not break the existing code that uses the base type. Without LSP, add a new subclass would require modifying the client code to handle the new behavior, violating OCP.
- LSP وDIP:] DIP advises depending on abstractions, not concretions. LSP is essential here because the abstraction (interface or base class) must be stable and reliable. If subclasses violate LSP, the abstraction is no longer a trustworthy dependency, and the system becomes fragile.
- LSP and Interface Segregation (ISP):] ISP encourages small, focused interfaces. This naturally supports LSP because a small interface defines a tight contract that is easier to honour. A class that implements an oversized interface may struggle to fulfill all parts, leading to violations like meeting .
For a comprehensive overview of the SOLID principles, check out ]Wikipedia’s SOLID article].
خاتمة
إن مبدأ ليزكوف البديل أكثر بكثير من مجرد لطيف نظري؛ فهو أداة عملية لبناء نظم ذات وجهة موضوعية آمنة للتمديد والسهلة الصيانة، وبضمان التصرفات التي تُستبدل في صفوف والديهم، يمكن للمطورين أن يعتمدوا على تعددية المورفات دون خوف من الحشرات الخفية، ويشجع المبدأ على التفكير بعناية في التسلسل الهرمي للفصل، مما يؤدي إلى تصميمات واضحة.
تذكر أن انتهاكات نظام الأفضليات المعمم كثيرا ما تبدو كتناقضات طفيفة في السلوك: أي طريقة تُلقي استثناء غير متوقع، أو طريقة لا تفعل شيئا صامتا، أو طريقة تُغير الدولة بطريقة لا يُقصد بها قط طبقة القاعدة، وبوضع هذه الأعلام الحمراء، وبتطبيق المبادئ التوجيهية التي نوقشت أعلاه، يمكن أن تخلق هياكل هرمية تصمد أمام اختبار الزمن.
المراجع الخارجية المستخدمة في هذه المادة: