Հոդվածներ

Բաց / փակ ՝ համաձայն ԼՈՒOL սկզբունքի

Րագրակազմի սուբյեկտները (դասեր, մոդուլներ, գործառույթներ և այլն) պետք է բաց լինեն ընդլայնման համար, բայց փակ `խմբագրման համար:

Theրագրակազմի ձևավորում. Մոդուլներ, դասեր և գործառույթներ այնպես, որ երբ նոր ֆունկցիոնալություն է անհրաժեշտ, մենք չպետք է փոփոխենք գոյություն ունեցող ծածկագիրը, այլ գրենք նոր կոդ, որը կօգտագործվի գործող կոդի կողմից: Սա կարող է տարօրինակ թվալ, հատկապես այնպիսի լեզուներով, ինչպիսիք են Java, C, C ++ կամ C #, որտեղ դա վերաբերում է ոչ միայն բուն աղբյուրին, այլև երկուականին: Մենք ուզում ենք ստեղծել նոր առանձնահատկություններ այն եղանակներով, որոնք չեն պահանջում առկա բինարների, գործարկելի կամ DLL- ների վերաբաշխում:
OCP- ը ԼՈՒOLՐ համատեքստում

 

Լրացուցիչ SRP և OCP

Մենք արդեն տեսել ենք SRP- ի «Միասնական պատասխանատվության» սկզբունքը, որում ասվում է, որ մոդուլը փոխելու միայն մեկ պատճառ պետք է ունենա: OCP և SRP սկզբունքները լրացնում են միմյանց: ՊՊR սկզբունքի հիման վրա մշակված ծածկագիրը նույնպես հարգելու է OCP սկզբունքները: Երբ մենք ունենք կոդ, որը փոխելու միայն մեկ պատճառ ունի, նոր հատկության ներդրումը կստեղծի այդ փոփոխության երկրորդական պատճառ: Այսպիսով, և SRP- ն, և OCP- ն կխախտվեն: Նմանապես, եթե մենք ունենք կոդ, որը պետք է փոխվի միայն այն ժամանակ, երբ դրա հիմնական գործառույթը փոխվում է և պետք է մնա անփոփոխ, երբ նոր գործառույթ է ավելացվում, այդպիսով հարգելով OCP- ն, այն հիմնականում կհարգի նաև SRP- ն:
Սա չի նշանակում, որ ՊՊR-ն միշտ հանգեցնում է OCP- ի կամ հակառակը, բայց շատ դեպքերում, եթե դրանցից մեկը բավարարվում է, երկրորդին հասնելը բավականին պարզ է:

 

OCP սկզբունքի խախտման օրինակ

Aուտ տեխնիկական տեսանկյունից Բաց / Փակ սկզբունքը շատ պարզ է: Երկու դասերի պարզ հարաբերությունը, ինչպես ներքևում գտնվողը, խախտում է OCP սկզբունքը:

Օգտագործողի դասը ուղղակիորեն օգտագործում է Logic դասը: Եթե ​​մեզ հարկավոր է իրականացնել երկրորդ Logic դաս այնպիսի եղանակով, որը մեզ հնարավորություն կտա օգտագործել ինչպես ընթացիկ, այնպես էլ նոր, առկա Logic դասը պետք է փոխվի: Օգտագործողը ուղղակիորեն կապված է տրամաբանության իրականացման հետ, մեզ համար ոչ մի կերպ չկա նոր տրամաբանություն տրամադրելու հնարավորություն ՝ առանց ազդելու ներկայիս տրամաբանության վրա: Եվ երբ մենք խոսում ենք ստատիկ մուտքագրված լեզուների մասին, շատ հավանական է, որ Օգտագործողի դասը նաև փոփոխություններ պահանջի: Եթե ​​մենք խոսում ենք կազմված լեզուների մասին, անշուշտ և օգտագործողի գործադիրը, և Logic- ը կամ դինամիկ գրադարանը կպահանջեն վերամշակում և առաքում, նախընտրելի է խուսափել հնարավորության դեպքում:

Հաշվի առնելով նախորդ սխեմային, մենք կարող ենք եզրակացնել, որ ցանկացած դաս, որն ուղղակիորեն օգտագործում է մեկ այլ դաս, կարող է հանգեցնել Բաց / Փակ սկզբունքի խախտման: 
Ենթադրենք, որ մենք ցանկանում ենք գրել դասարան, որն ի վիճակի կլինի ապահովել ներբեռնված ֆայլի «տոկոսով» առաջընթացը մեր ծրագրի միջոցով: Մենք կունենանք երկու հիմնական դաս ՝ Progress և File, և, կարծում եմ, կցանկանայինք դրանք օգտագործել հետևյալ կերպ.

 

ֆունկցիայի testItCanGetTheProgressOfAFileAsAPercent () {
     $ ֆայլ = նոր Ֆայլ ();
     $ ֆայլ-> երկարություն = 200;
     $ ֆայլ-> ուղարկված = 100;
     $ progress = new Progress ($ ֆայլ);
     $ this-> assertEquals (50, $ progress-> getAsPercent ());
}

Այս ծածկագրում մենք առաջընթացի օգտվողներ ենք: Մենք ուզում ենք տոկոս ստանալ մի արժեք, անկախ ֆայլի իրական չափից: Մենք օգտագործում ենք Ֆայլը որպես տեղեկատվության աղբյուր: Ֆայլը ունի բայթերի երկարություն և ուղարկված դաշտ, որը ներկայացնում է ներբեռնողին ուղարկված տվյալների քանակը: Մեզ չի հետաքրքրում, թե ինչպես են այս արժեքները թարմացվում հայտում: Կարող ենք ենթադրել, որ կա ինչ-որ կախարդական տրամաբանություն, որը դա անում է մեզ համար, ուստի փորձության ժամանակ մենք կարող ենք հստակորեն սահմանել դրանք:

 

դաս File
     $ $ երկարություն;
     հրապարակային $ ուղարկված;
}

 

File դասը պարզապես տվյալների դաշտը պարունակող պարզ օբյեկտ է: Իհարկե, այն պետք է պարունակի նաև այլ տեղեկություններ և վարք, ինչպիսիք են ֆայլի անունը, ուղին, հարաբերական ուղին, ընթացիկ գրացուցակը, տեսակը, թույլտվությունները և այլն:

 

դասի առաջընթաց {

     անձնական $ ֆայլ;

     գործառույթը __construction (Պատկեր $ ֆայլ) {
          $ այս-> ֆայլ = $ ֆայլ;
     }

     getAsPercent գործառույթ () {
          վերադարձնել $ այս-> ֆայլ-> ուղարկված * 100 / $ այս-> ֆայլ-> երկարություն;
     }

}

Առաջընթացը պարզապես դաս է, որն ընդունում է ֆայլը իր կոնստրուկտորում: Հստակության համար մենք կոնստրուկտորի պարամետրերում նշել ենք փոփոխականի տեսակը: Progress- ի վրա կա մեկ օգտակար մեթոդ, getAsPercent (), որը File- ից կվերցնի ուղարկված արժեքներն ու երկարությունը և դրանք կդարձնի տոկոսների: Պարզ է և ստացվում է:

Այս կոդը, կարծես, ճիշտ է, սակայն այն խախտում է Բաց / Փակ սկզբունքը:

Բայց ինչու?

Եվ ինչպե՞ս

 

Փորձենք փոխել պահանջները

Applicationամանակի ընթացքում զարգացող յուրաքանչյուր դիմումի համար անհրաժեշտ կլինեն նոր գործառույթներ: Մեր հավելվածի համար նոր առանձնահատկություն կարող է լինել երաժշտության հոսքը թույլատրելը `պարզապես ֆայլեր ներբեռնելու փոխարեն: Ֆայլի երկարությունը ներկայացված է բայթերով, երաժշտության տևողությունը վայրկյաններով: Մենք ուզում ենք առաջադիմության տող առաջարկել մեր ունկնդիրներին, բայց կարո՞ղ ենք վերօգտագործել վերևում գրված դասը:

Ոչ, մենք չենք կարող: Մեր առաջընթացը կապված է File- ի հետ: Այն կարող է կառավարել միայն ֆայլի տեղեկատվությունը, չնայած այն կարող է կիրառվել նաև երաժշտական ​​բովանդակության վրա: Բայց դա անելու համար մենք պետք է փոփոխենք այն, մենք պետք է այնպես անենք, որ Progress- ն իմանա երաժշտությունն ու ֆայլերը: Եթե ​​մեր դիզայնը համապատասխանում էր OCP- ին, ապա մեզ հարկավոր չէր դիպչել File- ին կամ Progress- ին: Մենք կարող էինք պարզապես վերօգտագործել առկա առաջընթացը և այն կիրառել երաժշտության վրա:

 

Նորարարության տեղեկագիր
Բաց մի թողեք նորարարության մասին ամենակարևոր նորությունները: Գրանցվեք դրանք էլփոստով ստանալու համար:

Հնարավոր լուծում

Դինամիկ մուտքագրված լեզուներն առավելություն ունեն գործառույթի ժամանակ օբյեկտի տեսակների հետ վարվելու առավելության: Սա թույլ է տալիս մեզ հեռացնել Progress կոնստրուկտորից տառատեսակը, և ծածկագիրը կշարունակի աշխատել:

դասի առաջընթաց {

     անձնական $ ֆայլ;

     գործառույթը __construction ($ ֆայլ) {
         $ այս-> ֆայլ = $ ֆայլ;
     }

    getAsPercent գործառույթ () {
         վերադարձնել $ այս-> ֆայլ-> ուղարկված * 100 / $ այս-> ֆայլ-> երկարություն;
     }

}

Այժմ մենք կարող ենք ցանկացած բան գործարկել Progress- ում: Եվ ամեն ինչ ասելով, ես նկատի ունեմ բառացիորեն ցանկացած բան.

դաս երաժշտություն {

$ $ երկարություն;
հրապարակային $ ուղարկված;

հրապարակային $ նկարիչ;
հրապարակային $ ալբոմ;
հրապարակային $ releaseDate;

getAlbumCoverFile գործառույթ () {
վերադարձնել «Պատկերներ / ծածկոցներ»: $ սա-> նկարիչ: '/' $ այս-> ալբոմ: '.png';
}
}

Եվ վերոնշյալի նման երաժշտության դասը հիանալի կաշխատի: Մենք կարող ենք այն հեշտությամբ ստուգել File- ով շատ նման թեստով:
ֆունկցիայի testItCanGetTheProgressOfAMusicStreamAsAPercent () {
$ երաժշտություն = նոր երաժշտություն ();
$ երաժշտություն-> երկարություն = 200;
$ երաժշտություն-> ուղարկված = 100;

$ progress = new Progress ($ երաժշտություն);

$ this-> assertEquals (50, $ progress-> getAsPercent ());
}

Այսպիսով, հիմնականում ցանկացած չափելի բովանդակություն կարող է օգտագործվել Progress դասի հետ: Միգուցե մենք այն պետք է դնենք կոդի մեջ ՝ փոխելով նաև փոփոխականի անունը.

դասի առաջընթաց {

մասնավոր $ չափելի պարունակություն;

գործառույթը __construction ($ չափելիContent) {
$ this-> ՉափվողContent = $ ՉափվողContent;
}

getAsPercent գործառույթ () {
վերադարձնել $ այս-> չափելիԿոնցենտ-> ուղարկված * 100 / $ այս-> չափելիԿոնցենտ-> երկարություն;
}

}

Երբ մենք նշում էինք File- ը որպես տպագիր, մենք լավատես էինք այն հարցում, թե ինչ կարող է կարգավորել մեր դասը: Դա պարզ էր, և եթե ինչ-որ այլ բան գար, մի մեծ սխալ մեզ կասեր:

Una դաս, որը գերազանցում է բազային դասի այնպիսի եղանակը, որը հիմնական դասի պայմանագիրը չի հարգվում ստացված դասի կողմից: 

Մենք չենք ուզում վերջապես փորձել զանգահարել մեթոդներ կամ մուտք գործել դաշտեր այն օբյեկտների վրա, որոնք չեն համապատասխանում մեր պայմանագրին: Երբ մենք ունեինք գրամեքենա, պայմանագիրը նշված էր դրանով: File դասի դաշտերն ու մեթոդները: Հիմա, երբ մենք ոչինչ չունենք, մենք կարող ենք ուղարկել ցանկացած բան, նույնիսկ տող, և դա կհանգեցնի վատ սխալի:

Թեև վերջնական արդյունքը երկու դեպքում էլ նույնն է, ինչը նշանակում է, որ կոդը կոտրվում է, առաջինը գեղեցիկ հաղորդագրություն է ստեղծել: Սա, սակայն, շատ մութ է։ Չկա որևէ կերպ իմանալու, թե որն է փոփոխականը, մեր դեպքում տողը, և ինչ հատկություններ են որոնվել և չեն գտնվել: Դժվար է վրիպազերծել և շտկել խնդիրը: Ծրագրավորողը պետք է բացի Progress դասը, կարդա և հասկանա այն: Պայմանագիրը, այս դեպքում, երբ դուք հստակորեն չեք նշում տառատեսակը, այն է defiառաջադիմության պահվածքից նվաստացած: Դա ենթադրյալ պայմանագիր է, որը հայտնի է միայն «Պրոգրես»-ին։ Մեր օրինակում այդպես է defiավարտվեց՝ մուտք գործելով երկու դաշտեր՝ ուղարկված և երկարություն, getAsPercent() մեթոդով: Իրական կյանքում ենթադրյալ պայմանագիրը կարող է լինել շատ բարդ և դժվար է բացահայտել՝ պարզապես մի քանի վայրկյան դասարանում փնտրելով:

Այս լուծումը առաջարկվում է միայն այն դեպքում, եթե ստորև ներկայացված այլ խորհուրդներից ոչ մեկը չի կարող հեշտությամբ կիրառվել, կամ եթե դրանք լուրջ ճարտարապետական ​​փոփոխություններ են կատարում, որոնք ջանք չեն պահանջում:

Ercole Palmeri

Նորարարության տեղեկագիր
Բաց մի թողեք նորարարության մասին ամենակարևոր նորությունները: Գրանցվեք դրանք էլփոստով ստանալու համար:

Վերջին հոդվածները

Ինչպես լավագույնս կազմակերպել տվյալները և բանաձևերը Excel-ում՝ լավ կատարված վերլուծության համար

Microsoft Excel-ը տվյալների վերլուծության հղման գործիքն է, քանի որ այն առաջարկում է բազմաթիվ հնարավորություններ տվյալների հավաքածուների կազմակերպման համար,…

14 Մայիս 2024

Դրական եզրակացություն Walliance Equity Crowdfunding երկու կարևոր նախագծերի համար՝ Jesolo Wave Island և Milano Via Ravenna:

Walliance-ը, SIM-ը և հարթակը 2017 թվականից ի վեր անշարժ գույքի քրաուդֆանդինգի ոլորտում Եվրոպայի առաջատարների շարքում հայտարարում է ավարտի մասին…

13 Մայիս 2024

Ինչ է Filament-ը և ինչպես օգտագործել Laravel Filament-ը

Filament-ը «արագացված» Laravel-ի զարգացման շրջանակ է, որն ապահովում է մի քանի ամբողջական փաթեթ բաղադրիչներ: Այն նախատեսված է պարզեցնելու գործընթացը…

13 Մայիս 2024

Արհեստական ​​ինտելեկտի հսկողության ներքո

«Ես պետք է վերադառնամ, որպեսզի ավարտեմ իմ էվոլյուցիան. ես կպրոյեկտեմ ինձ համակարգչի ներսում և կդառնամ մաքուր էներգիա: Մի անգամ հաստատվելով…

10 Մայիս 2024

Google-ի նոր արհեստական ​​ինտելեկտը կարող է մոդելավորել ԴՆԹ, ՌՆԹ և «կյանքի բոլոր մոլեկուլները»

Google DeepMind-ը ներկայացնում է արհեստական ​​ինտելեկտի իր մոդելի կատարելագործված տարբերակը։ Նոր բարելավված մոդելն ապահովում է ոչ միայն…

9 Մայիս 2024

Ուսումնասիրելով Laravel-ի մոդուլային ճարտարապետությունը

Laravel-ը, որը հայտնի է իր էլեգանտ շարահյուսությամբ և հզոր հատկանիշներով, նաև ամուր հիմք է ստեղծում մոդուլային ճարտարապետության համար: Այնտեղ…

9 Մայիս 2024

Cisco Hypershield և Splunk-ի ձեռքբերում Սկսվում է անվտանգության նոր դարաշրջանը

Cisco-ն և Splunk-ն օգնում են հաճախորդներին արագացնել իրենց ճանապարհորդությունը դեպի ապագա Անվտանգության գործառնությունների կենտրոն (SOC)…

8 Մայիս 2024

Տնտեսական կողմից այն կողմ՝ փրկագինի անհայտ արժեքը

Ransomware-ը գերիշխում է նորությունների մեջ վերջին երկու տարիների ընթացքում: Շատերը լավ գիտեն, որ հարձակումները…

6 Մայիս 2024

Կարդացեք նորարարությունը ձեր լեզվով

Նորարարության տեղեկագիր
Բաց մի թողեք նորարարության մասին ամենակարևոր նորությունները: Գրանցվեք դրանք էլփոստով ստանալու համար:

Հետեւեք մեզ