Обновить
22
0
Алексей@pankraty

Разработчик

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

Так нельзя.

var x = MyMethod();

var y = MyMethod;

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

Смотрите, идея такая:

if (_blob != null)
  return _blob;
lock (_lock)
{
  return _blob ?? (_blob = new Blob());
  
}

До входа в lock мы проверяем, не инициализирован ли уже объект, и если да (а это, мы предполагаем 99+% обращений) - быстро возвращаем этот экземпляр. А если нет - то идём по медленному пути, с заходом в lock; а так как за время нашего ожидания входа в lock кто-то мог успеть инициализировать поле, то внутри мы тоже проверяем на null, чтобы случайно не инициализировать дважды. При таком подходе гонки исключены и ресурсы на тратятся впустую.

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

А как быть, если класс реализует 2 интерфейса, и его нужно зарегистрировать как синглтон таким образом, чтобы при резолве любого из интерфейсов возвращался один и тот же экземпляр?

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

Мне ещё с операторами понравилось - довольно изящно получилось.

JSON в РСУБД - это плохо. EAV, как принцип хранения всех основных данных в РСУБД - тоже плохо.

Такая аргументация нормальна при общении с трехлеткой. Для людей постарше желательно давать какое-то обоснование.

Как по мне, так наоборот, разветвленные сущности с переменным составом полей, которые обычно извлекаются целиком, намного удобнее и эффективнее хранить в JSON-е, чем делать 20 left join-ов при сильно нормализованной форме или танцевать с таблицами атрибутов, пытаясь хоть как-то выжать из них перформанс. Ваш опыт может отличаться от моего, но на доводах "это плохо, потому что плохо" дискуссию не построить.

Там был NULL, насколько я помню.

Медиана так не работает. Чтобы получить медиану в 500К, надо чтобы половина выборки получала более 500К.

В защиту кандидатов, указывающих опыт вне 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-ками. Макросы я бы оставил для каких-нибудь более сложных манипуляций.

Абсолютно неадекватные цифры для 2024 г. Даже затрудняюсь сказать, на сколько лет они отстали от рынка.

1
23 ...

Информация

В рейтинге
5 663-й
Откуда
Саратов, Саратовская обл., Россия
Дата рождения
Зарегистрирован
Активность