Эшу быдлокодит
298 subscribers
128 photos
12 videos
7 files
169 links
Дневник C# разработчика.

Личка: @EshuMarabo
Гитхаб: https://github.com/vladzvx

Стек: C#, PostgreSQL
Download Telegram
Эшу быдлокодит
Получил лвлап и кучу экспириенса по работе с тарантулом, что характерно - на ровном месте. Рассмотрим кейс: есть некая запись, относящаяся к человеку (user_id, unsigned(UInt64)). У нее есть время создания (creation_time, integer (Int64)) и время закрытия…
Решил добавить в индекс еще пару измерений. Теперь главное не пытаться представить, как выглядит запись в базе данных в качестве 4х мерного прямоугольника-параллелепипеда (термин из тарантуловской документации), где измерения - id пользователя, время, ранг записи в древовидной структуре и её тип.
Тут хороший человек работу ищет:
CV_StolbovV_short.pdf
90.2 KB
А разнесите резюму по своим каналам, что ли.
👍1💩1
Эшу быдлокодит
И сегодня, на эти же грабли, в этом же самом месте, два раза, хренак, хренак! Да, я так и не написал генератор данных, поленился.
И в четвертый раз, на те же грабли, в том же месте!

Да, я пока ленюсь написать нормальный генератор данных.
🤡4🤣2
Пока монга выполняет роль хранилища-помойки, вида: положил кучку - забрал по id или паре простых запросов - она прекрасна и крайне дружелюбна.

Но стоит сделать шаг в темноту сторону каких-то статистических запросов - все перестает быть столь уютным.

Для человека, два года пользующегося монгой и казалось бы привычного к ней, первое составление запроса вида (дико извиняюсь за псевдо-sql):

select distinct field1, field2 from table where (пара условий) order by field2 limit 100 skip 100

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

Сначала, как обычно, пытаешься слепить запрос прямо в c#, используя синтаксический сахар, предоставляемый библиотекой-конектором.

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

Теперь я имею json в 30 строк, который при выполнении в монге выдает нужный мне результат. Осталось корректно перенести его в с#.

#mongodb
💩2
Эшу быдлокодит
Пока монга выполняет роль хранилища-помойки, вида: положил кучку - забрал по id или паре простых запросов - она прекрасна и крайне дружелюбна. Но стоит сделать шаг в темноту сторону каких-то статистических запросов - все перестает быть столь уютным. Для…
Вот примерный json, генерируемый запросом. Сравните по читаемости с псевдо-sql версией в прошлом посте.

[{
$match: {
Field3: "qwerty123",
},
},
{
$group: {
_id: "$Field1",
id: {
$first: "$Field1",
},
Field2: {
$first: "$Field2",
},
},
},
{
$sort: {
Field2: -1,
},
},
{
$skip: 0,
},
{
$limit: 2,
},
{
$project: {
_id: 1,
},
},
]

group в данном случае используется для получения эффекта distinct из sql запроса.

Монга умеет в distinct запросы, но туда не завезли пагинации (постраничной отдачи), потому идём окольным путём 🤡

#mongodb
А от шарповой версии запроса уже конкретно начинает течь кровь из глаз, при том, что простые запросы там прекрасны. В качестве примерна приведу получение всех записей, где определенное поле равно чему-то:

_mongoCollection.Find(record=>record.Field3=="qwerty123").ToList();

В примере используется трансляция в монговский формат внутришарпового языка запросов к коллекциям LINQ, потому всё максимально прозрачно.

#mongodb
Примерно год назад я перетаскивал базу данных Палантира (чуть больше терабайта) с сервера на сервер. С помощью консольных утилит это было то ещё удовольствие, требующее как минимум стабильного соединения с сервером в течение многих часов.

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

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

Прилагаю статью с описанием процесса переноса продакшн базы без остановки доступа к данным. Кросивое.

Теперь надо бы для общего развития поднять кластер где-нибудь у себя.

#mongo
В прошлом году итоги я подвёл в ноябре при запуске #палантир@eshu_coding, после него ничего особо интересного не было.

В этом году никаких проектов не под NDA, я в общем-то не делал. Если без подробностей, то вот краткие итоги личностного роста:
1. Научился готовить Tarantool, прошёлся по куче граблей, примерно понял, где он реально нужен, и главное, где не нужен. Пришлось поверхностно познакомиться и с механизмом построения кластеров: репликация, шардирование, вот это вот всё.

2. Нырнул в MongoDB на уровне, отличном от "положил как в помойку, достал по id/однострочному запросу". Многоступенчатые запросы, подписки на обновления коллекций, TTL, транзакции, materialised view. Впервые завел реплика-сет вместо отдельностоящего инстанса.

3. Построил пару обменников на RabbitMQ, пришло осознание проглоченного и применённого на коленке в 2021.

4. Влюбился в систему сбора метрик Prometheus. Если раскидать их по приложению и заодно подключить сбор с компонентов системы (баз данных и т.д.), получается крайне информативно. Дефолтный визуализатор так себе, но основные функции выполняет.

5. Познакомился с EKL стеком - сбор и визуализация логов. Особой любви не случилось, уж больно оно огромно и прожорливо. Можно кстати использовать ELK для построения красивых дашбордов по данным из Prometheus-а, но это мне пока не особо нужно.

6. Прогресс как шарписта у меня вышел так себе. Научился красиво описывать rest api с помощью Swagger, да в общем-то и всё. Ну ещё окончательно освоил разработку с использованием докера: приложение сразу запускается и отлаживается в контейнере, окружённое соседними сервисами. При прогоне тестов также активно использую песочницу, поднятую в docker-compose.

P.S. NoSQL я накушался досыта, 2023 - время вернуться к истокам - C# + PostgreSQL.
👍91
Ну чтож, надо посмешить богов, озвучить свои планы.

Чего хочу я в этом году:
1. Немного обмазаться фронтенд разработкой, но без фанатизма. Пока думаю о связке React + Typescript.

2. Попробовать на практике стандартную шарповую ORM: Entity Framework.

3. Углубиться в PostgreSQL, поиграться с уровнями изоляции транзакций, подтянуть оптимизацию запросов, возможно попробовать пособирать разные конфигурации кластеров на foreign table.

4. Прочитать несколько умных книжек, что-то типа:
a) Рихтер
b) Высоконагруженные приложения Фаулера
c) Ещё что-нибудь по архитектуре.

5. Начать подтягивать базу по Computer Science, мб копнуть алго задачи.

Вот такие планы, интересно, что исполнится к концу года:)
🔥7👍4👏2
Эшу быдлокодит
Ну чтож, надо посмешить богов, озвучить свои планы. Чего хочу я в этом году: 1. Немного обмазаться фронтенд разработкой, но без фанатизма. Пока думаю о связке React + Typescript. 2. Попробовать на практике стандартную шарповую ORM: Entity Framework. 3.…
Ну что же, фронтенд мой пока закончился на попытке нормально подружить Visual Studio и фронтенд разработку.

Я стремительно расширяю сознание в части строительства всякого интересного на базе MongoDB, скоро буду выходить на новый уровень в части работы с RabbitMQ.

PostgreSQL? Entity Framework? Фронтенд? Планирование? Не, это для лохов.
🔥3🤡2🤔1
Не прошло и 5 лет работы с с#, как я сподобился начать читать в режиме "от корки до корки" базовую книгу: Рихтера. Она несколько устарела: относится к версии языка от 2012 года. Но т.к. базовые концепции, лежащие в основе, с тех пор не поменялись, так что ознакомиться надо.

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

Так, операцию сравнения - == между двумя экземплярами класса надо применять с осторожностью, результат зависит далеко не только от их содержимого.

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

Во всех экземплярах классов хранится ссылка на объект-тип. GetType как раз ее и возвращает. Не то, чтобы что-то революционное, просто небольшой штрих в общей картине.

Далее здесь будет что-то типа конспекта, который буду писать по мере прочтения. Ну и будут новые теги:
#книги
#Рихтер
👍2
Практически осилил фундаментальную главу про типы. В целом - почти ничего нового, но пару занятных нюансов вычитал.

В с# есть разделение на типы - значимые (структуры, живут обычно в стеке) и ссылочные (обычные классы, живут в куче).

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

Обычная практика - сделать структуру вида "координата", содержащую х, у и z и пользоваться ей.

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

Ещё из интересного - если выдавливать максимум производительности, то использовать штатные методы -ToString, GetType, GetHashCode для значимых типов стоит с осторожностью - легко наступить на грабли и засрать кучу мусором - во многих случаях сначала будет произведена операция упаковки (сама по себе не очень быстрая) значимого типа в кучу из стека, а потом уже вызван метод. Те из них, которые поддаются переопределению - переопределить. А GetType - использовать только по большой нужде. Кроме траты времени на упаковку мы нагружаем сборщик мусора, что в некоторых случаях даже печальнее.

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

#книги
#рихтер
👍3
Сколько времени программисту нужно, чтобы разобраться с тем, как включить мультики с usb с телевизора?

15 минут и помощь системного аналитика, знающего бэкдор: направлять пульт строго в правый нижний угол телевизора.
😁5
Эшу быдлокодит
Практически осилил фундаментальную главу про типы. В целом - почти ничего нового, но пару занятных нюансов вычитал. В с# есть разделение на типы - значимые (структуры, живут обычно в стеке) и ссылочные (обычные классы, живут в куче). Для значимых сравнение…
Продолжаю читать про типы. Наткнулся на пару моментов, где я по незнанию лепил избыточный код:
1. Увидел как вызывать конструктор из другого конструктора. Чуть меньше копипасты:)
2. Узнал, что статический конструктор по умолчанию потокобезопасен. То есть все мои неэстетичные огородики с блокировками в таких конструкторах отправляются на помойку. Отлично.

#рихтер
#книги
👍4
Наткнулся на забавный вопрос к собеседованиям:

Как изменить в уже запущенной программе значение строковой константы?

Константа на то и константа, чтобы быть неизменной. Да ещё строки в c# неизменяемые, но есть обходной путь, правда череватый выстрелом даже не в ногу, а в живот.

В c# есть особый раздел языка: unsafe. По сути, это что-то вроде урезанного языка c++. И вот с помощью такой вставки можно получить указатель на место в памяти, где хранится эта константа и нагадить записать туда свои байтики.

Потому родился встречный вопрос:
А у вас в кодовой базе такое практикуется?
🔥6
Forwarded from javawatch
ChatGPT достигла уровня человека! Я попросил ее написать пример использования модулей в C++23 через cmake, и у нее не получилось. У меня тоже не получилось. Каких высот мы достигли!
😁6🤡1
Познакомился с работой с координатами на карте. Широта и долгота, x и y, логично ведь? Север на карте - сверху, вертикаль - это y. А горизонталь - x.

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

#csharp