SlideShare a Scribd company logo
Максим Аршинов
IT–гуру, μISV
Обрел просветление в разработке ПО
Программирование – это как секс
• DDD
• CQRS
• Event Sourcing
• Эволюционный рефакторинг
• Горизонтальное масштабирование и облачная архитектура
• Эффективное взаимодействие между командами
Один раз ошибешься, а
потом поддерживать
всю жизнь
Программирование – это как секс
А проектирование – это как петтинг
Распределенные и/или
нагруженные бизнес-приложения
• Система продажи билетов
• Трейдинговая площадка
• Баннерная сеть для порно-сайтов
Проблемы
• Специфическая терминология
• Сложная предметная область, не
очевидные бизнес-правила
• Бизнес-логика может часто меняться
• Высокая и/или неравномерная нагрузка
Цели разработчика
• Сохранять темпы разработки
• Повысить bus factor
• Обеспечить горизонтальное
масштабирование системы
«Архитектура»
• Что это такое?
• Чем отличается от «инфраструктуры»?
Всему свое время
Трёхуровневая архитектура
UI
Business Rules
Data Access Layer
Metal Gear
• S – Single responsibility principle
• O – Open/closed principle
• L – Liskov substitution principle
• I – Interface segregation principle
• D – Dependency inversion principle
Как структурировать бизнес-логику?
Как структурировать бизнес-логику?
• DDD (Domain Driven Design)
• Инфраструктура – не домен!
• Persistence ignorance
• Aggregation Roots
• Anemic Domain Model Rich Models
• Active Record Unit of Work
• Controller Service Layer
• using(var uow = new UoW()), Singleton, Registry
IOC
Единый язык (Ubiquitous language)
ticket.State = TicketState.Sold;
ticketRepository.Update(ticket);
var ticket = cashdesk.Sale (seat);
DDD vs OOP
• Гвоздь суше воды
• DDD про отделение мух от котлет домена от
инфраструктуры
• DDD про взаимодействие с бизнесом
Entity
• Есть Id
• У вас есть, у гвоздя – нет
• Наличие или отсутствие Id может зависеть
от контекста
CRUD
Что не так с Repository?
public interface IRepository<T>
{
T GetById(int id);
IEnumerable<T> GetAll();
bool Add(T entity);
bool Remove(T entity);
}
Что не так с Repository?
class AccountRepository : IRepository<Account>
{
public Account GetByName(string name);
public Account GetByEmail(string email);
public Account GetByAge(int age);
// ...
public Account GetByAreYouFuckingKiddingMe(SomeCriteria c);
}
Что не так с Repository?
• 100500 методов, в т.ч. в интерфейсе
IAccountRepository
• Не удобно тестировать
• Многа-букаф, чтобы написать новый метод
• Приходится прокидывать сигнатуры в
сервисный слой
• Рефакторинг затруднен
Ок, я понял
public interface IRepository<T>
{
T GetById(int id);
//во имя луны
IQueryable<T> GetAll();
bool Add(T entity);
bool Remove(T entity);
}
Что не так с Repository?
repo.GetAll()
.Where(a => a.IsDeleted = false);
repo.GetAll()
.Where(a => a.IsDeleted = false &&
a.Balance > 0);
repo.GetAll()
.Where(a => a.CreationDate <
getCurrentDate());
Coding like a sex
Specification Pattern
public interface ISpecification<T>
{
bool IsSatisfiedBy(T candidate);
}
Expression Specification
public interface ISpecification<T>
{
Expression<Func<T, bool>> IsSatisfiedBy();
}
Стало лучше
IEnumerable<T> GetBySpecifications(
IEnumerable<ISpecification<T>> specifications,
params IFetchStrategy<T>[] fetchStrategies);
FilterPolicy (Value Object)
public class FilterPolicy<T>
{
public IEnumerable<ISpecification<T>> Specifications { get; private set; }
public IEnumerable<IFetchStrategy<T>> FetchStrategies { get; private set; }
public FilterPolicy(
IEnumerable<ISpecification<T>> specifications,
IEnumerable<IFetchStrategy<T>> fetchStrategies)
{
Specifications = specifications;
FetchStrategies = fetchStrategies;
}
}
Более подробно о Value Object
• Не Entity
• Immutable
• Value - не Reference
Защитное программирование на
страже инварианта
public class FilterPolicy(
IEnumerable<ISpecification<T>> specifications,
IEnumerable<IFetchStrategy<T>> fetchStrategies)
{
if(specifications == null) throw new ArgumentException(
"specifications can't be null", "specifications");
if(fetchStrategies == null) throw new ArgumentException(
"fetchStrategies can't be null", "fetchStrategies");
Specifications = specifications;
FetchStrategies = fetchStrategies;
}
Composite
• OrSpecification
• AndSpecification
• ActiveAccountSpecification …
Composite
public class OrSpecification<T> : ISpecification<T>
{
private readonly ISpecification<T>[] _specs;
public OrSpecification(params ISpecification<T>[] specs)
{
if(specs.Length == 0) throw new ArgumentException(
"specs length must be > 0", "specs");
_specs = specs;
}
public Expression<Func<T, bool>> IsSatisfiedBy()
{
throw new NotImplementedException();
}
}
Декларативный стиль >
императивного
• DSL
• Функциональное программирование,
монады
• Мета-программирование и AOP, Code
Contracts
• Кодогенерация
• Динамическая компиляция
Монада Maybe
string postCode;
if (person != null)
{
if (HasMedicalRecord(person) && person.Address != null)
{
CheckAddress(person.Address);
if (person.Address.PostCode != null)
postCode = person.Address.PostCode.ToString();
else
postCode = "UNKNOWN";
}
}
public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
where TResult : class where TInput : class
{
if (o == null) return null;
return evaluator(o);
}
string postCode = this.With(x => person)
.With(x => x.Address)
.With(x => x.PostCode)
.Return(x => "UNKNOWN");
Conventions > configuration
[DisplayName("Категории продуктов")]
[DataContract]
public class ProductCategory : EntityBase
{
[Display(Name = "Название")]
[Column(TypeName = "VARCHAR"), StringLength(255), Required]
[DataMember(IsRequired = true)]
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
Иногда лучше по-быстрому, чем SRP, если
знаешь как будешь рефакторить
public class ProductCategoryController :
AdminControllerBase<ProductCategory>
{
public ProductCategoryController(DbContext dbContext) :
base(dbContext)
{
}
}
Например, INotifyPropertyChanged
Дай разработчику дефолтное поведение и он будет
штамповать формочки весь день. Научи как
переопределить его…
• Во FreeBSD ты можешь настроить все, и ты
%$@ть будешь настраивать все
• ASP.NET MVC
• WCF
Разделяй и властвуй
• Module aka Package
• Onion - архитектура
• SOA
Bounded Context
• Anti-Corruption Layer
• Контекстов может быть много
Anti-Corruption Layer. How To?
class Messy
{
String concat(String param, String str) { /* ... */ }
bool contains(String param, String s) { /* ... */ }
bool isEmpty(String param) { /* ... */ }
bool matches(String param, String regex) { /* ... */ }
bool startsWith(String param, String prefix) { /* ... */ }
}
class Reasonable // anti-corruption layer
{
String param;
Messy messy = new Messy();
Reasonable(String param)
{
this.param = param;
}
String concat(String str) { return messy.concat(param, str); }
bool contains(String s) { return messy.contains(param, s); }
bool isEmpty() { return messy.isEmpty(param); }
bool matches(String regex) { return messy.matches(param, regex); }
bool startsWith(String prefix) { return messy.startsWith(param, prefix); }
}
Разгрузочный слайд
Shared DB
Реляционная база данных – узкое
место
Оптимизация БД
• Убираем ORM для лучшей оптимизации
• Оптимизируем индексы
• Убираем весь код выборки в хранимые
процедуры
• Строим/оптимизируем индексы
• Денормализуем данные (когда ничего не
помогает)
Стратегии денормализации
• Убрать JOIN’ы, добавить
денормализованные колонки
• Создаем отдельные таблицы/view
• Хранилище с «плоскими» данными
Теорема CAP
• Consistency (согласованность данных)
• Availability (доступность)
• Partition tolerance (устойчивость к
разделению)
2 из 3
• Consistency + Availability (традиционные СУБД)
• Consistency + Partition tolerance
(пессимистические блокировки)
• Availability + Partition tolerance (NOSQL-решения)
CQS
• Command–query separation
• Commands – update state (C, U, D)
• Queries – fetch results (R)
CQS – зачем?
• Отсутствие сайд-эффектов
• Поддержка декларативного стиля (WCF)
• Горизонтальное масштабирование
Query Object как альтернатива
Repository
• Абстракция от ORM (но велосипед)
• Не надо городить кучу IEntityRepository
• Просто тестировать
• SRP
QueryObject и QueryBuilder
public interface IQueryFor<out T>
{
T With(ISpecification<T> specification)
T ById(int id);
IEnumerable<T> All();
}
public interface IQueryBuilder
{
IQueryFor<TResult> For<TResult>();
}
var account = queryBuilder.For<Account>()
.With(new LoginSpecification("Вася"))
.All();
Command Pattern
public interface ICommand
{
void Execute();
}
Не все CQS by design
• Например Стек
• Помним про Bounded Context
Синхронизация хранилищ
• Синхронно (C,U,D)
Синхронизация хранилищ
• Асинхронно
Команды и шина
• bus.Send(command);
• Диспетчеризация
• Логирование
Минусы
• Eventually consistent
• Архитектура гораздо сложнее, чем Shared
DB
• Обработка ошибок
• UX Issues
Горизонтальное масштабирование
записи данных
• Очередь сообщений (Producer-Consumer
pattern)
• RabbitMQ
• IronMQ
• NServiceBus
Разгрузочный слайд
Event Sourcing – вспомнить все
Проблемы
• Рефакторинг
• Сложность системы, Bus factor
• Сторонние сервисы
• Выбор Aggregation Root
• Tool Support
Взаимодействие между командами,
границы применимости
• И снова Bounded Context
• UI-команда – клиент для Backend-команды
• Сначала интерфейс, потом реализация
• CQRS и ES могут жить в подсистеме
• Code Review – не блажь, а необходимость
• Парное программирование для сложных
задач
Вопросы?

More Related Content

PPTX
рентабельный код
PDF
Применение CQRS и EventSourcing в DDD-проекте
PDF
Микросервисы, чистый PaaS и конкурс Мисс Россия
PDF
Илья Ефимов «IoC/DI на примере Autofac»
PPTX
Модульная структура. Цветцих Денис D2D Just.NET
PDF
ASP.NET MVC за пределами Hello World. Дятлов Александр D2D Just.NET
PPTX
Эволюция корпоративных Web приложений. Молотков Андрей D2D Just.NET
PPTX
Самодиагностика сервисов на базе платформы .NET
рентабельный код
Применение CQRS и EventSourcing в DDD-проекте
Микросервисы, чистый PaaS и конкурс Мисс Россия
Илья Ефимов «IoC/DI на примере Autofac»
Модульная структура. Цветцих Денис D2D Just.NET
ASP.NET MVC за пределами Hello World. Дятлов Александр D2D Just.NET
Эволюция корпоративных Web приложений. Молотков Андрей D2D Just.NET
Самодиагностика сервисов на базе платформы .NET

What's hot (19)

PDF
Денис Трифонов
PDF
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
PDF
Андрей Лузин
PDF
Как жить в согласии с SOLID?
PPTX
Как мы данные готовили ORM и все-все-все в приложении Почта Mail.Ru / Кирилл ...
PDF
"Производительность MySQL: что нового?"
PDF
Модульная архитектура Сбербанк Онлайн, Владимир Озеров и Александр Черушнико...
PDF
Игорь Кашкута
PPTX
Система обработки бизнес-логики server-side приложения на Groovy
ODP
Архитектура программных систем на Node.js
PDF
Артем Титаренко
PPT
презентация.1
PDF
Архитектура А/Б тестирования: сделай сам
PDF
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
PDF
"Новые возможности MySQL 5.7"
PPT
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
PDF
Порядок для скорости. Система структурирования фронтендовой части веб-приложе...
PDF
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
PDF
Java c человеческим (и даже богатым) лицом / Филипп Дельгядо
Денис Трифонов
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Андрей Лузин
Как жить в согласии с SOLID?
Как мы данные готовили ORM и все-все-все в приложении Почта Mail.Ru / Кирилл ...
"Производительность MySQL: что нового?"
Модульная архитектура Сбербанк Онлайн, Владимир Озеров и Александр Черушнико...
Игорь Кашкута
Система обработки бизнес-логики server-side приложения на Groovy
Архитектура программных систем на Node.js
Артем Титаренко
презентация.1
Архитектура А/Б тестирования: сделай сам
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
"Новые возможности MySQL 5.7"
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
Порядок для скорости. Система структурирования фронтендовой части веб-приложе...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Java c человеческим (и даже богатым) лицом / Филипп Дельгядо
Ad

Viewers also liked (10)

PDF
CQRS на практике. В поиске точки масштабирования и новых метафор
PDF
Гедонизм и выбор повседневных занятий
PDF
Rambler.iOS #5: Переходы и передача данных между VIPER модулями
PDF
RDSDataSource: Чистые тесты на Swift
PDF
Design & Process Models
PDF
Магия в Python: Дескрипторы. Что это?
PDF
Rambler.iOS #5: VIPER и Swift
PPTX
Dapper + QueryObject
PPTX
Node.JS error handling best practices
PDF
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
CQRS на практике. В поиске точки масштабирования и новых метафор
Гедонизм и выбор повседневных занятий
Rambler.iOS #5: Переходы и передача данных между VIPER модулями
RDSDataSource: Чистые тесты на Swift
Design & Process Models
Магия в Python: Дескрипторы. Что это?
Rambler.iOS #5: VIPER и Swift
Dapper + QueryObject
Node.JS error handling best practices
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Ad

Similar to Coding like a sex (20)

PPTX
Есть ли жизнь с ORM или типовая архитектура CRUD приложения
PDF
Гатиятов Руслан, технический директор ООО “Дроид Лабс”: “Система управления п...
PDF
C# Web. Занятие 04.
PPT
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
PPTX
разработка бизнес приложений (9)
PPT
Уменьшение влияния человеческого фактора при разработке бизнес приложений
PPTX
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
PDF
Архитектура в Agile: слабая связность
PPTX
разработка бизнес приложений (7)
PPT
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
PPTX
Строим простые и масштабируемые бекэнды
PPTX
Как писать красивый код или основы SOLID
PPTX
разработка бизнес приложений (8)
PPT
Net 3.0 & Linq
PPT
Обзор платформы B4
ODP
Entity framework
PDF
SECON'2014 - Александр Бындю - Переход от монолитной архитектуры к распределе...
PDF
Илья Ефимов «IoC/DI на примере Autofac»
PDF
Переход от монолитной архитектуры к распределенной
PPTX
SOLID Principles in the real world
Есть ли жизнь с ORM или типовая архитектура CRUD приложения
Гатиятов Руслан, технический директор ООО “Дроид Лабс”: “Система управления п...
C# Web. Занятие 04.
ORM технологии в .NET (Nhibernate, Linq To SQL, Entity Framework)
разработка бизнес приложений (9)
Уменьшение влияния человеческого фактора при разработке бизнес приложений
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Архитектура в Agile: слабая связность
разработка бизнес приложений (7)
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
Строим простые и масштабируемые бекэнды
Как писать красивый код или основы SOLID
разработка бизнес приложений (8)
Net 3.0 & Linq
Обзор платформы B4
Entity framework
SECON'2014 - Александр Бындю - Переход от монолитной архитектуры к распределе...
Илья Ефимов «IoC/DI на примере Autofac»
Переход от монолитной архитектуры к распределенной
SOLID Principles in the real world

Coding like a sex