SlideShare una empresa de Scribd logo
1 de 44
Descargar para leer sin conexión
Костадин Голев 
@kotseto 
github.com/kotse 
WRITING SOLID CODE 
преразказ с елементи на разсъждение
SOLID CODE ДИЗАЙН ПРИНЦИПИ 
• Първоначално наречени “първите 
пет принципа” от чичо Боб 
• SOLID e акроним, съставен от 
първата буква на всеки принцип 
• Целят да ни помогнат да пишем код, 
който е по-лесен за четене, 
поддръжка и надграждане
КОИ СА SOLID ПРИНЦИПИТЕ? 
• (S)ingle Responsibility Principle 
• (O)pen-Closed Principle 
• (L)iskov Substitution Principle 
• (I)nterface segregation Principle 
• (D)ependency inversion Principle
КАК ГИ ИЗПОЛЗВАМЕ? 
• Не са правила или закони 
• Идеи, които ни помагат в взимане на решения 
• Служат като средство да комуникираме дизайна на 
кода, който пишем 
• Ако имаме усещането, че един код е добър или лош, 
често можем да намерим принцип, който да обясни 
това
КРУШКАТА И ВЕНТИЛАТОРА
SINGLE RESPONSIBILITY PRINCIPLE 
Всеки клас/функция/променлива трябва да прави 
едно нещо и да го прави добре 
По-просто - само една причина да се промени
class TaxiService { 
public void orderTaxi(String phoneNumber, String address) { 
if (phone.length() < 7 
|| phone.length() > 12 
|| phone.contains(BAD_CHARACTERS)) { 
throw new Exception("Phone number not valid!"); 
} 
Taxi taxi = taxiPool.getTaxi(address); 
smsClient.sendMessage(phoneNumber, “Taxi on the way!”); 
} 
}
class TaxiService { 
boolean validatePhoneNumber() { 
if (phone.length() < 7 
|| phone.length() > 12 
|| phone.contains(BAD_CHARACTERS)) { 
return false; 
} 
return true; 
} 
public void orderTaxi(String phoneNumber, String address) { 
if (!validatePhoneNumber(phoneNumber)) { 
throw new Exception("Phone number not valid!"); 
} 
Taxi taxi = taxiPool.getTaxi(address); 
smsClient.sendMessage(phoneNumber, “Taxi on the way!”); 
} 
}
class SMSService { 
boolean validatePhoneNumber() { 
if (phone.length() < 7 
|| phone.length() > 12 
|| phone.contains(BAD_CHARACTERS)) { 
return false; 
} 
return true; 
} 
void sendSms(String phoneNumber, String message) { 
smsClient.sendMessage(phoneNumber, “Taxi on the way”); 
} 
}
class TaxiService { 
SMSService smsService; 
public void orderTaxi(String phoneNumber, String address) { 
if (smsService.validatePhoneNumber(phoneNumber)) { 
throw new Exception("Phone number not valid!"); 
} 
Taxi taxi = taxiPool.getTaxi(address); 
smsService.sendSMS(phoneNumber, “Taxi on the way!”); 
} 
}
SUMMARY 
• Може би най-труден за прилагане от петте 
принципа 
• По-четим и лесен за преизползване код 
• Код в един метод се асоциира с името на метода 
• Името на всеки метод се асоциира с името на 
класа
СТАРИЯ ТЕЛЕВИЗОР
OPEN-CLOSED PRINCIPLE 
Кодът, който пишем трябва да е отворен за 
разширение и затворен за модификация
class PaymentService { 
int calculatePayment (int amount, Customer customer) { 
double discount = 0; 
switch (customer.type()) { 
case SILVER : discount = 0.1; break; 
case GOLD : discount = 0.2; break; 
... 
... 
} 
amountToPay = amount - amount*discount; 
return amountToPay; 
} 
}
class Customer { 
double getDiscount() { 
return 0; 
} 
} 
class SilverCustomer extends Customer { 
double getDiscount() { 
return 0.1; 
} 
} 
class GoldCustomer extends Customer { 
double getDiscount() { 
return 0.2; 
} 
}
class PaymentService { 
int calculatePayment (int amount, Customer customer) { 
double discount = customer.getDiscount(); 
amountToPay = amount - amount*discount; 
return amountToPay; 
} 
}
SUMMARY 
• Вместо да променяме код, който вече работи, 
надграждаме го 
• Използваме наследяване за целта 
• Нарушаване на принципа води до много трудна 
поддръжка на кода, тъй като една малка промяна 
в един клас води до множество промени в други
САЛАТЕНИЯ БАР
LISKOV SUBSTITUTION PRINCIPLE 
Обектите в програмата могат да бъдат заменени 
от наследниците им без промяна в тяхното 
поведение
public interface Duck { 
public void papa(); 
} 
public class RealDuck implements Duck { 
public void papa() { 
//papa code goes here! 
} 
} 
public class ElectricDuck implements Duck { 
public void papa() { 
if (turnedOn) { 
//papa code goes here! 
} 
} 
}
Duck realDuck = new RealDuck(); 
duck.papa(); //works! 
Duck electricDuck = new ElectricDuck(); 
duck.papa(); //does not work! 
if (duck instanceof ElectricDuck) { 
((ElectricDuck)duck).turnOn(); 
} 
duck.papa(); //now works!
class ElectricDuck implements Duck { 
public void turnOn() { 
turnedOn = true 
} 
public void papa() { 
if (!turnedOn) { 
turnOn(); 
} 
//papa code goes here! 
} 
} 
Duck duck = new AnyKindOfDuck(); 
duck.papa(); //just works with all Ducks now!
SUMMARY 
• Ако бъде нарушен, даден обект нарушава 
обичайното си “поведение” 
• На практика представлява допълнение към 
Open-Closed принципа, като ни "повелява", че 
не можем едновременно да надградим един 
модул и да променим неговото поведение
КНИГАТА С РЕЦЕПТИ
INTERFACE SEGREGATION PRINCIPLE 
Не принуждавайте кода си за зависи от неща, от 
които няма нужда
public interface Worker { 
public void work(); 
public void getPaid(); 
} 
public class RegularWorker implements Worker { 
public void work() {} 
public void getPaid() {} 
} 
public class Manager { 
Worker worker; 
public void setWorker(Worker worker) { 
this.worker = worker; 
} 
public manage () { 
worker.work(); 
} 
}
public class Robot implements Worker { 
public void work() {} 
public void getPaid() {} ??? 
}
interface IWork { 
public void work(); 
} 
interface IGetPaid { 
public void getPaid(); 
} 
class Worker implements IWork, IGetPaid { 
@Override 
public void work() { 
} 
@Override 
public void getPaid() { 
} 
} 
class Robot implements IWork { 
@Override 
public void work() { 
} 
}
class Manager { 
IWork worker; 
void setWorker(IWork worker) { 
this.worker = worker; 
} 
void manage() { 
worker.work(); 
} 
}
SUMMARY 
• Да се пише код, който да е лесен за разбиране е 
не по-малко важно от това кода да работи 
• Интерфейсите ни помагат да опишем как трябва 
да работи кода, който пишем 
• Множество малки интерфейси е по-добре от това 
да имаме един голям т.нар "замърсен" интерфейс
ФАБРИКАТА В ЛОВЕЧ
DEPENDENCY INVERSION PRINCIPLE 
Зависимостите в кода е добре да се основават на 
абстракции, а не конкретни неща 
Модулите на по-високо ниво в кода не трябва да 
зависят от тези на по-ниско
public class Steed5 { 
Diesel130HPEngine engine; 
public Steed5() { 
engine = new Diesel130HPEngine(); 
} 
public void start() { 
engine.ignition(); 
} 
} 
Steed5 car = new Steed5(); 
car.start();
public class Steed5V8 { 
V8Engine engine; 
public Steed5V8() { 
engine = new V8Engine(); 
} 
public void start() { 
engine.ignition(); 
} 
}
public interface Engine { 
public void ignition(); 
} 
public class V8Engine implements Engine { 
public void ignition () {} 
} 
Engine engine = new V8Engine(); 
Steed5 car = new Steed5(engine); 
car.start();
public class Steed5 { 
Engine engine; 
public Steed5(Engine engine) { 
this.engine = engine; 
} 
public void start() { 
engine.ignition(); 
} 
}
SUMMARY 
• При нарушаване на принципа поддръжката на 
кода се затруднява значително 
• Ако един модул се променя, той не трябва да 
променя модулите на по-високо ниво от 
неговото
Благодаря за вниманието!

Más contenido relacionado

Similar a Presentation on SOLID design principles

Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функцииКурс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функцииDAVID Academy
 
Dependency injection Pattern Lecture
Dependency injection Pattern LectureDependency injection Pattern Lecture
Dependency injection Pattern LectureLachezar Lechev
 
Училищен курс по програмиране на C# (2013/2014), занятие №11
Училищен курс по програмиране на C# (2013/2014), занятие №11Училищен курс по програмиране на C# (2013/2014), занятие №11
Училищен курс по програмиране на C# (2013/2014), занятие №11DAVID Academy
 
Демо урок по програмиране със Светлин Наков
Демо урок по програмиране със Светлин НаковДемо урок по програмиране със Светлин Наков
Демо урок по програмиране със Светлин НаковSvetlin Nakov
 
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQLКурс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQLDAVID Academy
 
Училищен курс по програмиране на C# (2013/2014), занятие №2
Училищен курс по програмиране на C# (2013/2014), занятие №2Училищен курс по програмиране на C# (2013/2014), занятие №2
Училищен курс по програмиране на C# (2013/2014), занятие №2DAVID Academy
 
High Quality Code Introduction
High Quality Code IntroductionHigh Quality Code Introduction
High Quality Code IntroductionSvetlin Nakov
 
Nakov High Quality Code
Nakov High Quality CodeNakov High Quality Code
Nakov High Quality CodeSvetlin Nakov
 
Web applications with Catalyst BG
Web applications with Catalyst BGWeb applications with Catalyst BG
Web applications with Catalyst BGsvilen.ivanov
 

Similar a Presentation on SOLID design principles (12)

Writing SOLID Code
Writing SOLID CodeWriting SOLID Code
Writing SOLID Code
 
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функцииКурс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции
 
Dependency injection Pattern Lecture
Dependency injection Pattern LectureDependency injection Pattern Lecture
Dependency injection Pattern Lecture
 
Училищен курс по програмиране на C# (2013/2014), занятие №11
Училищен курс по програмиране на C# (2013/2014), занятие №11Училищен курс по програмиране на C# (2013/2014), занятие №11
Училищен курс по програмиране на C# (2013/2014), занятие №11
 
Демо урок по програмиране със Светлин Наков
Демо урок по програмиране със Светлин НаковДемо урок по програмиране със Светлин Наков
Демо урок по програмиране със Светлин Наков
 
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQLКурс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
 
Училищен курс по програмиране на C# (2013/2014), занятие №2
Училищен курс по програмиране на C# (2013/2014), занятие №2Училищен курс по програмиране на C# (2013/2014), занятие №2
Училищен курс по програмиране на C# (2013/2014), занятие №2
 
C++ OpenFest 2015
C++ OpenFest 2015C++ OpenFest 2015
C++ OpenFest 2015
 
High Quality Code Introduction
High Quality Code IntroductionHigh Quality Code Introduction
High Quality Code Introduction
 
Nakov High Quality Code
Nakov High Quality CodeNakov High Quality Code
Nakov High Quality Code
 
