Информация об изменениях

Сообщение Re[4]: Что не так с тестовым заданием? от 08.03.2019 23:48

Изменено 09.03.2019 2:08 arth

Re[4]: Что не так с тестовым заданием?
Здравствуйте, maxkar, Вы писали:

M>Здравствуйте, arth, Вы писали:


A>>Здравствуйте, maxkar, Вы писали:


реально не поленюсь

M>>>Как уже правильно сказали, в readme не написано, как собирать. Одна-две строчки много времени не займут, а для читающего приятно и не надо вспоминать, какая там у вас культура.

A>>камон. я не для домохозяек туториал пишу.
M>Не для домохозяек. Но вы предполагаете, что проверяющий хорошо знает все модные тренды во всех трех предложенных языках. А это может быть и не так. Может, они Java позволяют только для того, чтобы иметь больший круг кандидатов и потом переучивать их на используемый стек. Можно не иметь подробного описания сборки для проектов внутри команды, общее знание достигается через onboarding и тренировку. А вот для тестового задания две-три строчки о сборке будут полезны. Еще показывают, что вы все-таки задумываетесь о пользователях и умеете в какой-то мере бороться с проекцией "я знаю, значит и все остальные должны знать".

давайте без демагогии. gradle это не "еще одна билд система из миллиона билд систем". если ты видишь build.gradle в проекте и все еще не знаешь куда смотреть чтобы его собрать — ну тогда у нас с тобой разная культура и нам не по пути

M>>>У вас там в бинарниках трояна нет?

A>>это тестовое задание. как и что это показывает — от "ничего" вплоть до "все"
M>Но вы же согласились его делать. Значит согласны, что что-то оно показывает? Свобода выбора технологий как раз полезна — показывает, о каких глубоких вопросах задумывался кандидат. И какие предпочтения имеет.

спроси меня прямо, вместо того, чтобы додумывать. попахивает демагогией. можно еще про порно на псевдографике в readme подумать. все зависит от того кто как думать привык

M>>>Тесты. Вы их с падающими assert проверяли? У меня вот подозрение, что после первого падения все остальное упадет с AddressAlreadyInUse. Что как-то нехорошо. Например потому, что после этого нужно исправлять первый упавший тест а не любой понравившийся.

A>>проверял
M>Ну и как? Удобно находить, где там ошибка? Я вот специально сейчас сломал один тест. Получил четыре AssertionError без каких-либо внятных сообщений об ошибках. Пришлось копаться в стеках, чтобы понять, откуда они происходят. Дополнительные сложности там, где их легко избежать.

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

M>>>Не StorageTest а StorageImplTest. Вот представьте, у вас есть несколько реализаций Storage. Какую из них тестирует StorageTest?

A>>вы серьезно?
M>Конечно. StorageTest по названию — это тест на соответствие спецификации (compliance). Т.е. любая реализация должна проходить эти тесты (которые с большой вероятностью property based). Здесь же можно поговорить про то, как сложно делать тесты, параметризованные объектами. При этом тесты конкретных реализаций либо расширяют StorageTest (и обходят ограничения фреймворков тестирования), или тестируют какие-то дополнительные свойства, характерные для этих реализаций.

это все круто, но не к месту совсем.

M>>>Ваш restful тянет только на Level 0 (используется HTTP). Банальный RPC over HTTP. SOAP, кстати, тоже попадает в REST Level 0. Хотелось бы видеть хотя бы Level 1 — Entities & Verbs (т.е. PUT /accounts/abc, GET /accounts, ...).

A>>кому хотелось и зачем?
M>Ну в первую очередь вам. Потому что вы хотели продолжения интервью или найма. Хотелось бы мне. Как минимум потому, что приятно поговорить с кандидатом с широким кругозором. За реализацию Rest Level 1 вы бы получили плюсик. А на самом деле при создании API вы скорее всего вспомнили бы причины, по которым REST был спроектирован в его виде. И задумались бы про идемпотентность (idempotency) операций. Не обязательно ее реализовывать, можно было просто упомянуть в readme: "идемпотентность не реализована из-за ограничений на время, могу прислать план реализации по запросу". И получили бы сразу пять плюсиков.

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

M>Idempotency здесь очень важна. Вот представьте, я вызвал ваш RPC API и получил IOException. Вот что я с ним должен делать? Ничего (и рисковать, что запрос был потерян)? Или повторять запрос (и рисковать, что я проведу операцию дважды)? Вот из-за вашего API мне придется городить Artificiall Intelligence (искуственную разведку), которая будет выяснять состояние предыдущей операции прежде чем повторять. А с идемпотентным REST я бы ее просто повторил и сказал вам большое спасибо. Ситуация вполне реальная, и в том числе в финансовой сфере . Это — основная причина, по которой Rest Level 1 хотелось бы видеть лично мне.


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

M>>>Ожидание ввода в main — решение спорное. Как оно поведет себя в каком нибудь Kubernetes? Там некому будет вводить порт. Вообще право на жизнь оно имеет, но такие сюрпризы должны описываться в readme.

A>>надеюсь вы несерьезно, потому что тест не для запуска в Kubernetes
M>Серьезно. Потому что кандидат, написавший 5 приложений под Kubernetes, не будет вообще писать ввод. И опишет аргументы командной строки в README. Может это и не страшно, зависит от конкретной позиции, на которую вы претендуете.

ну да, не написал, то джуниор, написал — архитект. ладно, спишем на разную культуру

M>>>*Impl. Это вот у вас ровно одна реализация предполагается? Почему бы не InMemoryStorage, например?

A>>а у вас? и почему если не одна, то не InMemoryCuncurrentHashSetStorageImpl? понятно куда клоню?
M>А у меня — несколько реализаций предполагается. И обычно их и есть несколько. Очень часто отдельная in-memory (или какая-то упрощенная) для тестов. Во многих случаях — декораторы. За что-то более осмысленное чем *Impl получили бы плюсик. Против вашего длинного варианта ничего не имею, он выше минимальных ожидаемых стандартов. За последовательное следование вашей конвенции (и сохранение нужных уровней абстракции и т.п.) получили бы сразу два плюсика. И я бы начал задумываться, а не стоит ли внедрить ваш стиль для всей команды.

Impl — вполне осмысленно, если нет ничего иного, и, опять же, в контексте тестового задания

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

A>>нечего добавить. не вижу в 2019 году задачи явно показывать знание Factory Method
M>А вот и не угадали . Это задача на проектирование API, минимизирующего изменения в кодовой базе и расширяющего круг возможных рефакторингов. Один конкретный случай, конечно, не влияет. Но ведь проектирование таких API — это автоматизированный навык (подобных решений разработчики делают много). А вот на большой кодовой базе преимущества factory method уже будут заметны. Опять же, я на самом деле не требую именно фабричный метод (это один плюсик). Любое другое API, служащее той же цели (минимизация потенциальных изменений и расширение простора для рефакторинга) даст вам как минимум два плюсика.

соразмерность решения и задачи. все что могу сказать. про рефакторинги можно отдельно поговорить на интервью

M>>>В StorageImpl вложенность кода глубокая. Можно было бы спрямить через if/throw и if/return.

A>>а можно было и нет. дело вкуса
M>Это конечно да. Но толерантность к глубоким стрелкам настроаживает. Очень часто приводит к длинным и глубоким вложенностям, условиям и т.п. А потом мне приходится вспоминать, к чему же относится одинокий else с одной строчкой после большого блока кода, где его if не влез на его страницу. Чем меньше надо помнить — тем лучше.

давайте не будем заниматься гаданием что к чему приводит. тут вложенность 3. 3, не 10. "сегодня он слугает джаз..." ага

M>>>Account интересен. Почему у вас конструктор по умолчанию создает счет с невалидным id?

A>>а с каким валидным id он может его создавать? это издержки json сериализации, нужен дефолтный конструктор, и вопросвалидности отдельный и серьезный
M>Вот! Именно таких вопросов (можно для начала и без ответов) я и жду от вас! Можно описать вопросы валидности в kotlindoc. Можно — в readme проекта. Можно взять сериализатор, не страдающий издержками (это тестовое задание, я хочу видеть, как вы видите идеальный код!). Пусть даже не распространенный, не важно. Я очень хочу иметь в команде разработчиков, видящих много факторов и находящих компромисс между ними. Пусть даже выбор будет не совпадать с моим, это не будет минусом.

ждете от меня? где? в readme? нет уж

M>>>А зачем model и core разделили? Тем более, что core зависит от model а не наоборот. Кстати, а зачем в "реальном проекте" разделение делать иначе? Какие фундаментальные причины этого требуют?

A>>чтобы model отдать клиенту, core ему не нужен (либо перенести ifaces из core в model, кто тоже стоит отдельного обсуждения)
M>Еще один хороший комментарий! Можно было бы про него в readme упоминуть. В том числе и потому, что решение по-умолчанию — странное. Для публичных API у вас клиенты будут не только на java. Им ваша модель вообще никак не поможет. И даже на Java — вы ведь не считаете всех остальных разработчиков полными идиотами? (Или все-же считаете?) Я думаю, они смогут сами написать модель, которая им нужна (с нужной им декомпозицией, используемыми полями и т.п.). Может, они даже возьмут десериализатор без издержек и им будут непонятны ваши компромиссы.

во-первых, я по-умолчанию буду думать, что клиенты на джава если явно не сформулировано иное — yagni
во-вторых, писать в readme то, что лучше обсудить — бред и трата времени
в-третьих — зачем писать что-то второй раз, если это уже написано? чтобы добавить багов? или чтобы притащить только ограниченный набор зависимостей? так вот эти все вопросы и нюансы использования обговариваются на собеседовании, но не пишется сочинение в readme

M>Да, стоит позаботиться о программистах с ограниченными возможностями навыками. Для них можно сделать отдельную библиотеку с моделями и даже API клиентом. Это будет внешняя по отношению к серверу библиотека. Или несколько библиотек на разных языках. Немного больше повторяющегося кода, но нет лишней связности меджу реализацией API и клиентом. Простое, понятное и скучное решение. А вот попытка сделать общую модель между сервером и клиентом — это как раз overarchitected.


боже, хватит всех считать за идиотов.

M>>>Вот весь тот список — это "элементы стиля". Вещи, которые делаются вообще автоматически. Показывает, насколько разработчик механически следует шаблонам и насколько все же задумывается о причинах определенных технических решений.

A>>большинсто про вкус, остальное minor по мне. нейминг — не технические решения, как и работа с Assert
M>Ну... Вкус, да. Вы ведь понимаете, что код больше читается, чем пишется? Поэтому мне очень интересен код, который легко читать. В котором не нужно задумываться, что же хотел нам сказать автор. В котором можно зайти в документацию и прояснить непонятные детали. Иначе через три месяца другой разработчик поймет ваш код немного не так, как он задумывался, и в системе возникнет плавающий баг. Стиль — это эвристики, учитывающие особенности работы человеческого мозга. Например, разворачивание глубокой вложенности в последовательный код — это workaround на ограниченность кратковременной памяти. Большинство обычных людей забудет к третьему вложенному if, что там было на верхнем уровне. А потом сделают ошибку или потратят дополнительное время на вспоминание.

а, ну знакомые слова — "все идиоты, пиши проще". прости чувак, но есть код который реально сложно и читать и писать. и поверь, мои 3 вложенных when не из их числа.
не в состоянии следить за простым контекстом? ну что могу сказать, се ля ви.

M>Я несколько лет назад осознал, что "технические решения" — это только половина программирования. А вторая половина — гуманитарные науки, литература в первую очередь. Те самые нелюбимые технарями сочинения — это суть написания кода. Точное описание своих мыслей не только для машины, но и для программистов, читающих и сопровождающих за вами ваш код. Понимание того, что ваши мысли, ваше изложение и то, что понял читатель — это три разные вещи. Умение встать на сторону читателя и писать так, чтобы он увидел то, что вы хотели сказать.


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

M>Вот все эти Assert — это как раз сложности выражать свои мысли в прямом и явном виде. Не технические, ну и что? Мне не нужны ребусы в коде. Мне нужен программист, который не поленился прочитать API и выбрать наиболее выразительный метод (для тестирования они еще и сообщения об ошибках лучше создают). Это один из многих факторов, на которые я обращаю внимание. И всегда очень интересно, когда на ревью кода кто-то другой показывает мне более выразительный (простой и понятный) вариант, чем я использовал.


ты делаешь ложные выводы из ложных предположений. это не сложности, это сознательный выбор в контексте задачи.
Re[4]: Что не так с тестовым заданием?
Здравствуйте, maxkar, Вы писали:

M>Здравствуйте, arth, Вы писали:


A>>Здравствуйте, maxkar, Вы писали:


реально не поленюсь

M>>>Как уже правильно сказали, в readme не написано, как собирать. Одна-две строчки много времени не займут, а для читающего приятно и не надо вспоминать, какая там у вас культура.

A>>камон. я не для домохозяек туториал пишу.
M>Не для домохозяек. Но вы предполагаете, что проверяющий хорошо знает все модные тренды во всех трех предложенных языках. А это может быть и не так. Может, они Java позволяют только для того, чтобы иметь больший круг кандидатов и потом переучивать их на используемый стек. Можно не иметь подробного описания сборки для проектов внутри команды, общее знание достигается через onboarding и тренировку. А вот для тестового задания две-три строчки о сборке будут полезны. Еще показывают, что вы все-таки задумываетесь о пользователях и умеете в какой-то мере бороться с проекцией "я знаю, значит и все остальные должны знать".

давайте без демагогии. gradle это не "еще одна билд система из миллиона билд систем". если ты видишь build.gradle в проекте и все еще не знаешь куда смотреть чтобы его собрать — ну тогда у нас с тобой разная культура и нам не по пути

M>>>У вас там в бинарниках трояна нет?

A>>это тестовое задание. как и что это показывает — от "ничего" вплоть до "все"
M>Но вы же согласились его делать. Значит согласны, что что-то оно показывает? Свобода выбора технологий как раз полезна — показывает, о каких глубоких вопросах задумывался кандидат. И какие предпочтения имеет.

спроси меня прямо, вместо того, чтобы додумывать. попахивает демагогией. можно еще про порно на псевдографике в readme подумать. все зависит от того кто как думать привык

M>>>Тесты. Вы их с падающими assert проверяли? У меня вот подозрение, что после первого падения все остальное упадет с AddressAlreadyInUse. Что как-то нехорошо. Например потому, что после этого нужно исправлять первый упавший тест а не любой понравившийся.

A>>проверял
M>Ну и как? Удобно находить, где там ошибка? Я вот специально сейчас сломал один тест. Получил четыре AssertionError без каких-либо внятных сообщений об ошибках. Пришлось копаться в стеках, чтобы понять, откуда они происходят. Дополнительные сложности там, где их легко избежать.

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

M>>>Не StorageTest а StorageImplTest. Вот представьте, у вас есть несколько реализаций Storage. Какую из них тестирует StorageTest?

A>>вы серьезно?
M>Конечно. StorageTest по названию — это тест на соответствие спецификации (compliance). Т.е. любая реализация должна проходить эти тесты (которые с большой вероятностью property based). Здесь же можно поговорить про то, как сложно делать тесты, параметризованные объектами. При этом тесты конкретных реализаций либо расширяют StorageTest (и обходят ограничения фреймворков тестирования), или тестируют какие-то дополнительные свойства, характерные для этих реализаций.

это все круто, но не к месту совсем.

M>>>Ваш restful тянет только на Level 0 (используется HTTP). Банальный RPC over HTTP. SOAP, кстати, тоже попадает в REST Level 0. Хотелось бы видеть хотя бы Level 1 — Entities & Verbs (т.е. PUT /accounts/abc, GET /accounts, ...).

A>>кому хотелось и зачем?
M>Ну в первую очередь вам. Потому что вы хотели продолжения интервью или найма. Хотелось бы мне. Как минимум потому, что приятно поговорить с кандидатом с широким кругозором. За реализацию Rest Level 1 вы бы получили плюсик. А на самом деле при создании API вы скорее всего вспомнили бы причины, по которым REST был спроектирован в его виде. И задумались бы про идемпотентность (idempotency) операций. Не обязательно ее реализовывать, можно было просто упомянуть в readme: "идемпотентность не реализована из-за ограничений на время, могу прислать план реализации по запросу". И получили бы сразу пять плюсиков.

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

M>Idempotency здесь очень важна. Вот представьте, я вызвал ваш RPC API и получил IOException. Вот что я с ним должен делать? Ничего (и рисковать, что запрос был потерян)? Или повторять запрос (и рисковать, что я проведу операцию дважды)? Вот из-за вашего API мне придется городить Artificiall Intelligence (искуственную разведку), которая будет выяснять состояние предыдущей операции прежде чем повторять. А с идемпотентным REST я бы ее просто повторил и сказал вам большое спасибо. Ситуация вполне реальная, и в том числе в финансовой сфере . Это — основная причина, по которой Rest Level 1 хотелось бы видеть лично мне.


вот про Idempotency в тему, наконец-то. это интересный топик поговорить, но не в рамках тестового задания. остальные замечания по поводу level'ов — странная любовь к классификациям. все, что идет после verbs вообще довольно мутная история.

M>>>Ожидание ввода в main — решение спорное. Как оно поведет себя в каком нибудь Kubernetes? Там некому будет вводить порт. Вообще право на жизнь оно имеет, но такие сюрпризы должны описываться в readme.

A>>надеюсь вы несерьезно, потому что тест не для запуска в Kubernetes
M>Серьезно. Потому что кандидат, написавший 5 приложений под Kubernetes, не будет вообще писать ввод. И опишет аргументы командной строки в README. Может это и не страшно, зависит от конкретной позиции, на которую вы претендуете.

ну да, не написал, то джуниор, написал — архитект. ладно, спишем на разную культуру

M>>>*Impl. Это вот у вас ровно одна реализация предполагается? Почему бы не InMemoryStorage, например?

A>>а у вас? и почему если не одна, то не InMemoryCuncurrentHashSetStorageImpl? понятно куда клоню?
M>А у меня — несколько реализаций предполагается. И обычно их и есть несколько. Очень часто отдельная in-memory (или какая-то упрощенная) для тестов. Во многих случаях — декораторы. За что-то более осмысленное чем *Impl получили бы плюсик. Против вашего длинного варианта ничего не имею, он выше минимальных ожидаемых стандартов. За последовательное следование вашей конвенции (и сохранение нужных уровней абстракции и т.п.) получили бы сразу два плюсика. И я бы начал задумываться, а не стоит ли внедрить ваш стиль для всей команды.

Impl — вполне осмысленно, если нет ничего иного, и, опять же, в контексте тестового задания

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

A>>нечего добавить. не вижу в 2019 году задачи явно показывать знание Factory Method
M>А вот и не угадали . Это задача на проектирование API, минимизирующего изменения в кодовой базе и расширяющего круг возможных рефакторингов. Один конкретный случай, конечно, не влияет. Но ведь проектирование таких API — это автоматизированный навык (подобных решений разработчики делают много). А вот на большой кодовой базе преимущества factory method уже будут заметны. Опять же, я на самом деле не требую именно фабричный метод (это один плюсик). Любое другое API, служащее той же цели (минимизация потенциальных изменений и расширение простора для рефакторинга) даст вам как минимум два плюсика.

соразмерность решения и задачи. все что могу сказать. про рефакторинги можно отдельно поговорить на интервью

M>>>В StorageImpl вложенность кода глубокая. Можно было бы спрямить через if/throw и if/return.

A>>а можно было и нет. дело вкуса
M>Это конечно да. Но толерантность к глубоким стрелкам настроаживает. Очень часто приводит к длинным и глубоким вложенностям, условиям и т.п. А потом мне приходится вспоминать, к чему же относится одинокий else с одной строчкой после большого блока кода, где его if не влез на его страницу. Чем меньше надо помнить — тем лучше.

давайте не будем заниматься гаданием что к чему приводит. тут вложенность 3. 3, не 10. "сегодня он слугает джаз..." ага

M>>>Account интересен. Почему у вас конструктор по умолчанию создает счет с невалидным id?

A>>а с каким валидным id он может его создавать? это издержки json сериализации, нужен дефолтный конструктор, и вопросвалидности отдельный и серьезный
M>Вот! Именно таких вопросов (можно для начала и без ответов) я и жду от вас! Можно описать вопросы валидности в kotlindoc. Можно — в readme проекта. Можно взять сериализатор, не страдающий издержками (это тестовое задание, я хочу видеть, как вы видите идеальный код!). Пусть даже не распространенный, не важно. Я очень хочу иметь в команде разработчиков, видящих много факторов и находящих компромисс между ними. Пусть даже выбор будет не совпадать с моим, это не будет минусом.

ждете от меня? где? в readme? нет уж

M>>>А зачем model и core разделили? Тем более, что core зависит от model а не наоборот. Кстати, а зачем в "реальном проекте" разделение делать иначе? Какие фундаментальные причины этого требуют?

A>>чтобы model отдать клиенту, core ему не нужен (либо перенести ifaces из core в model, кто тоже стоит отдельного обсуждения)
M>Еще один хороший комментарий! Можно было бы про него в readme упоминуть. В том числе и потому, что решение по-умолчанию — странное. Для публичных API у вас клиенты будут не только на java. Им ваша модель вообще никак не поможет. И даже на Java — вы ведь не считаете всех остальных разработчиков полными идиотами? (Или все-же считаете?) Я думаю, они смогут сами написать модель, которая им нужна (с нужной им декомпозицией, используемыми полями и т.п.). Может, они даже возьмут десериализатор без издержек и им будут непонятны ваши компромиссы.

во-первых, я по-умолчанию буду думать, что клиенты на джава если явно не сформулировано иное — yagni
во-вторых, писать в readme то, что лучше обсудить — бред и трата времени
в-третьих — зачем писать что-то второй раз, если это уже написано? чтобы добавить багов? или чтобы притащить только ограниченный набор зависимостей? так вот эти все вопросы и нюансы использования обговариваются на собеседовании, но не пишется сочинение в readme

M>Да, стоит позаботиться о программистах с ограниченными возможностями навыками. Для них можно сделать отдельную библиотеку с моделями и даже API клиентом. Это будет внешняя по отношению к серверу библиотека. Или несколько библиотек на разных языках. Немного больше повторяющегося кода, но нет лишней связности меджу реализацией API и клиентом. Простое, понятное и скучное решение. А вот попытка сделать общую модель между сервером и клиентом — это как раз overarchitected.


боже, хватит всех считать за идиотов.

M>>>Вот весь тот список — это "элементы стиля". Вещи, которые делаются вообще автоматически. Показывает, насколько разработчик механически следует шаблонам и насколько все же задумывается о причинах определенных технических решений.

A>>большинсто про вкус, остальное minor по мне. нейминг — не технические решения, как и работа с Assert
M>Ну... Вкус, да. Вы ведь понимаете, что код больше читается, чем пишется? Поэтому мне очень интересен код, который легко читать. В котором не нужно задумываться, что же хотел нам сказать автор. В котором можно зайти в документацию и прояснить непонятные детали. Иначе через три месяца другой разработчик поймет ваш код немного не так, как он задумывался, и в системе возникнет плавающий баг. Стиль — это эвристики, учитывающие особенности работы человеческого мозга. Например, разворачивание глубокой вложенности в последовательный код — это workaround на ограниченность кратковременной памяти. Большинство обычных людей забудет к третьему вложенному if, что там было на верхнем уровне. А потом сделают ошибку или потратят дополнительное время на вспоминание.

а, ну знакомые слова — "все идиоты, пиши проще". прости чувак, но есть код который реально сложно и читать и писать. и поверь, мои 3 вложенных when не из их числа.
не в состоянии следить за простым контекстом? ну что могу сказать, се ля ви.

M>Я несколько лет назад осознал, что "технические решения" — это только половина программирования. А вторая половина — гуманитарные науки, литература в первую очередь. Те самые нелюбимые технарями сочинения — это суть написания кода. Точное описание своих мыслей не только для машины, но и для программистов, читающих и сопровождающих за вами ваш код. Понимание того, что ваши мысли, ваше изложение и то, что понял читатель — это три разные вещи. Умение встать на сторону читателя и писать так, чтобы он увидел то, что вы хотели сказать.


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

M>Вот все эти Assert — это как раз сложности выражать свои мысли в прямом и явном виде. Не технические, ну и что? Мне не нужны ребусы в коде. Мне нужен программист, который не поленился прочитать API и выбрать наиболее выразительный метод (для тестирования они еще и сообщения об ошибках лучше создают). Это один из многих факторов, на которые я обращаю внимание. И всегда очень интересно, когда на ревью кода кто-то другой показывает мне более выразительный (простой и понятный) вариант, чем я использовал.


ты делаешь ложные выводы из ложных предположений. это не сложности, это сознательный выбор в контексте задачи.