Download - cpp-2013 #20 Best practices
Практики написання коду
Simple
http://www.infoq.com/presentations/Simple-Made-Easy
http://www.slideshare.net/evandrix/simple-made-easy
vector<vector<int>> getData(){ vector<vector<int>> vector1; for (auto x = vector.begin();
x != vector.end(); ++x) { if (x->at(0) == 4) { vector1.push_back(*x); } } return vector1;}
Це може бути легко(для вас)(зараз)
http://amzn.com/0132350882
http://amzn.com/0132350882
vector<vector<int>> getFlaggedCells(){ vector<vector<int>> flaggedCells; for (auto cell : gameBoard) { if (cell.at(STATUS) == FLAGGED) { flaggedCells.push_back(cell); } } return flaggedCells;}
Цей код легший для розуміння
vector<Cell> getFlaggedCells(){ vector<Cell> flaggedCells; for (auto cell : gameBoard) { if (cell.isFlagged()) { flaggedCells.push_back(cell); } } return flaggedCells;}
Цей код легший і простіший!
Цей код простіший
vector<Cell> getFlaggedCells(){ vector<Cell> flaggedCells; copy_if( begin(gameBoard), end(gameBoard), back_inserter(flaggedCells), [](Cell cell) { return cell.isFlagged(); }); return flaggedCells;}
Простота і складність об’єктивні і абсолютніЛегкість і важкість суб’єктивні і відносніСкладно – коли функція відповідає за декілька концепцій:
Що + ЯкI/O + бізнес правилаБД + бізнес правилаConcurrency + domain…
Idiomatic code
http://herbsutter.com/elements-of-modern-c-style/
Least surprise
http://en.wikipedia.org/wiki/Principle_of_least_astonishment
http://fomuvi.ru/zadachki/raznoobraznye-zadachki/xudozhnik-i-proxozhij.html
http://fomuvi.ru/zadachki/raznoobraznye-zadachki/xudozhnik-i-proxozhij.html
http://fomuvi.ru/zadachki/raznoobraznye-zadachki/xudozhnik-i-proxozhij.html
for (int i = 0; i < v.size(); i++){ cout << i << " " << v[i] << endl;}
for (int i = 0; v.size() - 1 >= i; ++i){ cout << i << " " << v[i] << endl;}
Side effects
Global mutable state
Coupling
Coupling (зв’язність)• Afferent– Скільки компонентів залежать від модуля– Показує наскільки модуль відповідальний
• Efferent– Від скількох компонентів залежить модуль– Показує наскільки модуль незалежний– Включає: наслідування, interface impl, типи
параметрів, типи змінних, exceptions,...• Ca and Ce є метриками стабільності
Instability I = Ce / (Ce + Ca)
• показує нестійкість до змін• 0 – стабільний модуль• 1 – нестабільний
Ce Ca
Cohesion (пов’язаність, зчеплення)• Показує наскільки сильні взаємозв’язки між
частинами одного модулю• Чи всі методи класу використовують всі
його поля• Низька пов’язаність:– Клас з багатьма статичними методами– “Несфокусований” клас
Cohesion
Кореляція: high complexity and low cohesion
Кореляція: complexity and number of defects
Low coupling + high cohesion сприяють легкому внесенню змін у ПЗ
Більшість шаблонів проектування є рецептами для зниження coupling та
підвищення cohesion
Dependencies
class Course{public: void Apply(shared_ptr<User> user) { auto application = new Application(/*...*/); //... auto email = new SmtpEmailSender(); email->send("New course application!", emailSettings.directorEmail()); }};
Course
SmtpEmailSender
High level module
Low level module
Depends on
class Course{private: IEmailSender* email;
public: Course(IEmailSender* email) : email(email) {}
void Apply(shared_ptr<User> user) { auto application = new Application(/*...*/); //... email->send("New course application!"); }};
Course
SmtpEmailSender
High level module
IEmailSender
Implements
Course
SmtpEmailSenderIEmailSender
Application
Course
SmtpEmailSender
High level module
IEmailSender
Dependency is inverted
Dependency inversion• High level modules should not depend on
low-level modules• Both should depend on abstractions• Abstractions should not depend on details• Details should depend on abstractions
Що отримуємо• Залежності вказуються явно, немає прихованих
залежностей• Класи самодокументовані• Класи більше не відповідають за створення об’єктів• Після створення клас гарантовано знаходиться у
робочому стані• Легко знаходити класи з багатьма параметрами в
конструкторі (і зменшувати їх відповідальності)• Легше знаходити методи, яким потрібні не всі
залежності класу
Lower coupling
class UsersImporter{public: void import() { auto importContext =
new ImportContext(currentUserName); // ... fileImporter->import(); // ... }};
? Залежить від ImportContext
? Тип повинен визначатись залежно від ImportContext
? Потрібно керувати часом життя FileImporter’а
void import(){ auto importContext = new ImportContext(currentUserName); // ... IFileImporter* fileImporter = new CsvFileImporter(importContext); fileImporter->import(); // ... delete fileImporter;}
Abstract Factory. Потреба:• Залежність залежить від параметра, який не
відомий клієнту на час його створення• if/else та switch блоки для вирішення, яку
залежність створити• Залежність потрібно до-ініціалізувати• Об’єкт повинен керувати часом життя
залежності
UsersImporter
CsvFileImporter
IFileImporter
UsersImporter
CsvFileImporter
IFileImporterFactory
IFileImporter
FileImporterFactory
Lowering coupling:simpler
but sometimes harder
Broken windows
http://en.wikipedia.org/wiki/Broken_windows_theory
Code Complete, Steve McConnellhttp://amzn.com/0735619670http://www.ozon.ru/context/detail/id/5508646/
Clean Code, Robert C. Martinhttp://amzn.com/0132350882http://www.ozon.ru/context/detail/id/6733562/