JavaRush /جاوا بلاگ /Random-UR /جاوا میں کلاس ڈیزائن (SOLID) کے پانچ بنیادی اصول
Ve4niY
سطح

جاوا میں کلاس ڈیزائن (SOLID) کے پانچ بنیادی اصول

گروپ میں شائع ہوا۔
کلاسز وہ بلاکس ہیں جہاں سے ایپلیکیشن بنائی جاتی ہے۔ جیسے کسی عمارت کی اینٹ۔ ناقص تحریری کلاسیں ایک دن مسائل کا سبب بن سکتی ہیں۔ جاوا میں کلاس ڈیزائن (SOLID) کے پانچ بنیادی اصول - 1یہ سمجھنے کے لیے کہ آیا کوئی کلاس صحیح لکھی گئی ہے، آپ "معیار کے معیارات" کو چیک کر سکتے ہیں۔ جاوا میں، یہ نام نہاد SOLID اصول ہیں۔ آئیے ان کے بارے میں بات کرتے ہیں۔

جاوا میں ٹھوس اصول

SOLID ایک مخفف ہے جو OOP اور ڈیزائن کے پہلے پانچ اصولوں کے بڑے حروف سے بنا ہے۔ یہ اصول 2000 کی دہائی کے اوائل میں رابرٹ مارٹن نے ایجاد کیے تھے، اور مخفف بعد میں مائیکل فیدرز نے وضع کیا تھا۔ یہاں یہ ہے کہ ٹھوس اصولوں میں کیا شامل ہے:
  1. واحد ذمہ داری کا اصول۔
  2. کھلا بند اصول۔
  3. لیسکوف کے متبادل اصول۔
  4. انٹرفیس علیحدگی کا اصول۔
  5. انحصار الٹا اصول۔

واحد ذمہ داری کا اصول (SRP)

یہ اصول بتاتا ہے کہ کسی بھی طبقے کو تبدیل کرنے کی ایک سے زیادہ وجہ نہیں ہونی چاہیے۔ ہر شے کی ایک ذمہ داری ہوتی ہے، جو مکمل طور پر ایک کلاس میں شامل ہوتی ہے۔ تمام طبقاتی خدمات کا مقصد اس ذمہ داری کو یقینی بنانا ہے۔ اگر ضروری ہو تو ایسی کلاسوں کو تبدیل کرنا ہمیشہ آسان ہوگا، کیونکہ یہ واضح ہے کہ کلاس کس چیز کے لیے ذمہ دار ہے اور کیا نہیں۔ یعنی، تبدیلیاں کرنا ممکن ہو گا اور اس کے نتائج سے خوفزدہ نہیں ہوں گے - دیگر اشیاء پر اثرات۔ اور اس طرح کے کوڈ کو جانچنا بہت آسان ہے، کیوں کہ آپ ایک فنکشنلٹی کو ٹیسٹ کے ساتھ دوسرے تمام سے الگ تھلگ کرتے ہوئے کور کرتے ہیں۔ ایک ماڈیول کا تصور کریں جو آرڈرز پر کارروائی کرتا ہے۔ اگر آرڈر صحیح طریقے سے بنتا ہے، تو یہ اسے ڈیٹا بیس میں محفوظ کرتا ہے اور آرڈر کی تصدیق کے لیے ای میل بھیجتا ہے:
public class OrderProcessor {

    public void process(Order order){
        if (order.isValid() && save(order)) {
            sendConfirmationEmail(order);
        }
    }

    private boolean save(Order order) {
        MySqlConnection connection = new MySqlConnection("database.url");
        // save the order to the database

        return true;
    }

    private void sendConfirmationEmail(Order order) {
        String name = order.getCustomerName();
        String email = order.getCustomerEmail();

        // Sending a letter to the client
    }
}
اس طرح کا ماڈیول تین وجوہات کی بنا پر تبدیل ہو سکتا ہے۔ اول، آرڈر پروسیسنگ کی منطق مختلف ہو سکتی ہے، دوم، اسے محفوظ کرنے کا طریقہ (ڈیٹا بیس کی قسم)، سوم، تصدیقی خط بھیجنے کا طریقہ (مثال کے طور پر، ای میل کے بجائے آپ کو SMS بھیجنے کی ضرورت ہے)۔ واحد ذمہ داری کے اصول کا مطلب ہے کہ اس مسئلے کے تین پہلو دراصل تین مختلف ذمہ داریاں ہیں۔ اس کا مطلب ہے کہ وہ مختلف کلاسوں یا ماڈیولز میں ہونے چاہئیں۔ متعدد اداروں کو یکجا کرنا جو مختلف اوقات میں اور مختلف وجوہات کی بناء پر تبدیل ہو سکتے ہیں ایک برا ڈیزائن فیصلہ سمجھا جاتا ہے۔ ماڈیول کو تین الگ الگ حصوں میں تقسیم کرنا بہت بہتر ہے، جن میں سے ہر ایک ایک فنکشن انجام دے گا:
public class MySQLOrderRepository {
    public boolean save(Order order) {
        MySqlConnection connection = new MySqlConnection("database.url");
        // save the order to the database

        return true;
    }
}

