Глава 3. Модель акторов. 30
Литература 65 
Actors: A Model of 
Concurrent Computations 
in Distributed Systems 
PhD thesis, 1985 
Gul A. Agha
Task 66 
1. Tag (уникальный идентификатор) 
2. Target (mail address) 
3. Communication (данные)
Абстракция актора 67 
1.Mail address 
2.Large mail queue 
3.Behavior
Шаг вычислений 68 
1.Отправить сообщения 
2.Создать новые акторы 
3.Изменить свое 
поведение для приема 
следующего сообщения 
(become method)
Литература 69
Обмен сообщениями 70 
1. Каналы 
2. Сообщения 
3. Фильтры 
4. Маршрутизация 
5. Преобразование 
6. Конечные точки
Каналы 71 
http://www.eaipatterns.com/MessageChannel.html
Сообщения 72 
http://www.eaipatterns.com/Message.html
Маршрутизация 73 
http://www.eaipatterns.com/MessageRouter.html
Конечные точки 74 
http://www.eaipatterns.com/MessageEndpoint.html
Глава 4. Важно знать. 75
Репозиторий GitHub 76 
Библиотека акторов, котрая будет написана в 
рамках спецкурса выложена по адресу 
https://github.com/hwdtech/HWdTech.DS
S.O.L.I.D 77 
• The Open-Closed Principle 
• The Liskov Substitution 
Principle 
• The Interface Segregation 
Principle 
• The Dependency Inversion 
Principle 
• The Single Responsibility 
Principle 
objectmentor.com 
Rob Martin (Uncle Bob)
The Open-Closed Principle 78 
Программные объекты 
должны быть открыты для 
расширения, но в тоже 
время закрыты для 
модификации
Открытые vs закрытые 79 
• Полиморфная 
операция 
• Паттерны 
• DI контейнеры 
• Код, ген. по 
метаописанию 
• switch 
• If /else – if/else 
• Неполиморфная 
операция 
• операторы 
приведения типа 
• enum
Открытые vs закрытые 80 
• Полиморфная 
операция 
• Паттерны 
• DI контейнеры 
• Код, ген. по 
метаописанию 
• … 
• Магические 
константы 
• Copy-paste 
• Public поля 
• Глобальные 
переменные
Открытые vs закрытые 81 
• Полиморфная 
операция 
• Паттерны 
• DI контейнеры 
• Код, ген. по 
метаописанию 
• … 
• Магические 
константы 
• Copy-paste 
• Public поля 
• Глобальные 
переменные
Программа Copy вер. 1 82 
void Copy() 
{ 
int ch; 
while ((ch = 
Keyboard()) != EOF) 
{ 
WritePrinter(c); 
} 
} 
enum OutputDevice 
{ 
printer, 
disk 
}; 
void Copy(OutputDevice dev) 
{ 
int c; 
while ((c = ReadKeyboard()) != EOF) 
{ 
if (dev == printer) 
WritePrinter(c); 
else 
WriteDisk(c); 
} 
}
Программа Copy вер. 2 83 
interface IReader 
{ 
int Read(); 
} 
interface IWriter 
{ 
void Write(char) = 0; 
} 
void Copy( 
IReader r, 
IWriter w 
) 
{ 
int c; 
while((c=r.Read()) != 
EOF) 
w.Write(c); 
}
Все дело в зависимостях 84
The Dependency Inversion Principle85 
Высокоуровневые компоненты не 
должны зависеть от 
низкоуровневых компонент. И те, и 
те должны зависеть от 
абстракций. 
Абстракции не должны зависеть от 
деталей. Детали должны зависеть 
от абстракций.
Слои 86
Литература 87
Фасад 88
Абстрактная фабрика 89 
void Copy( 
IReader r, 
IWriter w 
) 
{ 
int c; 
while((c=r.Read()) != 
EOF) 
w.Write(c); 
}
DI Container Autofac 90 
var builder = new ContainerBuilder(); 
builder.RegisterType<LibraryBook>().As<IBook>(); 
builder.RegisterType<MainViewModel>().AsSelf(); 
var container = builder.Build(); 
var model = container.Resolve<MainViewModel>(); 
var view = new MainWindow (DataContext = 
model); 
view.Show();
Логика Хоара 91 
Тройка Хоара 
{pred} statement {post} 
Пример: Чарльз Хоар 
{x+1 == 43} y=x+1; {y == 43 ^ x == 42}
Аксиомы и правила логики Хоара 92 
Аксиома пустого оператора 
{P} skip {P} 
Аксиома присваивания 
{P[E/x]} x := E {P} 
Правило композиции 
{P} S {Q}, {Q} T {R} ╞ {P} S;T {R} 
Правило условного оператора 
{B ^ P} S {Q}, {B’ ^P} T {Q} ╞ {P} if B then S else T endif {Q} 
Правило вывода 
P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1} 
Правило оператора цикла 
{P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}
Аксиомы и правила логики Хоара 93 
Аксиома пустого оператора 
{P} skip {P} 
Аксиома присваивания 
{P[E/x]} x := E {P} 
Правило композиции 
{P} S {Q}, {Q} T {R} ╞ {P} S;T {R} 
Правило условного оператора 
{B ^ P} S {Q}, {B’ ^P} T {Q} ╞ {P} if B then S else T endif {Q} 
Правило вывода 
P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1} 
Правило оператора цикла 
{P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}
Пример: pow(x,y) 94 
http://freehabr.ru/blog/programming/1933.html 
int power(int a, int n) { 
assert(n > 0 || (a != 0 || n != 0)); 
if (n == 0) return 1; 
else { 
int a2 = power(a, n/2); 
if (n & 1) return a*a2*a2; 
else return a2*a2; 
} 
}
Пример: pow(x,y) 95 
http://freehabr.ru/blog/programming/1933.html 
int power(int a, int n) { 
assert(n > 0 || (a != 0 || n != 0)); 
if (n == 0) return 1; 
else { 
int a2 = power(a, n/2); 
if (n & 1) return a*a2*a2; 
else return a2*a2; 
} 
}
pow(x,y) - итерация 96 
int power(int a, int n) { 
assert(n > 0 || (a != 0 || n != 0)); 
int r = 1, a0 = a, n0 = n; 
/* r == 1 and a0 == a and n0 == n and n >= 0 
инвариант_цикла: a0**n0 == r*a**n 
ограничивающая_функция(n): n */
pow(x,y) - итерация 97 
while(n > 0) { 
/* n > 0 and ограничивающая_функция(n) > 0 
and инвариант_цикла */ 
if (n & 1) r *= a; 
/* (n - нечетно and a0**n0*a == r*a**n) or 
инвариант_цикла */ 
n >>= 1;
pow(x,y) - итерация 98 
/* n == 0 
and инвариант_цикла 
and ограничивающая_функция(n) == 0 */ 
// a0**n0 == r 
return r; 
}
Очень трудно! 99 
Правило композиции 
{P} S {Q}, {Q} T {R} ╞ {P} S;T {R} 
Проверку каждого оператора 
заменить на проверку группы 
операторов
Контрактное программирование 100 
 Инвариант 
 Предусловие 
 Постусловие
Следствия 101 
Конструктор используется для 
инвариантов класса
Следствия 102 
Конструктор используется для 
инвариантов класса 
При нарушении условия выбрасывается 
исключение
Следствия 103 
Конструктор используется для 
инвариантов класса 
При нарушении условия выбрасывается 
исключение 
Техника RAII
Следствия 104 
Конструктор используется для 
инвариантов класса 
При нарушении условия выбрасывается 
исключение 
Техника RAII 
Модульное тестирование
Модульное тестирование 105 
Это всего лишь 
автоматизация 
проверки контракта
Модульное тестирование 106 
1. Arrange 
2. Act 
3. Assert
Пример теста 107 
Библиотека Nunit 
using NUnit.Framework; 
[TestFixture] 
public class Tests { 
[Test] 
public void testStringReverse() { 
String input = "abc"; 
String result = Util.reverse(input); 
Assert.AreEquals("cba", result); 
}
Схема теста состояния 108
Недостатки 109 
Тестирование основанное на состояниях: 
• Требует знания о внутреннем состоянии 
объекта –возможно нарушение 
инкапсуляции 
• Нарушает принципы ООП 
• Некоторые вещи трудно тестировать: 
закрытые свойства и методы, 
алгоритмическую сложность
Но! А как же инкапсуляция? 110 
Надо тестировать 
не состояние, а 
поведение!
Как тестировать поведение? 111 
Полиморфизм: подменяя 
поведение серверного кода 
тестируем поведение 
клиентского
Что тестировать? 112 
Был ли вызван метод? 
Сколько раз был вызван? 
Порядок вызова методов 
С какими параметрами? 
Что вернул на выходе? 
Выбросил ли исключение?
Пример Mock-теста 113 
Библиотеки NUnit, Moq 
[TestFixture] 
public class ActorTests 
{ 
MockRepository repository = new MockRepository(MockBehavior.Strict); 
IMessage message; 
[Test] 
public void AnActorShouldHandleAMessage() 
{ 
Mock<Actor> actor = repository.Create<Actor>(); 
actor.Setup(a => a.Handle(message)).Verifiable(); 
actor.Object.Receive(message); 
actor.VerifyAll(); 
} 
}
Mock-тесты схема 114
Необходимое условие 1 115 
Принцип подстановки Лисков 
Функции, которые используют 
ссылки на базовые классы, должны 
иметь возможность 
использовать объекты 
производных классов, не зная об 
этом.
Необходимое условие 2 116 
Принцип обращения зависимостей 
Высокоуровневые компоненты не 
должны зависеть от низкоуровневых 
компонент. И те, и те должны 
зависеть от абстракций. 
Абстракции не должны зависеть от 
деталей. Детали должны зависеть от 
абстракций.

разработка серверов и серверных приложений лекция №3

  • 1.
    Глава 3. Модельакторов. 30
  • 2.
    Литература 65 Actors:A Model of Concurrent Computations in Distributed Systems PhD thesis, 1985 Gul A. Agha
  • 3.
    Task 66 1.Tag (уникальный идентификатор) 2. Target (mail address) 3. Communication (данные)
  • 4.
    Абстракция актора 67 1.Mail address 2.Large mail queue 3.Behavior
  • 5.
    Шаг вычислений 68 1.Отправить сообщения 2.Создать новые акторы 3.Изменить свое поведение для приема следующего сообщения (become method)
  • 6.
  • 7.
    Обмен сообщениями 70 1. Каналы 2. Сообщения 3. Фильтры 4. Маршрутизация 5. Преобразование 6. Конечные точки
  • 8.
  • 9.
  • 10.
  • 11.
    Конечные точки 74 http://www.eaipatterns.com/MessageEndpoint.html
  • 12.
  • 13.
    Репозиторий GitHub 76 Библиотека акторов, котрая будет написана в рамках спецкурса выложена по адресу https://github.com/hwdtech/HWdTech.DS
  • 14.
    S.O.L.I.D 77 •The Open-Closed Principle • The Liskov Substitution Principle • The Interface Segregation Principle • The Dependency Inversion Principle • The Single Responsibility Principle objectmentor.com Rob Martin (Uncle Bob)
  • 15.
    The Open-Closed Principle78 Программные объекты должны быть открыты для расширения, но в тоже время закрыты для модификации
  • 16.
    Открытые vs закрытые79 • Полиморфная операция • Паттерны • DI контейнеры • Код, ген. по метаописанию • switch • If /else – if/else • Неполиморфная операция • операторы приведения типа • enum
  • 17.
    Открытые vs закрытые80 • Полиморфная операция • Паттерны • DI контейнеры • Код, ген. по метаописанию • … • Магические константы • Copy-paste • Public поля • Глобальные переменные
  • 18.
    Открытые vs закрытые81 • Полиморфная операция • Паттерны • DI контейнеры • Код, ген. по метаописанию • … • Магические константы • Copy-paste • Public поля • Глобальные переменные
  • 19.
    Программа Copy вер.1 82 void Copy() { int ch; while ((ch = Keyboard()) != EOF) { WritePrinter(c); } } enum OutputDevice { printer, disk }; void Copy(OutputDevice dev) { int c; while ((c = ReadKeyboard()) != EOF) { if (dev == printer) WritePrinter(c); else WriteDisk(c); } }
  • 20.
    Программа Copy вер.2 83 interface IReader { int Read(); } interface IWriter { void Write(char) = 0; } void Copy( IReader r, IWriter w ) { int c; while((c=r.Read()) != EOF) w.Write(c); }
  • 21.
    Все дело взависимостях 84
  • 22.
    The Dependency InversionPrinciple85 Высокоуровневые компоненты не должны зависеть от низкоуровневых компонент. И те, и те должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
  • 23.
  • 24.
  • 25.
  • 26.
    Абстрактная фабрика 89 void Copy( IReader r, IWriter w ) { int c; while((c=r.Read()) != EOF) w.Write(c); }
  • 27.
    DI Container Autofac90 var builder = new ContainerBuilder(); builder.RegisterType<LibraryBook>().As<IBook>(); builder.RegisterType<MainViewModel>().AsSelf(); var container = builder.Build(); var model = container.Resolve<MainViewModel>(); var view = new MainWindow (DataContext = model); view.Show();
  • 28.
    Логика Хоара 91 Тройка Хоара {pred} statement {post} Пример: Чарльз Хоар {x+1 == 43} y=x+1; {y == 43 ^ x == 42}
  • 29.
    Аксиомы и правилалогики Хоара 92 Аксиома пустого оператора {P} skip {P} Аксиома присваивания {P[E/x]} x := E {P} Правило композиции {P} S {Q}, {Q} T {R} ╞ {P} S;T {R} Правило условного оператора {B ^ P} S {Q}, {B’ ^P} T {Q} ╞ {P} if B then S else T endif {Q} Правило вывода P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1} Правило оператора цикла {P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}
  • 30.
    Аксиомы и правилалогики Хоара 93 Аксиома пустого оператора {P} skip {P} Аксиома присваивания {P[E/x]} x := E {P} Правило композиции {P} S {Q}, {Q} T {R} ╞ {P} S;T {R} Правило условного оператора {B ^ P} S {Q}, {B’ ^P} T {Q} ╞ {P} if B then S else T endif {Q} Правило вывода P1 → P, {P} S {Q}, Q → Q1 ╞ {P1} S {Q1} Правило оператора цикла {P ^ B} S {P} ╞ {P} while B do S done {B’ ^ P}
  • 31.
    Пример: pow(x,y) 94 http://freehabr.ru/blog/programming/1933.html int power(int a, int n) { assert(n > 0 || (a != 0 || n != 0)); if (n == 0) return 1; else { int a2 = power(a, n/2); if (n & 1) return a*a2*a2; else return a2*a2; } }
  • 32.
    Пример: pow(x,y) 95 http://freehabr.ru/blog/programming/1933.html int power(int a, int n) { assert(n > 0 || (a != 0 || n != 0)); if (n == 0) return 1; else { int a2 = power(a, n/2); if (n & 1) return a*a2*a2; else return a2*a2; } }
  • 33.
    pow(x,y) - итерация96 int power(int a, int n) { assert(n > 0 || (a != 0 || n != 0)); int r = 1, a0 = a, n0 = n; /* r == 1 and a0 == a and n0 == n and n >= 0 инвариант_цикла: a0**n0 == r*a**n ограничивающая_функция(n): n */
  • 34.
    pow(x,y) - итерация97 while(n > 0) { /* n > 0 and ограничивающая_функция(n) > 0 and инвариант_цикла */ if (n & 1) r *= a; /* (n - нечетно and a0**n0*a == r*a**n) or инвариант_цикла */ n >>= 1;
  • 35.
    pow(x,y) - итерация98 /* n == 0 and инвариант_цикла and ограничивающая_функция(n) == 0 */ // a0**n0 == r return r; }
  • 36.
    Очень трудно! 99 Правило композиции {P} S {Q}, {Q} T {R} ╞ {P} S;T {R} Проверку каждого оператора заменить на проверку группы операторов
  • 37.
    Контрактное программирование 100  Инвариант  Предусловие  Постусловие
  • 38.
    Следствия 101 Конструкториспользуется для инвариантов класса
  • 39.
    Следствия 102 Конструкториспользуется для инвариантов класса При нарушении условия выбрасывается исключение
  • 40.
    Следствия 103 Конструкториспользуется для инвариантов класса При нарушении условия выбрасывается исключение Техника RAII
  • 41.
    Следствия 104 Конструкториспользуется для инвариантов класса При нарушении условия выбрасывается исключение Техника RAII Модульное тестирование
  • 42.
    Модульное тестирование 105 Это всего лишь автоматизация проверки контракта
  • 43.
  • 44.
    Пример теста 107 Библиотека Nunit using NUnit.Framework; [TestFixture] public class Tests { [Test] public void testStringReverse() { String input = "abc"; String result = Util.reverse(input); Assert.AreEquals("cba", result); }
  • 45.
  • 46.
    Недостатки 109 Тестированиеоснованное на состояниях: • Требует знания о внутреннем состоянии объекта –возможно нарушение инкапсуляции • Нарушает принципы ООП • Некоторые вещи трудно тестировать: закрытые свойства и методы, алгоритмическую сложность
  • 47.
    Но! А какже инкапсуляция? 110 Надо тестировать не состояние, а поведение!
  • 48.
    Как тестировать поведение?111 Полиморфизм: подменяя поведение серверного кода тестируем поведение клиентского
  • 49.
    Что тестировать? 112 Был ли вызван метод? Сколько раз был вызван? Порядок вызова методов С какими параметрами? Что вернул на выходе? Выбросил ли исключение?
  • 50.
    Пример Mock-теста 113 Библиотеки NUnit, Moq [TestFixture] public class ActorTests { MockRepository repository = new MockRepository(MockBehavior.Strict); IMessage message; [Test] public void AnActorShouldHandleAMessage() { Mock<Actor> actor = repository.Create<Actor>(); actor.Setup(a => a.Handle(message)).Verifiable(); actor.Object.Receive(message); actor.VerifyAll(); } }
  • 51.
  • 52.
    Необходимое условие 1115 Принцип подстановки Лисков Функции, которые используют ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом.
  • 53.
    Необходимое условие 2116 Принцип обращения зависимостей Высокоуровневые компоненты не должны зависеть от низкоуровневых компонент. И те, и те должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.