Комментарии 14
Если плясать от идеи того, что нам нужно сделать что-то гексагональное, неважно на чем — то наверное да, берем и натягиваем птиц любых видов на глобусы любых размеров, не маленькие уже.
А если плясать от идеи того, что нужно писать чистый код (насколько это можно на C#, F# и Scala, и имея в виду Haskell как пример хороших практик), то можно писать по-разному. Возникает вопрос — какой функциональный дизайн можно считать действительно хорошим. И что немаловажно, как именно записать это в синтаксисе языка. Например, для большинства людей совершенно неочевидно, что если мы откажемся от dependency injection, это не повлечет за собой замусоривание кода упоминанием зависимостей.
Для ясного и наглядного введения в монады типа Either смотрите отличную статью Скотта Улашина (Scott Wlaschin) «Railway oriented programming» (EN)
Перевод есть на Хабре.
Похоже на то, как в js, асинхронщину в виде стримов или async/await выносят выше, что б в функции оставалась чистая бизнес логика.
Я так понимаю, это делается что б было проще переиспользовать и тестировать чистые функции.
Но нечистые все-равно же никуда не денутся, они просто выше окажутся, их тестировать и мочить тоже надо, смысл тогда какой в переносе, только в упрощении слоя с чистой логикой?
В статье вроде подразумевается, что этот подход лучше, чем DI и SOLID, а чем лучше — не понятно. Как здесь решить проблему с контекстами, когда детали верхнего уровня не знают о деталях нижних уровней. В DI можно определить реализацию интерфейса выше и не прокидывать его вниз, а просто прописать зависимость в конструкторе.
Как простому фронтендщику, мне было бы гораздо понятнее, если б хотя бы два todomvc запилили на dependency rejection и на dependency injection, и сравнили плюсы и минусы.
Насколько я понимаю, автор не совсем это хотел сказать.Вроде бы он сразу обозначил, что говорит про некие границы (порт/адаптер) и что этому способствуют и SOLID и чистота ФП.
По-моему он намекал не на проблемы SOLID в-прицнипе, а на проблемы его поддержки. Среда разработки не дает контроля за выполением этого самого SOLID. А вот в случае с чистыми функциями это контролируется. Чтобы что-то испортить тебе нужно явно это указать. А это очень быстро бросится в глаза на код-ревью.
Ну примерно как кто-то где-то изменил тип возвращаемого значения с int
на object
. Понижение уровня контроля сразу же бросается в глаза и ты спешишь проверить, а действительно ли оно требовалось… Действительно ли в данном конкретном месте и т.д.
Среда разработки не дает контроля за выполением этого самого SOLIDЧто значит не дает контроля за выполнением? Проверка типов есть, интерфейсы есть. Испортил реализацию — приложение не соберется.
Почему быстро бросится в глаза, а в SOLID значит не быстро? Это разве не от строгости языка зависит?
Как без DI быть с абстракциями, когда где-то наверху надо сказать, замени на 10м уровне вложенности класс X на Y, не влезая в иерархию деталей нижних уровней.
Что значит не дает контроля за выполнением? Проверка типов есть, интерфейсы есть. Испортил реализацию — приложение не соберется.
Соблюдение SRP не проверить даже статическим анализом.
Соблюдение OCP в теории частично можно автоматизировать, но не встречал.
Соблюдение LSP проверяемо.
Соблюдение ISP только частично. В теории конечно есть контроль на уровне статического анализа. Но анализатор не в состоянии подсказать, что ты используешь абстракцию слишком широко, что есть возможность использовать другой метод и уточнить абстракцию.
DIP — окей.
Итого только две состовляющие, но все равно с некой натяжкой. Какого-то 100% контроля не видно. К тому же из коробки этого нет. Нужно цеплять статический анализ.
Почему быстро бросится в глаза, а в SOLID значит не быстро? Это разве не от строгости языка зависит?
Как скоро на ревью тебе бросится в глаза разрыв SRP? При первом обновлении не заметил. Второе обновление ревьювил другой. Усталость, загруженность, ну и т.д.
Смену ключевого слова сразу заметишь и задумаешься. С остальным прицнипами лучше. Но опять же, глаза чаще будут закрываться на нарушение того или иного прицнипа. Потому что в данный конкретный момент это может выглядеть небольшим минорным изменением, которое не порушит идею в целом. Но по мелочам потом скопится тот еще огород. А вот делать функцию нечистой — это очень пахучий ход.
Мое понимание статьи примерно такое.
Прием — обработка, в том или ном виде, заявки от клиента (опр. по контексту статьи). Например, прием звонков, прием заявлений, прием обращений и т.д.
«Бронь» — жаргонизм от бронировать. Например, сделать бронь в ресторане.
В тексте комбинация из этих понятий используется в заголовках. Под первым из них
«Прием брони на F#, попытка первая»
излагается пояснение
«В моем Pluralsight-курсе Test-Driven Development with F# (доступна сокращенная бесплатная версия: www.infoq.com/presentations/mock-fsharp-tdd) я демонстрирую, как реализовать HTTP API для онлайн-системы бронирования ресторанов, который принимает заявки на резервирование. Один из шагов при обработке запроса на резервирование — проверить, достаточна (заставляет задуматься о грамотности перевода, прим.) ли свободных мест в ресторане для приема брони.»
В переводе присутствует такая же жаргонная фраза — «бронирования ресторанов» — при прочтении текста становится очевидно, что бронируются не рестораны, а места в них.
Оригинальный текст не читал, поэтому не могу сказать, является ли сам текс безграмотным или таков лишь перевод.
обратите внимание, что функция liftIO вызывается дважды. Вам не нужно в деталях понимать, что она делает, но она необходима, чтобы «вытащить» значение из IO-типа
Это совершенно неправильно. liftIO
нужен для выполнения IO
внутри стека монадических трансформеров. В коде автора никаких трансформеров нет, всё выполняется в IO, трансфомеры есть только в коде на github. «Вытаскивает» значение из IO-типа бинд (>>=
) или x <- m
в do
-сахаре.
"Похоже, с таким количеством переводов он скоро станет топовым хаброавтором, даже не имея здесь аккаунта!"
Вы переводы от своего лица имеете ввиду?
тут вообще случилось смешное — мы переводили вдвоем одну статью одновременно с mitutee (одновременно, Карл!). Я выпустил на два дня раньше, что привело mitutee в некоторое уныние
вообще, Марк пишет статьи быстрей, чем успеваешь их читать. Если начать их переводить все, блог «функциональное программирование» окажется ими переполнен
Функциональная архитектура — это порты и адаптеры