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

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

Канал в Max: https://max.ru/id544512614458_biz

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

На той недели мне в комментах подсветили батл между Робертом Мартином (он же «Дядя Боб») и Кейси Муратори, который в итоге свёлся к полиморфизму против свитчей (но с неожиданным поворотом).

Батл заканчивается фразой анкл Боба «Я думаю, нам стоит на этом остановиться в нашем споре и предоставить нашей аудитории вынести окончательный вердикт» (I believe we should let our disagreement stand at this point and let our audience be the final judge).

И мой вердикт таков: Муратори всю дорогу вёл по очкам и победил нокаутом, разнеся в пух и прах SRP, OCP и DIP. Правда, сделал он это в очень узком контексте — API, предназначенного для реализации внешними поставщиками (SPI в мире Java). Соответственно для разработчиков прикладных приложений (коих в мире большинство) это не имеет никакого практического значения. Тем не менее, ознакомится с ним полезно всем, на мой взгляд.

Так как батл у них получился невероятно длинный (я читал часа четыре) и довольно нудный, я советую прочитать только мякотку, начинающуюся во втором файле со слов «I’m not even talking about machine-cycles, I was just focusing on programmer-cycles». А для того чтобы сделать позицию Муратори более доступной русскоязычной аудитории, я решил сделать её близкий к дословному перевод.
🔥8
Привет!

Я недавно сделал Web Push уведомления в Trainer Advisor и попутно снова узнал и придумал пачку прикольных штук, о которых накатал очередной "микропост" на 30-40 минут чтения по оценке ФФ.

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

* Отправка пушей
* Архитектура
* Абстракция vs очевидность эффектов и разделение ввода и вывода
* И снова про уровни абстракции/стратификацию
* Пример №1: код открытия диплинка по клику
* Пример №2: фетч ресурсов с фолбэком на кэш и кастомную страницу «Сервис недоступен"
* Postgres GENERATED-колонки для ограничений целостности в JSONB
* TrainerAdvisorApis
* В Gradle-плагин GitProperties завезли поддержку git worktrees
* Отказ от Kotest Matchers в пользу shuold*-методов

#case@ergonomic_code #ergo_approach@ergonomic_code #ergo_arch@ergonomic_code #ergo_testing@ergonomic_code #trainer_advisor@ergonomic_code #ergo_persistance@ergonomic_code
🔥4❤3👍2
о, а вы знали, что вчера Spring Boot 4.0 пошёл в GA?

и там завезли нормальную поддержку версионирования HTTP API (вроде как - надо проверять)
и, имхо самое крутое, распилили наконец-то адовый spring-boot-autoconfigure.jar и теперь спринг на старте не будет пытаться загружать всю ту гору барахла, которую подерживает спринг, но из которой я ну от силы процентов 25 использую
👍13
Привет!

Вычитал тут в синей книги интересное про сущности.

Modeling ENTITIES
ENTITIES are defined by their identities. Attributes are attached and change. Therefore, strip the ENTITY object’s definition down to the most intrinsic characteristics, particularly those that identify it, or are commonly used to find or match it. Separate other characteristics into other objects associated with the core ENTITY.

Figure 5. 1
The name does not define a person’s identity, but it is often used as part of the means of determining it.

Many would dispute moving phone and address into Customer. It depends on how Customers are typically matched or distinguished. If a Customer has many contact phone numbers for different purposes, then the phone number is not associated with identity and should stay with the Sales Contact. The customerID is the one and only identifier of the ENTITY, but the phone number, name and address would often be used to find or match a Customer.

—

Моделирование СУЩНОСТЕЙ (ENTITIES)

СУЩНОСТИ определяются своей идентичностью. Их атрибуты прикреплены к ним и могут изменяться. Поэтому необходимо свести определение объекта-СУЩНОСТИ к его наиболее внутренним, сущностным характеристикам — особенно тем, которые идентифицируют его или часто используются для поиска или сопоставления. Остальные характеристики следует вынести в отдельные объекты, связанные с ядром СУЩНОСТИ.

Иллюстрация 5.1
Имя само по себе не определяет идентичность человека, но часто используется как часть механизма её определения. Многие поспорили бы насчёт включения телефона и адреса в Customer. Это зависит от того, как обычно клиентов сопоставляют или различают. Если у клиента есть много телефонных номеров для разных целей, то телефон не связан с идентичностью и должен оставаться в Sales Contact. customerID — единственный истинный идентификатор СУЩНОСТИ, но телефон, имя и адрес часто используются для поиска или сопоставления клиента.


Я смотрю в этот абзац и вижу там свои сущности-аспекты (и пример).
Меш тем, сущности-аспекты - это основная причина, почему я завожу собственную номенклатуру блоков, вместо ддд-шных сущностей и объектов-значений.
Сижу теперь и думаю, то ли дальше со своей сидеть (прописав в примечании совместимость с ДДД), то ли перейти на ДДД-шную, дополнив её типами сущностей (мне ещё справочники нужны) и сделав отсылку на это место.

#ddd@ergonomic_code #books@ergonomic_code
❤7
Привет!

Прокопал вопрос "когда использовать top-level функции в Kotlin" и собрал находки в статью на вики

ТЛДР:
1. Официальной рекомендации нет
2. Судя по всему команда разработки Котлина предпочитает использовать top-level объявления по максимуму
3. Но у меня и не только с этим возникли проблемы на практике
4. Поэтому:
4.1 используйте публичные top-level объявления только тогда, когда они будут использоваться повсеместно
4.2 приватные top-level объявления использовать можно и нужно
4.3 сложные/значительные функции, которые технически могли бы быть top-level, заворачивайте в объекты singleton-ы, чтобы "занеймспейсить" их

#kotlin@ergonomic_code #ergo_wiki@ergonomic_code
🔥6❤3
Привет!

Наткунлся на любопытную публикацию об исследовании характеристик поддерживаемых кодовых баз от настоящих учёных - Questioning Software Maintenance Metrics: A Comparative Case Study :)

Публикация любопытна в первую очередь тем, что базируется на данных предыдущего исследования, в котором они заказали реальную разработку реального (но небольшого - 2-3 месяца разработки) проекта в 4-ёх разных конторах.

Затем они посчитали для этих систем различные метрики поддерживаемости в духе размера, цикломатической сложности, глубины наследования и т.п.

Затем они наняли 6 новых профессиональных и примерно равных по квалификации разработчиков, чтобы они внесли по 3 одинаковые правки в двух системах, с замером времени работы над задачами с помощью плагина в ИДЕ.

А потом посмотрели, как трудозатраты связаны с метриками поддерживаемости.

И тут мы приходим ко второй любопытной штуке - TLDR-у исследования: лучшими метриками поддерижваемости системы являются её общий размер (в строках кода) и не низкая cohesion (в виде TCC - проценте пар методов, которые используют хотя бы одно обшее поле).

И этот результат для меня неоднозначен.

С одной сторны, в ЭП много практик, которые уменьшают общий размер системы - отказ от DIP-а по дефолту, открытая архитектура (обращение из контроллеров в репозы в обход сервисов/юз кейсов), минимизация маппинга (прямой маппинг sql result set -> final dto в простых операциях чтения данных), разделение доменной и персистеной модели только по необходимости.

С другой стороны, есть практика, которая плодит много кода. Я её ещё не полностью сформулировал, но она во много базируется на make illegal states unrepresentable.
В частности, например, если ей следовать и у вас есть операции создания и получения сущности, с генерацией ИДа бэком, то это значит, что вам надо завести две практически идентичных дтошки - с идом для ответов и без него для запросов.
И под каждый контекст надо завести по дтошечке с актуальным для него набором полей
И когда у сущности меняется состав полей - вносить правки во все дтошки не то чтобы прям боль, но дико бесит:)

И тут, как назло, ещё и Котлин со своей нуллабельностью не помогает - теоретически можно сделать одну дтошку с нуллабельным идом на все случаи жизни, но тогда везде кроме операции создания вам надо будет как минимум !! на иды развешивать, что будет бесить не меньше.

В общем. Не пишите лишний код. А какой код лишний - вопрос открытый:)

#papers@ergonomic_code
🔥6❤4👍4🤔2
Привет!

Обещаю в 2026 году не написать ни одного коммента со словами (и их производными) "TODO" или "временный":)

С наступающим!:)

PS>
Не спрашивайте почему я смотрю в код в 9 утра 31 декабря 🤦‍♂️
😁17
Привет!

Выпилил в #project_e поддержку АПИ в1 двухлетней давности.
Это примерно 7% всей кодовой базы проекта

Лучшее начало года, пожалуй, сложно представить:)

Ставьте лайк, если тоже больше любите коммиты, в которых удаляете код, а не добавляете новый:)
👍30😁5🔥3
Привет!

Итоги 2025 года - лучше поздно, чем никогда, правда же?:)

Итог №1 - Больше реального кода

Больше всего сил в 2025 году (192 коммита, против 43 и 36 в вики и блог) я вложил в Trainer Advisor - публичный пример проекта, написанного по ЭП.
За 2025 год я в нём сделал 34 различных фичи и фикса, самые крупные и трудозатратные из которых были:
1. Интеграция с Гугл Календарями (PR, пост)
2. Пуш-уведомления (PR, пост)

В результате, TA дорос до 20К строк исходников и 20 таблиц.

Помимо этого в #project_e мы за прошлый год сделали пару новых сервисов и допилили новых фич в ядро на 2.2, 4.1 и 6К строк соответственно.

В итоге суммарное количество промышленного кода, написанного по ЭП, перевалило уже за 121 тысячу строк Kotlin и Java-кода.

Итог №2 - Эргономичная архитектура

Также значительным на мой взгляд итогом 2025 года стало появление Эргономичной архитектуры и её представление с помощью трёх проекций. Описание Эргономичной архитектуры всё ещё в статусе черновика и публичных обновлений не было давно, но за кулисами я весь четвёртый квартал 25-ого года работал над проекцией модели данных. С четвёртой попытки у меня вышел текст, который мне нравится, но ещё надо убрать исторические наслоения из ТА, чтобы он стал хорошей иллюстрацией и собственно добавить эту иллюстрацию.

Итог №3 - Исследование характеристик поддерживаемых кодовых баз

Затем, довольно много времени и сил я потратил на проведение исследования характеристик поддерживаемых кодовых баз backend-приложений. К сожалению, собрать достаточное количество анкет не вышло (хотя анкета всё ещё открыта и вы всё ещё можете её заполнить:) ), поэтому все эти усилия по большому счёту пошли прахом. Тем не менее, у меня появилось слабое, но подтверждение, что ЭП как минимум не вредит поддерживаемости:)

Итог №4 - Большие посты

На поприще блоггинга я смог написать два больших поста:

1. Вам не нужна Чистая архитектура. Скорее всего
2. Учимся читать SQL SELECT

А всего в блог и вики я добавил (немного пугающие) 6660 строк. Это не считая незакоммитанных черновиков:)

Итог №5 - Новые паттерны

Ещё в 2025 году у меня оформилось несколько паттернов, немного сокращающих трудозатраты на разработку (за счёт того, что не надо велосипед придумывать):

1. Переход на UUID v7 в качестве идов сущностей
2. Пресеты сложных фикстур
3. [Wire]MockServers
4. и ещё пачка более мелких см. историю коммитов

Итог №6 - +1см в направлении книги

Прошлый год начался с того, что мне написал проектный менеджер ИД Питер с предложением издать книгу. На этой волне я немного полежал в направлении книги, но переключился на исследование. Знаете как расшифровывается СДВГ? "Синдром дефицита Вау! Голубь!".
И вот в конце прошлого года ко мне пришёл представитель уже второго крупного издательства с тем же предложением. Мы с ним довольно серьёзно продвинулись в планировании книги и ред. коллегия была готова заключить договор на издание книги, но с условием, что авторский текст я сдам до конца 26 года. А я по ряду причин не готов на это подписываться, поэтому и в этот раз не срослось.
Но, держим пальчики, процесс потихоньку сходится, когда-нибудь книга обязательно будет:)

#ergo_approach@ergonomic_code #traineradvisor@ergonomic_code #ergo_book@ergonomic_code
❤8👍7🔥3
Чего ждать в 2026 году

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

Поэтому список далее - это то, что у меня сейчас есть в голове и чего хотя бы теоретически можно от меня ожидать. А что будет на самом деле - только время покажет. Вы же уже знаете, как расшифровывается СДВГ:)

Итак, чего от меня можно ожидать в 2026 году:

1. Актуализация Project Mariotte - это то, чем я занимался до итогов. Обновляю платформу и зависимости и перевожу реализацию на актуальные паттерны ЭП.
2. Пост с опытом миграции на Spring Boot 4. Я уже смигрировал Project Mariotte и два небольших сервиса в Project E. И уже словил и решил гору проблем (с Jackson 3 в основном). На горизонте пары месяцев, я надеюсь мигрировать TA и основной сервис Project E и по результатам написать большой пост с граблями (и решениями), которые я словил в процессе.
3. Рефакторинг TA на актульный гайдлайн ЭП. ТА у меня будет иллюстрацией и для ЭА и для книги, поэтому надо убрать оттуда исторические наслоения и компромиссные решения
4. Описание проекции модели данных ЭА с примером из ТА.
5. Проекция поведения ЭА - там, похоже, тоже придётся ещё повозиться
6. Описание процесса транзакционного анализа и процессов проектирования модели данных и компонентов на его основе.
7. В целом пп 3-6 - это всё работа в направлении книги. Но помимо этого, возможно удастся начать описывать кейсы.
8. Наверняка я придумаю что-то ещё, столь же неожиданное, как и исследование:)

На что я готов подписаться, так это на то, что в 2026 году я продолжу работу над ЭП и продолжу писать о своих приключениях на этом пути в канале:)

В общем как всегда: стей тюнед, будет интересно:)

#ergo_approach@ergonomic_code #traineradvisor@ergonomic_code #ergo_book@ergonomic_code
👍10❤6🔥4
Привет!

У нас в группе вчера зашла речь про использование ИИ в кодировании.

А я как раз последний месяц сам код практически не пишу и активно занимаюсь отстройкой процесса разработки на базе ИИ:)
Поэтому я и в группе подробно ответил и сюда решил репостнуть:)

Общий сетап:
1. Платная подписка на OpenAI за 23 евро
2. Идея для работы с кодом самому
3. VS Code + Codex для работы с агентом

Сейчас у меня процесс устроен так:
1. Я: завожу рабочую директорию задачи
2. Я: в режиме потока сознания сливаю постановку задачи в файл
3. Я: пуляю exec-spec-space-prompt.md (см. аттачи) в модель
4. Gpt-5.2 medium reasoning (в сложных на мой взгляд случаях - high/extra high): задаёт вопросы
5. Я: отвечаю
6. Модель: генерит 4 варианта реализации
7. Я: вот тут идёт самая вариативная часть
7.1. выбираю вариант
7.2. задаю доп вопросы и выбираю вариант
7.3. вижу что какой-то рефакторинг упростит решение -> обсуждаю его с моделью -> прошу сгенрять краткую постановку задачу на рефакторинг -> "делаю" рефакторинг -> на п. 6 с новыми вводными
7.4. даю уточнения к одному из вариантов модели и выбираю его
7.5 вкидываю свой вариант -> на п. 6
8. Модель: генерит 02-solution-options.md, 03-solution-hld.md и пишет транскрипт чата
9. Я: полуяю exec-spec-prompt.md в новый чат
10. Модель: генерит ТЗ
11. Я: тщательно ревьювлю ТЗ.
11.1 Если есть замечания: мелкие правлю сам, больше отдаю модели
12. Я пуляю промпт "реализуй ТЗ" в новый чат с GPT-5.2-Codex low
13. Модель реализует ТЗ
14. Я: смотрю результаты запуска тестов в чате и если их нет, или запущен не полный набор - запускаю сам. Если не прошли - скидываю логи модели и говорю починить.
15. Я: ревьювлю код и
15.1 мелочь правлю сам
15.2 большие куски прошу поправить модель
16. Я: прошу модель записать транскрипт чата реализации
17. Профит

Если модель лажает в кодировании - я пока просто в режиме свалки скидываю указания в AGENTS.md.

Касательно эффективности этого процесса у меня объективных данных нет.
Субъективно:
1. Этап проектирования и написания ТЗ - эффективнее, так как я люблю затупить при генерации или выборе вариантов, а потом не люблю аккуратно их расписывать, поэтому делаю это со множеством перекуров, перекусов, переписов и перекаков.
2. Этап реализации - пожалуй, не быстрее чем делать самому, если в потоке. А если делать на морально-волевых - модель, пожалуй, быстрее справляется. Плюс тут пока модель работает, можно самому заняться чем-то другим
3. Как альтернатива работе со стажёрами/джунами - намного эффективнее. На самом деле, раньше я и с юниорами примерно в таком же режиме работал и это было очень долго. Плюс у модели лучше получается мимикрировать под окружающий код (читай: под ЭП).

Я несколько раз слышал, что соннет лучше код пишет, но не осилил подтвердить у них телефон:)

#ai@ergonomic_code #tips@ergonomic_code
🔥10❤6👍2
Привет!

У меня недавно в Проекте Э случилась поучительная и многогранная история. Эта история одновременно:

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

#why_fp@ergonomic_code #ergo_testing@ergonomic_code #project_e@ergonomic_code
Привет!

Новости с ИИ-полей.

Этот "compelling launch hero" сначала фризит мне ФФ на Андроиде, а потом крэшит его.

Так и живём:)
😢4
Привет!

Саша меня опередил - я сейчас примерно такую же штуку под ЭП делаю.

Но у меня там есть отдельный слой концептов ЭП, на которых я в скиллах ссылаюсь - типа "Диаграмма эффектов", "Эргономичная модель данных", "IRW-анализ" (бывшй транзакционный анализ).
🔥4
Продолжаем про вайбкод

0. Подарочек

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

1. Про мотивацию

Короче, уже видно, что AI-assisted software engineering - это 100% состоявшаяся практика. Ждать ничего уже не надо, это работает уже сейчас - надо брать и переезжать.

Поясняю:
- Обычный поток разработки (по ощущениям, конечно) раза в 3-4 быстрее, но это вилами по воде, потому что никто нормально не мерил и, вероятно, не измерит;
- Отдельные задачи (фронт, доки, инфра и т.д.) идут в десятки раз быстрее и делаются автономно;
- Инструмент совершенствуется в процессе работы, развивают его и вендоры, поэтому скорость растет постоянно.

В итоге, получается несколько даже перекошенный (хоть и в правильную сторону) результат. Если базовый функционал все так же едет вперед с неплохой стабильной скоростью, то вот обвязка, которую часто раньше делали по остаточному принципу (документация, UI/UX, тесты, инфраструктура и многие другие "фишечки") ИИ делает теперь автономно и очень быстро. Поэтому, когда функционал готов, он готов уже сразу весьма хорошо, на уровне лучших домов.

2. Про инженерный подход

Сегодня мне скинули вот этот пост, и, в целом, я с ним согласен. Если кратко, то там хаотичному "вайб-кодингу" противопоставляется "Инженерный подход". Я бы даже сказал ИИнженерный.

Вообще говоря, у меня есть некоторая аллергия на "инженерные подходы", связанная с известными проблемами водопада. Ну и к документации некоторый негатив из-за её вечно догоняющего состояния расхождения с реальностью. И из-за того, что её часто пишут люди, которым тяжело осознать, где бизнес-требования превращаются уже в детали имплементации.

Поэтому в нашей команде очень серьезно относятся к идеям Executable Specification, когда реальное поведение смотрят по тестам, а документация нужна лишь для заметок аналитиков и коммуникации между аналитками и разработкой.

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

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

3. Про ментальную модель

А вот с чем я не согласен, так это с аналогией, что LLM - это компилятор нового поколения. В книге у Vibe Coding Джина Кима и Стива Йегге указывается, что более корректная ментальная модель - не инструмент, а тиммейт. И наш опыт взаимодействия тоже показывает, что одна лишь фраза "What do you think?" в конце каждого промпта полностью меняет процесс взаимодействия.

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

А вот что работает круто:
- объяснить, что не нравится
- спросить мотивацию такого решения (если оно было принято только что)
- предложить свой вариант решения
- спросить мнение нейросети и попросить её предложить свои варианты

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

4. К скиллам

У меня получился целый фреймворк, который мы зовём "заводиком", заточенный чисто под мою разработку. Я не планировал им делиться, но раз уж спросили, то вот. Из подготовки к публикации - только сожженые 50% макс-сессии токенов на замену любых упоминаний моего проекта на таск-менеджер. Поэтому не серчайте сильно, что не очень user-friendly.
👍8❤4
Привет!

У меня в Эргономичной архитектуре есть ограничение на количество атрибутов сущностей и зависимостей операций (сервисов) с рекомендуемым значением "до 7 +/- 2".

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

Я тут в рамках разработки Ergo AI Agent Framework пошёл снова ботанить понятия cohesion и coupling, и, в частности, пошёл читать Code Complete (aka Совершенный код).

И там на странице 143 английским по белому написано:

Be critical of classes that contain more than about seven data members
The number “7±2” has been found to be a number of discrete items a person can remember while performing other tasks (Miller 1956). If a class contains more than about seven data members, consider whether the class should be decomposed into multiple smaller classes (Riel 1996). You might err more toward the high end of 7±2 if the data members are primitive data types like integers and strings, more toward the lower end of 7±2 if the data members are complex objects.

—

Критически относитесь к классам, содержащим более чем примерно семь полей данных.
Число «7±2» было выявлено как количество отдельных элементов, которое человек способен удерживать в памяти, выполняя при этом другие задачи (Miller, 1956). Если класс содержит более примерно семи полей данных, сто́ит задуматься о том, не следует ли разложить его на несколько более мелких классов (Riel, 1996).

Можно смещаться ближе к верхней границе диапазона 7±2, если поля представлены примитивными типами данных, такими как целые числа и строки; и ближе к нижней границе, если поля являются сложными объектами.


Возможно, вы, глядя на свою MyCoreEntity с 100+ полей и MyCoreEntityService с 80+ зависимостей, думаете, что мы с Макконнеллом теоретики, которые реального кода в глаза не видели.
Но это не так:)

Может быть, и не до 7 полей, но существенно упросить MyCoreEntity можно с помощью:
1. активного выделения Value Object-ов — например, завести класс PersonName(first, middle, last) и заменить три поля на одно;
2. активного выделения аспектов сущности в отдельные сущности — например, убрать из коренной сущности пользователя поле с его подписками, на веб-пуши.

А справиться с MyCoreEntityService поможет:
1. переход от сервисов к классам-операциям (ака юз-кейсам, интеракторам) — выделение каждого метода класса сервиса в отдельный класс с одним публичным методом. С непривычки это кажется дичью — по себе знаю, мне самому так казалось 2.5 года назад — но к этому быстро привыкаешь и назад уже не хочется;
2. повышение уровня абстракции ресурсов/гейтвеев/портов — например, если у вас агрегат включает в себя блоб (картинку), то можно заменить зависимость от UsersRepo и FilesStorage на сложный/составной ресурс/порт/гейтвей, которые внутри себя держит UsersDao для работы с РСУБД и FilesStorage для работы с хранилищем блобов.

#ergo_arch@ergonomic_code #books@ergonomic_code
❤9👍5👀2
Привет!

Реклама

Всем привет!
Давно состою в сообществе ЭП, и, мне кажется, тут должны быть одни из лучших специалистов.
У меня сейчас интересный этап жизни, участвую в удивительно амбициозном проекте, у которого есть много причин прийти у успеху.
Есть вакансия Lead backend Kotlin developer https://hh.ru/vacancy/130258007
Стадия ранняя, так что можно поучаствовать в мотивационных механизмах, в принятии ключевых технических решений и поработать с максимально (возможно даже слишком)) прогрессивным Kotlin стеком.
Все соглашения в правовом поле РФ.
Если будут вопросы, можете обращаться в том числе в личку в телегу. Рад, что могу осветить такую интересную возможность.
Алексей Горбунов @at3r7
❤7