JavaRush /Java блогы /Random-KK /Java тіліндегі класс дизайнының (SOLID) бес негізгі қағид...
Ve4niY
Деңгей

Java тіліндегі класс дизайнының (SOLID) бес негізгі қағидасы

Топта жарияланған
Сыныптар - қолданба құрастырылатын блоктар. Ғимараттағы кірпіш сияқты. Нашар жазылған сабақтар бір күні қиындықтар тудыруы мүмкін. Java тіліндегі класс дизайнының (SOLID) бес негізгі қағидасы - 1Сыныптың дұрыс жазылғанын түсіну үшін «сапа стандарттарын» тексеруге болады. Java тілінде бұл SOLID принциптері деп аталады. Олар туралы сөйлесейік.

Java тіліндегі SOLID принциптері

SOLID — OOP және дизайнның алғашқы бес қағидасының бас әріптерінен жасалған аббревиатура. Принциптерді 2000 жылдардың басында Роберт Мартин ойлап тапты, ал акронимді кейінірек Майкл Фэрс ойлап тапты. SOLID принциптеріне мыналар кіреді:
  1. Бірыңғай жауапкершілік қағидасы.
  2. Ашық жабық принцип.
  3. Лисковтың алмастыру принципі.
  4. Интерфейсті бөлу принципі.
  5. Тәуелділіктің инversion принципі.

Бірыңғай жауапкершілік қағидасы (SRP)

Бұл принцип сыныпты өзгертуге ешқашан бірден көп себеп болмауы керек екенін айтады . Әрбір нысанның сыныпта толығымен инкапсуляцияланған бір жауапкершілігі бар. Барлық сыныптық қызметтер осы жауапкершілікті қамтамасыз етуге бағытталған. Мұндай сыныптарды қажет болған жағдайда өзгерту әрқашан оңай болады, өйткені сыныптың не үшін жауапты екені және ненің жауапты еместігі анық. Яғни, өзгерістер енгізуге және оның салдары - басқа an objectілерге әсер етуден қорықпауға болады. Және мұндай codeты тестілеу әлдеқайда оңай, өйткені сіз бір функционалдылықты басқаларынан оқшауланған сынақтармен қамтысыз. Тапсырыстарды өңдейтін модульді елестетіңіз. Тапсырыс дұрыс жасалған болса, ол оны дерекқорда сақтайды және тапсырысты растау үшін электрондық поштаны жібереді:
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);
        }
    }

}

Ашық/жабық принцип (OCP)

Бұл принцип келесідей қысқаша сипатталған: бағдарламалық жасақтама нысандары (сыныптар, модульдер, функциялар және т.б.) кеңейту үшін ашық, бірақ өзгерту үшін жабық болуы керек . Бұл сыныптың өзіне физикалық өзгерістер жасамай-ақ, сыныптың сыртқы мінез-құлқын өзгертуге болатынын білдіреді. Осы принципті басшылыққа ала отырып, сыныпты қолданудың нақты шарттарына сәйкестендіру үшін оны кеңейтіп, кейбір функцияларды қайта анықтау жеткілікті болатындай сыныптар әзірленеді. Сондықтан жүйе икемді, бастапқы codeты өзгертпестен айнымалы жағдайларда жұмыс істей алатын болуы керек. Тапсырыс үлгісін жалғастыра отырып, тапсырыс өңделмес бұрын және растау электрондық поштасы жіберілгеннен кейін кейбір әрекеттерді орындау керек делік. Сыныптың өзін өзгертудің орнына 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)

Бұл бұрын талқыланған ашық/жабық принциптің нұсқасы. Оны былай сипаттауға болады: программадағы an objectілерді программаның қасиеттерін өзгертпей-ақ олардың мұрагерлерімен ауыстыруға болады. Бұл базалық классты кеңейту арқылы әзірленген класс оның әдістерін клиенттің көзқарасы бойынша функционалдылықты бұзbyteын етіп қайта анықтауы керек дегенді білдіреді. Яғни, егер әзірлеуші ​​сыныпты кеңейтіп, оны қолданбада пайдаланса, ол қайта анықталған әдістердің күтілетін әрекетін өзгертпеуі керек. Ішкі сыныптар негізгі класс әдістерін клиенттің көзқарасы бойынша функционалдылықты бұзbyteындай етіп қайта анықтауы керек. Мұны келесі мысал арқылы егжей-тегжейлі қарастыруға болады. Бізде тапсырысты тексеруге жауапты және барлық тапсырыс элементтерінің қоймада бар-жоғын тексеретін сынып бар делік. Бұл сыныпта true немесе falseisValid мәнін қайтаратын әдіс бар :
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 орнына, біздің әдіс ерекше жағдайды шығарады . Бұл codeтың клиенттері мұны күтпейді: олар true немесе false қайтарылады деп күтеді . Бұл бағдарламадағы қателерге әкелуі мүмкін.

Интерфейсті бөлу принципі (ISP)

Келесі мәлімдемемен сипатталады: Клиенттер қолданылмайтын әдістерді енгізуге мәжбүр болмауы керек . Интерфейстерді бөлу принципі тым «қалың» интерфейстерді кішігірім және нақтырақ интерфейстерге бөлу қажет екенін көрсетеді, осылайша шағын интерфейстердің клиенттері олардың жұмысына қажетті әдістер туралы ғана біледі. Нәтижесінде интерфейс әдісін өзгерткен кезде бұл әдісті пайдаланbyteын клиенттер өзгермеуі керек. Мысал қарастырайық. Әзірлеуші ​​Алекс «есеп» интерфейсін жасап, екі әдісті қосты: generateExcel()және generatedPdf(). Енді A клиенті осы интерфейсті пайдаланғысы келеді, бірақ ол Excel емес, тек PDF есептерін пайдаланғысы келеді. Ол бұл функцияға қанағаттанады ма? Жоқ. Ол екі әдісті жүзеге асыруға мәжбүр болады, олардың бірі негізінен қажет емес және бағдарламалық жасақтаманы жасаушы Алекстің арқасында ғана бар. Клиент басқа интерфейсті пайдаланады немесе Excel өрісін бос қалдырады. Сонымен, шешім қандай? Ол бар интерфейсті кішірек екіге бөлуден тұрады. Бірі PDF форматындағы есеп, екіншісі Excel пішіміндегі есеп. Бұл пайдаланушыға тек өзіне қажетті функционалдылықты пайдалану мүмкіндігін береді.

Тәуелділіктің инversion принципі (DIP)

Java тіліндегі бұл SOLID принципі келесідей сипатталған: жүйедегі тәуелділіктер абстракциялар негізінде құрылады . Жоғарғы деңгейлі модульдер төменгі деңгейдегі модульдерден тәуелсіз. Абстракциялар бөлшектерге тәуелді болмауы керек. Мәліметтер абстракцияларға байланысты болуы керек. Бағдарламалық қамтамасыз ету әртүрлі модульдер автономды және абстракцияны қолдану арқылы бір-бірімен қосылатындай етіп жасалуы керек. Бұл принциптің классикалық қолданылуы көктемгі шеңбер болып табылады. Spring шеңберінде барлық модульдер бірге жұмыс істей алатын жеке құрамдас бөліктер ретінде жүзеге асырылады. Олардың дербестігі сонша, оларды Spring Framework-тен басқа бағдарламалық жасақтама модульдерінде де оңай пайдалануға болады. Бұған жабық және ашық принциптердің тәуелділігі арқылы қол жеткізіледі. Барлық модульдер басқа модульде пайдалануға болатын абстракцияға ғана қатынасты қамтамасыз етеді. Мұны мысалмен көрсетуге тырысайық. Жалғыз жауапкершілік қағидасы туралы айта отырып, біз кейбірін қарастырдық OrderProcessor. Осы сыныптың codeын тағы бір қарастырайық:
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. Біз сондай-ақ осы сыныптар үшін codeты ұсынамыз:
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. Біз Java тіліндегі SOLID - дизайн принциптерін қарастырдық. Жалпы OOP туралы толығырақ, осы бағдарламалау тілінің негіздері - жалықтырмайтын және жүздеген сағаттық тәжірибемен - JavaRush курсында. Кейбір мәселелерді шешу уақыты :) Java тілінде сыныпты жобалаудың бес негізгі қағидасы (SOLID) - 2
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION