Information
- Rating
- 3,789-th
- Location
- Кольцово, Новосибирская обл., Россия
- Date of birth
- Registered
- Activity
Specialization
Chief Technology Officer (CTO), Software Architect
Lead
From 500,000 ₽
Functional programming
Object-oriented design
Design information systems
TDD/BDD
Kotlin
PostgreSQL
Java Spring Framework
Linux
Git
Docker
Ещё, кстати, прикольная идея в этом ключе и без фокуса на разделении ио и логики - Integration Operation Separation Principle и Integration Operation Data API Architecture
Да ну как сказать. React (да и Compose на андроиде) именно так и делает, насколько я знаю, и не чё "пипл юзает".
Да, полагаю, под капотом они хачат реальную модель "на месте", но сами UI компоненты и их состояние (с Redux-ом по крайней мере) с точки зраения разработчика - чистые функции и неизменяемые данные. Опять же насколько знаю, сам ни на React, ни на Compose не писал ничего.
Но вообще я возьму самоотвод - UI в целом и его рендеринг в частности - не моя специализация.
Как я писал - в вашем конкретном примере я бы ничего не стал глобально менять. Там нет логики, на которую хотелось бы писать десятки тестов - ваш конкретный случай я бы вообще покрыл 4 интеграционными тестами - хеппи пас, и по тесту на каждую из ошибок.
Ещё, пожалуй, стоит проговорить, что цепочка - ввод -> бизнес-логика -> вывод - это идеал, которого часто, но не всегда можно достичь.
А вот штука, которой можно достичь практически всегда - это сендвич - io -> logic -> io -> logic -> io.
Но большой вопрос стоит ли оно того.
Плюс по моим канонам, сам io на внутри себя и на своём уровне абстракции может содержать логику. Вот тут у меня описан пример такого случая.
Вот ещё пара ссылок по теме, как упоровшись по ФП выжимать возможный максимум разделения ио и логики:
https://blog.ploeh.dk/2017/02/02/dependency-rejection/
https://blog.ploeh.dk/2019/12/02/refactoring-registration-flow-to-functional-architecture/
Не правильно.
Идеи тащтельного проектирования АПИ и разделения ио и логики - универсальные и годятся веде.
Код серверного рендеринга - естественно придётся выкинуть в трубу при разработке десктопного клиента.
Код бизнес-логики от вида клиента никак не зависит и будет работать и дальше.
Если вы захотите запустить весь сервис на дескотопе в одном процессе - выкинуть придётся код контроллеров (связывающий HTTP и бизнес-логику).
Если вы при этом захотите отказаться и от реляционки (хотя бы в виде SQLlite) в пользу файликов - так же придётся написать занового код репозиториев (связывающий бизнес-логику с постоянным хранилищем)
:)
Судя по этому сообщению, вы, путаете клиентский и серверный рендеринг:) Это такая технология древних, когда браузер отправляет HTTP-запросы, получает HTML и, действительно, ререндерит всю страницу. Вообще без JS-а.
Советую ознакомится с HTMX и идеями за этой либой - позволяет делать "good enough" UI за очень дёшево.
Технически (в нормальных языках :troll:) это можно сделать так:
Но стоит ли оно того в данном конкретном случае - для меня большой вопрос.
PS>
Ну а если у вас Прям Нормальный Язык для ФА (Haskell) - оно всё автоматом будет лениво тянуться
На самом деле это довольно сложно в имеющихся условиях.
Во-первых, структура графа вызовов - это только один из трёх аспектов архитектуры, по которой я сейчас работаю.
И, возможно, если бы у меня был бы доступ до всей вашей кодовой базы и цель перепроектировать - получилось бы что-то совсем другое. А может и нет.
Во-вторых, вы меня даже вменяемого нейминга лишили и мне приходится работать только с синтаксисом. А дизайн - про семантику, а не синтаксис.
В-третьих, в вашем примере практически нет бизнес-логики.
Но тем не менее, давайте я попробую.
Что бы я точно сделал:
Собрал вычисление h в отдельный метод
Сделал бы данные неизменяемыми, а сохранение обновлений явным
Возможно ещё обернул бы логические выражения проверок в методы с вменяемыми именами, особенно для b и c:
Но это всё косметика. Тут надо либо сильно глубже смотреть, либо в этом примере и правда бизнес-логика предельно простая и самоочевидная.
Публичных примеров прям кода прям с бизнес-логикой у меня ещё нет. Но есть:
Пример кода оркестрации и графа вызовов операции для операции со сложной бизнес-логикой
Пример построения сложной модели представления
Тривиальная оркестрация
Развесистая логика на чистых функциях
Пример построения docx-дока
Тривиальная оркестрация
Относительно развесистая логика построения в виде чистой функции
Тут код - прям наскоряк написанный говнокод - это был прототип фичи, которая оказалось не востребованной, поэтому рефакторить я его не стал. Но это чистый говнокод - если ему в fetchImage подсунуть Map::get - он для одних и тех же аргументов всегда будет возвращать один и тот же результат.
Здесь, здесь, здесь и здесь
Вот он
Чуть позже
Ответ на ваши опасения относительно Функциональной (а Симан в дополнение к Фрактальной топит и за Функциональную) архитектуру так же есть в посте:
Ответ есть в посте
Да, это правда. В моём случае так и есть - последние 4 года я либо делаю проекты с нуля, либо реорганизую их.
В этом случае, имхо, надо держать в голове только два стандарта - тот за который платят прямо сейчас, и тот, за который вы хотите чтобы вам платили:)
Цель для меня - психологическое благополучие - у меня низкая стрессоустойчивость, поэтому в условиях горящих сроков и критов на проде мне жить некомфортно. А цель для бизнеса - минимизация суммарной стоимости владения продуктом. Структурный дизайн - это часть моего комплексного подхода к разработке бакендов. И опыт показывает что на горизонте от 6 месяцев работы этот подход позволяет снижать трудозатраты на разработку, в том числе за счёт снижения количества багов.
Нет, это действительно проблема и я её решаю описывая свой подход и рассказывая про него. Но опять же опыт показывает, что даже джуны за 2-3 месяца могут понять как писать такой код и потом их надо только на ревью минимально контролировать.
Значит у вас всё хорошо со скоростью и качеством разработки:)
Если вы любите хайлоад, то лучше меня знаете, что все оптимизации делаются на основе конкретных цифр, конкретного кода. Поэтому в общем случае и правда не ясно.
Конкретно в моей практике нехайлоада (там где вопрос производительности вообще возникает) производительность только улучшается, так как в 100 случаях из 100 она упирается в неэффективную работу с БД.
В оригинальных книгах речь не о сбалансированной форме дерева, а о балансе уровня абстракции основных ветвей.
Тут вам, возможно, будет интересен другой мой доклад - Рациональный подход к декомпозиции систем на модули или микросервисы. Я там как раз рассказываю о своём подходе к декомпозиции системы на минимально сцепленные модули-объекты. Правда я сейчас отказался от него:)
Да это так, но тут сильно повлияла специфика Joker - там ПК очень любит "мясцо"
Написать гайдлайн по проектированию кода трансформаций я тоже собираюсь. Пока что планирую взять за основу Stratified Design. Он хорошо расписан в книге Grokking Simplicity и есть доклад на эту тему от автора книги (сам не смотрел ещё)
К такому проекту я и на пушечный выстрел не подойду:)
Но если проект на 3M строк и 100 разработчиков попилен на 30 сервисов по 100К кода и покрыт качественными тестами - каждый сервис мигрируется также в пределах рабочего дня. Тот же проект, когда он был уже на 50К строк Котлин кода (и я его уже этом размере попилил на два сервиса) на минорные версии обновлялся за минуты.
Я в прошлом году переводил проект меньше раз в 7 (~300 Котлин файлов), но порядка на 2-3 быстрее:
Для перехода я:
очевидным образом, обновил версии
заменой по проекту поправил javax.* -> jakarta.*
Поменял com.github.tomakehurst:wiremock-jre8:2.35.0 -> com.github.tomakehurst:wiremock-jre8-standalone:2.35.0. Без этого были проблемы со спекой сервлетов, что ли
В конфиге Spring Security заменой по файлу поправил antMatchers -> requestMatchers
Руками поудалял ConstructorBinding
Больше всего времени ушло на то, чтобы реанимировать вытягивание доков к эндпоинтам в сваггере из котлин доков. Для этого пришлось руками добавить зависимость runtimeOnly("com.github.therapi:therapi-runtime-javadoc:0.15.0"), а допетрить до того, что этот джарник пропал из зависимостей (без ошибок) пришлось самостоятельно
всё. Все 100+ тестов (преимущественно пользовательских/внешних/функциональных/е2е) прошли, приложение благополучно задеплоилось на тестовый стенд. И потом обошлось без факапов в проде
Всё это я сделал часа за два грустным вечером 5-ого января:)
Возможно секрет в том, что проект у меня был на Spring Data JDBC:)
Блин, это я уже после правок поворошил блог и опять линку сломал 🤦♂️ снова поправил
О каких именно sql-е и идеях вы говорите?
Процедурное программирование. Я так называю подход, когда классы сущностей (данных) изменяемые и имеют только геттеры/сеттеры, а вся логика - в сервисах/юзкейсах
Я на Паскале писал ток лабы и курсовик в первом семестре первого курса, у меня с тех пор от собственного кода вьетнамские флешбеки, которые в моей голове намертво приколочены к BTP - короче я. ничего. не. забыл :)
На хабр пришло поколение людей, которые родились позже (де-факто) смерти Borland Turbo Pascal:)
В мокей картине мира Functional Core/Imperative Shell = структурный дизайн + неизменяемая модель данных.
Т.е. преимуществ нет, а большая для вас сложность закралась где-то в моём объяснении и/или вашем восприятии:)
В общем если вы владеете FC/IS - вы умеете и балансировку делать:)
Ещё, кстати, мысль дилетанта - а оно (архитектура) вам вообще надо?:)
Бакендеры заморачиваются, потому что бакэнды живут годами и десятилетиями. И покопавшись в говне мамонта невольно начинаешь задумываться о том, чтобы в следующий раз позаботиться о себе и сделать понятную и поддерживаемую кодовую базу.
А игры, кажется - максимально быстро запилил, зарелизал и ещё до релиза забыл про первую игру и начал пилить вторую.