Pull to refresh
8K+
65
Стас Выщепан@gandjustas

Оптимизирую программы

8
Rating
108
Subscribers
Send message

Как и зачем я сделал свой маппер

Level of difficultyEasy
Reading time16 min
Reach and readers5K

Я не люблю Clean Architecture, не люблю DTO и не люблю мапперы.

Они превращают сохранение одной строки в базу в путешествие через четыре проекта, три слоя абстракций и папку Mappings, в которую никто не заглядывал со времён первого коммита. Чтобы добавить одно поле на форму, надо поменять сущность, DTO, команду, валидатор, профиль маппинга и тест на профиль маппинга. Шесть файлов ради одной колонки. А если в одном из них забыть, никто ничего не скажет.

Поэтому я, конечно же, написал маппер.

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

AI SLOP WARNING. Большую часть кода этой библиотеки написали нейросети, как и 98% текста этой статьи. Я ставил задачи, проверял и исправлял. Если вас это оскорбляет - дальше можно не читать, ничего хорошего вас там не ждёт.

Читать далее

Очередь на Postgres: почему Kafka не нужна

Reading time8 min
Reach and readers8.5K

Это история про архитектуру одного сервиса. Рассказанная до конца, а не только до того места, где обычно останавливаются статьи про архитектуру. Намеренно упрощена бизнес-логика, чтобы не размывать основной смысл.

Сервис принимал запрос, писал строку в базу, отвечал 201. Никто не пишет статей про такой код, потому что в нём нечего обсуждать.

Рано или поздно один сервис перестаёт быть одним сервисом. Появляется второй, которому важно узнать о том же событии — обсчитать аналитику, обновить поисковый индекс, отправить письмо. Возникает соблазн просто дёрнуть его по HTTP, и это первая ошибка, которую все совершают и все же исправляют: синхронный вызов делает вас настолько же надёжным, насколько надёжен самый хрупкий из ваших соседей.

Значит нужно асинхронно, через брокер. И почти всегда этим брокером оказывается Kafka.

Читать далее

Ваш кэш в Redis неэффективен, что с этим делать?

Level of difficultyMedium
Reading time21 min
Reach and readers8.9K

Однажды в проде контейнеры одного из сервисов начали падать по OutOfMemory. Контейнерам было выделено по 4 ГБ оперативной памяти, нагрузка была вполне обычной: десятки страниц в секунду.

Расследование показало, что проблема была в JSON-конфиге.

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

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

Казалось бы, если мы запрашиваем один и тот же JSON, размер не должен так критично влиять.

Но всё оказалось интереснее…

Читать далее

Merge для IAsyncEnumerable<T>

Level of difficultyMedium
Reading time10 min
Reach and readers8.3K

В рамках одного из обсуждении с чатах я предложил использовать функцию Merge для  IAsyncEnumerable<T>, чтобы объединить результаты чтения однотипных данных из разных источников. Но когда попытался сделать пример оказалось что такой функции в System.Linq.Async нет. Есть аналог в Reactive Extensions, но тащить библиотеку для одного примера не захотел и решил написать сам.

Читать далее

Система резервации заказов на Postgres, продолжение

Level of difficultyHard
Reading time8 min
Reach and readers6.8K

В комментариях к предыдущему посту "Система резервации на 600 заказов в секунду без буферизации и другой дичи" только ленивый не упомянул явные блокировки в Postgres, как способ борьбы с дедлоками.

Это не удивительно, так как select for update - очень популярный прием во всех СУБД, даже на Хабре есть статья на эту тему.

Что же окажется быстрее?

Система резервации на 600 заказов в секунду без буферизации и другой дичи

Level of difficultyHard
Reading time23 min
Reach and readers11K

Я прочитал статью, и меня поразило, сколько сомнительных решений можно использовать для одной простой задачи.

В этой статье я расскажу, как правильно создать сервис для конкурентных обновлений остатков данных в базе данных. Буду использовать .NET, C#, Entity Framework и PostgreSql.

Читать далее

Сортировка слиянием — не так просто, как кажется

Reading time20 min
Reach and readers37K

В одной конторе соискателю на позицию Senior C# developer выдали тестовое задание: отсортировать файл со строками определенного формата.

Требования такие:

* Формат строки: число, точка, пробел, далее любые символы до конца строки.

* Порядок сортировки — сначала сортируем текстовой части строки, потом по числу если текстовые части совпадают.

* Кодировка — UTF-8.

* Размер файла — 100гб - гарантированно больше объема ОП.

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

Как и многие другие программисты, узнав о таком тестовом задании, я возмутился. Внешнюю сортировку слиянием практически всех проходили в ВУЗе, но практически никто никогда не писал её. Задача очень непрактическая и непонятно какие навыки проверяет. Так мне казалось.

Эта задача вызвала бурные обсуждения о способах её решения. Многие программисты, причисляющие себя к рангу senior, предложили использовать базы данных, ибо не барское это дело - вручную писать алгоритмы сортировки. Некоторые даже попытались сделать решение на Apache Spark. Однако никто до конца задачу не решил, ибо мало кому удалось отсортировать в нужном порядке даже 10ГБ файл менее чем за 15 минут без SSD.

Я подумал, что стоит решить задачу до конца с помощью программирования, и тоже причислить себя к рангу senior developer.

Читать далее

Воины и волшебники, часть пятая, финал

Reading time7 min
Reach and readers3.7K

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

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

В третьем и четвертом эпизодах этой серии мы увидели, что также было трудно понять как вызвать правильный код для обработки различных конкретных правил, а также куда поместить этот код. Даже если оставить в стороне проблемы с очень многословным и сложным шаблоном посетителя и опасным шаблоном динамического вызова, у нас все еще есть фундаментальная проблема: почему «Паладин в церкви атакует оборотня с мечом» является ответственностью одного из этих типов, а не другого?

Читать далее

Воины и волшебники, часть четвертая

Reading time4 min
Reach and readers3.1K

В прошлой статье мы увидели что для одинарной диспетчеризации, то есть выбора метода по типу времени выполнения одного аргумента, мы можем использовать виртуальные методы. Для двойной диспетчеризации мы можем использовать шаблон проектирования с неподходящим названием "Посетитель". Он работает, но имеет недостатки. Он тяжеловесный, сложный для понимания и плохо расширяется для множественной диспетчеризации.

Прошлый раз я сказал, что C# не поддерживает двойную диспетчеризацию. Это была наглая ложь! На самом деле C# поддерживает множественную диспетчеризацию. Вы можете выбрать метод на основании типа времен выполнения любого количества аргументов.

Читать далее

Воины и волшебники, часть третья

Reading time6 min
Reach and readers4.2K

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

У нас есть еще одна проблема. Предположим, у нас также есть классы Оборотней и Вампиров, которые являются разновидностью Монстров. Нам нужно правило, которое гласит, что если Воин попытается ударить Оборотня после полуночи, то вероятность успеха будет снижена. (У волшебников нет такого штрафа, потому что… магия?)

Подождите минутку — разве текущий момент времени это не после полуночи всегда? Короче, когда можно безопасно кормить могваев? Хотя это увлекательная проблема, я уверен, что это не та проблема, о которой я хочу говорить сегодня.

Читать далее

Воины и волшебники, часть вторая

Reading time4 min
Reach and readers4.8K

В этой серии мы исследуем проблему «игрок может использовать оружие, волшебник — разновидность игрока, посох — разновидность оружия, а волшебник может использовать только посох». Лучшее решение, которое мы придумали до сих пор — выдать нарушение преобразования типа во время выполнения, если разработчик допустил ошибку. Это не кажется оптимальным решением.

(Если вы не читали первую статью серии, то обязательно начните с нее)

создадим решение лучше

Воины и волшебники, часть первая

Reading time2 min
Reach and readers7.7K

Распространенная проблема, которую я вижу в объектно-ориентированном проектировании:

* Волшебник — это разновидность игрока.
* Воин — это разновидность игрока.
* У игрока есть оружие.
* Посох — это разновидность оружия.
* Меч — это разновидность оружия.

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

давайте напишем несколько классов

Неполная, неточная и наполовину выдуманная история исключений

Reading time9 min
Reach and readers8.6K

Давным-давно, когда деревья были маленькие, дискеты большие, а трава зеленая, все писали на языках низкого уровня. В этих языках все было целыми числами. Переменные были числами, массивы были и структуры были просто адресами (числами) и смещениями (тоже числами). Даже если указывали тип данных, то он определял только размер памяти для значения.

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

Чтобы программа не грохалась, а выдавала осмысленное сообщение и давала возможность продолжить работу, надо было добавить проверку.

Читать далее

IDisposable — что ваша мама не говорила об освобождении ресурсов. Часть 1

Reading time8 min
Reach and readers10K

Это перевод первой части статьи. Статья была написана в 2008 году. Спустя 10 лет почти не потеряла актуальности.


Детерминированное освобождение ресурсов — необходимость


В течение более чем 20-летнего опыта кодирования я иногда разрабатывал собственные языки для решения задач. Они варьировались от простых имеративных языков до специализрованных регулярных выражений для деревьев. При создании языков есть множество рекомендаций и некоторые простые правила не должны нарушаться. Одно из них:


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

Угадайте какой рекомендации не следует рантайм .NET, и как следствие все языки на его базе?

Читать дальше →

Еще одно сравнение производительности С++ и C#

Reading time5 min
Reach and readers46K
Навеяно вот этой статьей.

Существует три мнения относительно производительности C++ и C#.

Те кто знают (или думают что знают) C++ считают, что C++ в разы или даже на порядки быстрее.
Те кто знают C++ и C# знают, что для обычных задач быстродействие C++ не нужно, а там где нужно — можно и C#-код заоптимизировать до невозможности. Верхний предел оптимизации у C++ выше, чем у C#, но такие рекорды никому не нужны.
Те кто знают только C# — никогда не испытывали проблем с его быстродействием.

Люди из первой категории все время пытаются доказать свою правоту. При этом приводят примеры оптимизированного кода на C++ и самого пессимизированного кода на C#.
Читать дальше →

Исследование факторов лидерства в ИТ

Reading time5 min
Reach and readers9.6K
Неделю назад я создал опрос, направленный на выявление факторов лидерства. Получилось всего 261 ответ, что, конечно, мало для полного исследования, но уже достаточно, чтобы выявить некоторые закономерности.

Особенно интересны комментарии участников опроса:
наберите в поиске «лидерские качества», «лидерство». Обладание какими-то супер-знаниями — это последнее, что вы там увидите. Тема лидерства топтана огромным количеством психологов. Наверное было бы интересно опровергнуть их теории, но доказывать их правильность не вижу смысла.

Или, например, такие:
Я думаю, что для лидера гораздо важнее другие качества:
Инициативность — он постоянно должен что-то делать, не дожидаясь указания от начальника.
Открытость к людям — стремление помочь им с их проблемами (но без фанатизма).
Харизма — банально, у человека который шумно рассказывает анекдоты, которые поднимают всем настроение больше шансов быть лидером, чем у человека который изучает очередной ЯП за компом и ни с кем не общается.

И даже такие:
По сути, это «авторитет». Что бы им стать нужно два фактора:
— Уметь быть убедительным, убеждать. Развитая речь и система аргументации, жизненный опыт (есть что рассказать)
— Поддерживать внутри коллектива справедливость, систему понятий ;-)
В итоге получается человек, с которым комфортно, на которого можно положиться, который никогда не паникует и не теряется. К таким людям внутри коллектива остальные тянутся, вот и получается лидер.

Но это все теоретизирование, а что же нам расскажут результаты опроса?
Читать дальше →

Применение инфраструктуры кеширования в ASP.NET, продолжение

Reading time6 min
Reach and readers20K
В прошлом посте я рассказывал, как применять инфраструктуру кеширования в ASP.NET для увеличения производительности сайта. Добавлением нескольких строк кода мне удалось увеличить производительность домашней страницы сайта в 5 раз. В этот раз пойдем дальше и выжмем еще больше производительности, не прибегая к различным хакам.
Читать дальше →

UDP и C# Reactive Extensions

Reading time4 min
Reach and readers23K
Недавно прочитал пост о UDP и C# async/await, в котором описание решения несложной задачи по опросу устройств по UDP одним клиентом. Решение задачи с помощью async\await действительно сокращает объем кода, по сравнению с ручной реализацией асинхронных вызовов. С другой стороны создает много проблем с синхронизацией задач, конкурентным доступом к данным и обработкой исключений. Полученное решение очень подвержено ошибкам. Первоначальная версия автора содержала ошибки неосвобождения ресурсов.

Можно ли сделать проще и надежнее?
Читать дальше →

Несколько фактов о CAP-«теореме»

Reading time4 min
Reach and readers17K
В любом обнаружении NoSQL баз данных кто-нибудь обязательно вспомнит о CAP-«теореме». Я не случайно пишу слово «теорема» в кавычках. CAP-«теорема» вовсе не теорема в математическом понимании этого слова. Это неформальное утверждение, сделанное Эриком Брюером в докладе на конференции Principles of Distributed Computing (PODC) в 2000 году. Эрик утверждал, что невозможно создать распределенное (состоящие из нескольких равноценных экземпляров — звеньев) веб-приложение, которое будет одновременно обладать тремя свойствами: согласованность (consistency), доступность(availability) и устойчивость к разделению(partition tolerance), сокращенно CAP. Неформальность утверждения заключается в том, что Брюер не дал определения этим трем понятиям.

Спустя два года Сет Гилберт и Ненси Линч опубликовали исследование, где дали определения понятиям CAP а также формализовали "отложенную согласованность" (Delayed Consistency), которую потом прозвали "согласованность в конечном счете" (Eventual Consistency) и доказали CAP-«теорему» в терминах указанных определений. Если вы еще не читали исследование, то это обязательно стоит сделать — lpd.epfl.ch/sgilbert/pubs/BrewersConjecture-SigAct.pdf

Эта «теорема» так бы и не была никому нужна, если бы её не взяли на вооружение маркетологи NoSQL.
Читать дальше →

Почему вы никогда не должны использовать MongoDB

Reading time16 min
Reach and readers290K
Дисклеймер от автора (автор — девушка): Я не разрабатываю движки баз данных. Я создаю веб-приложения. Я участвую в 4-6 разных проектах каждый год, то есть создаю много веб-приложений. Я вижу много приложений с различными требованиями и различными потребностями хранения данных. Я разворачивала большинство хранилищ, о которых вы слышали, и несколько, о которых даже не подозреваете.

Несколько раз я делала неправильный выбор СУБД. Эта история об одном таком выборе — почему мы сделали такой выбор, как бы узнали что выбор был неверен и как мы с этим боролись.Это все произошло на проекте с открытым исходным кодом, называемым Diaspora.
Читать дальше →
1

Information

Rating
852-nd
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity

Specialization

Software Architect, Delivery Manager
Lead
C#
.NET Core
Entity Framework
ASP.Net
Database
High-loaded systems
Designing application architecture
Git
PostgreSQL
Docker