Comments 13
А мы можем в рамках интерфейса указать, что какие-то значения мы поглощаем, а какими-то только пользуемся? Например, если мы из UnregisteredUser делаем RegisteredUser, то как можно сказать, что после передачи объекта типа Unregistereduser в конструктор RegisteredUser::register, оригинальным значением больше нельзя использовать?
Мне кажется, что это как раз то, чем занимается borrow checker в Rust.
Наверное это может выглядеть аналогичено тому как реализуется Lazy Load. Как вариант, в интерфейсе это может выглядеть так:
public RegisteredUser Register(IWouldAbsorbedHere<UnregisteredUser> user)
Для описанного в статье подхода Хориков в своей книге использует термины "широкий и глубокий код".
Только непонятно, почему автор использует термин "архитектура". Раз мы оперируем классами, то речь идёт об иммутабельном дизайне. Архитектура лежит выше и даже не знает, что там внизу - ООП, ФП или процедурщина.
А вот теперь я с Вами не соглашусь :)
Если мы говорим за архитектуру, в которой иммутабельное ядро (обычно это домен) оборачивается в мутабельную оболочку (оболочки), то тогда это луковичная (onion) или гексагональная архитектуры, и слоёв там больше чем два. Приведённые же иллюстрации (те, на которых круги) как раз таки очень хорошо подходят для концепции широкого и глубокого кода, которая про дизайн.
К слову, ещё один вариант архитектуры с разделением на мутабельные и иммутабельные части – CQRS, только там они не оборачивают друг друга, а существуют параллельно.
А пример с CQRS мне кажется притянут за уши. Ну типо можно провести аналогию, что команды только изменяют данные, а запросы только читают данные, но в случае комманд там же тоже можно разделить на иммутабельную часть и мутабельную, где домменный объект это иммутабельная часть, а сама команда (слой приложения) мутабельная. В тоже время запросы могут косвенно (через события) менять состояние, например, если у нас есть статистика просмотров.
Так я и говорю о том, что на Ваших иллюстрациях ни луковая, ни гексагональная архитектура. Так что эти иллюстрации подходят для дизайна, но не подходят для архитектуры.
Примеры тоже все про разделение ответственности по классам, а значит -- про дизайн.
CQRS я просто вспомнил как ещё один пример архитектуры с разделением мутабельности/иммутабельности, к теме статьи это никак не относится.
Хотелось бы уточнить, что сам я за такой подход – разделение мутабельного и иммутабельного кода – всеми руками и ногами, что у меня есть :), просто мы с Вами расходимся во мнении, где кончается архитектура и начинается дизайн. Предлагаю на этом закончить и разойтись, каждый со своим мнением :).
Думаю, автору понравится MediatR и введение в F#, включая Railway Oriented Programming.
Иммутабельная архитектура