Meginreglan um eina ábyrgð. Ekki eins einfalt og það virðist

Meginreglan um eina ábyrgð. Ekki eins einfalt og það virðist Reglan um eina ábyrgð, einnig þekkt sem meginreglan um eina ábyrgð,
aka meginreglan um einsleitan breytileika - ákaflega sleipur náungi að skilja og svo taugaveikluð spurning í forritaraviðtali.

Fyrstu alvarlegu kynni mín af þessari reglu áttu sér stað í byrjun fyrsta árs þegar þeir ungir og grænu voru dregnir í skóginn til að gera nemendur úr lirfum - alvöru nemendur.

Í skóginum var okkur skipt í 8-9 manna hópa hver og var keppt - hvaða hópur myndi drekka vodkaflösku hraðast, að því gefnu að fyrsti úr hópnum hellti vodka í glas, sá seinni drekki það, og sá þriðji er með snakk. Einingin sem hefur lokið starfsemi sinni færist í lok biðröð hópsins.

Tilvikið þar sem biðraðastærðin var margfeldi af þremur var góð útfærsla á SRP.

Skilgreining 1. Ein ábyrgð.

Opinber skilgreining á einni ábyrgðarreglunni (SRP) segir að hver aðili hafi sína eigin ábyrgð og ástæðu fyrir tilveru og hún ber aðeins eina ábyrgð.

Lítum á hlutinn „Drykkjari“ (Tippler).
Til að innleiða SRP meginregluna munum við skipta ábyrgðinni í þrennt:

  • Einn hellir (PourOperation)
  • Einn drekkur (DrinkUp Operation)
  • Einn fær sér snarl (TakeBiteOperation)

Hver þátttakandi í ferlinu er ábyrgur fyrir einum þætti ferlisins, það er að segja, hefur eina frumeindaábyrgð - að drekka, hella eða snarl.

Drykkjarholið er aftur á móti framhlið þessara aðgerða:

сlass Tippler {
    //...
    void Act(){
        _pourOperation.Do() // налить
        _drinkUpOperation.Do() // выпить
        _takeBiteOperation.Do() // закусить
    }
}

Meginreglan um eina ábyrgð. Ekki eins einfalt og það virðist

Hvers vegna?

Mannlegur forritari skrifar kóða fyrir apamanninn og apamaðurinn er athyglislaus, heimskur og alltaf að flýta sér. Hann getur haldið og skilið um 3 - 7 hugtök í einu.
Ef um handrukkara er að ræða eru þrjú af þessum hugtökum. Hins vegar, ef við skrifum kóðann með einu blaði, þá mun hann innihalda hendur, gleraugu, slagsmál og endalaus rifrildi um stjórnmál. Og allt þetta mun vera í meginmáli einnar aðferðar. Ég er viss um að þú hefur séð slíkan kóða á æfingum þínum. Ekki mannúðlegasta prófið fyrir sálarlífið.

Aftur á móti er apamaðurinn hannaður til að líkja eftir raunverulegum hlutum í höfðinu á honum. Í hugmyndafluginu getur hann þrýst þeim saman, sett saman nýja hluti úr þeim og tekið þá í sundur á sama hátt. Ímyndaðu þér gamlan bíl. Í ímyndunaraflið geturðu opnað hurðina, skrúfað hurðarklæðninguna af og séð þar gluggalyftingarbúnaðinn, þar sem gír verða inni í. En þú getur ekki séð alla íhluti vélarinnar á sama tíma, í einni "skráningu". Að minnsta kosti getur „apamaðurinn“ það ekki.

Þess vegna sundra mannlegir forritarar flóknum aðferðum í safn af minna flóknum og vinnandi þáttum. Hins vegar getur hann brotnað niður á mismunandi vegu: í mörgum gömlum bílum fer loftrásin inn í hurðina og í nútímabílum kemur bilun í rafeindabúnaði læsingar í veg fyrir að vélin fari í gang sem getur verið vandamál við viðgerð.

Núna, SRP er meginregla sem útskýrir HVERNIG á að sundrast, það er hvar á að draga deilina.

Hann segir að nauðsynlegt sé að brjóta niður samkvæmt meginreglunni um skiptingu „ábyrgðar“, það er að segja eftir verkefnum ákveðinna hluta.

