Как стать автором
Обновить

Комментарии 14

Это случаем не то, что нынче называется гексагональной архитектурой и от парадигмы особо не зависит?
Вопрос с акцентом на то, почему это привязано к F# и Haskell? Потому что автор на них пишет, конечно же! :)

Если плясать от идеи того, что нам нужно сделать что-то гексагональное, неважно на чем — то наверное да, берем и натягиваем птиц любых видов на глобусы любых размеров, не маленькие уже.

А если плясать от идеи того, что нужно писать чистый код (насколько это можно на C#, F# и Scala, и имея в виду Haskell как пример хороших практик), то можно писать по-разному. Возникает вопрос — какой функциональный дизайн можно считать действительно хорошим. И что немаловажно, как именно записать это в синтаксисе языка. Например, для большинства людей совершенно неочевидно, что если мы откажемся от dependency injection, это не повлечет за собой замусоривание кода упоминанием зависимостей.
Для ясного и наглядного введения в монады типа Either смотрите отличную статью Скотта Улашина (Scott Wlaschin) «Railway oriented programming» (EN)

Перевод есть на Хабре.
Я правда ни разу не ФП-шник, но понял из статьи, что в check была зависимость от getReservedSeats, выносим ее выше и check зависит уже от результата getReservedSeats. Просто перенесли сложность из одного места в другое.

Похоже на то, как в 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-сахаре.

"Похоже, с таким количеством переводов он скоро станет топовым хаброавтором, даже не имея здесь аккаунта!"
Вы переводы от своего лица имеете ввиду?

так ведь куча переводов и не от моего лица, поищите. e_fedorov очередную стаью цикла про монады буквально на днях выпустил

тут вообще случилось смешное — мы переводили вдвоем одну статью одновременно с mitutee (одновременно, Карл!). Я выпустил на два дня раньше, что привело mitutee в некоторое уныние

вообще, Марк пишет статьи быстрей, чем успеваешь их читать. Если начать их переводить все, блог «функциональное программирование» окажется ими переполнен
Зарегистрируйтесь на Хабре , чтобы оставить комментарий