Transcript

Практики написання коду

Simple

http://www.infoq.com/presentations/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/

top related