Cum cei doi programatori au coace pâine

Cum cei doi programatori au coace pâine

Am lucrat timp de mulți ani ca programator, timp în care, ciudat cum mi se pare, programez ceva tot timpul. Și un lucru interesant pe care l-am observat: în codul pe care l-am scris acum o lună, mereu vreau să îmbunătățesc ceva puțin. În codul de jumătate de an în urmă, vreau să schimb foarte mult, iar codul scris acum doi sau trei ani mă transformă într-un emo: vreau să plâng și să mor. În acest articol voi descrie două abordări. Mulțumită primului, arhitectura programului se dovedește a fi confuză, iar suportul este extrem de costisitor, iar al doilea este principiul lui KISS.







Deci, să ne imaginăm că există doi programatori. Unul dintre ei este inteligent, citește o grămadă de articole despre Habr, cunoaște catalogul GoF, iar Fowler - în persoană. Celălalt face totul simplu. Primul va fi, de exemplu, Boris N. și al doilea - Markus P. Desigur, numele sunt fictive, iar toate coincidențele cu oamenii reali și cu programatorii sunt aleatorii.

Deci, pentru ambii apare managerul de proiect (dacă în universul tău PM nu merge la programatori înșiși, cheamă-l altceva, de exemplu BA sau plumb), nu schimbă esența) și spune:
- Baieti, trebuie sa facem pâine.

Așa a fost "făcut", fără a specifica modul de producție.

Ce vor face programatorii noștri?

Cum cei doi programatori au coace pâine

Boris creează prima sa abstractizare - clasa Produs, de la care moștenește clasa de pâine, și instanŃează instanŃele din această clasă cu metoda din fabrică a clasei ProductFactory - createProduct ().

Marcus face cam la fel. Creează o clasă de pâine și o clasă Manager cu metoda createBread () din fabrică.

În timp ce diferența este minimă. Managerul de proiect, înțelegând un pic mai adânc (așa i se pare, da), în nevoile clientului, vine a doua oară și spune:
"Avem nevoie de pâine nu numai pentru a fi făcute, ci pentru a fi coapte în aragaz".

Și imediat a fost imposibil să spunem că pâinea nu este coaptă în vid, ci într-o aragaz? Ei bine, ce fac programatorii?

Cum cei doi programatori au coace pâine

Boris redenumește clasa ProductFactory în cuptor și selectează abstractizarea - AbstractOven. Pentru a fi destul de frumos, creează metoda create () pentru a coace produsul (). Astfel, pentru prima dată Boris a efectuat refactorizarea, aplicând "abstractizarea", și a implementat, de asemenea, șablonul "fabrica abstractă" exact așa cum este descris în literatură. Bine, Boris.

Dar Marcus nu face nimic. Din punctul său de vedere, totul este atât de bun. Ei bine, poate merită ușor modificarea implementării lui createBread ().

Faza lunii se schimbă, iar managerul vine la programatori pentru a treia oară. El spune:
"Avem nevoie de sobe pentru a fi de diferite feluri".

Ei bine, asta e corect.

Cum cei doi programatori au coace pâine

Boris, frecându-și mâinile fericite, creează trei moștenitori ai AbstractOven - ElectricOven, MicrowaveOven și GasOven. Și elimină clasa Cuptorului pentru inutilitate.

Marcus face de asemenea schimbări în program. Se adaugă un parametru furType întreg la metoda createBread.







A patra oară vine managerului programatorilor. A citit doar una din cărțile din seria "Cunosc lumea". Interferența noilor informații și a PMBoK au dat un rezultat neașteptat. Managerul spune:
"Avem nevoie de cuptorul de gaz pentru a nu putea să coacem fără gaz."

Cum cei doi programatori au coace pâine

Boris apreciază fără îndoială că poate exista o singură sursă de gaz. Și pentru astfel de cazuri, există întotdeauna șablonul nostru preferat. El creează un singur GasSourceSingleton, și pentru a reduce conectivitatea, îl injectează prin interfața GasSource în GasOven. Hurray, el a folosit introducerea dependenței prin setter!

Modest de natură, Marcus creează un câmp privat de gaze la clasa Manager. Firește, trebuie să schimbați puțin logica metodei createBread, dar ce puteți face!

Dar câteva zile mai târziu managerul vine pentru a cincea oară și, lins buzele, spune:
- Avem nevoie de sobe pentru a coace plăcinte (separat - cu carne, separat - cu varză) și prăjituri.

Programatorii doresc, de asemenea, să mănânce, astfel încât să ia de lucru.

Cum cei doi programatori au coace pâine

Boris începe deja să simtă așa ceva, dar nu se poate opri. Cum află soba ce exact are nevoie pentru a găti? Se pare că are nevoie de un bucătar. Și Boris, nu pentru mult timp (și poate pentru o lungă perioadă de timp) gândind, el creează clasa Cook. El va avea o metodă de gătit, luând pe un cuptor abstract - bucătar (owen: AbstractOwen): Produs. La urma urmei, este logic - bucătarul ia cuptorul și se pregătește cu el. Apoi Boris creează mai mulți moștenitori ai clasei de produse - Cake and Pasty, iar de la Pasty moștenește MeatPasty și CabbagePasty. Și apoi pentru fiecare tip de produs creează un bucătar separat - BreadCook, PastyCook și CakeCook.

Se pare că este normal, dar a fost nevoie de mult mai mult timp decât pentru Marcus, care a adăugat pur și simplu un alt parametru întreg la metoda createBread - breadType.

A șasea oară vine managerul. Apropo, ceea ce cere acum nu este cerința clientului, ci propria sa inițiativă. Dar nimeni nu va ști despre asta, nu?
- Avem nevoie de pâine, plăcinte și prăjituri pentru a fi coapte în funcție de diferite rețete.

Cum cei doi programatori au coace pâine

"Hmm," spune Boris și își amintește șablonul "constructor" (împreună cu "interfața liberă". Desigur). Creează o clasă de rețete, și pentru ea un constructor RecipeBuilder. Reteta el introduce (dintr-o dată!) În foc, cu ajutorul unui setRecipe setter (reteta: Rețetă).

Și Marcus (nu veți crede) adaugă încă un parametru întreg în createBread - rețetă.

Cel mai interesant, ca întotdeauna, se întâmplă departe de calculatoare. Anume: managerul întâlnește clientul pentru prima dată după începerea dezvoltării și în cele din urmă își dă seama de ce a fost nevoie de aragaz. El (managerul) pentru a șaptea oară vine la programatori și spune:
"Trebuie să ardem cărămizi în cuptor."

Cum cei doi programatori au coace pâine

Pentru Boris, aceasta este ultima intalnire cu managerul, dar totusi face cele mai recente schimbari in arhitectura. Alocă clasa abstractă AbstractHeatingSmth - încălzire abstractă. Pentru el, el creează o fabrica de încălzire. Din AbstractHeatingSmth, el moștenește ProductOven și Furance. Acesta din urmă are o metodă de fabricare a fabricației, care reprezintă un obiect din cărămidă. Dar nimic nu funcționează. Cititorul este invitat să găsească pe cont propriu o eroare în arhitectură.

Și la Marcus nu toate sunt așa de netede. Trebuie să creeze clasa a treia (!). El îl numește Brick și adaugă metoda MakeBrick managerului său.

Desigur, puteți argumenta că Marcus în cadrul metodei createBread creează Ad și Israel. și acest lucru este de fapt așa. Dar, cu ajutorul modelului "metodei șablonului", tulburarea poate fi complet structurată. Și în abundența de fabrici și abstracții de a înțelege, bine, un pic mai dificil.

Concluziile pe care vreau să le fac sunt probabil puțin previzibile.

Abordarea lui Boris este bună deoarece aproape fiecare parte a sistemului poate fi izolată și acoperită cu teste. Dar timpul pentru a crea un astfel de număr mare de clase va lăsa multe indecente, și fiecare schimbare cerințe se va transforma schimbarea codului în cascadă. O încercare de a face arhitectura flexibilă, anticipând dorințele clientului, de obicei nu reușește - arhitectura este îndoită complet. La urma urmei, după cum știm, "lumea nu este doar mai uimitoare decât ne imaginăm -
el este mai uimitor decât ne putem imagina. " Și, după ce a primit următoarea solicitare de schimbare, programatorul este convins de acest lucru ca nimeni altcineva.

Abordarea lui Marcus, în cele din urmă, nu permite utilizarea testelor unitare, dar dă rezultatul mult mai rapid, iar schimbările sunt date mai puțin de sânge. Aceasta abordare este cel mai rapid inceput pe care starii de toate dungile doresc. Și, destul de ciudat, într-un astfel de cod este într-adevăr mai ușor de înțeles, pentru că este mai ușor.

Și pentru a rescrie totul, dacă asta este întotdeauna de succes.







Articole similare

Trimiteți-le prietenilor: