В защиту кандидатов, указывающих опыт вне IT в своем резюме - в этом может определенная польза, если кандидат работал в том же бизнес-домене, куда ищется специалист. Зная кухню изнутри, он гораздо быстрее и качественнее вольётся в работу при прочих равных. Но это относится, в первую очередь, к аналитикам и QA, а к разработчикам - пожалуй, в малой степени.
Так я и не призываю все гвозди забивать одним молотком. Ваше решение хорошее и подходит для многих сценариев, но одновременно есть сценарии, где другие решения (например, те же enum-ы или record struct, как в SmartEnum) кажутся более уместными. Пользователю библиотеки знание о том, что какой-то тип занимаем 7 бит, мало что даёт, для него это чаще всего малосущественная деталь реализации. А вот гарантия на уровне типов, что переменная с номером канала не будет записана в поле, ожидающее ноту - это полезно, это удобно.
Что касается возможности получения невалидного значения в enum-е при совершении арифметических операций - так это для любого способа представления так. Контроль выхода за границы необходимо делать независимо от формата. И я не знаю, может быть пользователи библиотеки и правда активно складывают и умножают ноты, но более рациональным видится дать возможность прибавить вычесть интервал (терция, квинта, октава...) или найти разницу между двумя нотами в виде интервала. Такой сценарий опять же удобнее реализовывать через отдельные типы (можно провести аналогию с DateTime + TimeSpan), а не через единый универсальный SevenBitNumber.
Для 127 значений можно подумать в направлении enum-ов. Они дают практически все те же преимущества, но сверх того помогают не перепутать порядок, в котором аргументы передаются в метод (note, velocity или velocity, note), а также позволяют задать человекочитаемую семантику:
enum Pitch : byte
{
C0 = 0, /*Значения наобум, я понятия не имею, какое соответствие нот кодам*/
Csharp0 = 1,
D0 = 2,
...
}
Для Velocity польза сомнительна, конечно, но для нот - вполне удобно, мне кажется.
Главный мой поинт в том, что не бывает одного "как надо". Вовремя заданный PO вопрос (вместо восприятия задачи как математически точной) может привести к ответу: эх, точно, а про это-то мы и не подумали, у нас верстка на дашборде ожидает строго одну фамилию, надо с дизайнером обсудить... А может не привести.
Запросы надо писать с нуля под задачу, а не костылить старые под "похожую" задачу.
Это довольно категоричное утверждение, как будто в реальности существует единственное "как надо" (что особенно иронично в контексте обсуждения статьи, где "начальник уверен, что запрос надо писать только одним единственно правильным образом"). На мой взгляд, реальность немного сложнее и в разных ситуациях может требоваться разное. Например, уточнить, а что делать с ситуацией, когда самую большую зарплату получают несколько сотрудников в отделе. Если надо вывести всех - то варианты с MAX, RANK и LEFT JOIN равно подходят. А если окажется, что вернуть надо строго одного сотрудника (иначе дальше где-то что-то сломается) - то стоит уточнить "по какому критерию выбирать топового сотрудника?" и использовать DENSE_RANK.
Помимо производительности запроса бывают и другие нефункциональные требования, которые тоже имеют значение. И когда нам нужна производительность любой ценой - ну да, тогда наверное оправдано под каждое изменение требований переписывать запрос целиком, чтобы выдать максимум. А если важны поддерживаемость и готовность к изменениям требований, при этом объемы данных не такие, чтобы доставлять проблемы - то лучше бы иметь понятный, легко читаемый запрос, который легко адаптируется от "топ 1" к "топ N" и к "все с наибольшей зп".
В защиту варианта с rank() отмечу, что с его помощью легче всего адаптировать запрос под внезапное изменение требований вида "а теперь выведи топ-3 сотрудников по зп в каждом отделе".
И в копилку вариантов добавлю ещё один без агрегатных и оконных функций
SELECT e.name AS employee, e.salary
FROM employees e
LEFT JOIN employees e_higher
ON e.department_id = e_higher.department_id
AND e.salary > e_higher.salary
WHERE e_higher.id IS NULL
Надо смотреть планы, но зачастую запросы в такой форме оказываются весьма эффективными.
Так своя разработка заведомо будет содержать несколько процентов от требуемой привычной функциональности, и ее долго-долго нужно будет развивать. И всё это время в ее сторону будут плеваться, называя никчёмной поделкой и обучая разработчиков жизни: "не могли что ли зрелое решение за основу взять?" Посмотрите тон обсуждений статей вида "мы пишем свою СУБД с нуля" - там то же самое.
Какие интересные комментарии. Представляю, если бы Сбер написал полностью своё решение, была бы тонна комментов в духе: "нахрена было столько ресурсов тратить на разработку с нуля, не могли VSCode форкнуть? Кто к этому будет плагины писать?" Форкнули бы VSCode, была бы тонна комментов "Нахрена было VSCode форкать, он и так бесплатен. Не могли что ли IDEA форкнуть?" И все лучше всех знают, как надо, ЧСХ.
Вот конкретно проблему поиска и замены в сотнях файлов XLSX как раз можно было решить за секунды плюс несколько минут на написание PowerShell скрипта, если воспользоваться тем фактом, что XLSX - это zip-архив с XML-ками. Макросы я бы оставил для каких-нибудь более сложных манипуляций.
По-моему, тема сообщений об ошибках неполна без рассказа об их локализации. В теории, там всё легко, локаль настраивается в одном месте, но в деталях вылезают всякие неприятные мелочи, вроде того, что текст сообщения выводится по-русски, а даты в плейсхолдерах форматируется в US-формате.
Всех подробностей не помню, но где-то что-то приходилось подпиливать напильником. И это у нас ещё не было потребности отдавать разным пользователям ответ на разном языке, там бы наверняка ещё что-то вылезло.
Если вы используете стороннюю библиотеку, в которой такие структуры не определены, а вам хочется свой код сделать более лаконичным и наглядным - то использование алиасов позволит это сделать без введения доп. типов, конвертации, нагрузки на GC и т.п. Понятно, что этот вариант использования является довольно узким, и без него вполне можно же жить, ну так это вообще ко всем алиасам относится (тот же `using static ...` всего лишь позволяет чуточку меньше символов писать. Мелкая, иногда приятная, но точно не необходимая "плюшка")
Джуниоры и Миддлы могут предложить новое решение с их прежнего места работы/учёбы,
Тут у меня большие сомнения. Так-то и джуниор, и сеньор могут сказать "у нас на прошлом проекте использовался X для Y", но навыков Джуна или Мидла (если только это не "сильный мидл, почти сеньор) вряд ли хватит на то, чтобы сопоставить требования, которые были "там" и есть "тут", оценить подводные камни и издержки по внедрению того решения и принять взвешенное решение о целесообразности этого. А у сеньора и опыта прошлых проектов побольше обычно. Так что этот пункт вообще мимо.
Я не о том немного. Если человечество внезапно оказывается уничтоженным, например, гигантским метеоритом, после которого большая часть жизни перестала существовать, то последующие цивилизации через тысячи/миллионы лет могут найти месторождения того же золота с необычно высокой концентрацией на месте нынешних золотохранилищ, некоторых музеев и т.п. Возможно, даже не слишком глубоко от поверхности. На месте нынешних городов вообще будет вся таблица Менделеева в концентрациях сильно выше природных, потому что металлы копились десятилетиями/веками на компактных территориях, при том что транспортировались с обширных территорий. Безусловно, освоить технологии их извлечения будет непросто, но нынешнее человечество с этим справилось, так что нельзя исключать, что и будущее человечество справится. Была бы энергия.
Update. А, ну и да, каждый трансформатор и электродвигатель - это медный самородок весьма внушительного размера. Чтобы обрабатывать самородную медь, высокоразвитой технологии не потребуется. Так что конкретно по меди нынешнее человечество оставит серьёзный подарок будущему, многократно повысив концентрацию легкодоступной меди, по сравнению с тем, что было доступно в древности.
Как раз-таки с металлами всё будет относительно неплохо - на месте современных промышленных конструкций будут обнаруживать многотонные "самородки" или "руды" с концентрацией сильно выше природных. Вот с нефтью-газом будут сложности, да.
Можно, но зачем? Тем более, если доля просроченных записей невелика, а выборка большая, сделав более селектиный джойн мы еще и запрос сделаем более эффективным, тогда как в случае CASE данные из связанной таблицы будут запрошены, даже если они нам не понадобятся.
OK, мы хотим вывести все договоры (таблица A), и для тех из них, у которых статус "Просрочен очередной платеж" хотим вывести дату последнего платежа, которую получаем из приджойненой таблицы B. Как выразить это через WHERE?
В защиту кандидатов, указывающих опыт вне IT в своем резюме - в этом может определенная польза, если кандидат работал в том же бизнес-домене, куда ищется специалист. Зная кухню изнутри, он гораздо быстрее и качественнее вольётся в работу при прочих равных. Но это относится, в первую очередь, к аналитикам и QA, а к разработчикам - пожалуй, в малой степени.
Так я и не призываю все гвозди забивать одним молотком. Ваше решение хорошее и подходит для многих сценариев, но одновременно есть сценарии, где другие решения (например, те же enum-ы или record struct, как в SmartEnum) кажутся более уместными. Пользователю библиотеки знание о том, что какой-то тип занимаем 7 бит, мало что даёт, для него это чаще всего малосущественная деталь реализации. А вот гарантия на уровне типов, что переменная с номером канала не будет записана в поле, ожидающее ноту - это полезно, это удобно.
Что касается возможности получения невалидного значения в enum-е при совершении арифметических операций - так это для любого способа представления так. Контроль выхода за границы необходимо делать независимо от формата. И я не знаю, может быть пользователи библиотеки и правда активно складывают и умножают ноты, но более рациональным видится дать возможность прибавить вычесть интервал (терция, квинта, октава...) или найти разницу между двумя нотами в виде интервала. Такой сценарий опять же удобнее реализовывать через отдельные типы (можно провести аналогию с DateTime + TimeSpan), а не через единый универсальный SevenBitNumber.
Для 127 значений можно подумать в направлении enum-ов. Они дают практически все те же преимущества, но сверх того помогают не перепутать порядок, в котором аргументы передаются в метод (note, velocity или velocity, note), а также позволяют задать человекочитаемую семантику:
Для Velocity польза сомнительна, конечно, но для нот - вполне удобно, мне кажется.
Главный мой поинт в том, что не бывает одного "как надо". Вовремя заданный PO вопрос (вместо восприятия задачи как математически точной) может привести к ответу: эх, точно, а про это-то мы и не подумали, у нас верстка на дашборде ожидает строго одну фамилию, надо с дизайнером обсудить... А может не привести.
Это довольно категоричное утверждение, как будто в реальности существует единственное "как надо" (что особенно иронично в контексте обсуждения статьи, где "начальник уверен, что запрос надо писать только одним единственно правильным образом"). На мой взгляд, реальность немного сложнее и в разных ситуациях может требоваться разное. Например, уточнить, а что делать с ситуацией, когда самую большую зарплату получают несколько сотрудников в отделе. Если надо вывести всех - то варианты с MAX, RANK и LEFT JOIN равно подходят. А если окажется, что вернуть надо строго одного сотрудника (иначе дальше где-то что-то сломается) - то стоит уточнить "по какому критерию выбирать топового сотрудника?" и использовать DENSE_RANK.
Помимо производительности запроса бывают и другие нефункциональные требования, которые тоже имеют значение. И когда нам нужна производительность любой ценой - ну да, тогда наверное оправдано под каждое изменение требований переписывать запрос целиком, чтобы выдать максимум. А если важны поддерживаемость и готовность к изменениям требований, при этом объемы данных не такие, чтобы доставлять проблемы - то лучше бы иметь понятный, легко читаемый запрос, который легко адаптируется от "топ 1" к "топ N" и к "все с наибольшей зп".
В защиту варианта с rank() отмечу, что с его помощью легче всего адаптировать запрос под внезапное изменение требований вида "а теперь выведи топ-3 сотрудников по зп в каждом отделе".
И в копилку вариантов добавлю ещё один без агрегатных и оконных функций
Надо смотреть планы, но зачастую запросы в такой форме оказываются весьма эффективными.
Так своя разработка заведомо будет содержать несколько процентов от
требуемойпривычной функциональности, и ее долго-долго нужно будет развивать. И всё это время в ее сторону будут плеваться, называя никчёмной поделкой и обучая разработчиков жизни: "не могли что ли зрелое решение за основу взять?" Посмотрите тон обсуждений статей вида "мы пишем свою СУБД с нуля" - там то же самое.Какие интересные комментарии. Представляю, если бы Сбер написал полностью своё решение, была бы тонна комментов в духе: "нахрена было столько ресурсов тратить на разработку с нуля, не могли VSCode форкнуть? Кто к этому будет плагины писать?" Форкнули бы VSCode, была бы тонна комментов "Нахрена было VSCode форкать, он и так бесплатен. Не могли что ли IDEA форкнуть?" И все лучше всех знают, как надо, ЧСХ.
Вот конкретно проблему поиска и замены в сотнях файлов XLSX как раз можно было решить за секунды плюс несколько минут на написание PowerShell скрипта, если воспользоваться тем фактом, что XLSX - это zip-архив с XML-ками. Макросы я бы оставил для каких-нибудь более сложных манипуляций.
Абсолютно неадекватные цифры для 2024 г. Даже затрудняюсь сказать, на сколько лет они отстали от рынка.
По-моему, тема сообщений об ошибках неполна без рассказа об их локализации. В теории, там всё легко, локаль настраивается в одном месте, но в деталях вылезают всякие неприятные мелочи, вроде того, что текст сообщения выводится по-русски, а даты в плейсхолдерах форматируется в US-формате.
Всех подробностей не помню, но где-то что-то приходилось подпиливать напильником. И это у нас ещё не было потребности отдавать разным пользователям ответ на разном языке, там бы наверняка ещё что-то вылезло.
Если вы используете стороннюю библиотеку, в которой такие структуры не определены, а вам хочется свой код сделать более лаконичным и наглядным - то использование алиасов позволит это сделать без введения доп. типов, конвертации, нагрузки на GC и т.п. Понятно, что этот вариант использования является довольно узким, и без него вполне можно же жить, ну так это вообще ко всем алиасам относится (тот же `using static ...` всего лишь позволяет чуточку меньше символов писать. Мелкая, иногда приятная, но точно не необходимая "плюшка")
Тут у меня большие сомнения. Так-то и джуниор, и сеньор могут сказать "у нас на прошлом проекте использовался X для Y", но навыков Джуна или Мидла (если только это не "сильный мидл, почти сеньор) вряд ли хватит на то, чтобы сопоставить требования, которые были "там" и есть "тут", оценить подводные камни и издержки по внедрению того решения и принять взвешенное решение о целесообразности этого. А у сеньора и опыта прошлых проектов побольше обычно. Так что этот пункт вообще мимо.
И то, если кто-то глобально на заменил табы на пробелы (или наоборот) где-то ближе к концу проекта
Это довод уровня "у меня нет проф. деформации, а значит её не бывает".
Я не о том немного. Если человечество внезапно оказывается уничтоженным, например, гигантским метеоритом, после которого большая часть жизни перестала существовать, то последующие цивилизации через тысячи/миллионы лет могут найти месторождения того же золота с необычно высокой концентрацией на месте нынешних золотохранилищ, некоторых музеев и т.п. Возможно, даже не слишком глубоко от поверхности. На месте нынешних городов вообще будет вся таблица Менделеева в концентрациях сильно выше природных, потому что металлы копились десятилетиями/веками на компактных территориях, при том что транспортировались с обширных территорий. Безусловно, освоить технологии их извлечения будет непросто, но нынешнее человечество с этим справилось, так что нельзя исключать, что и будущее человечество справится. Была бы энергия.
Update. А, ну и да, каждый трансформатор и электродвигатель - это медный самородок весьма внушительного размера. Чтобы обрабатывать самородную медь, высокоразвитой технологии не потребуется. Так что конкретно по меди нынешнее человечество оставит серьёзный подарок будущему, многократно повысив концентрацию легкодоступной меди, по сравнению с тем, что было доступно в древности.
Как раз-таки с металлами всё будет относительно неплохо - на месте современных промышленных конструкций будут обнаруживать многотонные "самородки" или "руды" с концентрацией сильно выше природных. Вот с нефтью-газом будут сложности, да.
Значит, все-таки создали! :-)
Можно, но зачем? Тем более, если доля просроченных записей невелика, а выборка большая, сделав более селектиный джойн мы еще и запрос сделаем более эффективным, тогда как в случае CASE данные из связанной таблицы будут запрошены, даже если они нам не понадобятся.
OK, мы хотим вывести все договоры (таблица A), и для тех из них, у которых статус "Просрочен очередной платеж" хотим вывести дату последнего платежа, которую получаем из приджойненой таблицы B. Как выразить это через WHERE?