Задачки на литкоде и аналогах заточены в том числе и на анализ производительности - так что может этому научить (скорее "заставить"). А вот "качество" кода там никак не отслеживается и научиться хорошему через них не выйдет. Скорее всего дело не в том что "разработчик после литкода становится лучше", а в том что "литкодом готовы заниматься более хорошие разработчики" - "после не значит в следствии".
Но если производительность не важна, лучше конечно написать более простое решение, которое понятно другим членам команды.
Производительность почти всегда важна, но не в ущерб читаемости и поддерживаемости. Ваше же решение получилось хоть и производительным, но, на мой взгляд, практически не поддерживаемым - любое минимальное изменение параметров из задания будет требовать картинальной переработки всего кода. И чаще всего такой write only код на проекте, в действительности, не нужен.
Ну нету - а чего странного? Конечно есть и хранилище исходников и система учёта задач и шаринг файлов, но всё это решается через "облака" и, в некоторых случаях, даже на бесплатных тарифах. Автор статьи, например, так и вовсе не совсем "фирма" и у них может и нет ничего кроме приведённых сервисов. А ещё есть стартапы, фирмы на начальном этапе организации и прочие и прочие.
Только вот результат получаем разный, на несколько порядков.
Впрочем, VPS за пару баксов/мес. справится с туннелированием.
А вот и велосипеды подъехали.
Что вы на нём собирать будете, и как долго? Как быстро упрётесь в ООМ?
Ну мало у кого занят сборочный сервер в режиме 24/7. Да и сам проект часто не требует много RAM для сборки. Причём в рамках рассмотренного решения никто не мешает заупскать сервер с большим количеством RAM, CPU и GPU - и это всё ещё будет иметь ценник подъёмный даже одиночному разработчику.
И только не надо рассказывать как надёжны облака. Например, чем они рискуют, случайно уничтожив все ваши данные? Дадут $5 скидку на следующий заказ?
И разве своё железо надёжнее "само по себе"? Сдохнет диск - кто-нибудь даст "хотя бы" скидку? Вынесут через окно? Уборщица "протрёт"? Тем более если брать б/у - оно может умереть даже без помощи извне. Возникают вопросы дублирования, бэкапов, активной поддержки.
Естественно я понимаю что "облака" это просто "чужие сервера", но в них входит не "просто железо", а так же его поддержка, сопровождение, замена, обновление (включая софт) а так же возможность гибко управлять выделяемыми ресурсами (RAM, CPU, HDD/SSD, GPU).
Вопрос переезда на bare-metal нужно решать тогда когда он реально себя проявляет, а не на начальном этапе организации компании - в этот момент ещё нет ни понимания требований к железу ни, собствено, средств которые можно "заморозить" в железе. Естественно крупная фирма существующая продолжительное время и имеющая план на ближашие несколько лет скорее всего получит профит от перехода на bare metal и self-hosted ПО.
Напомню что статья рассказывает про решение для "создания публикаций в социальных сетях", используемом в неком "профсоюзе". И они получили требуемый им функционал за ~250 р./мес. что в год будет около 3к руб. Плюс время на ресёч и реализацию. Вы же предлагаете им сразу использовать bare metal за 100к, причём б/у, без дублирования, гарантий, поддержки, с необходимостью оплачивать Интернет и электричество для него, плюс сервер для реализации точки доступа в его сеть, плюс место для организации "серверной", плюс администрирование всего этого "счастья". И всё это - в ультимативной форме. Да, bare metal будет производительнее, но будет ли такое решение лучше удовлетворять изначальным требованиям?
Да, именно - внешний доступ в сеть с таким сервером тоже нужно будет как-то обеспечивать, так же как и максимальный аптайм электричества и интернета вкупе с фиксированным IP для точки входа (или через dyn-dns привязывать его к домену) что превращается в кучу головняка с велосипедами, которые в итоге становятся не проще и не дешевле решения "с облаком".
Исходная постановка звучит примерно так: Решите задачу X с помощью опрятного и поддерживаемого кода. По результирующему коду будет оцениваться то как будет писаться код для боевых задач.
Решая конкретную задачу, разумно использовать знания об этой задаче.
Но ваша реализация уже выходит за границы KISS и сильно уходит в сторону преждевременной оптимизации: требований по написанию максимально эффективного кода не было, в отличии от пожеланий написания поддерживаемого кода.
А причём тут "методы работы со String"? Вычисление "суммы цифр" числа через преобразование числа в строку и получение потока символов используется только у вас и у @DenisPantushev тогда как есть более "алгоритмический" вариант без, так сказать "зубрения".
Из-за проверки String.valueOf(i).length() > 1 ваш код упускает часть корректных значений.
Вместо String.valueOf(i).chars().mapToObj(c -> Integer.valueOf(""+(char)c)).reduce(0, Integer::sum) можно использовать гораздо более короткий, понятный и эффективный вариант: String.valueOf(i).chars().map(Character::getNumericValue).sum().
ваш, @rombell, вариант самый быстрый, но корректно работает строго в диапазоне до 1000 (так как проверяет только 3 знака) и при сумме цифр именно 10
потом идёт вариант от @igolikov, за счёт отсутствия проверки делимости на 3 и внесения проверки лимита суммы цифр в цикл подсчёта этой суммы
потом идёт вариант от @pin2t, за счёт проверки суммы только трёх знаков (из-за чего и работает корректно только на диапазоне до 1000)
и потом мой вариант
Плюс 14% это весьма хороший показатель. А вот с учётом поддерживаемости, расширяемости и тестируемости побеждает вариант от @igolikov - он и работает на любых диапазонах и делает это довольно быстро (ваш быстрее всего на 5%) и доступен для понимания.
Работодателю здесь важно понять, как соискатель владеет основами синтаксиса языка и может ли писать код сразу чисто. С помощью задач такого типа мы проверяем уровень соискателя: как много он писал код сам, а также косвенно — сталкивался ли с «грязным» кодом и рефакторил ли его. По такому заданию можно косвенно увидеть, как быстро и «чисто» (понятно и поддерживаемо) специалист будет писать собственный код.
Из этого следует что код должен быть достаточно "опрятным" и "поддерживаемым". Да, Sonar тут не будет прогоняться и код, действительно, будет "выброшен", но именно по этому коду идёт оценка того что кандидат будет "творить" в дальнейшем - можно писать "лишь бы работало", но это явно не покажет кандидата с лучшей стороны.
Да и вы сами пишете:
Результат такой же, но гораздо проще для понимания и поддержки
, хотя проверка суммы цифр явно таковой не является даже в текущем варианте (суммирующем всего 3 позиции) и только ухудшится при изменении условий (что часто происходит с таким кодом на собесах - типа "а что будет если диапазон будет не до 1000, а до 20000?" - см. упоминание рефакторинга).
Решение работает для конкретного заданного случая и заданного диапазона, естественно не является универсальным
Вычисление суммы цифр легко превращается в функцию, которая
Если в БД существует нормальный FK, то в e.department_id не будет ерунды, в том числе нуля и других значений которых нет в таблице department. Если же FK нет (что как раз и позволяет хранить в e.department_id значения навроде 0) тогда JOIN будет верятно всё же более адекватным вариантом чем проверки на уровне записей.
Я считаю что изначально нужно рассчитывать на FK, если другое не сказано явно и уже после уточнения вносить правки в запрос на основе новых сведений, а додумывать что-то дело не благодарное - иначе можно дойти до того что "не привязанных к отделам" можно интепретировать как "работник может быть приязан к нескольким отделам", а значит в department_id будет лежать список id отделов и это нужно учитывать.
Проверка e.id not in (select id from department) не просто "сомнительна" она в принципе не корректна, так как select id from department выберет идентификаторы департаментов, тогда как e.id это идентификаторы сотрудников и они не связаны между собой и в том числе могут и пересекаться
В комментариях уже предложили решение: e.department_id is null. Правда оно рассчитано на то что структура БД корректна и e.department_id имеет FK на таблицу department
Sonar всё равно возмутится хардкоду значений в коде - и нужно будет выносить константы
развёрнутое вычисление суммы цифр это быстро, но работает только для 1000 - если максимум увеличится в размере всего на пару цифр, то развёрнутая формула вычисления суммы станет совсем не читаемой
1000 не делится на 3 и должно отсутствовать в выводе, а оно присутствует
Это, конечно, не повод использовать стримы, но и пропускать такой код через ревью я бы не стал.
Спасибо за вопрос (жаль только я увидел его только сейчас, хотя он задан был ещё в день публикации). При создании строк в Java можно указывать значения сиволов юникода:
P.S. На Kotlin код, выглядящий точно также, в обоих случаях будет возвращать true так как там вызывается кастомный CharSequence::isBlank, вызывающий кастомный Char::isWhitespace, добавлящий проверку на все пробельные символы.
Вопрос 6. Почему для var всегда нужен инициализатор в правой части? Тип переменной вычисляется на основе инициализатора. Это означает, что var можно использовать только при наличии инициализатора.
Начиная с Java 11 (вышла 4 года назад) ключевое слово var можно использовать и не только при наличии инициализатора, а например и у аргументов в лямбдах:
Например, в одной и тем четко и ясно разъяснил свою позицию для автора, заминусовали ...
Я не минусовал там и не минусовал тут, но поддерживаю желание поставить минус и по этому хотел бы раскрыть свою причину этого желания. В комментарии "там" я не вижу "чёткого и ясного разъяснения позиции" я вижу только вот это:
Это не тоже самое и X. Повторю общеизвестную информацию. Тут был хак "на маршруте пула" и мы решили что это не честно. Я повторяю что "это не тоже самое что и X или Y". Управляющие _ решили так как решили.
Я вот не вижу тут ни "чёткости" ни "разъяснения" - просто "мы решили как решили и чужое мнение нас не волнует". И за что мне плюсовать этот коммент?
И ровно таже ситуация в текущем комменте: вы пришли, показали "совершенно корректно заминусованный с моей точки зрения коммент" считая при этом что вас "не заслуженно минусуют" и уже этот коммент опять заминусовали. А за что его плюсовать? Я вот не вижу тут конструктивного начала, а вижу только "я хороший, а все плохие, и из-за них я тут завожу новые аккаунты".
И ещё приходит @myhambr и называет всех "токсиками, затыкающими рот". И тоже получает минусы.
P.S. Посмотрю сбудутся ли прогнозы @Moskus относительно диалога с вами.
Они есть в тестах в репе с реализацией
Задачки на литкоде и аналогах заточены в том числе и на анализ производительности - так что может этому научить (скорее "заставить").
А вот "качество" кода там никак не отслеживается и научиться хорошему через них не выйдет.
Скорее всего дело не в том что "разработчик после литкода становится лучше", а в том что "литкодом готовы заниматься более хорошие разработчики" - "после не значит в следствии".
Наиболее производительное на данный момент. Более чем в два раза чем "простой" и вариант@igolikov.
Производительность почти всегда важна, но не в ущерб читаемости и поддерживаемости.
Ваше же решение получилось хоть и производительным, но, на мой взгляд, практически не поддерживаемым - любое минимальное изменение параметров из задания будет требовать картинальной переработки всего кода.
И чаще всего такой
write only
код на проекте, в действительности, не нужен.Ну нету - а чего странного?
Конечно есть и хранилище исходников и система учёта задач и шаринг файлов, но всё это решается через "облака" и, в некоторых случаях, даже на бесплатных тарифах.
Автор статьи, например, так и вовсе не совсем "фирма" и у них может и нет ничего кроме приведённых сервисов.
А ещё есть стартапы, фирмы на начальном этапе организации и прочие и прочие.
Как и их стоимость. Особенно с учётом этой ветки.
А вот и велосипеды подъехали.
Ну мало у кого занят сборочный сервер в режиме 24/7. Да и сам проект часто не требует много RAM для сборки. Причём в рамках рассмотренного решения никто не мешает заупскать сервер с большим количеством RAM, CPU и GPU - и это всё ещё будет иметь ценник подъёмный даже одиночному разработчику.
И разве своё железо надёжнее "само по себе"? Сдохнет диск - кто-нибудь даст "хотя бы" скидку? Вынесут через окно? Уборщица "протрёт"? Тем более если брать б/у - оно может умереть даже без помощи извне.
Возникают вопросы дублирования, бэкапов, активной поддержки.
Естественно я понимаю что "облака" это просто "чужие сервера", но в них входит не "просто железо", а так же его поддержка, сопровождение, замена, обновление (включая софт) а так же возможность гибко управлять выделяемыми ресурсами (RAM, CPU, HDD/SSD, GPU).
Вопрос переезда на bare-metal нужно решать тогда когда он реально себя проявляет, а не на начальном этапе организации компании - в этот момент ещё нет ни понимания требований к железу ни, собствено, средств которые можно "заморозить" в железе.
Естественно крупная фирма существующая продолжительное время и имеющая план на ближашие несколько лет скорее всего получит профит от перехода на bare metal и self-hosted ПО.
Напомню что статья рассказывает про решение для "создания публикаций в социальных сетях", используемом в неком "профсоюзе".
И они получили требуемый им функционал за ~250 р./мес. что в год будет около 3к руб. Плюс время на ресёч и реализацию.
Вы же предлагаете им сразу использовать bare metal за 100к, причём б/у, без дублирования, гарантий, поддержки, с необходимостью оплачивать Интернет и электричество для него, плюс сервер для реализации точки доступа в его сеть, плюс место для организации "серверной", плюс администрирование всего этого "счастья".
И всё это - в ультимативной форме.
Да, bare metal будет производительнее, но будет ли такое решение лучше удовлетворять изначальным требованиям?
Да, именно - внешний доступ в сеть с таким сервером тоже нужно будет как-то обеспечивать, так же как и максимальный аптайм электричества и интернета вкупе с фиксированным
IP
для точки входа (или черезdyn-dns
привязывать его к домену) что превращается в кучу головняка с велосипедами, которые в итоге становятся не проще и не дешевле решения "с облаком".Сервер в "локальной сети" удобен, когда все разработчики тоже находятся в этой "локальной сети".
Исходная постановка звучит примерно так: Решите задачу
X
с помощью опрятного и поддерживаемого кода. По результирующему коду будет оцениваться то как будет писаться код для боевых задач.Но ваша реализация уже выходит за границы
KISS
и сильно уходит в сторону преждевременной оптимизации: требований по написанию максимально эффективного кода не было, в отличии от пожеланий написания поддерживаемого кода.А причём тут "методы работы со
String
"? Вычисление "суммы цифр" числа через преобразование числа в строку и получение потока символов используется только у вас и у @DenisPantushev тогда как есть более "алгоритмический" вариант без, так сказать "зубрения".Из-за проверки
String.valueOf(i).length() > 1
ваш код упускает часть корректных значений.Вместо
String.valueOf(i).chars().mapToObj(c -> Integer.valueOf(""+(char)c)).reduce(0, Integer::sum)
можно использовать гораздо более короткий, понятный и эффективный вариант:String.valueOf(i).chars().map(Character::getNumericValue).sum()
.А зачем
IntStream
боксируется вStream<Integer>
?Всё это у вас бы спросили на собесе.
Я накидал бенчмарк по вариантам предложенным в комментариях (плюс мои) и получил вот такие данные:
Что интерпретировать можно так:
ваш, @rombell, вариант самый быстрый, но корректно работает строго в диапазоне до
1000
(так как проверяет только 3 знака) и при сумме цифр именно10
потом идёт вариант от @igolikov, за счёт отсутствия проверки делимости на
3
и внесения проверки лимита суммы цифр в цикл подсчёта этой суммыпотом идёт вариант от @pin2t, за счёт проверки суммы только трёх знаков (из-за чего и работает корректно только на диапазоне до
1000
)и потом мой вариант
Плюс
14%
это весьма хороший показатель.А вот с учётом поддерживаемости, расширяемости и тестируемости побеждает вариант от @igolikov - он и работает на любых диапазонах и делает это довольно быстро (ваш быстрее всего на
5%
) и доступен для понимания.Вариант с
i+3
уже предложили.А по остальным предложениям: напишите код, а не мысли вслух - давайте рассмотрим.
Выдержка из постановки к задаче 1:
Из этого следует что код должен быть достаточно "опрятным" и "поддерживаемым".
Да,
Sonar
тут не будет прогоняться и код, действительно, будет "выброшен", но именно по этому коду идёт оценка того что кандидат будет "творить" в дальнейшем - можно писать "лишь бы работало", но это явно не покажет кандидата с лучшей стороны.Да и вы сами пишете:
, хотя проверка суммы цифр явно таковой не является даже в текущем варианте (суммирующем всего 3 позиции) и только ухудшится при изменении условий (что часто происходит с таким кодом на собесах - типа "а что будет если диапазон будет не до
1000
, а до20000
?" - см. упоминание рефакторинга).Вычисление суммы цифр легко превращается в функцию, которая
работает для любых значений
повышает читаемость и поддерживаемость
не снижает производительности
повышает тестируемость и модульность
Если в БД существует нормальный
FK
, то вe.department_id
не будет ерунды, в том числе нуля и других значений которых нет в таблицеdepartment
.Если же
FK
нет (что как раз и позволяет хранить вe.department_id
значения навроде0
) тогдаJOIN
будет верятно всё же более адекватным вариантом чем проверки на уровне записей.Я считаю что изначально нужно рассчитывать на
FK
, если другое не сказано явно и уже после уточнения вносить правки в запрос на основе новых сведений, а додумывать что-то дело не благодарное - иначе можно дойти до того что "не привязанных к отделам" можно интепретировать как "работник может быть приязан к нескольким отделам", а значит вdepartment_id
будет лежать списокid
отделов и это нужно учитывать.P.S.
И это тоже обсуждалось.
Проверка
e.id not in (select id from department)
не просто "сомнительна" она в принципе не корректна, так какselect id from department
выберет идентификаторы департаментов, тогда какe.id
это идентификаторы сотрудников и они не связаны между собой и в том числе могут и пересекатьсяВ комментариях уже предложили решение:
e.department_id is null
. Правда оно рассчитано на то что структура БД корректна иe.department_id
имеетFK
на таблицуdepartment
Данное решение
в дальнейшем нужно будет поддерживать
Sonar
всё равно возмутится хардкоду значений в коде - и нужно будет выносить константыразвёрнутое вычисление суммы цифр это быстро, но работает только для
1000
- если максимум увеличится в размере всего на пару цифр, то развёрнутая формула вычисления суммы станет совсем не читаемой1000
не делится на3
и должно отсутствовать в выводе, а оно присутствуетЭто, конечно, не повод использовать стримы, но и пропускать такой код через ревью я бы не стал.
Спасибо за вопрос (жаль только я увидел его только сейчас, хотя он задан был ещё в день публикации).
При создании строк в
Java
можно указывать значения сиволов юникода:P.S.
На
Kotlin
код, выглядящий точно также, в обоих случаях будет возвращатьtrue
так как там вызывается кастомный CharSequence::isBlank, вызывающий кастомный Char::isWhitespace, добавлящий проверку на все пробельные символы.Начиная с
Java 11
(вышла 4 года назад) ключевое словоvar
можно использовать и не только при наличии инициализатора, а например и у аргументов в лямбдах:Так ведь же за комменты старее месяца голосовать уже нельзя - какие тут "года"?
На карму это не распространяется, конечно.
Я не минусовал там и не минусовал тут, но поддерживаю желание поставить минус и по этому хотел бы раскрыть свою причину этого желания.
В комментарии "там" я не вижу "чёткого и ясного разъяснения позиции" я вижу только вот это:
Я вот не вижу тут ни "чёткости" ни "разъяснения" - просто "мы решили как решили и чужое мнение нас не волнует". И за что мне плюсовать этот коммент?
И ровно таже ситуация в текущем комменте: вы пришли, показали "совершенно корректно заминусованный с моей точки зрения коммент" считая при этом что вас "не заслуженно минусуют" и уже этот коммент опять заминусовали. А за что его плюсовать?
Я вот не вижу тут конструктивного начала, а вижу только "я хороший, а все плохие, и из-за них я тут завожу новые аккаунты".
И ещё приходит @myhambr и называет всех "токсиками, затыкающими рот". И тоже получает минусы.
P.S.
Посмотрю сбудутся ли прогнозы @Moskus относительно диалога с вами.
В первом сезоне юмор был как-то по-лучше
Запросить пачку из нескольких десятков ключей, проверить парочку, а остальные продать.