Эргономичный код
819 subscribers
81 photos
3 videos
20 files
401 links
Канал о разработке поддерживаемых бакэндов - про классическую школу TDD, прагматичное функциональное программирование и архитектуру и немного DDD.

Группа: https://t.me/+QJRqaHI8YD

https://azhidkov.pro
Download Telegram
Привет!

Экспозиция примеров нарушения LSP и их мотивации: https://github.com/spring-projects/spring-framework/issues/17787

> it would be easier to only maintain the additional feature of the "overridden" method.

> The
easiest solution for us, if it were possible, would be to mark the PUT/POST/DELETE methods of the subclass as not accessible.

Наследование вообще плохая идея, а такое его использование - просто ужас

#posts@ergonomic_code #solid@ergonomic_code #spring@ergonomic_code
Привет!

Я два месяца возился с SOLID вообще и SRP в частности и наконец-то осилил первый пост про SRP.

И этот факт многое говорит о простоте и понятности этих штуковин:)

Чтобы следующие два месяца ждать было повеслее, раскажу о чём я хочу ещё написать:)

Про SRP можно написать ещё как минимум два поста:
- часто забываемая половина про объединение "штук" которые меняются вместе
- подробнее расписать, чем я предлагаю руководствоваться при разработке ПО.

И про остальные принципы мне тоже есть что сказать:)

Плюс на ближайшее время у меня есть идея двух небольших заметок:
- читайте свой код. О технике поиска проблем в дизайне через чтение кода как текста на естественном языке
- ещё чутка попинать JPA, за нарушение структуры поддерживаемых приложений, открытого ещё в 70ых

Далее у меня есть хвосты о которых я помню:
1) Дописать итог к серии постов о видах функций
2) Пост с критикой пакетирования по слоям

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

Но что, в каком порядке и в какие сроки я опубликую - я уже не берусь предсказывать, так что стей тюнед:)

#posts@ergonomic_code #solid@ergonomic_code
Случилось чудо

В поисках Structured design: fundamentals of a discipline of computer program and systems design я перекапал весь инет и даже по оффлайн библиоткам пошукал - нашёл только на архив.орге.

От безисходности начал читать там, прочитал полкниги, дочитал до ссылки на ещё одну инетерсную книгу, пошёл гуглить эту книгу и нашёл пдфку структурнгого дизайна - отлично отсканеную и с распознаным текстом.

В общем рекомендую эту книгу. Она хоть и 77ого года, ну уже тогда изобрели как правильно делать информационные системы и с тех пор по сути ничего особо не поменялось.

Ну и заодно - https://archive.org/ тоже оказалась крутая штука:)
Там читать не особо удобно (картинки в браузере с арендой на час), но там много того, что нагуглить не получается. Плюс читать там - легально:)

#books@ergonomic_code #structured_design@ergonomic_code
Фух, опубликовал наконец статью об СРП, вздохнул полной грудью и Остапа понесло:)

Сам ещё не читал, но судя по картинкам накапал прям огненную статью о дизайне информационных систем: https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/

у неё в конце даже ссылка на русскую версию есть:)

#posts@ergonomic_code
Привет!

Крутой доклад о единственно верном функциональном подходе к управлению состоянием.
И львиная доля кода на JSе:)

Настоятельно рекомендую всем, у кого состояние ещё раскидано по всему приложению

#talks@ergonomic_code #functional_architecture@ergonomic_code #js@ergonomic_code
Привет!

Канал уходит на каникулы.

На фоне Новосибирской жары я понял что дико устал, так что ухожу на каникулы до сентября.

Всем хорошего (и комфорнтного!), лета:)

Может быть буду эпизодически скидывать интересные ссылки или даже не большие заметки, но не обещаю - как пойдёт.
Привет!

Начинаю потихоньку возвращаться с каникул и решил написать линко-мысли-в-слухо-пост.

Подвернулся недавно вот этот пост.

Если вкратце, Лукас Эдер (автор jooq-а), предлагает тянуть json сразу из базы, не заморачиваясь на маппинг в энтити, а потом в ДТО.

И этот пост прям хорошо лёг на то, что я в последние пару месяцев качнулся в сторону "облегчения" разработки. Я тут недавно в одном из своих "хорошо" спроектированных проектов добавлял одно поле и мне для этого потребовалось потрогать штук 5-6 классов, в паре-тройке пакетов. И мне это не понравилось. А с таким подходом мне надо было бы поправить ровно два места - в схеме БД и в запросе. Это та самая вторая часть SRP - одна "вещь" должна делаться в одном месте.

До этого подхода тоже, конечно, можно докопаться с разной степенью успешности:

1. Он подходит только если json сливается напрямую в ответ, без какой либо обработки в приложении.
2. Он не подходит если итоговый ответ надо собрать из нескольких источников.
3. Слой работы с БД по факту сцепляется с веб-слоем. Если в ответе надо будет поменять имя поля, то это надо будет делать в репозе.
4. Логика помещается в БД. Тут я уже не согласен. Во-первых, это вообще сейчас модно (Datomic, VoltDB, например, реализуют транзакции только через хранимки). Во-вторых, логика всё равно остаётся в "приложении" - в том же репозитории, по соседству с вызывающим кодом. Написана просто на встроенном DSL-е.
5. Зависит от технологии работы с БД и самой БД, но скорее всего прямо json из базы вернётся каким-то специфичным для базы типом. И это уже будет нарушением принципа сокрытия информации, что совсем плохо. Это можно обойти, вернув из базы или репоза строку и получив stringly typed код.

Тем не менее, мне кажется что для простого веб АПИ к БД, такой подход должен хорошо работать. Я собираюсь попробовать:)

Так же этот подход хорошо согласуется с ещё одной идеей по облегчению разработки - замена "тупых" сервисов на функциональные типы. Мне всегда резал глаз код вроде этого:
class UsersConf {
@Bean fun usersRepo() = UsersRepo()
@Bean fun usersService() = UsersService(usersRepo())
@Bean fun usersController() = UsersController(usersService())
}
class UsersController(val usersService: UsersService) {
fun findById(id: Long) = userService.findById(id)
}
class UsersService(val usersRepo: UsersRepo) {
fun findById(id: Long) = userRepo.findById(id)
}


Сейчас я хочу попробовать вместо этого писать так:
class UsersConf {
@Bean fun usersRepo() = UsersRepo()
@Bean fun usersController() = UsersController(usersRepo()::findById)
}
class UsersController(val findUserById: (Long) -> User) {
fun findById(id: Long) = findUserById(id)
}


Кода меньше, а в плане связности так даже лучше - контроллер вообще зависит только от платформы.

В общем буду теперь двигать эргономичный подход в сторону баланса между удобством навигации/рефакторинга/типобезопасностью и количеством кода, который надо навигировать/рефакторить/использовать.

P.S.

Как вытянуть json в Postgres

#posts@ergonomic_code #ergo_persistance@ergonomic_code #ergo_approach@ergonomic_code #databases@ergonomic_code
Привет!

Протип: в идее (ультимейте) есть встроенный тул для визуализации планов SQL-запросов

Попасть туда можно через Ctrl+Shift+A -> Explain*, стоя курсором на запросе

https://www.jetbrains.com/datagrip/features/executing.html

#tools@ergonomic_code
И ещё линка
Я постоянно между делом попинываю тестирование с моками, но свой развёрнутый пост на эту тему ещё не написал. А тут мужик всё правильно написал, да ещё и на русском.

Я уже находил блог этого мужика - хороший мужик, рекомендую подписаться. Блог правда на английском

#posts@ergonomic_code #ergo_testing@ergonomic_code #terminology@ergonomic_code
Красный + Зелёный = ?
Anonymous Poll
22%
Жёлтый
78%
Коричневый
Привет!

Ночные мысли.

Хибер и спринговый компонент скан вроде как дожны увеличить продуктивность программиста. С одной стороны.

С другой стороны, по моему опыту, проект на хибере и компонент скане в среднем стартует 30-60 секунд. На моём топовом 12-ядерном i7 19ого года с 32 гигами быстрой оперативы и быстром ссд.

И я никогда не жду эти 30-60 глядя в консоль. В лучшем случае иду чатики проверить. А то и покурить. И хорошо если не в курилку, где легко можно на полчаса залипнуть (когда в офисе работал).

В итоге один рестарт приложения стоит в среднем минут 5.

А спринг и хибер не особо дружат с хот релоадом. Да и я не уверен, что многие девелоперы вообще знают о нём. Но даже с хот релоадом у меня выходит

В общем такой наброс: компонент скан и хибер увеличивают время разработки на 10% только за счёт времени старта (не говоря уж о войне с автомагией и адовыми багами вызванными её не правильным использованием).

Увеличивают ли они продуктивность на столько же? Не уверен.

#ergo_approach@ergonomic_code #whynojpa@ergonomic_code #spring@ergonomic_code
Прикольный тред (не сильно длинный, минут 5-10) о происхождении термина boilerplate. И, внезапно, это однокоренное слово с "Бойлер"

#posts@ergonomic_code
Привет!

Утренние мысли.

В рамках концепции
> В общем буду теперь двигать эргономичный подход в сторону баланса между удобством навигации/рефакторинга/типобезопасностью и количеством кода, который надо навигировать/рефакторить/использовать.

решил попробовать чутка сдать позиции, и пустить spring data jdbc в слой домена, и спринг в целом в слой приложения/юз кейсов/интеракторов. На этом фоне, внезапно подумал, что надо поглядедь на код анкл Боба - может всё-таки без этого можно обойтись и всё придумано до нас.

А там - ни одной информационной системы. Есть Fitnesse, которая судя по всему с БД вообще не работает. Есть пачка всяких игр и симуляторов, всякая мелочёвка и всё.

Тогда я решил залезть в репоз 8th light (которы вроде бы связанной с анкл Бобом). Там тоже всякая мелочёвка.

Дальше я пошёл просто шукать по гитхабу Clean Architecture. Тут уже появились демо проектики с одной сущностью. Но всё ещё ни одного реального репоза с проектом хотя бы на 5-10 сущностей.

Писать посты и рисовать красивые картинки легко - сам так делаю:) Но “Talk is cheap. Show me the code.” (c) Torvalds.
Знаете хоть один живой пример проекта с чистой архитектурой?

При том, что мне концептуально нравиться идея чистой архитектуры, мне надо учить людей писать реальный код за конкурентноспособную цену, а не демо проектики или шедевры дизайна.

Пойду дальше искать своего Грааля:)

#ergo_approach@ergonomic_code #ergo_persistance@ergonomic_code #clean_architecture@ergonomic_code #posts@ergonomic_code
Привет!

Линкопост

What Modules Are About

Вообще статья о Jigsaw модулях, но там есть пара нужных мне цитат:
> A Java module is a set of packages that declares which of them form an API accessible to other modules and which are internal and encapsulated — similar to how a class defines the visibility of its members.

> If you’re a team lead or an architect of a big new project, or just hope that your software will grow big and/or popular someday, you might well reap great dividends from modules for little effort.

> Over time, the application’s components become entangled, making evolution painful as any change anywhere can affect pretty much anything else.

И тут мы приходим к топику пакетирования, и его самого распостранённого вида - по типу кода (controllers, services, models и т.п.). Ну и заодно к слоёной "архитектуре".

По моему опыту, при таком подходе к "архитектуре" в проектах инкапсуляция отсутсвует как класс. Все классы вынуждены быть публичными и даже просто логически попадают в интерфейс "модуля". И инкапсулировать становится просто не чего. Особенно если разработчик мыслит ~5 категориями - кнотроллер, сервис, модель, репоз, ДТО, исключение. В итоге получаем "application’s components become entangled, making evolution painful as any change anywhere can affect pretty much anything else".

А когда генерят заголовчные интерфейсы, для них *Impl реализации, а потом скалдывают их в пакет .impl и делают всё паблик - это не инкапсуляция. Это карго культ.

Как делать по другому? Я работаю над этим вопросом:) Кажется, медленно, буквально по капли, но верно, но я нахожу ответ на него. Так что, стей тюнед:)

#posts@ergonomic_code
Привет!

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

И сегодня у нас Simplicity enables an evolutionary software architecture.

Избранные цитаты:
1) Для того чтобы держать дизайн простым и изменяемым, он должен отражать ментальную модель пользователя (примечание переводчика: а не технические аспекты реализации)
2) Мы ограничены в количестве вещей, которые можем одновременно держать в голове. Изменять ПО сложно потому что, необходимо понимать все последствия изменений, для того чтобы не внести регрессий. Поэтому мы разбиваем ПО на модули. Работая внутри [хорошо спроектированного модуля] в голове надо держать только сам модуль, интерфейсы модулей с которыми взаимодействуем и контракт самого модуля
3) Совет 1: добавляйте новую функциональность добавлением нового кода. Только новая функциональность знает о существующем коде, с которым ей надо взаимодействовать. [Но не наоборот]
4) Совет 2: Если новая функциональность не может быть добавлена только новым кодом, минимизируйте изменения в старом коде
5) Есть прикольная картинка со списком архитектурных аспектах, о которых стоит задуматься при старте проекта
6) Есть прикольная картинка с тем как выбираться из ямы техдолга, когда на саппорт и баг фикс уходит всё время. Там среди прочего есть любопытная идея политики 0 багов - баги чинятся или сразу или не чинятся вообще.

#posts@ergonomic_code
Привет!

Всегда запускал БД в тестконтейнере один раз на запуск тестов и чувствовал себя при этом плохишом.

А тут выяснилось, что это идиоматичный способ работы с тестконтейнерами. Стабильность тестов при этом не увеличилась, конечно, зато чувствую себя теперь пионером:) Тем который всем пример:)

#posts@ergonomic_code #ergo_testing@ergonomic_code #integration_tests@ergonomic_code