public class ConfirmationEmailSender {
    public void sendConfirmationEmail(Order order) {
        String name = order.getCustomerName();
        String email = order.getCustomerEmail();

        // Sending a letter to the client
    }
}

public class OrderProcessor {
    public void process(Order order){

        MySQLOrderRepository repository = new MySQLOrderRepository();
        ConfirmationEmailSender mailSender = new ConfirmationEmailSender();

        if (order.isValid() && repository.save(order)) {
            mailSender.sendConfirmationEmail(order);
        }
    }

}

کھلا/بند اصول (او سی پی)

اس اصول کو اختصار کے ساتھ اس طرح بیان کیا گیا ہے: سافٹ ویئر کے اداروں (کلاسز، ماڈیولز، فنکشنز، وغیرہ) کو توسیع کے لیے کھلا ہونا چاہیے، لیکن تبدیلی کے لیے بند ہونا چاہیے ۔ اس کا مطلب یہ ہے کہ کلاس میں جسمانی تبدیلیاں کیے بغیر کسی طبقے کے بیرونی رویے کو تبدیل کرنا ممکن ہونا چاہیے۔ اس اصول کی پیروی کرتے ہوئے، کلاسز تیار کی جاتی ہیں تاکہ کلاس کو مخصوص ایپلیکیشن کی شرائط کے مطابق ایڈجسٹ کرنے کے لیے، اسے بڑھانا اور کچھ فنکشنز کی نئی وضاحت کرنا کافی ہے۔ لہذا، نظام کو لچکدار ہونا چاہیے، ماخذ کوڈ کو تبدیل کیے بغیر متغیر حالات میں کام کرنے کے قابل ہونا چاہیے۔ ہمارے آرڈر کی مثال کو جاری رکھتے ہوئے، ہم کہتے ہیں کہ ہمیں آرڈر پر کارروائی سے پہلے اور تصدیقی ای میل بھیجے جانے کے بعد کچھ کارروائیاں کرنے کی ضرورت ہے۔ کلاس کو تبدیل کرنے کے بجائے OrderProcessor، ہم اسے بڑھا دیں گے اور OCP اصول کی خلاف ورزی کیے بغیر مسئلے کا حل حاصل کریں گے:
public class OrderProcessorWithPreAndPostProcessing extends OrderProcessor {

    @Override
    public void process(Order order) {
        beforeProcessing();
        super.process(order);
        afterProcessing();
    }

    private void beforeProcessing() {
        // Perform some actions before processing the order
    }

    private void afterProcessing() {
        // Perform some actions after order processing
    }
}

باربرا لیسکوف متبادل اصول (LSP)

یہ کھلے/بند اصول کی ایک تبدیلی ہے جس پر پہلے بات کی گئی ہے۔ اسے اس طرح بیان کیا جا سکتا ہے: کسی پروگرام میں موجود اشیاء کو پروگرام کی خصوصیات کو تبدیل کیے بغیر ان کے وارثوں سے تبدیل کیا جا سکتا ہے۔ اس کا مطلب یہ ہے کہ بیس کلاس کو بڑھا کر تیار کی گئی کلاس کو اپنے طریقوں کو اس طرح اوور رائڈ کرنا چاہیے جو کلائنٹ کے نقطہ نظر سے فعالیت کو نہ توڑے۔ یعنی، اگر کوئی ڈویلپر آپ کی کلاس بڑھاتا ہے اور اسے کسی ایپلیکیشن میں استعمال کرتا ہے، تو اسے اوور رائیڈڈ طریقوں کے متوقع رویے کو تبدیل نہیں کرنا چاہیے۔ ذیلی طبقات کو بنیادی طبقے کے طریقوں کو اس طرح اوور رائڈ کرنا چاہیے جو کلائنٹ کے نقطہ نظر سے فعالیت کو نہ توڑے۔ مندرجہ ذیل مثال کا استعمال کرتے ہوئے اس کا تفصیلی جائزہ لیا جا سکتا ہے۔ فرض کریں کہ ہمارے پاس ایک کلاس ہے جو آرڈر کی توثیق کے لیے ذمہ دار ہے اور چیک کرتی ہے کہ آیا آرڈر کی تمام اشیاء اسٹاک میں ہیں یا نہیں۔ اس کلاس کا ایک طریقہ ہے isValidجو صحیح یا غلط کو لوٹاتا ہے :
public class OrderStockValidator {

    public boolean isValid(Order order) {
        for (Item item : order.getItems()) {
            if (! item.isInStock()) {
                return false;
            }
        }

        return true;
    }
}
آئیے یہ بھی مان لیں کہ کچھ آرڈرز کو مختلف طریقے سے تصدیق کرنے کی ضرورت ہے: چیک کریں کہ آیا آرڈر میں موجود تمام سامان اسٹاک میں ہیں یا نہیں اور کیا تمام سامان پیک کیا گیا ہے۔ ایسا کرنے کے لیے، ہم نے کلاس کو OrderStockValidatorکلاس کے ساتھ بڑھایا OrderStockAndPackValidator:
public class OrderStockAndPackValidator extends OrderStockValidator {

    @Override
    public boolean isValid(Order order) {
        for (Item item : order.getItems()) {
            if ( !item.isInStock() || !item.isPacked() ){
                throw new IllegalStateException(
                     String.format("Order %d is not valid!", order.getId())
                );
            }
        }

        return true;
    }
}
تاہم، اس کلاس میں ہم نے LSP اصول کی خلاف ورزی کی، کیونکہ اگر آرڈر کی توثیق نہیں ہوتی ہے تو غلط واپس کرنے کے بجائے ، ہمارا طریقہ مستثنیٰ ہے IllegalStateException۔ اس کوڈ کے کلائنٹس اس کی توقع نہیں کرتے ہیں: وہ سچ یا غلط کی واپسی کی توقع کرتے ہیں ۔ یہ پروگرام میں غلطیوں کی قیادت کر سکتا ہے.

انٹرفیس سپلٹ پرنسپل (ISP)

درج ذیل بیان کی خصوصیت: کلائنٹس کو ان طریقوں کو نافذ کرنے پر مجبور نہیں کیا جانا چاہئے جو وہ استعمال نہیں کریں گے ۔ انٹرفیس علیحدگی کا اصول بتاتا ہے کہ جو انٹرفیس بہت "موٹے" ہیں ان کو چھوٹے اور زیادہ مخصوص میں تقسیم کرنے کی ضرورت ہے، تاکہ چھوٹے انٹرفیس کے کلائنٹس کو صرف اپنے کام کے لیے ضروری طریقوں کے بارے میں معلوم ہو۔ نتیجے کے طور پر، انٹرفیس کے طریقہ کار کو تبدیل کرتے وقت، جو کلائنٹ اس طریقہ کو استعمال نہیں کرتے انہیں تبدیل نہیں ہونا چاہیے۔ آئیے ایک مثال دیکھتے ہیں۔ ڈویلپر ایلکس نے "رپورٹ" انٹرفیس بنایا اور دو طریقے شامل کیے: generateExcel()اور generatedPdf(). اب کلائنٹ اے اس انٹرفیس کو استعمال کرنا چاہتا ہے، لیکن وہ صرف پی ڈی ایف رپورٹس استعمال کرنے کا ارادہ رکھتا ہے نہ کہ ایکسل۔ کیا وہ اس فعالیت سے مطمئن ہو گا؟ نہیں. اسے دو طریقے لاگو کرنے ہوں گے، جن میں سے ایک بڑی حد تک غیر ضروری ہے اور یہ صرف سافٹ ویئر ڈیزائنر ایلکس کی بدولت موجود ہے۔ کلائنٹ یا تو ایک مختلف انٹرفیس استعمال کرے گا یا ایکسل فیلڈ کو خالی چھوڑ دے گا۔ تو اس کا حل کیا ہے؟ یہ موجودہ انٹرفیس کو دو چھوٹے حصوں میں تقسیم کرنے پر مشتمل ہے۔ ایک پی ڈی ایف فارمیٹ میں رپورٹ ہے، دوسری ایکسل فارمیٹ میں رپورٹ ہے۔ اس سے صارف کو صرف وہی فنکشنلٹی استعمال کرنے کا موقع ملے گا جو اس کے لیے ضروری ہے۔

انحصار الٹا اصول (DIP)

