Как стать автором
Обновить
32
172.3
Алексей @cupraer

OSS contributor

Отправить сообщение

Умение создать простое, понятное решение сложной проблемы — это высшее мастерство в программировании.

Прямая аллюзия на:

There is always an evident solution to every human problem—neat, plausible, and wrong.
H. L. Mencken

Мне кажется, что задачи бывают разные, и грести их все в одну кучу — упрощение.

Например, в коде библиотек общего назначения следование принципам YAGNI и KISS — самоубийство (вашим пользователям потребуется всё то, о чем вы подумали, и еще примерно три раза по столько того, о чем вам даже в страшном сне не приснится).

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

Если ваша сущность зависит от внешней сущности, dependency injection лучше организовать прямо сейчас, а не когда «потребуется».

А вот определять всякие свойства и методы с заглушками на вырост — это нет.

Я помню, как на заре появления докера, еще до того, как исходный код открыли, в сеть просочился кусочек инициализации чего-то там, с двузначной вложенностью условных операторов. Лет 10 назад, наверное, или типа того.

Они это наверняка подчистили уже, но я с тех пор запускаю докер только, если прям совсем припрет — и только в песочнице :)

у го есть особенность технологическая — позволяющая запустить обычным test suite сервис с его интеграционными зависимостями

Ну в эрланге/эликсире это дефолтное (и труднообходимое) поведение; тестовые фреймворки обычно позволяют запускать сразу кластер из нескольких нод (по желанию — в разном окружении).

Что можно инициализировать тысячами строк? Вселенную?

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

если не планируется расширение функциональности, то и не нужно на это закладываться, тратить на это лишние ресурсы

Вот я и говорю, что принесло кучу вреда. Чтобы заложиться на расширение функциональности — никакие лишние ресурсы тратить не нужно. Достаточно писать более-менее адекватный код (а не идеальный). Расширяемость обеспечивается очень просто, я бы сказал — тривиально. Просто не надо ее реализовывать сразу.

Простой, как березовое полено, принцип dependency injection вместо приколоченных гвоздями кросс-зависимостей — решает примерно 99% проблем расширяемости совершенно бесплатно. Псевдокод:

# неправильно
function getTemperature(city) {
  return WeatherService.getTemp(city)
}

# правильно
function getTemperature(service = WeatherService, city) {
  return service.getTemp(city)
}

С++ — компилируемый.
Питон — интерпретируемый (в оригинале).

А Ватсон на самом деле Уоатсн, и некоторые переводчики даже сделали шаг в эту сторону с «Уотсоном». К счастью, до конца этого пути не дошел никто.

В русском интернете он Линус. Так же, как французский город Бордо (Bordeaux) — в Испании — «Бордеус».

Мало что принесло бизнесу столько вреда, как YAGNI. Да и KISS слишком многие понимают как «фу, декоратор — это слишком сложно, будем прямо из сущности джейсон строить».

Этот кусок я в тексте видел; тоже — никак, потому что вам это не нужно. Как и тесты.

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

Понял.

А тестировать-то как? Раньше я передавал другую имплементацию на моках в качестве dependency и получал красивые, ёмкие и внятные тесты. А теперь?

То, что описано вот тут (под заголовком «Необходимость явных контрактов», прямую ссылку дать не могу из-за того, как хабр рендерит маркдаун).

В ООП это чаще всего реализуется интерфейсом.

Проблема с кодом выше в том, что при изменении имплементации DbClient без изменения его внешнего API тесты могут запросто поломаться, и с увеличением сложности проекта, увеличивается связность — а следовательно, снижается легкость сопровождения.

Я знаю, как это можно сделать. Я утверждаю, что вы ломаете контракт (в данном примере контракта вообще нет, но обычно он есть).

для разных случаев можно определить разное поведение

Ну представьте, что вы ходите в базу потенциально из пяти (ста) разных потоков, и вам нужно проверить, что только один правильный поток вызывается при вызове myService.doSomething(). Тут 2025 год на дворе, моки должны легко и внятно уметь тестировать параллельное выполнение.

мест в этой партии совсем было мало, всем желающим точно не хватило бы

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

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

TL;DR: как с помощью правильных промптов заставить автодополнение автодополняться по выборке из текстов о когнитивном развитии.

Я вообще ничего не записываю, кроме собственных мыслей, пришедших в голову перед сном (да и то).

Один журналист, держа в руках записную книжку и карандаш, спросил Эйнштейна:
— У вас есть записная книжка, чтобы записывать ваши мысли?

Эйнштейн посмотрел на него и ответил:
— Молодой человек! Сто́ящие мысли приходят в голову так редко, что их нетрудно и запомнить.

А про всё остальное, если оно действительно кому-то важно, мне напомнят.

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

Я посмотрел на библиотеку выше — и увидел навскидку две очень серьезные проблемы (насколько я понял по поверхностному взгляду): глобальность моков и нечеловеческое количество бойлерплейта.

Как быть, если у меня ну пусть два гринтреда, в одном мне нужен один мок, а в другом — другой? Такая задача передо мной встает довольно часто, и в эликсире она решается эксплицитным указанием, какому процессу (гринтреду) какой мок принадлежит. Тут я так и не смог понять, как быть, если в синтетическом примере из документации функция Bar должна вести себя по-разному в разных гринтредах.

Справедливости ради, main покрывать тестами довольно бессмысленно: оно же либо запустилось, либо нет. Ошибки обычно возникают в бизнес-логике, в высоконкурентной среде, в гонках, в алгоритмике. Но уж никак не в инициализации.

Информация

В рейтинге
30-й
Дата рождения
Зарегистрирован
Активность

Специализация

Это другое
Junior
От 120 000 €