ABONAMENTE VIDEO REDACȚIA
RO
EN
Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 22
Abonament PDF

Perspective asupra principiilor în design-ul orientat pe obiecte

Cătălin Tudor
Principal Software Engineer
@IXIA



PROGRAMARE

Definiția entropiei pe care cu siguranță am auzit-o cu toții nu lasă loc de interpretare: cu cât entropia este mai mare cu atât dezordinea și haosul încep să îsi facă de cap. Acest lucru înseamnă impredictibilitate care nu se numără cu siguranță printre calitățile dorite ale unui design bun. Cu toate acestea, după cum vom vedea în cele ce urmează, o entropie mare (si aici mă refer la entropia Shannon și nu la versiunea sa termodinamică, deși există similitudini între cele două) nu este defectul principal al unui design prost.

De fapt, folosind ca reper doar entropia design-ului în ansamblul, nu suntem în măsură să spunem foarte multe despre acel design, putem spune de exemplu că el rezolvă o anumită problemă care are nevoie de un anumit număr de stări. Poate părea contraintuitiv, dar pentru a obține un design bun clasele care moștenesc alte clase trebuie să aibă o entropie mai mare decât cea a claselor de bază, orice încercare de a reduce entropia într-o clasă derivată va duce în general la situații de strong-coupling și la un comportament ciudat, în general complicat și nedorit.

Scopul acestui articol este să studieze modul în care principiile binecunoscute de OOD (Object Oriented Design) influențează entropia locală a designului.

Voi începe cu Principiul Substituției Liskov (LSP) pentru că influența entropiei este observabilă într-un mod clar și permite exemplificări concrete.
În câteva cuvinte, LSP este o regulă care ajută programatorii să decidă când anume o clasă poate moștenească o altă clasă. Unul dintre cele mai cunoscute exemple de încalcare LSP este următorul:
Imaginați-vă că ați creat o aplicație care gestionează dreptunghiuri. Aplicația are un success atât de mare încât utilizatorii solicită un nou feature pentru ca aplicația să poată gestiona și pătrate.

Știind că un pătrat este un dreptunghi cu toate laturile egale, cea mai la îndemâna alegere de a extinde design-ul este să folosim moștenirea. Astfel, adăugăm o nouă clasa numita Square care va moșteni clasa Rectangle, în acest fel putem reutiliza toate funcționalitățile deja implementate.

class Rectangle
{
public:
  void SetWidth(double w) {
    width = w; }

  double GetWidth() const { 
    return width; }
 
 void SetHeight(double h) { 
    height = h; }

  double GetHeight() const { 
    return height; }        

private:
  double height;
  double width;
};

In Square suprascriem SetWidth si SetHeight pentru a ne asigura că cele patru laturi sunt egale.

void Square::SetWidth(double w)
{
   Rectangle::SetWidth(w);
   Rectangle::SetHeight(w);
}
void Square::SetHeight(double h)
{
   Rectangle::SetHeight(h);
   Rectangle::SetWidth(h);
}

Această alegere nu este una fericită insă nu voi insista asupra motivelor clasice. Vă voi arăta însă o altă perspectivă a implicațiilor acestei alegeri de extindere a design-ului, din punctul de vedere al variației entropiei.

Mai întâi, câteva cuvinte despre entropie. Entropia Shannon este o măsură a incertitudinii asociată unei variabile aleatoare și este de obicei măsurată în biți. Remarcați că este aceeași unitate de măsura folosită pentru a determina capacitatea memoriei sau lățimea de bandă pentru transferul in rețea. În cazul în care acestă observație nu vi se pare suprinzătoare, aflați că o singură aruncare a unei monede (datul cu banul) are o entropie de un bit! Entropia măsoară cantitatea de informație necesară pentru a reprezenta toate stările unei variabile aleatoare.

Pentru cantități mici de informație putem identifica reguli simple de reprezentare concisă a tuturor stărilor variabilei. Însă în cazul haosulului sau al secvențelor de numere aleatorii avem de a face cu entropii uriașe, adevărate explozii de informație unde nu există reguli simple pentru a anticipa, de exemplu, următorul număr din secvență.

[Vă oferim câteva detalii legate de asemănărea dintre entropia din termodinamică și entropia Shannon. În final,ambele reprezintă de fapt același lucru. Imaginați-vă un container cu două lichide (unul alb și unul negru) separate de un perete. După îndepărtarea peretelui lichidele se amestecă, prin urmare entropia termodinamica crește. Din punctul de vedere al teoriei informației, identificarea poziției fiecărei particule în raport cu poziția sa inițială față de peretele despărtitor (la stânga sau la dreapta de acesta) necesită mult mai multă informație decât atunci când lichidele nu sunt amestecate.]

Există, de asemenea, o definiție și o formulă pentru calculul entropiei:
Pentru o variabilă aleatoare X cu n valori posibile (x1, x2, x3…, xn) entropia Shannon (notata cu H (X)) se poate calcula după formula:

unde p(xi) reprezintă probabilitatea ca variabila aleatoare să ia valoarea xi.

Să luăm câteva exemple în scopul de a căpăta o înțelegere asupra a ceea ce reprezintă formula și de ce are sens să măsurăm entropia în biți.

[Mai exact, în funcție de baza logaritmului entropia este măsurată în biți (baza 2), nats (baza e) sau in bans (pentru baza 10)]

Exemplul 1

