"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > التنمية الموجهة الصلبة

التنمية الموجهة الصلبة

تم النشر بتاريخ 2024-08-06
تصفح:913

Desenvolvimento Orientado a SOLID

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

1. مبدأ المسؤولية الفردية

ينص مبدأ المسؤولية الفردية (SRP) على أن الفصل يجب أن يكون لديه سبب واحد فقط للتغيير، أي أنه يجب أن يكون لديه مسؤولية واحدة داخل النظام.

// Antes de aplicar o SRP
class ProductService {
    public void saveProduct(Product product) {
        // Lógica para salvar o produto no banco de dados
    }

    public void sendEmail(Product product) {
        // Lógica para enviar um email sobre o produto
    }
}
// Após aplicar o SRP
class ProductService {
    public void saveProduct(Product product) {
        // Lógica para salvar o produto no banco de dados
    }
}

class EmailService {
    public void sendEmail(Product product) {
        // Lógica para enviar um email sobre o produto
    }
}

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

2. مبدأ مفتوح/مغلق

يقترح المبدأ المفتوح/المغلق (OCP) أن الكيانات البرمجية (الفئات، الوحدات، الوظائف، إلخ) يجب أن تكون مفتوحة للتوسيع، ولكنها مغلقة للتعديل. ويتم تحقيق ذلك من خلال استخدام التجريد والميراث.

// Exemplo inicial violando o OCP
class AreaCalculator {
    public double calculateArea(Rectangle[] rectangles) {
        double area = 0;
        for (Rectangle rectangle : rectangles) {
            area  = rectangle.width * rectangle.height;
        }
        return area;
    }
}
// Exemplo após aplicar o OCP
interface Forma {
    double calculateArea();
}
class Rectangle implements Forma {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double calculateArea() {
        return width * height;
    }
}

class AreaCalculator {
    public double calculateArea(Forma [] formas) {
        double area = 0;
        for (Forma formas: formas) {
            area  = forma.calculateArea();
        }
        return area;
    }
}

في هذا المثال الثاني، كانت فئة AreaCalculator في البداية تعتمد بشكل مباشر على فئة Rectangle. هذا يعني أنك إذا أردت إضافة نوع آخر من الأشكال، مثل دائرة أو مثلث، فستحتاج إلى تعديل فئة AreaCalculator، وبالتالي انتهاك OCP. مع إنشاء واجهة الشكل، أصبحت فئة AreaCalculator قادرة على استقبال أشكال هندسية جديدة دون تعديل الكود الموجود.

3. مبدأ استبدال ليسكوف

ينص مبدأ استبدال ليسكوف (LSP) على أن كائنات الفئة الفائقة يجب أن تكون قابلة للاستبدال بكائنات من فئاتها الفرعية دون التأثير على سلامة النظام. بمعنى آخر، يجب أن يكون سلوك الفئات الفرعية متسقًا مع سلوك الفئات الفائقة.

// Classe base
class Bird {
    public void fly() {
        // Método padrão que imprime "Flying"
        System.out.println("Flying");
    }
}

// Classe derivada que viola o LSP
class Duck extends Bird {
    @Override
    public void fly() {
        // Sobrescrita que imprime "Ducks cannot fly"
        System.out.println("Ducks cannot fly");
    }
}

المشكلة: تتجاوز فئة Duck طريقة fly () لطباعة "البط لا يستطيع الطيران"، وبالتالي تغيير السلوك الافتراضي المحدد في فئة الطيور الأساسية، وهو أن جميع الطيور تطير ("تحلق"). هذا ينتهك LSP لأن أي كود يتوقع أن يطير كائن Bird أو فئاته الفرعية لن يعمل بشكل صحيح مع البطة، والتي نعلم بالفعل أنها لا تطير.

// Classe derivada que respeita o LSP
interface Bird {
    void fly();
}
class Eagle implements Bird {
    @Override
    public void fly() {
        System.out.println("Flying like an Eagle");
    }
}
class Duck implements Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Ducks cannot fly");
    }
}

مع هذا النهج، يمكن استبدال Eagle وDuck حيث يُتوقع وجود طائر، دون كسر التوقعات التي حددتها واجهة Bird. يشير الاستثناء الذي طرحه Duck بوضوح إلى أن البط لا يطير، دون تعديل سلوك الطبقة المتفوقة بطريقة قد تسبب مشاكل غير متوقعة في الكود.

4. مبدأ فصل الواجهة

يقترح مبدأ فصل الواجهة (ISP) أن واجهات الفصل يجب أن تكون خاصة بالعملاء الذين يستخدمونها. يؤدي هذا إلى تجنب الواجهات "السمينة" التي تتطلب تنفيذ أساليب لا يستخدمها العملاء.

// Exemplo antes de aplicar o ISP
interface Worker {
    void work();
    void eat();
    void sleep();
}

class Programmer implements Worker {
    @Override
    public void work() {
        // Lógica específica para programar
    }
    @Override
    public void eat() {
        // Lógica para comer
    }
    @Override
    public void sleep() {
        // Lógica para dormir
    }
}
// Exemplo após aplicar o ISP
interface Worker {
    void work();
}
interface Eater {
    void eat();
}
interface Sleeper {
    void sleep();
}
class Programmer implements Worker, Eater, Sleeper {
    @Override
    public void work() {
        // Lógica específica para programar
    }
    @Override
    public void eat() {
        // Lógica para comer
    }
    @Override
    public void sleep() {
        // Lógica para dormir
    }
}

في المثال، قمنا بتقسيم واجهة العامل إلى واجهات أصغر (العمل، تناول الطعام، النوم) للتأكد من أن الفئات التي تنفذها لديها فقط الأساليب التي تحتاجها. وهذا يمنع الفئات من الاضطرار إلى تنفيذ أساليب غير ذات صلة بها، مما يحسن وضوح التعليمات البرمجية وتماسكها.

5. مبدأ انعكاس التبعية

يقترح مبدأ انعكاس التبعية (DIP) أن الوحدات عالية المستوى (مثل فئات الأعمال أو التطبيقات، التي تنفذ قواعد العمل الرئيسية) لا ينبغي أن تعتمد على وحدات منخفضة المستوى (فئات البنية التحتية، مثل الوصول إلى البيانات الخارجية و الخدمات التي تدعم العمليات رفيعة المستوى). كلاهما يجب أن يعتمد على التجريدات.

// Exemplo antes de aplicar o DIP
class BackendDeveloper {
    public void writeJava() {
        // Lógica para escrever em Java
    }
}
class Project {
    private BackendDeveloper developer;

    public Project() {
        this.developer = new BackendDeveloper();
    }
    public void implement() {
        developer.writeJava();
    }
}
// Exemplo após aplicar o DIP
interface Developer {
    void develop();
}
class BackendDeveloper implements Developer {
    @Override
    public void develop() {
        // Lógica para escrever em Java
    }
}
class Project {
    private Developer developer;

    public Project(Developer developer) {
        this.developer = developer;
    }
    public void implement() {
        developer.develop();
    }
}

تعتمد فئة المشروع الآن على التجريد (المطور) بدلاً من التنفيذ الملموس (BackendDeveloper). يسمح هذا بدمج أنواع مختلفة من المطورين (مثل FrontendDeveloper وMobileDeveloper) بسهولة في فئة Project دون تعديل الكود الخاص بها.

خاتمة

إن اعتماد مبادئ SOLID لا يؤدي فقط إلى رفع جودة التعليمات البرمجية الخاصة بك، بل يعزز أيضًا مهاراتك التقنية، ويزيد من كفاءة عملك، ويعزز مسارك المهني كمطور برامج.

بيان الافراج تم نشر هذه المقالة على: https://dev.to/womakerscode/desenvolvimento-orientado-a-solid-al7?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] لحذفه
أحدث البرنامج التعليمي أكثر>

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

Copyright© 2022 湘ICP备2022001581号-3