Documente Academic
Documente Profesional
Documente Cultură
4. Faza de proiectare
Florin Leon
Universitatea Tehnică „Gheorghe Asachi” din Iași
Facultatea de Automatică și Calculatoare
http://florinleon.byethost24.com/curs_ip.htm
5
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Nivelurile proiectării
Arhitectura sistemului
Identificarea subsistemelor principale și a modului în
care comunică acestea
Are un impact major asupra performanțelor și
caracteristicilor sistemului
Module / componente
Partiționarea subsistemelor (un modul poate însemna
un namespace, un pachet, o bibliotecă de funcții etc.)
Interfețele publice (contracte)
6
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Nivelurile proiectării
Clase și tipuri de date
Proiectare mai puțin formală, mai ușor de schimbat
Tot trebuie să existe o fază distinctă de proiectare
Metode / funcții
Mai degrabă un exercițiu mental decât o procedură
documentată
Proiectarea explicită este necesară pentru algoritmi
deosebiți
7
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Calitatea proiectării
Presiunea comercială
Nu este niciodată timp să se
proiecteze corect, dar e întotdeauna
timp să se proiecteze de două ori
Codul proiectat corect este:
Mai ușor de scris
Mai ușor de înțeles
Mai ușor de corectat
Cu mai puține defecte
(erorile nu sunt ascunse)
Mai ușor de extins
8
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Proiectarea corectă: întrebări
Pentru orice problemă există mai multe variante de
proiectare
Va funcționa?
Deseori apar probleme neprevăzute
Este completă?
Abia când se încearcă implementarea soluției se înțelege de fapt
problema
Este cea mai bună soluție?
Este suficient de bună?
Pentru orice problemă se fac compromisuri
Performanțele se pot observa doar când sistemul este funcțional
9
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Compromisuri
Extensibilitate vs. simplitate
Niveluri suplimentare de generalitate
Eficiență vs. claritate
Creșterea cuplării pentru evitarea accesului indirect
Sistemele optimizate sunt mai puțin clare
Număr de trăsături vs. efort de dezvoltare
Mai multe trăsături au nevoie de mai mult efort
Prioritizarea depinde de cerințele proiectului
10
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Abordarea recomandată
Iterativă
Proiectare incrementală
Prudentă
Pași mici, număr limitat de decizii, localizarea erorilor
Realistă
Aplicarea metodologiilor, dar și utilizarea experienței
Rezultatul depinde de calitatea specificațiilor, experiența echipei
și rigoarea aplicării procedurilor
Informată
Trebuie înțelese complet cerințele și principiile problemei
Altfel, se poate rezolva altă problemă
11
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Faza de proiectare
1. Introducere
2. Arhitectura software
3. Proiectarea modulelor
4. Metrici de proiectare
5. Principii de proiectare
6. Șabloane de proiectare
7. Concluzii
13
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Componente și conexiuni
Componentele
Unitățile logice ale sistemului: clase, procese,
biblioteci, baze de date etc.
În mod ideal, o componentă îndeplinește un singur
scop (sau activitate)
Conexiunile
Apeluri de funcții, evenimente, mesaje ale sistemului
de operare sau din rețea (sincrone sau asincrone)
Unele comunicații sunt indirecte (de exemplu, prin
resurse partajate: variabile, fișiere)
14
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Rolul arhitecturii
Identifică modulele cheie și módul în care interacționează acestea
Nu cum funcționează intern
Identifică interfețele importante
Clarifică rolurile și responsabilitățile subsistemelor
Primul pas în trecerea de la domeniul problemei către domeniul soluției
De exemplu, la analiză: sistem distribuit; la proiectare: număr de mașini și
cum își vor împărți sarcinile
Compromis:
Informații în arhitectură vs. flexibilitate în fazele ulterioare
Arhitectura influențează:
Modul de lucru al echipelor (3 straturi ⇒ 3 echipe)
Evoluția produsului (reflectă capacitatea de adaptare a produsului la noi
cerințe)
15
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Calitatea arhitecturii
Simplă, ușor de înțeles, reprezentabilă vizual
Clară, fără ambiguități
Număr optim de componente
Prea multe: prea multe detalii
Prea puține: fiecare componentă face prea mult
(dificil de extins și întreținut)
Flexibilă, extensibilă, dar nu exagerat de generală
Consecință: aspect estetic plăcut
16
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Faza de proiectare
1. Introducere
2. Arhitectura software
3. Proiectarea modulelor
4. Metrici de proiectare
5. Principii de proiectare
6. Șabloane de proiectare
7. Concluzii
19
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Niveluri de cuplare
Cuplare prin conținut
Cuplare prin structuri comune
Cuplare prin control
Cuplare prin marcaj
Cuplare prin date
20
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea prin conținut
Modulele partajează codul: se int Func1(int a)
{
poate „sări” dintr-un modul în printf("In Func1\n");
a++;
codul celuilalt modul goto F2A;
return a;
Limbajele moderne de }
programare nu permit acest
lucru void Func2()
{
printf("In Func2\n");
F2A:
printf("At Func2A\n");
}
21
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea prin structuri comune
Modulele referențiază aceleași structuri de date globale (common
coupling) sau aceleași variabile globale (external coupling)
Module A
ReadCustomerRecord()
{
Read(customerRecord); Structura de date comună
if (eof) este customerRecord
eofFlag = true;
}
ModuleB
ValidateCustomerRecord()
{
if (customerRecord.Number is not numeric)
{
errorMessage = "invalid customer number";
PrintErrorReport();
}
} 22
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea prin control
Un modul trimite celuilalt modul o variabilă de control
care îi determină fluxul de execuție
Module A
ProcessInputCode()
{
Read(inputCode);
ChooseAppropriateAction(inputCode);
}
Module B
ChooseAppropriateAction(inputCode)
{
switch (inputCode)
{
case 1: ReadEmployeeRecord();
case 2: PrintPageHeadings();
case 3: OpenEmployeeMasterFile();
case 4: errorMessage = "Employee number not numeric";
} 23
}
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea prin marcaj
Un modul trimite celuilalt modul o structură de date
ca parametru
Module A
ProcessTransactionRecord()
{
if (transactionRecord is for a male)
ProcessMaleStudent(currentRecord);
else
ProcessFemaleStudent(currentRecord);
}
Module B
ProcessMaleStudent(currentRecord)
{
Structura de date trimisă este maleStudentCount++;
currentRecord if (currentRecord.studentAge > 21)
matureMaleCount++;
}
24
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplare prin date
Un modul trimite celuilalt modul variabile ca parametri
Module A
ProcessCustomerRecord()
{
CalculateSalesTax(totalPrice, salesTax);
}
Module B
CalculateSalesTax(totalPrice, salesTax)
{
if (totalPrice < 10)
salesTax = totalPrice * 0.25;
else if (totalPrice < 100)
salesTax = totalPrice * 0.3;
else
salesTax = totalPrice * 0.4;
}
25
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Factori ce afectează cuplarea
Gradul de cuplare dintre două module depinde
de complexitatea interfațării lor
Scop: cuplare slabă
Minimizarea numărului de interfețe ale unui modul
Minimizarea complexității interfețelor (numărul de
parametri)
Trimiterea ca parametri numai a câmpurilor necesare,
nu a unui întreg obiect
Evitarea comunicațiilor hibride: date și control
26
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Factori ce afectează cuplarea
Control
27
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea în sisteme orientate
pe obiecte
Cuplarea prin interacțiune
Se referă la apelul dintr-o metodă a unei clase a
unei metode din altă clasă
Accesarea secțiunilor interne
De exemplu, conceptul de friend din C++ violează
principiul încapsulării
Folosirea câmpurilor pentru a stoca date
temporare și nu starea obiectelor
Metodele comunică doar prin parametri
Sunt trimise numai date și numai variabilele necesare
28
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea în sisteme orientate
pe obiecte
Cuplarea prin compunere
O clasă folosește instanțe ale altor clase
Câmpuri, parametri: cuplare mai slabă
Variabile locale, invizibile din exterior: cuplare mai
puternică
Cuplarea cu o clasă A înseamnă cuplarea
potențială cu toate subclasele lui A
29
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cuplarea în sisteme orientate
pe obiecte
Cuplarea prin moștenire
Moștenirea poate reduce cuplarea generală din
sistem
A cuplată cu B, B are subclasele C, D
Dacă o metodă m este „ridicată” din C și D în B,
A va fi cuplată numai cu B, nu cu C și D
Pot fi adăugate fără probleme noi subclase ale lui B
Cuplarea minimă are loc când clasele derivate nu
modifică metodele moștenite, ci doar adaugă noi
metode
30
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea
Coeziunea arată cât de apropiate sunt
elementele aceluiași modul
Scop: coeziune puternică
În general, o coeziune puternică este corelată cu o
cuplare slabă
Întrucât există mai multe niveluri de coeziune
(prezentate în continuare), coeziunea unui
modul se consideră a fi nivelul maxim de
coeziune aplicabil elementelor acestuia
31
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Niveluri de coeziune
Coeziune prin coincidență
Coeziune logică
Coeziune temporală
Coeziune procedurală
Coeziune comunicațională
Coeziune secvențială
Coeziune funcțională
32
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea prin coincidență
FileProcessing()
Module create doar pentru a evita {
duplicarea codului din mai multe secțiuni Open(employeeUpdatesFile);
Read(employeeRecord);
Module rezultate prin partiționarea Print(pageHeadings);
Open(employeeMasterFile);
artificială a altor module (de exemplu, pageCount = 1;
conform criteriului ca un modul să }
errorFlag = false;
33
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea logică
Un modul conține funcții care ReadAllFiles(fileCode)
{
aparțin aceleiași clase logice, switch (fileCode)
{
adică toate elementele sale case 1:
realizează operații similare Read(customerTransactionRecord);
if (not eof)
De exemplu, tratarea tuturor customerTransactionCount++;
case 2:
intrărilor sau ieșirilor Read(customerMasterRecord);
Este nevoie de o variabilă de if (not eof)
customerMasterCount++;
control care să determine ce case 3:
Read(productMasterRecord);
instrucțiuni se execută în fiecare if (not eof)
caz (informații hibride, cuplarea productMasterCount++;
}
crește) }
34
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea temporală
Coeziunea temporală poate fi Initialisation()
{
privită ca un tip de coeziune Open(transactionFile);
Print("Enter today's date - DDMMYY");
logică în care timpul este Read(todaysDate);
elementul comun transactionCount = 0;
Read(transactionRecord);
Modulele conțin funcții asociate if (not eof)
transactionCount++;
în timp Open(reportFile);
Print(pageHeadings);
De obicei, sunt module de reportTotal = 0;
inițializare sau finalizare, iar }
35
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea procedurală
Modulele conțin funcții care aparțin ReadStudentRecordsAndTotalStudentAges()
{
unei unități procedurale comune numberOfRecords = 0;
totalAge = 0;
De exemplu, unele părți dintr-un Read(studentRecord);
while (more records exist)
modul sunt puse într-un nou {
modul: un bloc de decizie mai totalAge += age;
numberOfRecords++;
mare sau un bloc iterativ sunt Read(studentRecord);
plasate într-o altă metodă }
Print(numberOfRecords, totalAge);
Un modul poate avea doar părți }
38
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea funcțională
Toate elementele unui modul CalculateDiscount()
{
sunt utilizate pentru efectuarea if (product is rated zero discount)
unei singure funcții discount = 0;
else if (productPrice < 50)
discount = productPrice * 0.25;
else if (productPrice < 100)
discount = productPrice * 0.35;
else
discount = productPrice * 0.5;
}
39
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Comparație
40
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Coeziunea în sisteme orientate
pe obiecte
Coeziunea metodelor
Fiecare metodă implementează o funcție clar definită (coeziune
funcțională)
Coeziunea claselor
De ce sunt împreună atributele și operațiile în aceeași clasă
O clasă reprezintă un concept, dacă nu, metodele și câmpurile
pot fi partiționate în mai multe clase
Coeziunea moștenirilor
Coeziunea este mare dacă ierarhia urmărește generalizarea-
specializarea unui concept
Coeziunea este mică dacă scopul ierarhiei este doar partajarea
codului
41
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Faza de proiectare
1. Introducere
2. Arhitectura software
3. Proiectarea modulelor
4. Metrici de proiectare
5. Principii de proiectare
6. Șabloane de proiectare
7. Concluzii
Metrici:
Complexitatea ciclomatică
Metrica de coeziune
43
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Complexitatea ciclomatică
Ideea de bază:
Considerând două programe cu aceeași dimensiune, programul
cu mai multe instrucțiuni de decizie este probabil mai complex
Complexitatea ciclomatică: M = e – n + 2p
n = numărul de noduri
e = numărul de arce
p = numărul de componente conexe (pentru un modul, este 1)
Numărul ciclomatic: V = e – n + p
Dacă se adaugă un arc de la nodul final la nodul inițial,
astfel încât graful să devină tare conex, M = V
44
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplul 1
M = 10 – 7 + 1 = 4
45
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplul 2
public string Test1(int x) public string Test2(int x)
{ {
switch (x) var retValues = new string[] { "a", "b", "c", "d", "e", "f" };
{ if (x > 0 && x <= 6)
case 1: return "a"; {
case 2: return "b"; return retValues[x - 1];
case 3: return "c"; }
case 4: return "d"; return "other";
case 5: return "e"; }
case 6: return "f";
}
return "other";
}
M=7 M=3
46
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Efecte
Complexitatea ciclomatică a unui modul este
numărul de decizii + 1
Recomandare: M < 10
M este o estimare a numărului de căi care trebuie
testate în faza de testare
Această metrică este corelată cu dimensiunea
modulului și cu numărul de defecte
47
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
.NET Reflector
48
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
.NET Reflector
49
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Metrica de coeziune
Ideea de bază este de a vedea cum sunt folosite
variabilele unui modul de către codul modulului
Se construiește graful fluxului de control al modulului
I este nodul inițial
T este nodul final
Fiecare nod Si este adnotat cu variabilele pe care le
referențiază
Se utilizează acest graf pentru a calcula mulțimile de
referințe pentru fiecare variabilă: Ri = mulțimea de noduri
care referențiază variabila i a modulului
50
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Metrica de coeziune
Pentru fiecare Ri , se calculează coeziunea:
unde:
dim(S) este numărul tuturor căilor independente de la I la T
care includ cel puțin o instrucțiune din mulțimea S
G este mulțimea tuturor instrucțiunilor din modul care
referențiază cel puțin o variabilă
Dacă S = G, atunci dim(S) este complexitatea ciclomatică a
modulului
Altfel, dim(S) este numărul de decizii din mulțimea de instrucțiuni
+ 1 (complexitatea ciclomatică a mulțimii de instrucțiuni)
51
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Metrica de coeziune
Coeziunea unui modul cu n variabile este:
52
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu (același program)
53
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Faza de proiectare
1. Introducere
2. Arhitectura software
3. Proiectarea modulelor
4. Metrici de proiectare
5. Principii de proiectare
6. Șabloane de proiectare
7. Concluzii
SOLID
Single responsibility principle
Open-closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
55
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Principiul deschis-închis
O clasă trebuie să fie deschisă pentru
extindere, dar închisă pentru modificări
(Bertrand Meyer, 1998)
Codul nou trebuie adăugat ușor, dar fără a
modifica codul existent
56
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu: problemă
public class Rectangle se adaugă public class Circle
{ alte forme {
public double Width { get; set; } geometrice public double Radius { get; set; }
public double Height { get; set; } }
}
public static double Area(object[] shapes)
public class AreaCalculator {
{ double area = 0;
public static double Area(Rectangle[] shapes) foreach (var shape in shapes)
{ {
double area = 0; if (shape is Rectangle)
foreach (var shape in shapes) {
{ Rectangle rectangle = (Rectangle)shape;
area += shape.Width * shape.Height; area += rectangle.Width * rectangle.Height;
} }
return area; else
} {
} Circle circle = (Circle)shape;
area += circle.Radius * circle.Radius * Math.PI;
}
return area;
}
} 57
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu: soluție
public abstract class Shape public class Circle : Shape
{ {
public abstract double Area(); public double Radius { get; set; }
}
public override double Area()
public class Rectangle : Shape {
{ return Radius * Radius * Math.PI;
public double Width { get; set; } }
public double Height { get; set; } }
58
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Principiul substituției
Subclasele trebuie să fie substituibile claselor
lor de bază (Barbara Liskov, 1997)
Metodele care folosesc instanțe ale unor clase de
bază trebuie să poată folosi și instanțe ale
claselor derivate cu același efect
O clasă derivată trebuie să facă tot ceea ce face
clasa ei de bază (și ceva în plus)
59
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplul 1: rața electrică
public interface IDuck public class ElectricDuck : IDuck
{ {
void Swim(); private bool _isTurnedOn = false;
}
public void Swim()
public class BioDuck : IDuck {
{ if (!_isTurnedOn)
public void Swim() TurnOn();
{
Console.WriteLine("Swimming..."); if (_isTurnedOn)
} Console.WriteLine("Swimming...");
} }
61
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cazul 1
private static void Print(Ellipse e)
{
Console.WriteLine("Ellipse: rx = {0}, ry = {1}, a = {2:F2}", e.Rx, e.Ry, e.Area);
}
62
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Cazul 1
private static void Main(string[] args)
{
Ellipse e = new Ellipse(1, 2);
Console.WriteLine("Ellipse r = new Ellipse() -> Type " + e.GetType().Name);
Print(e);
e.Stretch(3);
Print(e);
Console.WriteLine();
Ellipse r = new Ellipse() -> Type Ellipse
Circle c = new Circle(1); Ellipse: rx = 1, ry = 2, a = 6.28
Console.WriteLine("Circle s = new Circle() -> Type " + c.GetType().Name); Ellipse: rx = 3, ry = 2, a = 18.85
Print(c);
c.Stretch(3); Circle s = new Circle() -> Type Circle
Print(c); Circle: rx = 1, (ry = 1), a = 3.14
Console.WriteLine(); Circle: rx = 1, (ry = 1), a = 3.14
public Circle(int r)
{
R = r;
}
68
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Soluția 2 (clase imutabile)
public class Ellipse
{
public int Rx { get; set; }
public int Ry { get; set; }
69
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Soluția 2 (clase imutabile)
public class Circle : Ellipse
{
public Circle(int r) : base(r, r)
{
}
70
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Soluția 2
private static void Main(string[] args)
{
Ellipse e = new Ellipse(1, 2);
Print(e);
e = e.Stretch(3);
Print(e);
Console.WriteLine(); Ellipse: rx = 1, ry = 2, a = 6.28
Ellipse: rx = 3, ry = 2, a = 18.85
Circle c = new Circle(1);
Print(c); Circle: rx = 1, (ry = 1), a = 3.14
e = c.Stretch(3); Ellipse: rx = 3, ry = 1, a = 9.42
Print(e);
Console.WriteLine(); Ellipse: rx = 1, ry = 1, a = 3.14
Ellipse: rx = 3, ry = 1, a = 9.42
Ellipse ec = c;
Print(ec); toate rezultatele sunt corecte,
ec = ec.Stretch(3); generalizarea este corectă,
Print(ec); iar cercurile pot fi convertite
Console.WriteLine(); în elipse
}
71
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Principiul inversiunii dependențelor
Clasele de nivel înalt nu trebuie să depindă
de clasele de nivel scăzut. Ambele trebuie să
depindă de abstracțiuni
Abstracțiunile nu trebuie să depindă de detaliile
concrete. Detaliile concrete trebuie să depindă de
abstracțiuni
72
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu: problemă
public class Worker public class SuperWorker
{ {
public void Work() public void Work()
{ {
// working // working more
} }
} }
74
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Principiul responsabilității unice
O clasă trebuie să aibă un singur motiv să se
modifice
O clasă trebuie să facă un singur lucru
75
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu: problemă
public class Customer
{
public void Add()
{
try
{
// database code
}
catch (Exception ex)
{
System.IO.File.WriteAllText("error.log", ex.ToString());
}
}
}
76
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu: soluție
public class Customer public class FileLogger
{ {
private FileLogger _logger = new FileLogger(); public void Handle(string error)
{
public void Add() System.IO.File.WriteAllText("error.log", error);
{ }
try }
{
// database code
}
catch (Exception ex)
{
_logger.Handle(ex.ToString());
}
}
}
77
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Principiul segregării interfețelor
Mai multe interfețe specifice pentru clienți
sunt mai bune decât o singură interfață de
uz general
Un client nu trebuie forțat să depindă de metode
pe care nu le folosește
78
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Exemplu public interface IPrinter
{
public interface IMachine void Print(List<Item> item);
{ }
void Print(List<Item> item);
void Staple(List<Item> item); public interface IStaple
void Fax(List<Item> item); {
void Scan(List<Item> item); void Staple(List<Item> item);
void PhotoCopy(List<Item> item); }
}
public interface IFax
{
void Fax(List<Item> item);
}
80
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Principii suplimentare
Principiul echivalenței lansare-reutilizare (release-reuse)
Granula pentru reutilizare este granula pentru lansare
Clasele reutilizabile trebuie grupate în pachete care pot fi
gestionate pe măsură ce versiunile evoluează
Principiul închiderii comune (common closure)
Clasele care se modifică împreună trebuie grupate împreună
Clasele trebuie grupate astfel încât coeziunea să fie mare
Principiul reutilizării comune (common reuse)
Clasele care nu sunt reutilizate împreună nu trebuie grupate
împreună
Clasele care se modifică determină o nouă versiune a întregului
pachet
81
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Euristici de proiectare
Dimensiunea unui modul este o indicație asupra
complexității acestuia
Modulele prea mari (≈ 100 linii) ar trebui partiționate
Modulele prea mici (≈ 2-3 linii) ar trebui combinate
...dar numai ținând cont de cuplarea și coeziunea
configurației rezultate
Fan-in (numărul de module care folosesc un modul)
și fan-out (numărul de module folosite de un modul)
Fan-in-ul trebuie maximizat
Fan-out-ul trebuie să fie < 5-6
82
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Caracteristicile unei proiectări
de calitate
Simplitatea
Cea mai importantă
Dimensiune redusă a codului
Codul bine proiectat pare evident, dar e greu de realizat
Eleganța
Aspect estetic
Fluxul de control este clar
Fiecare componentă adaugă ceva distinct
Lucrurile asemănătoare sunt asociate
Schimbările sunt localizate
Extensibilitatea
Structură logică și maleabilă
Interfețe, plug-in-uri dinamice
Echilibru: ce trebuie acum – ce va trebui în viitor – ce ar putea să
trebuiască în viitor
83
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Caracteristicile unei proiectări
de calitate
Modularitatea
Calitatea descompunerii
Lipsa duplicărilor
Copy-paste, apoi schimbările nu se fac în toate cazurile
Reinventarea roții
Generalizare: superclase, metode cu parametri
Portabilitatea
Nu trebuie compromisă calitatea codului dacă portabilitatea nu este
necesară
Abstractizarea secțiunilor neportabile (care depind de SO sau hardware)
Proiectare idiomatică
C++: supraîncărcarea operatorilor
C#: proprietăți
Proiectare bine documentată: specificații ale arhitecturii, API
84
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Faza de proiectare
1. Introducere
2. Arhitectura software
3. Proiectarea modulelor
4. Metrici de proiectare
5. Principii de proiectare
6. Șabloane de proiectare
7. Concluzii
86
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Șabloane software
Soluții generale reutilizabile la probleme care
apar frecvent în proiectare
Sunt descrieri despre cum se poate rezolva o problemă
Nu pot fi transformate direct în cod
Un șablon este o soluție la o problemă într-un
context
Contextul: situațiile recurente în care se aplică șablonul
Problema: scopurile și constrângerile
Soluția: regula de proiectare
87
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Conținutul unui șablon
Numele Contextul rezultant
Problema: obiectivele Justificarea: cum
Contextul: pre-condițiile funcționează intern și
Forțele: constrângerile de ce (soluția – extern)
care indică un Șabloanele înrudite
compromis, de unde și Exemple
apare nevoia de șablon Moduri de utilizare
Soluția: cum se ating cunoscute
obiectivele
88
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Tipuri de șabloane
Șabloane arhitecturale
Nivelul arhitecturii
Șabloane de proiectare
Nivelul modulelor/claselor
Idiomuri
Nivelul limbajului de programare
89
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Arhitectura multi-strat
poate fi la rândul
său multi-strat
90
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Arhitectura multi-nivel
Multi-strat = descompunere fizică:
dll, exe, mașini separate
91
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Arhitectura MVC
Model-Vizualizare-Controlor (Model-View-Controller, MVC)
92
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Varianta clasică
Modelul: conține datele, starea și logica aplicației. Deși nu
cunoaște Controlorul și Vizualizarea, furnizează o interfață
pentru manipularea și preluarea stării și poate trimite notificări cu
privire la schimbarea stării. De obicei primește cereri privind
starea datelor de la Vizualizare și instrucțiuni de modificare a
datelor sau stării de la Controlor
Vizualizarea: afișează Modelul într-o formă potrivită pentru
utilizator. Pentru un singur Model pot exista mai multe Vizualizări;
de exemplu, o listă de elemente poate fi afișată într-un control
vizual precum ListBox, într-o consolă sau într-o pagină web
Controlorul: primește intrările de la utilizator și apelează obiectele
Modelului pentru a prelucra noile informații
Pentru explicații suplimentare, vezi suportul de curs
93
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
O variantă modernă
Model-Vizualizare-Prezentator (Model-View-Presenter, MVP)
Stratul de prezentare constă în obiecte de Vizualizare, iar logica
aplicației constă în obiecte de control (Prezentator/Controlor)
Pentru fiecare obiect de vizualizare există un obiect de control
Modelul gestionează accesul la date
95
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Arhitectura orientată pe servicii
Funcționalitățile sunt separate în
unități distincte, numite servicii,
accesibile într-o rețea
Pot fi combinate și reutilizate
Scopul este tot cuplarea slabă
Interfațarea este deosebit de
importantă
Furnizorii de servicii se pot
înregistra la un broker, iar
consumatorii caută serviciile dorite
Mai mulți furnizori pot oferi același
serviciu: calitate, reputație
Servicii web: REST, SOAP
96
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Pipeline
Un lanț de elemente de prelucrare în care ieșirea unuia
corespunde cu intrarea următorului
De exemplu: dir | sort | more
Transformările sunt de obicei incrementale
Formatul de date este de obicei simplu, deseori text
Tratarea erorilor este mai dificilă
Utilizări:
Browsere
Aplicații de grafică
Interfețe grafice pentru programe consolă portabile
97
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Pipeline
Programare funcțională, F#
|> trimite rezultatul unei funcții următoarei funcții
enumFilesRec
(filterOutPaths ["c:\\Windows";"c:\\ProgramData";"c:\\Program Files"])
(filterExt [".jpg"; ".gif"])
"c:\\Multimedia"
|> Seq.groupBy (fun pth -> (Path.GetExtension pth, (FileInfo pth).Length))
|> Seq.filter (fun (_, s) -> (Seq.length s) > 1)
|> Seq.map (fun (_, sq) -> [for path in sq -> path])
|> Seq.map groupEqualFiles
|> Seq.map filterOutSingletons
|> Seq.collect Seq.ofList
|> Seq.iter (fun lst -> printfn "%A" lst)
http://bartoszmilewski.com/2011/01/05/using-f-sequences-and-pipelines/ 98
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Platforma
engl. “framework”
Pentru o bibliotecă tradițională, programul apelează
funcțiile din bibliotecă
Într-o platformă, apelul codului client este făcut de
către platformă
Exemple:
Platforma multi-agent JADE, care rulează agenții
înregistrați în așa-numitele “containere”
Tensorflow, în sensul că execută un graf computațional
(unii autori îl consideră bibliotecă)
99
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Blackboard (tablă)
Presupune existența mai multor „surse de
cunoaștere” specializate pe domenii
diverse
Mai întâi, pe tablă „se scriu” specificațiile
problemei
Fiecare sursă de cunoaștere (specialist)
caută ocazia de a contribui la rezolvarea
problemei
Când cineva scrie pe tablă ceva care
permite unui specialist să contribuie,
acesta scrie la rândul său soluția la
subproblema pe care o poate rezolva
Procesul de adăugare a contribuțiilor pe
tablă continuă până când problema este
rezolvată
100
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Blackboard (tablă)
Propusă inițial pentru rezolvarea unor probleme
complexe, insuficient definite
În general, folosită pentru unele aplicații legate de
inteligența artificială, de exemplu:
Sisteme militare de detectare și urmărire a obiectelor (C4ISTAR)
Vizualizare interactivă a datelor de la sateliți (RADARSAT-1)
Recunoașterea optică a caracterelor (Adobe Acrobat Capture)
Interpretarea datelor de la senzori, data fusion
Roboți mobili, planificare, învățare simbolică
101
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Șabloane de proiectare
Erich Gamma, Richard Helm, Ralph Johnson,
John Vlissides (“Gang of Four”, GoF): Elements
of Reusable Object-Oriented Software (1994)
102
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Clasificare
104
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Anti-șabloane
Abstraction inversion Anemic domain model
Input kludge BaseBean
Permite, de exemplu,
Circle-Ellipse problem
code injection (vezi slide-ul următor)
Interface bloat God object
Magic pushbutton Object orgy
Race hazard Poltergeists
Stovepipe system Yo-yo problem
106
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm
Concluzii
Faza de proiectare arată CUM dorim să construim
Se referă la domeniul soluției
Există trei tipuri de șabloane de proiectare, corespunzătoare
nivelurilor de generalitate ale proiectării:
Șabloane arhitecturale (pentru proiectarea arhitecturii)
Șabloane de proiectare (pentru proiectarea modulelor)
Idiomuri (pentru proiectarea detaliată)
Capacitatea de a proiecta bine vine din respectarea principiilor de
proiectare și din experiență
În general, proiectarea corectă asigură o cuplare slabă și o coeziune
puternică
Complexitatea ciclomatică a unui modul este numărul de decizii + 1
107
Florin Leon, Ingineria programarii, http://florinleon.byethost24.com/curs_ip.htm