Meginreglan um eina ábyrgð. Ekki eins einfalt og það virðist

Snúum okkur aftur að drykkjunni og kostunum sem apamaðurinn fær við niðurbrot:

  • Kóðinn er orðinn mjög skýr á öllum stigum
  • Kóðinn getur verið skrifaður af nokkrum forriturum í einu (hver skrifar sérstakan þátt)
  • Sjálfvirk prófun er einfölduð - því einfaldari sem þátturinn er, því auðveldara er að prófa hann
  • Samsetning kóðans birtist - þú getur skipt út DrinkUp Operation að aðgerð þar sem handrukkari hellir vökva undir borðið. Eða skiptu úthellingaraðgerðinni út fyrir aðgerð þar sem þú blandar víni og vatni eða vodka og bjór. Það fer eftir viðskiptakröfum, þú getur gert allt án þess að snerta aðferðarkóðann Tippler.Act.
  • Frá þessum aðgerðum er hægt að brjóta mathárið saman (aðeins með því að nota TakeBitOperation), Áfengt (aðeins notað DrinkUp Operation beint úr flöskunni) og uppfylla margar aðrar viðskiptakröfur.

(Ó, það virðist sem þetta sé nú þegar OCP regla og ég braut gegn ábyrgð þessarar færslu)

Og auðvitað gallarnir:

  • Við verðum að búa til fleiri tegundir.
  • Handrukkari drekkur í fyrsta skipti nokkrum tímum seinna en ella.

Skilgreining 2. Sameinaður breytileiki.

Leyfðu mér, herrar mínir! Drykkjunámskeiðið ber líka eina ábyrgð - það drekkur! Og almennt séð er orðið „ábyrgð“ afar óljóst hugtak. Einhver ber ábyrgð á örlögum mannkyns og einhver ber ábyrgð á því að ala upp mörgæsirnar sem var velt við pólinn.

Við skulum íhuga tvær útfærslur á drykkjaranum. Sá fyrsti, sem nefndur er hér að ofan, inniheldur þrjá flokka - hella, drekka og snarl.

Annað er skrifað með aðferðafræðinni „Áfram og aðeins áfram“ og inniheldur alla rökfræði aðferðarinnar Lög:

//Не тратьте время  на изучение этого класса. Лучше съешьте печеньку
сlass BrutTippler {
   //...
   void Act(){
        // наливаем
    if(!_hand.TryDischarge(from:_bottle, to:_glass, size:_glass.Capacity))
        throw new OverdrunkException();

    // выпиваем
    if(!_hand.TryDrink(from: _glass,  size: _glass.Capacity))
        throw new OverdrunkException();

    //Закусываем
    for(int i = 0; i< 3; i++){
        var food = _foodStore.TakeOrDefault();
        if(food==null)
            throw new FoodIsOverException();

        _hand.TryEat(food);
    }
   }
}

Báðir þessir flokkar, frá sjónarhóli utanaðkomandi áhorfenda, líta nákvæmlega eins út og bera sömu ábyrgð að „drekka“.

Rugl!

Síðan förum við á netið og finnum út aðra skilgreiningu á SRP - The Single Changeability Principle.

SCP segir að "Eining hefur eina og eina ástæðu til að breyta". Það er, "Ábyrgð er ástæða fyrir breytingum."

(Svo virðist sem strákarnir sem komu með upprunalegu skilgreininguna hafi verið öruggir í fjarskiptahæfileikum apamannsins)

Nú fellur allt á sinn stað. Sérstaklega getum við breytt uppáhellingu, drykkju og snakkaðferðum, en í drykkjaranum sjálfum getum við aðeins breytt röð og samsetningu aðgerða, til dæmis með því að færa snakkið áður en það er drukkið eða bæta við lestri á ristuðu brauði.

Í „Forward and Only Forward“ nálguninni er öllu sem hægt er að breyta aðeins breytt í aðferðinni Lög. Þetta getur verið læsilegt og áhrifaríkt í tilfellum þar sem lítið er um rökfræði og það breytist sjaldan, en oft endar það í hræðilegum aðferðum upp á 500 línur hver, með fleiri ef-yfirlýsingum en þarf til að Rússar gangi í NATO.

Skilgreining 3. Staðfærsla breytinga.

Drykkjumenn skilja oft ekki hvers vegna þeir vöknuðu í íbúð einhvers annars, eða hvar farsíminn þeirra er. Það er kominn tími til að bæta við nákvæmri skráningu.

Við skulum byrja að skrá þig með upphellingarferlinu:

class PourOperation: IOperation{
    PourOperation(ILogger log /*....*/){/*...*/}
    //...
    void Do(){
        _log.Log($"Before pour with {_hand} and {_bottle}");
        //Pour business logic ...
        _log.Log($"After pour with {_hand} and {_bottle}");
    }
}

Með því að hylja það inn PourOperation, við brugðumst skynsamlega út frá sjónarhóli ábyrgðar og hjúpunar, en nú erum við að rugla saman við breytileikaregluna. Auk aðgerðarinnar sjálfrar, sem getur breyst, verður skógarhöggið sjálft einnig breytilegt. Þú verður að aðskilja og búa til sérstakan skógarhöggsmann fyrir upphellingaraðgerðina:

interface IPourLogger{
    void LogBefore(IHand, IBottle){}
    void LogAfter(IHand, IBottle){}
    void OnError(IHand, IBottle, Exception){}
}

class PourOperation: IOperation{
    PourOperation(IPourLogger log /*....*/){/*...*/}
    //...
    void Do(){
        _log.LogBefore(_hand, _bottle);
        try{
             //... business logic
             _log.LogAfter(_hand, _bottle");
        }
        catch(exception e){
            _log.OnError(_hand, _bottle, e)
        }
    }
}

Nákvæmur lesandi tekur eftir því LogAfter, LogBefore и OnError er einnig hægt að breyta fyrir sig og, á hliðstæðan hátt við fyrri skref, mun búa til þrjá flokka: PourLoggerBefore, PourLoggerAfter и PourErrorLogger.

Og minnug þess að það eru þrjár aðgerðir fyrir drykkjumann, þá fáum við níu skógarhöggstíma. Fyrir vikið samanstendur allur drykkjuhringurinn af 14 (!!!) bekkjum.

Hyperbóla? Varla! Apamaður með niðurbrotshandsprengju mun skipta „hellan“ í karfa, glas, upphellingartæki, vatnsveituþjónustu, líkamlegt líkan af árekstri sameinda, og næsta ársfjórðunginn mun hann reyna að leysa ósjálfstæðin. hnattrænar breytur. Og trúðu mér, hann mun ekki hætta.

Það er á þessum tímapunkti sem margir komast að þeirri niðurstöðu að SRP séu ævintýri frá bleikum konungsríkjum og fara í burtu til að spila núðlur...

... án þess nokkurn tíma að læra um tilvist þriðju skilgreiningar á Srp:

„Meginreglan um eina ábyrgð segir það hlutir sem líkjast breytingum ættu að vera geymdir á einum stað". eða "Það sem breytingarnar saman ættu að vera á einum stað"

Það er að segja ef við breytum skráningu aðgerða, þá verðum við að breyta henni á einum stað.

Þetta er mjög mikilvægt atriði - þar sem allar skýringar SRP sem voru hér að ofan sögðu að það væri nauðsynlegt að mylja tegundirnar á meðan þær voru muldar, það er að segja þær settu „efri mörk“ á stærð hlutarins, og núna við erum nú þegar að tala um „neðri mörk“ . Með öðrum orðum, SRP krefst ekki aðeins „mölunar meðan á mulning stendur“, heldur einnig að ofleika það ekki - „ekki mylja samtengda hluti“. Þetta er hin mikla barátta milli rakvél Occams og apamannsins!

Meginreglan um eina ábyrgð. Ekki eins einfalt og það virðist

Nú ætti drykkjumanninum að líða betur. Til viðbótar við þá staðreynd að það er engin þörf á að skipta IPourLogger skógarhöggsmanninum í þrjá flokka, getum við líka sameinað alla skógarhöggsmanninn í eina tegund:

class OperationLogger{
    public OperationLogger(string operationName){/*..*/}
    public void LogBefore(object[] args){/*...*/}       
    public void LogAfter(object[] args){/*..*/}
    public void LogError(object[] args, exception e){/*..*/}
}

Og ef við bætum við fjórðu gerð aðgerða, þá er skógarhöggið fyrir það þegar tilbúið. Og kóðinn fyrir starfsemina sjálfa er hreinn og laus við hávaða í innviðum.

Fyrir vikið höfum við 5 flokka til að leysa drykkjuvandann:

  • Upphellingaraðgerð
  • Drykkjuaðgerð
  • Jammaðgerð
  • Skógarhöggsmaður
  • Drinker framhlið

Hver þeirra ber stranglega ábyrgð á einni virkni og hefur eina ástæðu fyrir breytingum. Allar reglur svipaðar breytingum eru staðsettar í nágrenninu.

Raunverulegt dæmi

Við skrifuðum einu sinni þjónustu til að skrá b2b viðskiptavin sjálfkrafa. Og GOD aðferð birtist fyrir 200 línur af svipuðu efni:

  • Farðu í 1C og búðu til reikning
  • Með þessum reikningi skaltu fara í greiðslueininguna og búa hana til þar
  • Athugaðu hvort reikningur með slíkum reikningi hafi ekki verið stofnaður á aðalþjóninum
  • Búðu til nýjan reikning
  • Bættu skráningarniðurstöðum í greiðslueininguna og 1c númerinu við skráningarniðurstöðuþjónustuna
  • Bættu reikningsupplýsingum við þessa töflu
  • Búðu til punktanúmer fyrir þennan viðskiptavin í punktaþjónustunni. Sendu 1c reikningsnúmerið þitt til þessarar þjónustu.

Og það voru um það bil 10 fyrirtæki í viðbót á þessum lista með hræðilega tengingu. Næstum allir þurftu reikningshlutinn. Nauðsynlegt var að nota punktauðkenni og nafn viðskiptavinar í helming símtalanna.

Eftir klukkutíma endurnýjun gátum við aðskilið innviðakóðann og nokkur blæbrigði þess að vinna með reikning í aðskildar aðferðir/flokka. Guðsaðferðin gerði það auðveldara, en það voru 100 línur af kóða eftir sem bara vildu ekki vera lausar.

Aðeins eftir nokkra daga varð ljóst að kjarninn í þessari „léttu“ aðferð er viðskiptaalgrím. Og að upprunalega lýsingin á tækniforskriftunum hafi verið nokkuð flókin. Og það er tilraunin til að brjóta þessa aðferð í sundur sem mun brjóta í bága við SRP, og ekki öfugt.

Formalismi.

Það er kominn tími til að láta drykkjuna okkar í friði. Þurrkaðu tárin - við munum örugglega snúa aftur til þess einhvern tíma. Nú skulum við formfesta þekkinguna úr þessari grein.

Formalismi 1. Skilgreining á SRP

  1. Aðskilja þættina þannig að hver þeirra ber ábyrgð á einu.
  2. Ábyrgð stendur fyrir „ástæðu til að breyta“. Það er, hver þáttur hefur aðeins eina ástæðu fyrir breytingum, hvað varðar viðskiptarökfræði.
  3. Hugsanlegar breytingar á viðskiptarökfræði. verður að vera staðbundið. Hlutir sem breytast samstillt verða að vera nálægt.

Formhyggja 2. Nauðsynleg viðmið sjálfsprófs.

Ég hef ekki séð nægjanleg skilyrði til að uppfylla SRP. En það eru nauðsynleg skilyrði:

1) Spyrðu sjálfan þig hvað þessi flokkur/aðferð/eining/þjónusta gerir. þú verður að svara því með einfaldri skilgreiningu. ( Þakka þér fyrir Brightori )

skýringar

Hins vegar er stundum mjög erfitt að finna einfalda skilgreiningu

2) Að laga villu eða bæta við nýjum eiginleika hefur áhrif á lágmarksfjölda skráa/flokka. Helst - einn.

skýringar

Þar sem ábyrgð (fyrir eiginleika eða villu) er innifalin í einni skrá/flokki, þá veistu nákvæmlega hvar þú átt að leita og hverju þú átt að breyta. Til dæmis: eiginleiki þess að breyta framleiðsla skógarhöggsaðgerða mun krefjast þess að breyta aðeins skógarhöggsmanni. Það er engin þörf á að keyra í gegnum restina af kóðanum.