Web applications with Catalyst BG
Web applications with Catalyst BGWeb applications with Catalyst BG
Web applications with Catalyst BG
 
Why do we need a language like go?
Why do we need a language like go?Why do we need a language like go?
Why do we need a language like go?
 

Presentation on SOLID design principles

  • 1. Костадин Голев @kotseto github.com/kotse WRITING SOLID CODE преразказ с елементи на разсъждение
  • 2. SOLID CODE ДИЗАЙН ПРИНЦИПИ • Първоначално наречени “първите пет принципа” от чичо Боб • SOLID e акроним, съставен от първата буква на всеки принцип • Целят да ни помогнат да пишем код, който е по-лесен за четене, поддръжка и надграждане
  • 3. КОИ СА SOLID ПРИНЦИПИТЕ? • (S)ingle Responsibility Principle • (O)pen-Closed Principle • (L)iskov Substitution Principle • (I)nterface segregation Principle • (D)ependency inversion Principle
  • 4. КАК ГИ ИЗПОЛЗВАМЕ? • Не са правила или закони • Идеи, които ни помагат в взимане на решения • Служат като средство да комуникираме дизайна на кода, който пишем • Ако имаме усещането, че един код е добър или лош, често можем да намерим принцип, който да обясни това
  • 6. SINGLE RESPONSIBILITY PRINCIPLE Всеки клас/функция/променлива трябва да прави едно нещо и да го прави добре По-просто - само една причина да се промени
  • 7.
  • 8. class TaxiService { public void orderTaxi(String phoneNumber, String address) { if (phone.length() < 7 || phone.length() > 12 || phone.contains(BAD_CHARACTERS)) { throw new Exception("Phone number not valid!"); } Taxi taxi = taxiPool.getTaxi(address); smsClient.sendMessage(phoneNumber, “Taxi on the way!”); } }
  • 9. class TaxiService { boolean validatePhoneNumber() { if (phone.length() < 7 || phone.length() > 12 || phone.contains(BAD_CHARACTERS)) { return false; } return true; } public void orderTaxi(String phoneNumber, String address) { if (!validatePhoneNumber(phoneNumber)) { throw new Exception("Phone number not valid!"); } Taxi taxi = taxiPool.getTaxi(address); smsClient.sendMessage(phoneNumber, “Taxi on the way!”); } }
  • 10. class SMSService { boolean validatePhoneNumber() { if (phone.length() < 7 || phone.length() > 12 || phone.contains(BAD_CHARACTERS)) { return false; } return true; } void sendSms(String phoneNumber, String message) { smsClient.sendMessage(phoneNumber, “Taxi on the way”); } }
  • 11. class TaxiService { SMSService smsService; public void orderTaxi(String phoneNumber, String address) { if (smsService.validatePhoneNumber(phoneNumber)) { throw new Exception("Phone number not valid!"); } Taxi taxi = taxiPool.getTaxi(address); smsService.sendSMS(phoneNumber, “Taxi on the way!”); } }
  • 12. SUMMARY • Може би най-труден за прилагане от петте принципа • По-четим и лесен за преизползване код • Код в един метод се асоциира с името на метода • Името на всеки метод се асоциира с името на класа
  • 14. OPEN-CLOSED PRINCIPLE Кодът, който пишем трябва да е отворен за разширение и затворен за модификация
  • 15.
  • 16. class PaymentService { int calculatePayment (int amount, Customer customer) { double discount = 0; switch (customer.type()) { case SILVER : discount = 0.1; break; case GOLD : discount = 0.2; break; ... ... } amountToPay = amount - amount*discount; return amountToPay; } }
  • 17. class Customer { double getDiscount() { return 0; } } class SilverCustomer extends Customer { double getDiscount() { return 0.1; } } class GoldCustomer extends Customer { double getDiscount() { return 0.2; } }
  • 18. class PaymentService { int calculatePayment (int amount, Customer customer) { double discount = customer.getDiscount(); amountToPay = amount - amount*discount; return amountToPay; } }
  • 19. SUMMARY • Вместо да променяме код, който вече работи, надграждаме го • Използваме наследяване за целта • Нарушаване на принципа води до много трудна поддръжка на кода, тъй като една малка промяна в един клас води до множество промени в други
  • 21. LISKOV SUBSTITUTION PRINCIPLE Обектите в програмата могат да бъдат заменени от наследниците им без промяна в тяхното поведение
  • 22.
  • 23. public interface Duck { public void papa(); } public class RealDuck implements Duck { public void papa() { //papa code goes here! } } public class ElectricDuck implements Duck { public void papa() { if (turnedOn) { //papa code goes here! } } }
  • 24. Duck realDuck = new RealDuck(); duck.papa(); //works! Duck electricDuck = new ElectricDuck(); duck.papa(); //does not work! if (duck instanceof ElectricDuck) { ((ElectricDuck)duck).turnOn(); } duck.papa(); //now works!
  • 25. class ElectricDuck implements Duck { public void turnOn() { turnedOn = true } public void papa() { if (!turnedOn) { turnOn(); } //papa code goes here! } } Duck duck = new AnyKindOfDuck(); duck.papa(); //just works with all Ducks now!
  • 26. SUMMARY • Ако бъде нарушен, даден обект нарушава обичайното си “поведение” • На практика представлява допълнение към Open-Closed принципа, като ни "повелява", че не можем едновременно да надградим един модул и да променим неговото поведение
  • 28. INTERFACE SEGREGATION PRINCIPLE Не принуждавайте кода си за зависи от неща, от които няма нужда
  • 29.
  • 30. public interface Worker { public void work(); public void getPaid(); } public class RegularWorker implements Worker { public void work() {} public void getPaid() {} } public class Manager { Worker worker; public void setWorker(Worker worker) { this.worker = worker; } public manage () { worker.work(); } }
  • 31. public class Robot implements Worker { public void work() {} public void getPaid() {} ??? }
  • 32. interface IWork { public void work(); } interface IGetPaid { public void getPaid(); } class Worker implements IWork, IGetPaid { @Override public void work() { } @Override public void getPaid() { } } class Robot implements IWork { @Override public void work() { } }
  • 33. class Manager { IWork worker; void setWorker(IWork worker) { this.worker = worker; } void manage() { worker.work(); } }
  • 34. SUMMARY • Да се пише код, който да е лесен за разбиране е не по-малко важно от това кода да работи • Интерфейсите ни помагат да опишем как трябва да работи кода, който пишем • Множество малки интерфейси е по-добре от това да имаме един голям т.нар "замърсен" интерфейс
  • 36. DEPENDENCY INVERSION PRINCIPLE Зависимостите в кода е добре да се основават на абстракции, а не конкретни неща Модулите на по-високо ниво в кода не трябва да зависят от тези на по-ниско
  • 37.
  • 38. public class Steed5 { Diesel130HPEngine engine; public Steed5() { engine = new Diesel130HPEngine(); } public void start() { engine.ignition(); } } Steed5 car = new Steed5(); car.start();
  • 39. public class Steed5V8 { V8Engine engine; public Steed5V8() { engine = new V8Engine(); } public void start() { engine.ignition(); } }
  • 40. public interface Engine { public void ignition(); } public class V8Engine implements Engine { public void ignition () {} } Engine engine = new V8Engine(); Steed5 car = new Steed5(engine); car.start();
  • 41. public class Steed5 { Engine engine; public Steed5(Engine engine) { this.engine = engine; } public void start() { engine.ignition(); } }
  • 42. SUMMARY • При нарушаване на принципа поддръжката на кода се затруднява значително • Ако един модул се променя, той не трябва да променя модулите на по-високо ниво от неговото
  • 43.