SlideShare a Scribd company logo
HWdTech, LLC
обоснование с помощью логики Хоара
S.O.L.I.D.
14 лет преподаю
ИМИТ, ФКН ОмГУ
ИТ-компании
Школа программиста
10 лет разрабатываю ПО
разработчик, архитектор,
PM, руководство до 70
человек
Тюменцев Евгений
Предыстория вопроса
Формулировка принципов, ключевые события
03
The Open-Closed Principle
Программные объекты должны
быть открыты для расширения, но
в тоже время закрыты для
модификации.
04
The Liskov Substitution Principle
Функции, которые используют
ссылки на базовые классы, должны
иметь возможность использовать
объекты производных классов, не
зная об этом.
05
Пример нарушения LSP 06
class Rectangle
{
double height, width;
public:
double getHeight() const { return height; }
virtual void setHeight(int value) { height = value;}
double getWidth() const { return width; }
virtual void setWidth(int value) { width = value; }
}
….
void f(Rectangle& r)
{
r.setHeight (5);
r.setWidth (4);
Debug.Assert(r.getHeight() * r.getWidth() == 20);
}
class Square extends Rectangle
{
public void setHeight(int value)
{
super.setHeight(value);
super.setWidth(value);
}
public void setWidth(int value)
{
super.setHeight(value);
super.setWidth(value);
}
}
class Square: public Rectangle
{
public:
virtual void setHeight(int value)
{
super.setHeight(value);
super.setWidth(value);
}
virtual void setWidth(int value)
{
super.setHeight(value);
super.setWidth(value);
}
}
The Dependency Inversion Principle
Высокоуровневые компоненты не
должны зависеть от низкоуровневых
компонент. И те, и те должны
зависеть от абстракций.
Абстракции не должны зависеть от
деталей. Детали должны зависеть
от абстракций.
07
Пример нарушения DIP 08
void Copy()
{
int ch;
while ((ch = Keyboard()) != EOF)
{
WritePrinter(c);
}
}
class Square extends Rectangle
{
public void setHeight(int value)
{
super.setHeight(value);
super.setWidth(value);
}
public void setWidth(int value)
{
super.setHeight(value);
super.setWidth(value);
}
}
enum OutputDevice
{
printer,
disk
};
void Copy(OutputDevice dev)
{
int c;
while ((c = ReadKeyboard()) != EOF)
{
if (dev == printer)
WritePrinter(c);
else
WriteDisk(c);
}
}
Пример соответствия DIP 09
class IReader
{
public:
virtual int Read() = 0;
}
class IWriter
{
public:
virtual void Write(char) = 0;
}
void Copy(IReader& r, IWriter& w)
{
int c;
while((c=r.Read()) != EOF)
w.Write(c);
}
The Interface Segregation Principle
Класс не должен зависеть от
интерфейсов, которые он не
использует.
10
Пример нарушения ISP 13
class matrix
{
public:
virtual int size() const = 0;
virtual void get_ij(int I, int j, double &value) const = 0;
virtual void set_ij(int I, int j, double value) = 0;
};
class diagonal: public matrix
{
public:
void set_ij(int I, int j, double value)
{
// ? Что делать, если i != j
}
};
The Single Responsibility Principle
Должна быть ровно одна причина для
изменения класса.
11
switch
If /else – if/else
enum
new
Операторы приведения типа
Магические константы
Примеры конструкций, нарушающих OCP 13
Что-о-о? switch,
new? Ты кто
такой?
LSP, OOPSLA’87
Если для каждого объекта o1
типа S существует объект o2
типа T, который для всех
программ P определен в
терминах T, то поведение P
не изменится, если o1
заменить на o2 при условии,
что S является подтипом T
История вопроса 15
Barbara Liskov
LSP, OOPSLA’87
1988, опубликованы в
Object-oriented Software
Construction
История вопроса 16
Bertran Meyer
LSP, OOPSLA’87
1988, опубликованы в
Object-oriented Software Construction
1994, A behavioral notion
of subtyping
История вопроса 17
Barbara Liskov
LSP, OOPSLA’87
1988, опубликованы в
Object-oriented Software Construction
1994, A behavioral notion of subtyping
1995-96, статьи в The
C++ Report
“Uncle Bob”
Автор названия
S.O.L.I.D.
История вопроса 18
Robert Martin
LSP, OOPSLA’87
1988, опубликованы в
Object-oriented Software Construction
1994, A behavioral notion of subtyping
1995-96, статьи в The C++ Report
2009, Spolsky VS Uncle Bob
they all sounded to me like
extremely bureaucratic
programming that came from
the mind of somebody that
has not written a lot of code…
История вопроса 19
Joel Spolsky
Выводимость и логика
Хоара
Доказательство свойств программ
20
Выводимость 21
Пусть L – множество формул, B – формула.
Тогда L ⊦ B, если ∃ B1, B2, …, Bn , что
1.Bn – это B,
2.Bi – это
либо формула из L,
либо аксиома,
либо общезначимая формула,
либо формула полученная при
помощи правила вывода
Исчисление высказываний 22
Modus Ponens (правило вывода) 23
1969 г. An Axiomatic Basis for
Computer Programming
1971 г. Procedures and Parameters:
An Axiomatic Approach
1980 г. премия Тьюринга
1990 г. Медаль “Пионер
компьютерной техники”
2000 г. рыцарский титул за заслуги в
области образования и
компьютерной техники, премия
Киото
Логика Хоара
Чарльз Хоар
24
{pred} statement {post}
Пример: {x == 42} y=x+1; {y == 43 ^ x == 42}
Тройка Хоара 25
{P} skip {P}
Аксиома пустого оператора 26
Пример: {(y+1)*3+w*(y+1+3) ==z}
x=y+1;
{ x*3+ w*(x+3)==z}
Аксиома оператора присваивания 27
{P[E/x]} x := E {P}
Аксиома оператора цикла 28
{P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}
Аксиома условного оператора 29
{B ^ P} S {Q}, {B’ ^P} T {Q}╞ {P} if B then S else T endif {Q}
{B ^ P} S {Q}╞ {P} if B then S endif {Q}
Аксиомы вывода 30
P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1}
P1 → P, {P} S {Q} ╞ {P1} S {Q}
{P} S {Q}, Q → Q1 ╞ {P} S {Q1}
Аксиома вывода и условный оператор 31
Пусть L = {{P} f {Q}}, B – предикат.
P^B→P (A3 исчисления
высказываний)
{P^B}f{Q} (аксиома вывода)
{P}if (B) then f endif {Q} (аксиома условного
оператора)
Неявные предположения 32
{P ^ B} с {Q}
{P} assert(B); c {Q}
Упрощение кода и аксиома вывода 33
node* insert(node& c, int v) {
node *n = new node;
n -> val = v;
if(c.next) {
n -> next = c.next;
}
else {
n -> next = 0;
}
c.next = n;
return n;
}
null
Аксиома оператора цикла 34
Закольцованный список с буферным элементом 35
node* insert(node& c, int v) {
node *n = new node;
n -> val = v;
if(c.next) {
n -> next = c.next;
}
else {
n -> next = 0;
}
c.next = n;
return n;
}
Закольцованный список с буферным элементом 36
node* insert(node& c, int v) {
node *n = new node;
n -> val = v;
n -> next = c.next;
c.next = n;
return n;
}
Аксиома композиции 37
{P} S {Q}, {Q} T {R} ╞ {P} S;T {R}
Контрактное программирование 38
• Предусловия
• Постусловия
• Инварианты
Модульные тесты 39
Arrange
Act
Assert
Рефакторинг 40
{P} S {Q}, {Q} T {R} ╞ {P} S;T {R}
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.
Если использовать
1. статическое связывание
2. Рекурсию
3. Вложенные процедуры
4. Процедуры, принимающие в качестве
параметров процедуры.
5. Глобальные переменные
то не существует полной системы аксиом.
Глобальные переменные 40
⊢ 𝐿 𝞿 и ⊢ 𝐿 `𝞿
Значит, что любое
изменение в коде надо
тестировать!
Противоречивость 40
Зависимости 40
Зависимости 40
Изменения – это проблема 40
int i = 0;
while( i < 100)
{
i = f();
}
int f()
{
return 20;
}
Зависимости 40
Зависимости 40
Так ли страшен hell… 40
24 марта https://habrahabr.ru/post/280099/
left-pad
«Многие разработчики не могли понять, что
случилось: они никогда не использовали такой
модуль. Однако его могли использовать другие
модули, о чем можно просто не догадываться»
https://meduza.io/feature/2016/03/28/kak-slomat-
internet
Введение любого нового
оператора при наличии
goto приводит к
противоречивости
goto и противоречивость 40
Вспоминаем про сложность разработки ПО 40
Фредерик Брукс
«Мифический человеко-
месяц»
Что делать? 40
SOLID – достаточное
условие линейной
производительности
S.O.L.I.D.
Математическое обоснование
41
Аксиома оператора цикла 42
Повторное использование кода — методология
проектирования компьютерных и других
систем, заключающаяся в том, что система
(компьютерная программа, программный
модуль) частично либо полностью должна
составляться из частей, написанных ранее
компонентов и/или частей другой системы, и
эти компоненты должны применяться более
одного раза (если не в рамках одного проекта,
то хотя бы разных).
https://ru.wikipedia.org/wiki/Повторное_использование_кода
Когда происходит повторное
использование?
Если нужно внести изменение в
существующее приложение, то мы
пытаемся повторно использовать свой
же собственный код, чтобы получить
тоже приложение, но с новой
функциональностью.
43
44
Выводимость прямо
предписывает строить новые
тройки из предыдущих!
Чем грозят правки кода? 45
B1, B2, …, A1
B3, A1, …, A2
B5, A2, …, A3
A2, B6, …, A4
A2, A4, …, A5
Программа рассыпается как карточный домик! 46
B1, B2, …, A1
B3, A1, …, A2
B5, A2, …, A3
A2, B6, …, A4
A2, A4, …, A5
Особенности разработки ПО 47
Фредерик Брукс
«Мифический человеко-месяц»
Из закрытости следует выводимость! 48
Программные объекты должны быть
открыты для расширения, но в тоже
время закрыты для модификации.
The Open-Closed Principle
Матрицы 49
class matrix {
int size;
double *body;
public:
matrix(int s): size(s) {
body = new double[s*s];
}
void transform() {
…
}
double det() const {
…
}
};
Матрицы: добавляем matrix() 50
class matrix {
int size;
double *body;
public:
matrix(int s): size(s) {
body = new double[s*s];
}
void transform() {
…
}
double det() const {
…
}
};
class matrix {
public:
matrix(): size(0), body(0) {
}
};
Матрицы: придется менять методы 51
class matrix {
int size;
double *body;
public:
matrix(): size(0), body(0) {
}
matrix(int s): size(s) {
body = new double[s*s];
}
void transform() {
if(!body) throw exception();
…
}
double det() const {
if(!body) throw exception();
…
}
};
53
Конструктор должен устанавливать
инвариант класса
Конструкторы по умолчанию часто этого не
делают
Стоит несколько раз подумать, прежде чем
использовать конструктор по умолчанию
Что случилось? 52
Инвариант класса matrix: size > 0
Конструктор matrix() нарушил инвариант: size = 0
Предусловия методов изменились с size > 0 на size ≥ 0, но
{size ≥ 0} det {Q} не выводится из {size > 0} det {Q}
Следовательно, надо изменять сами методы
Импликация на множестве 54
Пусть P1 → P,
B = { x | P1(x) = 1},
A = { x | P (x) = 1}.
Тогда B ⊂ A.
P ⊨ P1. Говорят, что P –
более слабое условие,
P1 – более сильное.
A
B
Построим вывод 55
{S} cb {P}, {P} c {Q}, {Q} ca {R} ⊦ {S} cb; c; ca {R}
Пусть P → P1, Q1 → Q
Известно, что
{S} cb {P}, {P1} c {Q1}, {Q} ca {R}
Тогда
{P} c {Q} (аксиома вывода)
{S} cb; c; ca {R}
А если импликации нет? 56
{S} cb {P}, {P} c {Q}, {Q} ca {R} ⊦ {S} cb; c; ca {R}
Пусть P ↛ P1, но P ^ P1 → P1
Известно, что
{S} cb {P}, {P1} c {Q}, {Q} ca {R}
Тогда
{P1} c {Q} ⊦ {P} if (P1) then c endif {Q}
{S} cb; if(P1) then c endif; ca {R}
Оператор расширения 57
Оператор расширения должен допускать:
1. Ослабление предусловий
2. Усиление постусловий
Метафора для оператора расширения 58
Для оператора расширения получаем 59
Высокоуровневые компоненты не
должны зависеть от низкоуровневых
компонент. И те, и те должны
зависеть от абстракций.
Абстракции не должны зависеть от
деталей. Детали должны зависеть от
абстракций.
The Dependency Inversion Principle
60
Как выглядит расширение?
Статический полиморфизм 61
template <class It, class Op>
void for_each(It begin, It end, Op op)
{
for(; begin != end; ++begin)
op(*begin);
}
int arr[] = {1, 2, 3, 4, 5};
for_each(arr, arr+6, max<int>());
Динамический полиморфизм 62
• указатель на функцию
void (*f) (int i);
f pf;
pf(5);
• виртуальный метод
class Shape {
public:
virtual void Draw() = 0;
};
shape->Draw();
Метапрограмирование 63
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(value);
}
}
Что такое класс?
Это набор методов, возможно,
виртуальных.
64
Условие для методов класса 65
Для каждого метода подкласса
1. предусловия могут быть ослаблены
2. Постусловия усилены
The Liskov Substitution Principle
Функции, которые используют
ссылки на базовые классы, должны
иметь возможность использовать
объекты производных классов, не
зная об этом.
66
Случай нескольких операторов расширения 67
Жирный интерфейс 68
Пустой метод – метод, который подходит не для всех! 69
The Interface Segregation Principle
Класс не должен зависеть от
интерфейсов, которые он не
использует.
А не для классов? 70
bool (*validator) (Document const & doc);
std::vector<validator> rules = …;
for (int i = 0; i < n; ++i)
if(!rules[i](document))
return false;
return true;
В каком случае гарантированно
удастся избежать жирного
интерфейса?
71
The Single Responsibility Principle 72
Должна быть ровно
одна причина для
изменения класса
А как же функциональщина?
73
Пишите: eytumentcev@hwdtech.ru
Звоните: +7 913 150 22 04
slideshare.com/etyumentcev
http://hwdtech.ru
Тюменцев
Евгений
Александрович

More Related Content

PDF
Математическое обоснование SOLID принципов - Евгений Тюменцев Dev2Dev v2.0 30...
PPT
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
PPTX
математическое обоснование Solid принципов. Конференция dotnetconf (Челябинск...
PPT
Математическое обоснование S.O.L.I.D принципов
PDF
Лекция №1. Введение. Предмет "Теория вычислительных процессов"
PPTX
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
PDF
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Математическое обоснование SOLID принципов - Евгений Тюменцев Dev2Dev v2.0 30...
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
математическое обоснование Solid принципов. Конференция dotnetconf (Челябинск...
Математическое обоснование S.O.L.I.D принципов
Лекция №1. Введение. Предмет "Теория вычислительных процессов"
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...

What's hot (20)

PDF
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
PPT
теория рекурсивных функций
PDF
Python: Модули и пакеты
PPT
паскаль. часть1
PDF
Алгоритмы и языки программирования
PDF
Лекция 11: Методы разработки алгоритмов
PDF
A Method of Reducing Computational Complexity in Verification of Programming ...
PPT
Лекция 2 Сортировки, поиск и порядковые статистики
PPT
чернякова г.в.
PPTX
Урок 8. Введение в редукцию графов
PPTX
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
PDF
Алгоритмы на ruby: перебор и рекурсия
PDF
Лекция 12: Методы разработки алгоритмов. Динамическое программирование. Жадны...
PDF
Probabilistic Verification in Computational Systems Design
PDF
Лекция 1. Анализ эффективности алгоритмов
PDF
Алгоритмы на ruby: жадные алгоритмы
PPT
Лекция 11 Приближенные алгоритмы
PDF
Факторизационные модели в рекомендательных системах
PPT
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
теория рекурсивных функций
Python: Модули и пакеты
паскаль. часть1
Алгоритмы и языки программирования
Лекция 11: Методы разработки алгоритмов
A Method of Reducing Computational Complexity in Verification of Programming ...
Лекция 2 Сортировки, поиск и порядковые статистики
чернякова г.в.
Урок 8. Введение в редукцию графов
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Алгоритмы на ruby: перебор и рекурсия
Лекция 12: Методы разработки алгоритмов. Динамическое программирование. Жадны...
Probabilistic Verification in Computational Systems Design
Лекция 1. Анализ эффективности алгоритмов
Алгоритмы на ruby: жадные алгоритмы
Лекция 11 Приближенные алгоритмы
Факторизационные модели в рекомендательных системах
Ad

Similar to Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D. (20)

PPT
2015-04-12 07 Евгений Тюменцев. Зачем программисту нужно знать математику?
PPT
07 HappyDev-lite-2015 spring. Евгений Тюменцев. Зачем программисту нужно зна...
PPTX
О SOLID-ности
PPTX
разработка серверов и серверных приложений лекция №3
PPTX
разработка серверов и серверных приложений лекция №3
PPTX
04 HappyDev-lite-2015 autumn. Евгений Тюменцев. Программирование глазами мате...
PPTX
Программирование глазами математика
PPT
20100927 28 reqformalization-kuliamin
PPTX
разработка бизнес приложений (6)
PPTX
SOLID
PPTX
Functional Programing
PPT
Принципы SOLID
PDF
HappyDev-lite-2016-весна 05 Евгений Тюменцев. Не все технологии одинаково по...
PPTX
SOLID – принципы объектно-ориентированного дизайна
PPTX
Yuri Trukhin - Software developement best practices
PPTX
Практические аспекты разработки ПО #3
PDF
ук 03.001.02 2011
PDF
C# Desktop. Занятие 01.
PDF
C++ осень 2012 лекция 1
PDF
ооп
2015-04-12 07 Евгений Тюменцев. Зачем программисту нужно знать математику?
07 HappyDev-lite-2015 spring. Евгений Тюменцев. Зачем программисту нужно зна...
О SOLID-ности
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
04 HappyDev-lite-2015 autumn. Евгений Тюменцев. Программирование глазами мате...
Программирование глазами математика
20100927 28 reqformalization-kuliamin
разработка бизнес приложений (6)
SOLID
Functional Programing
Принципы SOLID
HappyDev-lite-2016-весна 05 Евгений Тюменцев. Не все технологии одинаково по...
SOLID – принципы объектно-ориентированного дизайна
Yuri Trukhin - Software developement best practices
Практические аспекты разработки ПО #3
ук 03.001.02 2011
C# Desktop. Занятие 01.
C++ осень 2012 лекция 1
ооп
Ad

More from SmartTools (10)

PDF
Стажировка 2016-08-11 01 Юлия Ашаева. Техники тест-анализа
PDF
Стажировка 2016-08-04 02 Юлия Ашаева. Делаем тесты лучше
PDF
Стажировка 2016-08-04 01 Денис Нелюбин. Шифрование и безопасность
PDF
Cтажировка 2016-08-02 02 Юлия Ашаева. Инструменты тестировщика
PDF
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
PDF
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
PDF
Стажировка 2016-07-12 02 Денис Нелюбин. Web, HTTP, TCP/IP
PPTX
Стажировка 2016-07-07 02 Евгений Тюменцев. Акторная модель
PDF
Стажировка 2016-07-06 03 Евгений Тарасенко. Основы HTML и CSS (часть 1).
PDF
Стажировка 2016-07-06 02 Денис Нелюбин. Linux и git.
Стажировка 2016-08-11 01 Юлия Ашаева. Техники тест-анализа
Стажировка 2016-08-04 02 Юлия Ашаева. Делаем тесты лучше
Стажировка 2016-08-04 01 Денис Нелюбин. Шифрование и безопасность
Cтажировка 2016-08-02 02 Юлия Ашаева. Инструменты тестировщика
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-12 02 Денис Нелюбин. Web, HTTP, TCP/IP
Стажировка 2016-07-07 02 Евгений Тюменцев. Акторная модель
Стажировка 2016-07-06 03 Евгений Тарасенко. Основы HTML и CSS (часть 1).
Стажировка 2016-07-06 02 Денис Нелюбин. Linux и git.

Стажировка 2016-07-08 01 Евгений Тюменцев. S.O.L.I.D.

  • 1. HWdTech, LLC обоснование с помощью логики Хоара S.O.L.I.D.
  • 2. 14 лет преподаю ИМИТ, ФКН ОмГУ ИТ-компании Школа программиста 10 лет разрабатываю ПО разработчик, архитектор, PM, руководство до 70 человек Тюменцев Евгений
  • 4. The Open-Closed Principle Программные объекты должны быть открыты для расширения, но в тоже время закрыты для модификации. 04
  • 5. The Liskov Substitution Principle Функции, которые используют ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом. 05
  • 6. Пример нарушения LSP 06 class Rectangle { double height, width; public: double getHeight() const { return height; } virtual void setHeight(int value) { height = value;} double getWidth() const { return width; } virtual void setWidth(int value) { width = value; } } …. void f(Rectangle& r) { r.setHeight (5); r.setWidth (4); Debug.Assert(r.getHeight() * r.getWidth() == 20); } class Square extends Rectangle { public void setHeight(int value) { super.setHeight(value); super.setWidth(value); } public void setWidth(int value) { super.setHeight(value); super.setWidth(value); } } class Square: public Rectangle { public: virtual void setHeight(int value) { super.setHeight(value); super.setWidth(value); } virtual void setWidth(int value) { super.setHeight(value); super.setWidth(value); } }
  • 7. The Dependency Inversion Principle Высокоуровневые компоненты не должны зависеть от низкоуровневых компонент. И те, и те должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. 07
  • 8. Пример нарушения DIP 08 void Copy() { int ch; while ((ch = Keyboard()) != EOF) { WritePrinter(c); } } class Square extends Rectangle { public void setHeight(int value) { super.setHeight(value); super.setWidth(value); } public void setWidth(int value) { super.setHeight(value); super.setWidth(value); } } enum OutputDevice { printer, disk }; void Copy(OutputDevice dev) { int c; while ((c = ReadKeyboard()) != EOF) { if (dev == printer) WritePrinter(c); else WriteDisk(c); } }
  • 9. Пример соответствия DIP 09 class IReader { public: virtual int Read() = 0; } class IWriter { public: virtual void Write(char) = 0; } void Copy(IReader& r, IWriter& w) { int c; while((c=r.Read()) != EOF) w.Write(c); }
  • 10. The Interface Segregation Principle Класс не должен зависеть от интерфейсов, которые он не использует. 10
  • 11. Пример нарушения ISP 13 class matrix { public: virtual int size() const = 0; virtual void get_ij(int I, int j, double &value) const = 0; virtual void set_ij(int I, int j, double value) = 0; }; class diagonal: public matrix { public: void set_ij(int I, int j, double value) { // ? Что делать, если i != j } };
  • 12. The Single Responsibility Principle Должна быть ровно одна причина для изменения класса. 11
  • 13. switch If /else – if/else enum new Операторы приведения типа Магические константы Примеры конструкций, нарушающих OCP 13
  • 14. Что-о-о? switch, new? Ты кто такой?
  • 15. LSP, OOPSLA’87 Если для каждого объекта o1 типа S существует объект o2 типа T, который для всех программ P определен в терминах T, то поведение P не изменится, если o1 заменить на o2 при условии, что S является подтипом T История вопроса 15 Barbara Liskov
  • 16. LSP, OOPSLA’87 1988, опубликованы в Object-oriented Software Construction История вопроса 16 Bertran Meyer
  • 17. LSP, OOPSLA’87 1988, опубликованы в Object-oriented Software Construction 1994, A behavioral notion of subtyping История вопроса 17 Barbara Liskov
  • 18. LSP, OOPSLA’87 1988, опубликованы в Object-oriented Software Construction 1994, A behavioral notion of subtyping 1995-96, статьи в The C++ Report “Uncle Bob” Автор названия S.O.L.I.D. История вопроса 18 Robert Martin
  • 19. LSP, OOPSLA’87 1988, опубликованы в Object-oriented Software Construction 1994, A behavioral notion of subtyping 1995-96, статьи в The C++ Report 2009, Spolsky VS Uncle Bob they all sounded to me like extremely bureaucratic programming that came from the mind of somebody that has not written a lot of code… История вопроса 19 Joel Spolsky
  • 21. Выводимость 21 Пусть L – множество формул, B – формула. Тогда L ⊦ B, если ∃ B1, B2, …, Bn , что 1.Bn – это B, 2.Bi – это либо формула из L, либо аксиома, либо общезначимая формула, либо формула полученная при помощи правила вывода
  • 23. Modus Ponens (правило вывода) 23
  • 24. 1969 г. An Axiomatic Basis for Computer Programming 1971 г. Procedures and Parameters: An Axiomatic Approach 1980 г. премия Тьюринга 1990 г. Медаль “Пионер компьютерной техники” 2000 г. рыцарский титул за заслуги в области образования и компьютерной техники, премия Киото Логика Хоара Чарльз Хоар 24
  • 25. {pred} statement {post} Пример: {x == 42} y=x+1; {y == 43 ^ x == 42} Тройка Хоара 25
  • 26. {P} skip {P} Аксиома пустого оператора 26
  • 27. Пример: {(y+1)*3+w*(y+1+3) ==z} x=y+1; { x*3+ w*(x+3)==z} Аксиома оператора присваивания 27 {P[E/x]} x := E {P}
  • 28. Аксиома оператора цикла 28 {P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}
  • 29. Аксиома условного оператора 29 {B ^ P} S {Q}, {B’ ^P} T {Q}╞ {P} if B then S else T endif {Q} {B ^ P} S {Q}╞ {P} if B then S endif {Q}
  • 30. Аксиомы вывода 30 P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1} P1 → P, {P} S {Q} ╞ {P1} S {Q} {P} S {Q}, Q → Q1 ╞ {P} S {Q1}
  • 31. Аксиома вывода и условный оператор 31 Пусть L = {{P} f {Q}}, B – предикат. P^B→P (A3 исчисления высказываний) {P^B}f{Q} (аксиома вывода) {P}if (B) then f endif {Q} (аксиома условного оператора)
  • 32. Неявные предположения 32 {P ^ B} с {Q} {P} assert(B); c {Q}
  • 33. Упрощение кода и аксиома вывода 33 node* insert(node& c, int v) { node *n = new node; n -> val = v; if(c.next) { n -> next = c.next; } else { n -> next = 0; } c.next = n; return n; } null
  • 35. Закольцованный список с буферным элементом 35 node* insert(node& c, int v) { node *n = new node; n -> val = v; if(c.next) { n -> next = c.next; } else { n -> next = 0; } c.next = n; return n; }
  • 36. Закольцованный список с буферным элементом 36 node* insert(node& c, int v) { node *n = new node; n -> val = v; n -> next = c.next; c.next = n; return n; }
  • 37. Аксиома композиции 37 {P} S {Q}, {Q} T {R} ╞ {P} S;T {R}
  • 38. Контрактное программирование 38 • Предусловия • Постусловия • Инварианты
  • 40. Рефакторинг 40 {P} S {Q}, {Q} T {R} ╞ {P} S;T {R}
  • 43. Если использовать 1. статическое связывание 2. Рекурсию 3. Вложенные процедуры 4. Процедуры, принимающие в качестве параметров процедуры. 5. Глобальные переменные то не существует полной системы аксиом. Глобальные переменные 40
  • 44. ⊢ 𝐿 𝞿 и ⊢ 𝐿 `𝞿 Значит, что любое изменение в коде надо тестировать! Противоречивость 40
  • 47. Изменения – это проблема 40 int i = 0; while( i < 100) { i = f(); } int f() { return 20; }
  • 50. Так ли страшен hell… 40 24 марта https://habrahabr.ru/post/280099/ left-pad «Многие разработчики не могли понять, что случилось: они никогда не использовали такой модуль. Однако его могли использовать другие модули, о чем можно просто не догадываться» https://meduza.io/feature/2016/03/28/kak-slomat- internet
  • 51. Введение любого нового оператора при наличии goto приводит к противоречивости goto и противоречивость 40
  • 52. Вспоминаем про сложность разработки ПО 40 Фредерик Брукс «Мифический человеко- месяц»
  • 53. Что делать? 40 SOLID – достаточное условие линейной производительности
  • 55. Аксиома оператора цикла 42 Повторное использование кода — методология проектирования компьютерных и других систем, заключающаяся в том, что система (компьютерная программа, программный модуль) частично либо полностью должна составляться из частей, написанных ранее компонентов и/или частей другой системы, и эти компоненты должны применяться более одного раза (если не в рамках одного проекта, то хотя бы разных). https://ru.wikipedia.org/wiki/Повторное_использование_кода
  • 56. Когда происходит повторное использование? Если нужно внести изменение в существующее приложение, то мы пытаемся повторно использовать свой же собственный код, чтобы получить тоже приложение, но с новой функциональностью. 43
  • 57. 44 Выводимость прямо предписывает строить новые тройки из предыдущих!
  • 58. Чем грозят правки кода? 45 B1, B2, …, A1 B3, A1, …, A2 B5, A2, …, A3 A2, B6, …, A4 A2, A4, …, A5
  • 59. Программа рассыпается как карточный домик! 46 B1, B2, …, A1 B3, A1, …, A2 B5, A2, …, A3 A2, B6, …, A4 A2, A4, …, A5
  • 60. Особенности разработки ПО 47 Фредерик Брукс «Мифический человеко-месяц»
  • 61. Из закрытости следует выводимость! 48 Программные объекты должны быть открыты для расширения, но в тоже время закрыты для модификации. The Open-Closed Principle
  • 62. Матрицы 49 class matrix { int size; double *body; public: matrix(int s): size(s) { body = new double[s*s]; } void transform() { … } double det() const { … } };
  • 63. Матрицы: добавляем matrix() 50 class matrix { int size; double *body; public: matrix(int s): size(s) { body = new double[s*s]; } void transform() { … } double det() const { … } }; class matrix { public: matrix(): size(0), body(0) { } };
  • 64. Матрицы: придется менять методы 51 class matrix { int size; double *body; public: matrix(): size(0), body(0) { } matrix(int s): size(s) { body = new double[s*s]; } void transform() { if(!body) throw exception(); … } double det() const { if(!body) throw exception(); … } };
  • 65. 53 Конструктор должен устанавливать инвариант класса Конструкторы по умолчанию часто этого не делают Стоит несколько раз подумать, прежде чем использовать конструктор по умолчанию
  • 66. Что случилось? 52 Инвариант класса matrix: size > 0 Конструктор matrix() нарушил инвариант: size = 0 Предусловия методов изменились с size > 0 на size ≥ 0, но {size ≥ 0} det {Q} не выводится из {size > 0} det {Q} Следовательно, надо изменять сами методы
  • 67. Импликация на множестве 54 Пусть P1 → P, B = { x | P1(x) = 1}, A = { x | P (x) = 1}. Тогда B ⊂ A. P ⊨ P1. Говорят, что P – более слабое условие, P1 – более сильное. A B
  • 68. Построим вывод 55 {S} cb {P}, {P} c {Q}, {Q} ca {R} ⊦ {S} cb; c; ca {R} Пусть P → P1, Q1 → Q Известно, что {S} cb {P}, {P1} c {Q1}, {Q} ca {R} Тогда {P} c {Q} (аксиома вывода) {S} cb; c; ca {R}
  • 69. А если импликации нет? 56 {S} cb {P}, {P} c {Q}, {Q} ca {R} ⊦ {S} cb; c; ca {R} Пусть P ↛ P1, но P ^ P1 → P1 Известно, что {S} cb {P}, {P1} c {Q}, {Q} ca {R} Тогда {P1} c {Q} ⊦ {P} if (P1) then c endif {Q} {S} cb; if(P1) then c endif; ca {R}
  • 70. Оператор расширения 57 Оператор расширения должен допускать: 1. Ослабление предусловий 2. Усиление постусловий
  • 72. Для оператора расширения получаем 59 Высокоуровневые компоненты не должны зависеть от низкоуровневых компонент. И те, и те должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. The Dependency Inversion Principle
  • 74. Статический полиморфизм 61 template <class It, class Op> void for_each(It begin, It end, Op op) { for(; begin != end; ++begin) op(*begin); } int arr[] = {1, 2, 3, 4, 5}; for_each(arr, arr+6, max<int>());
  • 75. Динамический полиморфизм 62 • указатель на функцию void (*f) (int i); f pf; pf(5); • виртуальный метод class Shape { public: virtual void Draw() = 0; }; shape->Draw();
  • 76. Метапрограмирование 63 void Counter::setValue(int value) { if (value != m_value) { m_value = value; emit valueChanged(value); } }
  • 77. Что такое класс? Это набор методов, возможно, виртуальных. 64
  • 78. Условие для методов класса 65 Для каждого метода подкласса 1. предусловия могут быть ослаблены 2. Постусловия усилены
  • 79. The Liskov Substitution Principle Функции, которые используют ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом. 66
  • 82. Пустой метод – метод, который подходит не для всех! 69 The Interface Segregation Principle Класс не должен зависеть от интерфейсов, которые он не использует.
  • 83. А не для классов? 70 bool (*validator) (Document const & doc); std::vector<validator> rules = …; for (int i = 0; i < n; ++i) if(!rules[i](document)) return false; return true;
  • 84. В каком случае гарантированно удастся избежать жирного интерфейса? 71
  • 85. The Single Responsibility Principle 72 Должна быть ровно одна причина для изменения класса
  • 86. А как же функциональщина? 73
  • 87. Пишите: eytumentcev@hwdtech.ru Звоните: +7 913 150 22 04 slideshare.com/etyumentcev http://hwdtech.ru Тюменцев Евгений Александрович

Editor's Notes

  • #2: Эта презентация демонстрирует новые возможности PowerPoint. Ее рекомендуется просматривать в режиме показа слайдов. Эти слайды должны дать вам представление о том, какие эффектные презентации можно создать с помощью PowerPoint 2010. Для доступа к другим образцам шаблонов перейдите на вкладку "Файл", а затем щелкните "Образцы слайдов" на вкладке "Создать".