Documente Academic
Documente Profesional
Documente Cultură
Obiective
1. Principii SOLID.
1. Principii SOLID
S.O.L.I.D este un acronim pentru primele principii propuse de Robert C. Martin cu privire la proiectarea
aplicatiilor orientate obiect.
S – Single-responsiblity principle (principiul responsabilitatii unice)
O– Open-closed principle (principiul open closed)
L – Liskov substitution principle (principiul substitutiei Liskov)
I – Interface segregation principle (principiul segregarii interfetelor)
D – Dependency Inversion Principle (principiul inversarii dependentelor)
Aceste principii, utilizate impreuna, ajuta un programator sa dezvolte aplicatii care sunt usor de
intretinut si extins. Ele ajuta de asemenea programatorii sa reorganizeze usor codul si sa se adapteze
usor la modificarile de tehnologie.
Orice context (clasă, funcție, variabilă etc.) trebuie să aibă o unică responsabilitate, iar
această responsibilitate trebuie să fie în întregime încapsulată în context. Toate serviciile sale
trebuie să fie orientate pentru a servi această unică responsabilitate.
Astfel, este important să avem o clasă concentrată pe o unică responsabilitate pentru a o face
mai robustă. Pe exemplul de mai sus, o schimbare în modul de generare a raportului ar putea
produce erori în modul de tipărire, dacă aceste funcționalități fac parte din aceeaşi clasă.
Solutie
Aplicand SRP activitatea de logare poate fi mutata in alta clasa (FileLogger) care se va ocupa
doar de activitati de logare. Astfel, clasa Customer poate delega activitatea de logare catre clasa
FileLogger si se poate concentra doar pe activitatile legate de customeri.
class FileLogger
{
public void Handle(string error)
{
System.IO.File.WriteAllText(@"c:\Error.txt", error);
}
}
class Customer
{
private FileLogger obj = new FileLogger();
public void Add()
{
try
{
// Database code goes here
}
catch (Exception ex)
{
obj.Handle(ex.ToString());
}
}
}
1
EventViewer este componenta Windows unde se pot vizualiza logurile sistemului de operare Windows
1.2. O - Principiul deschis/închis (Open-closed principle - OCP)
Acest principiu implică ca entitățile software (clase, module, metode) să fie deschise pentru
extensie dar închise pentru modificare. Astfel, o entitate îşi poate extinde comportamentul fără
modificari în codul sursă.
Clasa Customer are o noua proprietate CustType care contine tipul customer-ului: 1 pentru un
customer de tip “Gold” sau 2 pentru un customer de tip “Silver”. In functie de acest tip se
calculeaza discount diferit in metoda getDiscount().
In conditiile in care apare un nou tip de customer („Bronze” de exemplu, cu discount doar de
25) trebuie modificata metoda getDiscount, deci trebuie MODIFICATA clasa Customer. La
fiecare astfel de schimbare trebuie sa verificam ca discount-urile sunt calculate corect pentru
vechile tipuri de customeri si ca aplicatiile care folosesc deja clasa Customer nu sunt afectate
de modificari.
class Customer
{
private int _CustType;
Solutie
Dacă S este un subtip al lui T, atunci obiectele de tip T pot fi substituite cu obiecte de tip S
fără a afecta niciuna din proprietățile programului (corectitudine, realizarea execuției etc.).
Consideram ca dorim sa calculam discountul si pentru posibilele cereri de oferta venite din
partea unor customeri generici. Aceste cereri nu se doresc a fi salvate in baza de date, prin
urmare implementarea va fi ca in secventa de mai jos. Clasa CerereOferta extinde clasa
Customer, supradefineste metoda getDiscount pentru a specifica discount-ul acordat si, de
asemenea, supradefineste metoda Add pentru a arunca o exceptie in caz de apel, deoarece aceste
cereri nu se doresc a fi salvate in baza de date.
class CerereOferta : Customer
{
public override double getDiscount(double TotalSales)
{
return base.getDiscount(TotalSales) - 5;
}
Solutie
Principiul LISKOV spune ca parintele ar trebui sa inlocuiasca cu usurinta copilul. Prin urmare,
pentru a implementa principiul LISKOV avem solutia prezentata mai jos: creare a doua
interfete: una pentru discount si una pentru accesul la baza de date.
interface IDiscount
{
double getDiscount(double TotalSales);
}
interface IDatabase
{
void Add();
}
Acest principiu afirmă că niciun client nu trebuie să fie forțat să depindă de metode pe care
nu le utilizează. Interfețele trebuie separate în alte interfețe mai mici şi mai specifice.
În exemplu de mai jos, clasa Robot este forțată să implementeze metoda eat. Putem introduce
o metodă care să nu facă nimic, dar pot apărea efecte nedorite în aplicație – de exemplu, rapoarte
care să arate mai multe mese servite decât numărul de oameni.
interface IWorker
{
void work();
void eat();
Solutie
Separarea interfeței Worker în două interfețe diferite are ca rezultat faptul că noua clasă Robot
nu mai este forțată să implementeze metoda eat.
interface IWorker
{
void work();
}
interface IEater
{
void eat();
}
class WorkerImpl : IWorker, IEater {
public void work()
{
// …
}
public void eat()
{
// …
}
}
class Robot : IWorker
{
public void work()
{
// …
}
}
Modulele de înalt nivel nu ar trebui să depindă de modulele de nivel scăzut. Ambele ar trebui
să depindă de abstracții.
In clasa Customer a fost utilizata clasa FileLogger pentru a respecta principiul SRP.
class Customer
{
private FileLogger obj = new FileLogger();
public void Add()
{
try
{
// Database code goes here
}
catch (Exception ex)
{
obj.Handle(ex.ToString());
}
}
}
In functie de setarile aplicatiei, vor fi utilizate loggere diferite la apelurile metodei Add. Pentru
a mentine codul simplu, s-a utilizat o conditie IF care decide ce clasa va fi instantiata.
Acest cod incalca principiul SRP, deoarece are o noua responsabilitate : sa decida ce obiect sa
creeze. Aceasta responsabilitate nu este specifica unui customer.
class Customer : IDiscount, IDatabase
{
private ILogger obj;
Solutie
class Program
{
static void Main(string[] args)
{
IDatabase i = new Customer(new EmailLogger());
}
}
Constructorul a devenit mai flexibil si permite trimiterea din exterior a obiectului folosit pentru
logare. In acest mod este responsabilitatea aplicatiei care utilizeaza clasa Customer sa decida
ce obiect de tip Logger sa injecteze.
Tema:
1. Proiectati clasele pentru proiectul propriu astfel incat sa respectati cat
mai multe din principiile de proiectare a aplicatiilor orientate obiect.
Bibliografie:
1. https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-principles-of-object-oriented-design
2. http://ctrl-d.ro/tips-and-tricks/programarea-orientata-pe-obiect-si-dezvoltarea-de-aplicatii-
5-principii-de-design/
3. https://blogs.msdn.microsoft.com/cdndevs/2009/07/15/the-solid-principles-explained-with-
motivational-posters/
4. https://www.codeproject.com/Articles/703634/SOLID-architecture-principles-using-simple-
Csharp#WhatisSOLID