Как стать автором
Обновить
10
0
Виктор Николаев @Veikedo

.net developer

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

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

NATS к сожалению обеспечивает лишь гарантии at most once в безброкерном режиме, а с брокером смысл его использования теряется. Кроме того задача переезда на него гораздо тяжелее чем задача переезда на grpc-прокси перед kafka без переезда данных.

Ну и проблемы с библиотеками от этого никуда не деваются :)

А не легче было поменять Kafka на NATS ?
производительность выросла бы в 2-3 раза ничего не делая :-)

Господа, я могу ответить на этот вопрос предметно на примере другой отрасли.

Моряки, которые работают именно в морях (танкера, контейнеровозы, газовозы, и.т.п) - имеют так называемый рабочий диплом. Он выдается не всратыми российскими ВУЗами/ССУЗами, а администрацией порта, после окончания образования и 6 месяцев практики. И именно на основании данного документа моряков берут на работы. Без рабочего диплома, но с дипломом российского морского ВУЗА - можно работать на берегу. Рабочий диплом нужен всем, даже российским компаниям.

Далее. Даже заключая контракты с российской компанией - Совкомфлот и прочие новошипы - моряками платят на международном уровне. Ровно так же, как и французам, итальянцам, норвегам (норвегов сейчас практически нет на флоте, он на берегу больше заработают). Как и IT-шникам сейчас в отечественных компаниях - в общем-то, по мировым ставкам. Скрипя зубами, матерясь на совещаниях (в отечественных морских компаниях en masse руководители из совка), но платят.

Секрет тот же самый, как и у IT - моряк не привязан географически к месту работы. Организацией и оплатой трансферта до судна и обратно занимается крюинг (крюингу естественно все это выгодно, но речь сейчас не об этом). Плюс полностью компании оплачивают постоянное обучение и ... назовем это переаттестацией, которую проходят раз в пять лет. Это стандарт.

Итак, мы знаем, что желторотый выпускник, делающий первый рейс третьим помощником (это не master, не chief engineer, не first officer), только получивший рабочий диплом, без опыта работы, спокойно зарабатывает 2900$/мес (это ближе к минимальной ставке).

Для сравнения - зарплата стармеха (chief engineer) 13 500 - $ 14 500/мес., это VLCC и 9 000$-11 000$./мес судно bulk. Это gross, но в этой отрасли 99% налоги в России не платят - больше полугода находятся за границами РФ.

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

Механик-старший помощник капитана
Судно: нефтяной танкер речной "НТ-152"
Стаж работы: от 3 лет
Наличие документов: полный пакет (для реки) в т.ч. танкерная подготовка
район плавания: р.Печора
Зар.плата: на ремонте 45 т.р. / в навигации 110 т.р.

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

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

P.S. Спасибо, что молча нагадили в карму.

НЛО прилетело и опубликовало эту надпись здесь
Спасибо за статью. А чем эту штука лучше призмы?
exec('google-chrome --headless --no-sandbox --disable-gpu --print-to-pdf=путь_К_Пдф.pdf --no-margins путь_где_брать_хтмл.html --virtual-time-budget=50000 >куда_писать_лог.log 2>&1');

Достаточно попросить верстальщика сделать хтмл «как в пдф будет». И проверять можно по Ctrl+P как получится финальный пдф — 1 в 1.
Для начала, нужно понимать, что есть разного рода ошибки. Есть исключительные ситуации, а есть валидация. Исключительные ситуации очень похожи на валидацию, но это как разница между интерфейсом и абстракным классом (особенно в C++) — она на уровне семантики (смысла кода). Исключительные ситуации нужны для проверки корректности работы системы. Валидация нужна для проверки корректности данных от пользователя.

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

Теперь рассмотрим другой пример. После редактирования сущности сервер должен в любом случае провалидировать корректность данных (даже если такие проверки есть на фронтовой части). При этом пользователь должен получить список всех ошибок, иначе его будет раздражать процесс работы с системой. Но вы можете бросить только одно исключение, которое увидит пользователь. Поэтому тут исключения враг. В данном случае очень хорошо работает подход с набором различных независимых валидаторов и собиранием результатов их работы. Тот же ASP.NET MVC/Web API с их ModelState.IsValid — это классический пример данного подхода. При этом при самой валидации нам не нужен стектрейс, а иногда еще и даже вреден — вы же не хотите, чтобы до юзера дошла информация о стектрейсе приложения?

Но, у подхода с набором различных независимых валидаторов есть проблемы.

Первая проблема: они независимы друг от друга.
Пример: у вас есть поля password и confirmPassword. На первое поле навешана валидация «пароль должен быть сильным», на второе поле навешана валидация «confirmPassword должен совпадать с password». Показывать обе ошибки немного странно.

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

Третья проблема: они очень плохо работают когда нужно гонять запросы к бд для того, чтобы выполнить валидацию.
Пример: вы делаете штуковину, которая валидирует изменения нескольких сущностей (банальная система с выгрузкой и загрузкой данных). На одну сущность может выпасть несколько ошибок. Причем, есть некоторые ошибки, которые пожирают другие ошибки. К примеру — есть ошибка «нельзя менять данную сущность при таких-то условиях» и есть ошибки «это свойство сущности нельзя менять при таких-то условиях». Причем под каждое валидационное правило нужно подгружать разнообразные данные, что медленно. Ваш код должен показывать максимум полезных ошибок и работать минимум времени. Соберите синхрофазотрон, короче.

Прикол заключается в том, что бросить исключение это легко, привычно и требует меньше действих, поскольку интегрировано в язык. Писать набор валидаторов или Result/Validation фокусы — непривычно, да и не всегда так явно и очевидно в рамках языка. Поэтому пока что разумным подходом является смешивание подходов. Но не стоит забывать о том, что требования рано или поздно могут измениться, а времени на рефакторинг не будет.
Вот то, что я рассказал бы про исключения тому, кто пока не умеет ими пользоваться.

  • Исключения нужно использовать тогда и только тогда, когда возникает развитие событий, не предусмотренное нормальным ходом работы приложения — исключительной ситуации. При этом причина может быть как статической (например, логическая ошибка в коде), так и динамическая (например, недоступность ресурсов).
  • Исключения нужно кидать максимально точно (узко) типизированными.
  • Исключения замечательны для решения своей задачи — прерывания процесса с информированием о возникшей проблеме — причине прерывания, потому что они всплывают по стеку до нужного места. Для других задач они не подходят.
  • Обрабатывать исключения нужно там, где их одновременно возможно и уместно обработать.
  • В прикладном ПО большинство бросаемых на практике исключений не обрабатываются, перехватываются в самой высокой точке стека и попадают в лог, а пользователь получает ошибку 500 «Что-то пошло не так».

Автор не потрудился почитать описание паттерна Репозиторий, какие проблемы он решает, а так же не понял где у него проблема в принципе(в разных источниках). Хотя с QueryObject еще не все так плохо и они вполне жизнеспособны, но в другом месте.


Начну с хорошего:


  • В папочке с QueryObject в принципе легче ориентороваться.
  • Их проще писать, проще внедрять в сервисы.
  • Проще вводить новые версии.
  • Проще моки писать в тестах — не надо все зависимости репозотория переопределять.
  • Еще отлично встроятся в read часть вашего приложения, если вы запилили CQRS.
    На этом все.

Теперь о плохом. Репозиторий.
В первую очередь Репозиторий — это интерфейс коллекции доменных объектов. Он абстрагирует нашу систему хранения данных. А ORM — Это вообще не про это. ORM про маппинг сток из базе на объекты.
Эти 2 паттерна решают разные проблемы и используются по разному.


Даже Фарулер говорит:


A Repository mediates between the domain and data mapping layers.
https://martinfowler.com/eaaCatalog/repository.html

Data Mapping Layer — это как раз таки Ваша ORM.


Использование класса из ORM вместо интерфейса репозитория — это циклическая зависимость в вашем коде. Если вы захотите заменить систему хранения данных — вы попали. Хотя в некоторых случаях такое упрощение в полне себе решение. Никому эти репозитории в блоге или сайте визитке не нужны.


Пример из реального проекта.
Одним из решений для задачи — было запилить EventSourcing. В качестве первого решения, было решено использовать MySQL как хранилище данных. Так было проще начать.
Со временем оказалось что:


  • все события просто напросто физически не влезут в него, хард не резиновый.
  • использовать MySQL финансово не выгодно.

По этому было решено переехать на DynamoDB. Если бы я использовал использовал репозитории ORM — мне бы пришлось выпилить его полностью. А так — я просто запилил новый класс, имплементировал пару методов и готово — в продакшин.


Это то что касается Репозиториев.


Теперь про количество методов в Репозиториях.
Репозиторий используется совместно с ОРМ. Сейчас мы обратим внимание на то что он используется именно для Маппинга Доменных Объектов. И возвращает коллекцию доменных объектов.
Большинство методов, от которых растет Репозиторий и на которые грешит автор — это методы для чтения данных.
Так вот. Если вы подумали хорошо, когда проектировали ваше приложение — то наверное запилили бы CQRS. Тогда в вашем слое C были бы UseCase, которые использовали бы Репозитории с ОРМ.
А в слое Q были бы ваши QueryObject или что по проще, без ОРМ. Он там нафиг не впился.


Другими словами — Репозитории с ОРМ вам нужны там, где бизнесс логика. Там где просто вывод данных — вам и ОРМ не впилась, используйте SQL.


Вы можете посмотреть видео Marco Pivetta "Doctrine Best Practices". Не надо плеваться что это Доктрина, принципы в ОРМ одни и те же.


А нафиг оно вообще все надо? Зачем усложнять?
Все эти дела с перозиториями, орм, интерфейсам, и т.д. и т.п. порой появляются на ровном месте.
Ваше решение должно быть обосновано, внимание, ТРЕБОВАНИЯМИ К ПРОЕКТУ, а не личными хотелками.
Если вы пишите блог — не надо там квери обьекты городить или отдельные репозитории вводить. Берите репозиторий ОРМ и в продакшин. А если у вас что-то больше — обязательно проверьте не будет ли меняться система хранения данных в конкретной части приложения. Ведь мы можем писать в мускуль, а клиенту отдавать из редиса. И то и то можно спрятать в репозитории. И когда прийдет время заменить имплементацию на что-то еще — вы не будете плакать.


Для лучшего понимания рекомендовал бы посмотреть видео Евгения Кривошеева "Осознанность проектирования" и "Как не угробить архитектуру сразу же". Можно найти тут же на хабре. Там еще интересное.

>> я голосую за явные контракты у репозитория.

«Загрузи сущности, удовлетворяющие спецификации» и есть явный контракт.
Проблема в том, что давать наружу ICriteria/IQueryable чревато потерей контроля над дао-слоем (как раз случай — сделали колонки для подсчёта count-ов, а клиентский код по прежнему считает кол-во на сервере).
Не давать наружу ICriteria/IQueryable и не использовать спецификации — распухает интерфейс дао (на каждый чих — свой метод). А в случае со спецификациями распухают контракты спецификаций, что легче поддерживать.

>> А если мне нужно получить кол-во элементов по условию?

Делаем два метода — «загрузи мне объекты по спецификации» и «посчитай кол-во объектов, удовлетворяющих спецификации».
Методы могут либо опираться на общий код построения критерии, в конце лишь добавляя проекцию count(), либо на абсолютно разные алгоритмы (ага, count-ы в отдельных столбцах) — слой выше код не должен видеть детали.

>> А если, получая коллекцию с кучей ассоциаций, я не хочу напороться на SELECT N+1 и в запросе необходимо указать правильный выбор JOIN или SUBSELECT?

Добавляем хинты загрузки в спецификацию.

>> А если при выборке по условию какие-то ассоциации необходимо загрузить сразу, минуя дефолтный lazy-load?

Аналогично. И остаёмся в рамках абстракции — список юзеров и список юзеров с подгруженной группой — разные списки, соответствтенно на них нужны разные спецификации.

>> Как обобщенные репозитории и интерфейс ISpecification ответят на эти «если»?

Имхо, бизнес-слой не должен видеть, что спецификация построена на общем интерфейсе или имеет AST внутри.
Да и строгое следование единой структуре — плохо, потому что ограничивает стратегии применения спецификации.

Удобно в спецификации давать ссылки на другие спецификации. Например, спецификация группы может содержать ссылку на спецификацию юзера, что трактуется как «найди мне группы, где есть юзеры с указанной спецификацией».

MobX, RxJS и Redux являютя, по сути, различными идеями реализации реактивного программирования (pull, push и что-то там особое), каждое из которых дает свое преимущество и недостатки (а еще их часто между собой комбинируют).


MobX, в отличие от redux, больше подходит для построения MVVM архитектуры приложения и хорошо структуризированного ООП, когда redux стремится в функциональщину и нормальным сторам. За счет того, что он (mobx) скрывает в себе много кода по обновлению компонентов, инкапсулирует логику обновления компонентов в себе (в хорошем mobx приложении вы ни разу не должны прописывать shouldComponentUpdate), при этом перерисовывает только непосредственные зависимости в отличие от перерисовки всего View в редуксе, ускоряет и облегчает разработку, требует меньше оверхеда в виде постоянного создавания всевозможных action и reducer, а так же увеличивает отзывчивость страницы. В теории.


Я бы даже сказал так: в очень оторванной от действительности теории, покуда на практике красивый код из todo-mvc примера превращается в достаточно запутанный VM слой с геморроем при lazy-загрузке, постоянными лишними перерисовками, которые устанешь вычищать, а так же хитрыми костылями там, где он по какой-то причине предпочел работать не так, как тебе нужно. Зато на нем действительно получается изящная MVVM архитектура.

я слоупок конечно, но может кому пригодится
pornhub.com -> pornhub.ru
youporn.com -> 31.192.116.27
Как человек, который поработал с Aurelia на проекте, проклинаю ее всем чем можно. Нормальной валидации, форм и всего такого нет, что нужно бизнесу. После этой медузы, перешел на Angular2 и доволен как слон был. Angular2 — это мощная, уже готовая к продакшену полная платформа. Хотите Redux? Есть круче NgRx, все на реактивных состояниях, сайд эффекты красиво отделяются от чистых данных за счест Effects (поведение похоже как у sagas только лучше и более декомпозируемое) Также я за выбирать под продакшен React и его экосистему.

Хотите что-то задекларировать?
Да! С Aurelia больше никогда не работать!
Выше — это выше по стеку вызовов. Как-то так:

Информация

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