Cât de multă informație este necesară pentru a stoca o variabilă aleatoare X care

ia valori în mulțimea {0, 1}? Considerăm [Aceasta înseamnă ca 0 și 1 au aceeași șansă, 50%, de a fi atribuite lui X].

Exemplul 2

Cât de multă informație este necesară pentru a stoca o variabilă aleatoare X care ia valori în mulțimea {00, 01, 10, 11}? Luăm în considerare

[Aceasta înseamnă că toate valorile au aceeași șansă, 25%, de a fi atribuite lui X]. Formula ne spune că

[Întrebați-vă dacă stiți definiția bitului. Definiția nu este evidentă însă fiecare programator crede că o cunoaște (este într-un fel amuzant când realizezi că poate nu ți-ai pus niciodată această întrebare)]

Dacă s-au mai clarificat lucrurile în privința entropiei, e important să vedem cum se aplică ea în analiza design-ului. Pentru început, vom încerca să răspundem la o întrebarea: Cât de mare este entropia clasei Rectangle? Analizăm domeniul în care ia valori, mai precis combinațiile posibile de lățime și înălțime. Vom folosi un caz simplificat în care acestea pot lua numai valorile 0 și 1. Se pare că putem defini clasa Rectangle ca o variabilă aleatoare XR={wh}, XR cu valori în multimea {00, 01, 10, 11} fiecare valoare reprezentând o combinație de lățime (w) și înălțime (h). Din exemplul anterior știm că entropia unei astfel de variabile aleatoare este egală cu 2.

H(XR)=2 (biți)

Cât de mare este entropia clasei Square? Observăm domeniul în care iau valori lățimea și înălțimea în cazul simplificat cu valorile permise 0 și 1. De asemenea, putem defini clasa Square ca o variabilă aleatoare XS={wh}, XS. În acest caz însă, entropia este diferită, deoarece lățimea și înălțimea nu mai variază în mod independent. De fiecare dată când este setată lățimea (w) este setată și înălțimea (h) cu aceeași valoare. Știm de la primul exercițiu că entropia este egala cu 1 în acest caz.

H(XS)=1 (bit)

Este momentul să identificăm prima regulă a modului în care entropia trebuie să varieze într-un design:
Ori de câte ori o clasă S (Square) extinde o clasă R (Rectangle), este necesar ca H(XS)>=H(XR). În cazul nostru 1=H(XS)R)=2 ! Ce se întâmplă de fapt când încălcăm "regula entropiei"?

  • Să presupunem că avem metoda (funcția) m care folosește obiecte de tip R.
  • În cazul în care clasa S extinde clasa R prin încălcarea regulii entropiei, atunci metoda m va trebui să plătească prețul entropiei lipsă din clasa S (a se citi strong-coupling, de exemplu un scenariu posibil este adăugarea de if-uri prin care să se discrimineze între Square și Rectangle).

[Aici aspectul important este modul în care designul crește entropia, deoarece haos-ul și dezordinea din interiorul codului provine și din modul în care entropia este crescută, structurată și utilizată în cadrul claselor.]

Un exemplu din lumea reală

Putem exemplifica regula entropiei folosind o ușă. Ce anume face o ușă? Care este comportamentul ei? Evident o ușă se deschide (dacă nu cumva este blocată) și folosește interiorul unei camere pentru a face acest lucru. Iată un mod simplu de a scrie aceasta în cod:

class Door
{
  void Open(Room r)
  {
  …. the door opens inside the room
  }
}

Imaginați-vă că entropia camerei este proporțională cu volumul său. Ce s-ar întâmpla dacă am extinde clasa Room prin reducerea entropiei (a volumului)? Să numim această nouă clasa FakeRoom. Ei bine ... următoarea imagine vorbește de la sine.

Informația (entropia) lipsă din noua camera ajunge să fie codificată în ușă (partea de jos a fost decupată pentru a se putea deschide). Acum ușa și camera sunt cuplate (strong-coupling). Nu vom mai putea utiliza această ușă la o altă cameră fără a ridica semne de intrebare!

[Dezvoltatorii trebuie să înțeleagă că designul lor va arăta la fel ca sistemul din această imagine sfatul meu fiind să nu ignore aceste semne, vaza si florile nu sunt suficiente pentru a-l transforma într-un design bun.]

[Ne putem imagina un alt doilea exemplu, cu o pompă de apă si țevi de diferite dimensiuni.]

Concluzii

  1. Scăderea entropiei prin utilizarea moștenirii este un semn de încălcare a încapsulării unei clase.
  2. Agregarea este recomandată în locul moștenirii. Nu există o modalitate de a încălca regula entropiei atunci când se utilizează agregarea. Entropia poate fi variată după dorință.
  3. Să depinzi de abstractizări este o practică recomandată pentru că interfațele nu au o limită inferioară a entropiei.
  4. Matematicienii ar spune despre regula entropiei că este necesară dar nu și suficientă pentru a semnala o încălcare a LSP în sensul că, dacă ne supunem regulii am putea obține un design bun, în timp ce dacă încălcăm regula acest lucru duce cu siguranță la un design prost.
  5. Entropia design-ului este o perspectivă care poate îmbunătăți metodele deja existente de detectare a încălcării LSP.

LANSAREA NUMĂRULUI 149

Marți, 26 Octombrie, ora 18:00

sediul Cognizant

Facebook Meetup StreamEvent YouTube

NUMĂRUL 147 - Automotive

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects