తరగతులు అప్లికేషన్ల బిల్డింగ్ బ్లాక్స్. ఒక భవనంలో ఇటుకలు లాగా. పేలవంగా వ్రాసిన తరగతులు చివరికి సమస్యలను కలిగిస్తాయి.
తరగతి సరిగ్గా వ్రాయబడిందో లేదో అర్థం చేసుకోవడానికి, అది "నాణ్యత ప్రమాణాలు" ఎలా కొలుస్తుందో మీరు తనిఖీ చేయవచ్చు. జావాలో, ఇవి SOLID సూత్రాలు అని పిలవబడేవి మరియు మేము వాటి గురించి మాట్లాడబోతున్నాము.

జావాలో SOLID సూత్రాలు
SOLID అనేది OOP మరియు క్లాస్ డిజైన్ యొక్క మొదటి ఐదు సూత్రాల పెద్ద అక్షరాల నుండి ఏర్పడిన సంక్షిప్త రూపం. ఈ సూత్రాలు 2000ల ప్రారంభంలో రాబర్ట్ మార్టిన్చే వ్యక్తీకరించబడ్డాయి మరియు తరువాత మైఖేల్ ఫెదర్స్ ద్వారా సంక్షిప్తీకరణను ప్రవేశపెట్టారు. ఇక్కడ SOLID సూత్రాలు ఉన్నాయి:- ఒకే బాధ్యత సూత్రం
- క్లోజ్డ్ ప్రిన్సిపల్ తెరవండి
- లిస్కోవ్ ప్రత్యామ్నాయ సూత్రం
- ఇంటర్ఫేస్ సెగ్రిగేషన్ ప్రిన్సిపల్
- డిపెండెన్సీ ఇన్వర్షన్ ప్రిన్సిపల్
సింగిల్ రెస్పాన్సిబిలిటీ ప్రిన్సిపల్ (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 in the database
return true;
}
private void sendConfirmationEmail(Order order) {
String name = order.getCustomerName();
String email = order.getCustomerEmail();
// Send an email to the customer
}
}
ఈ మాడ్యూల్ మూడు కారణాల వల్ల మారవచ్చు. ముందుగా, ప్రాసెసింగ్ ఆర్డర్ల లాజిక్ మారవచ్చు. రెండవది, ఆర్డర్లను సేవ్ చేసే విధానం (డేటాబేస్ రకం) మారవచ్చు. మూడవది, నిర్ధారణ పంపబడే విధానం మారవచ్చు (ఉదాహరణకు, మనం ఇమెయిల్ కాకుండా వచన సందేశాన్ని పంపాలని అనుకుందాం). ఒకే బాధ్యత సూత్రం ఈ సమస్య యొక్క మూడు అంశాలు వాస్తవానికి మూడు వేర్వేరు బాధ్యతలు అని సూచిస్తుంది. అంటే అవి వేర్వేరు తరగతుల్లో లేదా మాడ్యూల్స్లో ఉండాలి. వేర్వేరు సమయాల్లో మరియు వివిధ కారణాల వల్ల మారగల అనేక ఎంటిటీలను కలపడం పేలవమైన డిజైన్ నిర్ణయంగా పరిగణించబడుతుంది. మాడ్యూల్ను మూడు వేర్వేరు మాడ్యూల్స్గా విభజించడం చాలా మంచిది, వీటిలో ప్రతి ఒక్కటి ఒకే ఫంక్షన్ను నిర్వహిస్తుంది:
public class MySQLOrderRepository {
public boolean save(Order order) {
MySqlConnection connection = new MySqlConnection("database.url");
// Save the order in the database
return true;
}
}
public class ConfirmationEmailSender {
public void sendConfirmationEmail(Order order) {
String name = order.getCustomerName();
String email = order.getCustomerEmail();
// Send an email to the customer
}
}
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);
}
}
}
ఓపెన్ క్లోజ్డ్ ప్రిన్సిపల్ (OCP)
ఈ సూత్రం క్రింది విధంగా వివరించబడింది: సాఫ్ట్వేర్ ఎంటిటీలు (క్లాస్లు, మాడ్యూల్స్, ఫంక్షన్లు మొదలైనవి) పొడిగింపు కోసం తెరవబడి ఉండాలి, కానీ సవరణ కోసం మూసివేయబడతాయి . క్లాస్ యొక్క ప్రస్తుత కోడ్కు మార్పులు చేయకుండానే తరగతి బాహ్య ప్రవర్తనను మార్చడం సాధ్యమవుతుందని దీని అర్థం. ఈ సూత్రం ప్రకారం, తరగతులు రూపొందించబడ్డాయి కాబట్టి నిర్దిష్ట పరిస్థితులకు సరిపోయేలా క్లాస్ను ట్వీక్ చేయడానికి దానిని పొడిగించడం మరియు కొన్ని ఫంక్షన్లను భర్తీ చేయడం అవసరం. సోర్స్ కోడ్ను మార్చకుండానే మారుతున్న పరిస్థితులలో పని చేయగల సామర్థ్యంతో సిస్టమ్ అనువైనదిగా ఉండాలి. ఆర్డర్ ప్రాసెసింగ్తో కూడిన మా ఉదాహరణను కొనసాగిస్తూ, ఆర్డర్ ప్రాసెస్ చేయడానికి ముందు అలాగే నిర్ధారణ ఇమెయిల్ పంపిన తర్వాత మేము కొన్ని చర్యలను చేయవలసి ఉందని అనుకుందాం. మార్చడానికి బదులుగాOrderProcessor
తరగతిలోనే, ఓపెన్ క్లోజ్డ్ ప్రిన్సిపల్ను ఉల్లంఘించకుండా మా లక్ష్యాన్ని సాధించడానికి మేము దానిని పొడిగిస్తాము:
public class OrderProcessorWithPreAndPostProcessing extends OrderProcessor {
@Override
public void process(Order order) {
beforeProcessing();
super.process(order);
afterProcessing();
}
private void beforeProcessing() {
// Take some action before processing the order
}
private void afterProcessing() {
// Take some action after processing the order
}
}
లిస్కోవ్ ప్రత్యామ్నాయ సూత్రం (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;
}
}
కానీ ఇక్కడ మేము Liskov ప్రత్యామ్నాయ సూత్రాన్ని ఉల్లంఘించాము, ఎందుకంటే ఆర్డర్ ధ్రువీకరణ విఫలమైతే తప్పుని తిరిగి ఇచ్చే బదులు , మా పద్ధతి ఒక త్రో చేస్తుంది IllegalStateException
. ఈ కోడ్ని ఉపయోగించే క్లయింట్లు దీన్ని ఆశించరు: వారు ఒప్పు లేదా తప్పుడు రిటర్న్ విలువను ఆశించారు . ఇది రన్టైమ్ ఎర్రర్లకు దారి తీస్తుంది.
ఇంటర్ఫేస్ సెగ్రిగేషన్ ప్రిన్సిపల్ (ISP)
ఈ సూత్రం కింది ప్రకటన ద్వారా వర్గీకరించబడుతుంది: క్లయింట్ వారు ఉపయోగించని పద్ధతులను అమలు చేయమని బలవంతం చేయకూడదు . ఇంటర్ఫేస్ విభజన సూత్రం అంటే చాలా "మందంగా" ఉండే ఇంటర్ఫేస్లను చిన్నవిగా, మరింత నిర్దిష్టంగా విభజించాలి, తద్వారా చిన్న ఇంటర్ఫేస్లను ఉపయోగించే క్లయింట్లు వారి పనికి అవసరమైన పద్ధతుల గురించి మాత్రమే తెలుసుకుంటారు. ఫలితంగా, ఇంటర్ఫేస్ పద్ధతి మారినప్పుడు, ఆ పద్ధతిని ఉపయోగించని క్లయింట్లు మారకూడదు. ఈ ఉదాహరణను పరిగణించండి: డెవలపర్ అయిన అలెక్స్ "రిపోర్ట్" ఇంటర్ఫేస్ను సృష్టించారు మరియు రెండు పద్ధతులను జోడించారు:generateExcel()
మరియుgeneratedPdf()
. ఇప్పుడు ఒక క్లయింట్ ఈ ఇంటర్ఫేస్ను ఉపయోగించాలనుకుంటున్నారు, కానీ నివేదికలను మాత్రమే PDF ఫార్మాట్లో ఉపయోగించాలనుకుంటున్నారు, Excelలో కాదు. ఈ కార్యాచరణ ఈ క్లయింట్ను సంతృప్తి పరుస్తుందా? లేదు. క్లయింట్ రెండు పద్ధతులను అమలు చేయాల్సి ఉంటుంది, వాటిలో ఒకటి పెద్దగా అవసరం లేదు మరియు సాఫ్ట్వేర్ను రూపొందించిన అలెక్స్కు మాత్రమే ధన్యవాదాలు. క్లయింట్ వేరే ఇంటర్ఫేస్ని ఉపయోగిస్తాడు లేదా Excel నివేదికల పద్ధతిలో ఏమీ చేయడు. కాబట్టి పరిష్కారం ఏమిటి? ఇది ఇప్పటికే ఉన్న ఇంటర్ఫేస్ను రెండు చిన్నవిగా విభజించడం. ఒకటి PDF నివేదికల కోసం, మరొకటి Excel నివేదికల కోసం. ఇది క్లయింట్లు వారికి అవసరమైన కార్యాచరణను మాత్రమే ఉపయోగించడానికి అనుమతిస్తుంది.
డిపెండెన్సీ ఇన్వర్షన్ ప్రిన్సిపల్ (డిఐపి)
జావాలో, ఈ SOLID సూత్రం క్రింది విధంగా వివరించబడింది: సిస్టమ్లోని డిపెండెన్సీలు సంగ్రహాల ఆధారంగా నిర్మించబడ్డాయి. ఉన్నత-స్థాయి మాడ్యూల్స్ దిగువ-స్థాయి మాడ్యూళ్లపై ఆధారపడవు. సంగ్రహణలు వివరాలపై ఆధారపడకూడదు. వివరాలు సారాంశాలపై ఆధారపడి ఉండాలి. వివిధ మాడ్యూల్స్ స్వీయ-నియంత్రణ మరియు సంగ్రహణ ద్వారా ఒకదానికొకటి కనెక్ట్ అయ్యేలా సాఫ్ట్వేర్ రూపకల్పన చేయాలి. ఈ సూత్రం యొక్క క్లాసిక్ అప్లికేషన్ స్ప్రింగ్ ఫ్రేమ్వర్క్. స్ప్రింగ్ ఫ్రేమ్వర్క్లో, అన్ని మాడ్యూల్స్ కలిసి పనిచేయగల ప్రత్యేక భాగాలుగా అమలు చేయబడతాయి. అవి చాలా స్వయంప్రతిపత్తి కలిగి ఉంటాయి, అవి స్ప్రింగ్ ఫ్రేమ్వర్క్ కాకుండా ప్రోగ్రామ్ మాడ్యూల్స్లో సులభంగా ఉపయోగించబడతాయి. క్లోజ్డ్ మరియు ఓపెన్ సూత్రాల ఆధారపడటం వలన ఇది సాధించబడుతుంది. అన్ని మాడ్యూల్లు సంగ్రహణకు మాత్రమే ప్రాప్యతను అందిస్తాయి, దీనిని మరొక మాడ్యూల్లో ఉపయోగించవచ్చు. ఒక ఉదాహరణను ఉపయోగించి దీనిని వివరించడానికి ప్రయత్నిద్దాం. ఒకే బాధ్యత సూత్రం గురించి మాట్లాడుతూ, మేము పరిగణించాము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 in the database
return true;
}
}
public class ConfirmationEmailSender {
public void sendConfirmationEmail(Order order) {
String name = order.getCustomerName();
String email = order.getCustomerEmail();
// Send an email to the customer
}
}
ఈ తరగతులు మనం అబ్స్ట్రాక్షన్స్ అని పిలిచే వాటికి దూరంగా ఉన్నాయి. మరియు డిపెండెన్సీ విలోమ సూత్రం యొక్క దృక్కోణం నుండి, నిర్దిష్ట అమలుల కంటే భవిష్యత్తులో మనం పని చేయగల కొన్ని సారాంశాలను సృష్టించడం ద్వారా ప్రారంభించడం మంచిది. రెండు ఇంటర్ఫేస్లను క్రియేట్ చేద్దాం: 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();
// Send an email to the customer
}
}
public class MySQLOrderRepository implements OrderRepository {
@Override
public boolean save(Order order) {
MySqlConnection connection = new MySqlConnection("database.url");
// Save the order in 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 గురించి మరియు జావా ప్రోగ్రామింగ్ యొక్క బేసిక్స్ గురించి మరింత తెలుసుకుంటారు — బోరింగ్ ఏమీ లేదు మరియు వందల గంటల ప్రాక్టీస్ —. కొన్ని పనులను పరిష్కరించే సమయం :)
GO TO FULL VERSION