Annað dæmi er að bæta við nýrri notendastýringu, svipað og þau fyrri. Ef þetta neyðir þig til að bæta við 10 mismunandi einingum og 15 mismunandi breytum lítur út fyrir að þú sért að ofleika það.

3) Ef nokkrir forritarar eru að vinna að mismunandi eiginleikum verkefnisins þíns, þá eru líkurnar á samrunaátökum, það er að segja líkurnar á því að sama skrá/flokki verði breytt af nokkrum forriturum á sama tíma, í lágmarki.

skýringar

Ef þú þarft að hafa áhrif á skógarhöggsmanninn, þegar þú bætir við nýrri aðgerð „Heltu vodka undir borðið“, aðgerðina við að drekka og hella, þá lítur út fyrir að ábyrgðin sé skáskipt. Þetta er auðvitað ekki alltaf hægt en við ættum að reyna að lækka þessa tölu.

4) Þegar þú ert spurður skýringarspurningar um viðskiptarökfræði (frá þróunaraðila eða stjórnanda), ferðu stranglega inn í einn flokk/skrá og færð aðeins upplýsingar þaðan.

skýringar

Eiginleikar, reglur eða reiknirit eru skrifuð þétt, hver á einum stað, og ekki dreift með fánum um allt kóðarýmið.

5) Nafnið er skýrt.

skýringar

Okkar flokkur eða aðferð ber ábyrgð á einu og ábyrgðin endurspeglast í nafni hans

AllManagersManagerService - líklegast guðsflokkur
LocalPayment - líklega ekki

Formalismi 3. Occam-fyrsta þróunaraðferðafræði.

Í upphafi hönnunar þekkir apamaðurinn ekki og finnur ekki fyrir öllum fíngerðum vandans vera leystur og getur gert mistök. Þú getur gert mistök á mismunandi vegu:

  • Gerðu hluti of stóra með því að sameina mismunandi ábyrgðir
  • Reframing með því að skipta einni ábyrgð í margar mismunandi gerðir
  • Skilgreina ranglega mörk ábyrgðar

Það er mikilvægt að muna regluna: „betra er að gera stór mistök,“ eða „ef þú ert ekki viss skaltu ekki skipta því upp“. Ef, til dæmis, bekkurinn þinn inniheldur tvær skyldur, þá er það samt skiljanlegt og hægt að skipta því í tvennt með lágmarksbreytingum á kóða viðskiptavinarins. Að setja saman gler úr glerbrotum er venjulega erfiðara vegna þess að samhengið er dreift yfir nokkrar skrár og skorts á nauðsynlegum ósjálfstæðum í kóða viðskiptavinarins.

Það er kominn tími til að kalla það dag

Umfang SRP er ekki takmarkað við OOP og SOLID. Það á við um aðferðir, aðgerðir, flokka, einingar, örþjónustur og þjónustu. Það á bæði við um þróun „figax-figax-and-prod“ og „eldflaugavísinda“, sem gerir heiminn aðeins betri alls staðar. Ef þú hugsar um það, þá er þetta nánast grundvallarreglan í allri verkfræði. Vélaverkfræði, eftirlitskerfi og reyndar öll flókin kerfi eru byggð úr íhlutum og „vansundrun“ sviptir hönnuði sveigjanleika, „of sundrungu“ sviptir hönnuði hagkvæmni og röng mörk svipta þá skynsemi og hugarró.

Meginreglan um eina ábyrgð. Ekki eins einfalt og það virðist

SRP er ekki fundið upp af náttúrunni og er ekki hluti af nákvæmum vísindum. Það brýtur út úr líffræðilegum og sálfræðilegum takmörkunum okkar.Þetta er bara leið til að stjórna og þróa flókin kerfi með því að nota apa-mann heilann. Hann segir okkur hvernig eigi að brjóta niður kerfi. Upprunalega samsetningin krafðist talsverðrar fjarskipta, en ég vona að þessi grein hreinsi eitthvað af reyktjaldinu.

Heimild: www.habr.com

Bæta við athugasemd