جاوا میں اس ٹھوس اصول کو اس طرح بیان کیا گیا ہے: نظام کے اندر انحصار تجرید کی بنیاد پر بنایا گیا ہے ۔ اعلیٰ سطح کے ماڈیول نچلے درجے کے ماڈیولز سے آزاد ہیں۔ خلاصہ تفصیلات پر منحصر نہیں ہونا چاہئے۔ تفصیلات کا انحصار تجرید پر ہونا چاہیے۔ سافٹ ویئر کو ڈیزائن کرنے کی ضرورت ہے تاکہ مختلف ماڈیول خود مختار ہوں اور تجرید کا استعمال کرتے ہوئے ایک دوسرے سے جڑیں۔ اس اصول کا ایک کلاسک اطلاق بہار کا فریم ورک ہے۔ بہار کے فریم ورک کے اندر، تمام ماڈیولز کو الگ الگ اجزاء کے طور پر لاگو کیا جاتا ہے جو ایک ساتھ کام کر سکتے ہیں۔ وہ اتنے خود ساختہ ہیں کہ انہیں بہار کے فریم ورک کے علاوہ دوسرے سافٹ ویئر ماڈیولز میں بھی آسانی سے استعمال کیا جا سکتا ہے۔ یہ بند اور کھلے اصولوں کے انحصار کے ذریعے حاصل کیا جاتا ہے۔ تمام ماڈیولز صرف ایک تجرید تک رسائی فراہم کرتے ہیں جسے کسی دوسرے ماڈیول میں استعمال کیا جا سکتا ہے۔ آئیے اس کو ایک مثال سے ظاہر کرنے کی کوشش کرتے ہیں۔ واحد ذمہ داری کے اصول کے بارے میں بات کرتے ہوئے، ہم نے کچھ غور کیا OrderProcessor۔ آئیے اس کلاس کے کوڈ پر ایک اور نظر ڈالتے ہیں:
public class OrderProcessor {
    public void process(Order order){

        MySQLOrderRepository repository = new MySQLOrderRepository();
        ConfirmationEmailSender mailSender = new ConfirmationEmailSender();

        if (order.isValid() && repository.save(order)) {
            mailSender.sendConfirmationEmail(order);
        }
    }

}
اس مثال میں، ہمارا OrderProcessorانحصار دو مخصوص طبقوں MySQLOrderRepositoryاور ConfirmationEmailSender. ہم ان کلاسوں کے لیے کوڈ بھی پیش کرتے ہیں:
public class MySQLOrderRepository {
    public boolean save(Order order) {
        MySqlConnection connection = new MySqlConnection("database.url");
        // save the order to the database

        return true;
    }
}

public class ConfirmationEmailSender {
    public void sendConfirmationEmail(Order order) {
        String name = order.getCustomerName();
        String email = order.getCustomerEmail();

        // Sending a letter to the client
    }
}
یہ کلاسیں تجرید کہلانے سے بہت دور ہیں۔ اور DIP اصول کے نقطہ نظر سے، کچھ تجریدات بنا کر شروع کرنا زیادہ درست ہوگا جو ہمیں مخصوص نفاذ کے بجائے مستقبل میں ان کے ساتھ کام کرنے کی اجازت دیں گے۔ آئیے دو انٹرفیس بنائیں MailSenderاور OrderRepository، جو ہمارے تجرید بن جائیں گے:
public interface MailSender {
    void sendConfirmationEmail(Order order);
}

public interface OrderRepository {
    boolean save(Order order);
}
اب آئیے ان انٹرفیس کو ان کلاسوں میں لاگو کریں جو اس کے لیے پہلے سے تیار ہیں:
public class ConfirmationEmailSender implements MailSender {

    @Override
    public void sendConfirmationEmail(Order order) {
        String name = order.getCustomerName();
        String email = order.getCustomerEmail();

        // Sending a letter to the client
    }

}

public class MySQLOrderRepository implements OrderRepository {

    @Override
    public boolean save(Order order) {
        MySqlConnection connection = new MySqlConnection("database.url");
        // save the order to the database

        return true;
    }
}
ہم نے تیاری کا کام کیا ہے تاکہ ہماری کلاس کا OrderProcessorانحصار ٹھوس تفصیلات پر نہیں بلکہ تجرید پر ہو۔ آئیے کلاس کنسٹرکٹر میں اپنے انحصار کو متعارف کروا کر اس میں تبدیلیاں کریں:
public class OrderProcessor {

    private MailSender mailSender;
    private OrderRepository repository;

    public OrderProcessor(MailSender mailSender, OrderRepository repository) {
        this.mailSender = mailSender;
        this.repository = repository;
    }

    public void process(Order order){
        if (order.isValid() && repository.save(order)) {
            mailSender.sendConfirmationEmail(order);
        }
    }
}
ہماری کلاس اب ٹھوس نفاذ کے بجائے تجرید پر منحصر ہے۔ مثال کے بننے کے وقت آپ مطلوبہ انحصار انجیکشن لگا کر آسانی سے اس کے رویے کو تبدیل کر سکتے ہیں OrderProcessor۔ ہم نے جاوا میں SOLID - ڈیزائن کے اصولوں کو دیکھا۔ عام طور پر OOP کے بارے میں مزید، اس پروگرامنگ زبان کی بنیادی باتیں - بورنگ نہیں اور سینکڑوں گھنٹے کی مشق کے ساتھ - JavaRush کورس میں۔ کچھ مسائل کو حل کرنے کا وقت :) جاوا میں کلاس ڈیزائن (SOLID) کے پانچ بنیادی اصول - 2
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION