Вопрос - а зачем тут IMediator? Можно же вот так написать:
namespace Vendor.Features.Statistics
{
public class GetAutomationStatisticsResult
{
public long TotalAutomations { get; set; }
public long ErrorsReported { get; set; }
public long WarningsReported { get; set; }
}
public class GetAutomationStatisticsHandler
{
private readonly GetAutomationsLogTotalCount _getAutomationsLogTotalCount;
private readonly GetAutomationsTotalCount _getAutomationsTotalCount;
public GetAutomationStatisticsHandler(
// Это делегаты на другие фичи (этакая инкапсуляция над медиатром)
GetAutomationsLogTotalCount getAutomationsLogTotalCount,
GetAutomationsTotalCount getAutomationsTotalCount)
{
_getAutomationsLogTotalCount = getAutomationsLogTotalCount;
_getAutomationsTotalCount = getAutomationsTotalCount;
}
public async Task<GetAutomationStatisticsResult> Handle(DateTime? FromDate, DateTime? ToDate, string TaskArn, CancellationToken ct)
{
// some logic
}
}
//не уверен что он нужен но пусть будет
public delegate Task<GetAutomationStatisticsResult> GetAutomationStatistics(DateTime? FromDate, DateTime? ToDate, string TaskArn, CancellationToken ct = default);
}
В таком виде мы явно видим что вызываем, понятны параметры вызова. Намного проще переходить по коду. Я честно не могу понять какую пользу приносит именно IMediator в реализацию такого хендлера. Да я понимаю что есть валидация, транзакции, логирование в пайплайне. Если именно для этого - то понятно. Но если без пайплайна - то зачем?
Вкурсах. По этому пытаются перевести Blazor под wasm-unknown toolchain (через WASI-Libc) вместо emscripten. Только вот проект очень медленно стоит на месте. Emscripten - это 18й век, который нужен что-бы запускать сужествующие С приложения на wasm без особых изменений. Wasm-unknown - куда более нативный и быстрый. Ну и основная часть работы над wasm вне браузера (WASI) ведется как раз на Rust. Так что выбор очевиден. Для браузерных API поддержка в Rust тоже прекрасна.
Мы понимаем DevOps как набор практик, с помощью которых фичакоманда может доставить свой продукт до конечного потребителя. Если кто-то делает это через зоопарк велосипедов (и это работает) — кто мы такие что-бы запрещать ковыряться в носу :)
У нас самих зоопарка если что нет :) k8s — наше все :)
Не очень понятно как при таком подходе будет обеспечивтаться сквозная аналитика всего хранилища. Получается, что все данные будут жить в своих silos и аналитика будет происходить на уровне каждого silos независимо.
Мы пока думаем как это сделать. И надо ли это делать вообще. Ведь вполне можно создать домен для ad-hook аналитики, с помощью которого можно решить 80% вопросов. А если задача не попадает под 80% стандартных — ну что-ж надо создавать узкий домен.
В одной из моих предыдущих компаний был такой подход: данные хранились и обрабатывались централизованно, однако у каждого data set был свой владелец (фича-команда), которые отвечал за наполнение этого сета свежими данными, а так же за публикации актуальной спецификации структуры данных. Спецификация хранилась в центральном репозитории в формате Protobuf.
Это тоже Data Mesh в нашем понимании. Основная идея для нас — чтобы не было господа-бога-данных, без которого нельзя решить ни один вопрос, касающийся данных.
Почитав ваши вопросы, мне показалось, что вам кажется что все что описано — внедрено внутри компании. Это пока не так :) Сейчас мы на примере одной команды разрабатываем процесс и инструменты для внедрения Data Mesh в Додо. Так что мои ответы будут основываться на том, как мы видим конечный результат внедрения сейчас, а не на рабочем процессе.
1 Как боретесь с дублированием данных в разных доменах? Как организовано их переиспользование? На первый взгляд создавать одинаковые датасеты для разных команд в режиме изоляции не выглядит оптимальным.
Никак. У нас нет такой задачи. Если это будет неоптимальным в будущем — будем думать. Как вариант — выносить в отдельный домен данных которым будет владеть команда Data Engeneering.
2 Датасеты BI команды строятся на данных из доменов продуктовых команд?
Не совсем. Например уже на этапе проектирования нам понадобился датасет который включает факты опубликованные несколькими сервисами. В данном конкретном случае — логика мерджа была сложная и использовалась в нескольких отчетах. Мы вынесли ее в отдельный домен.
3 Расскажите больше о том, как команды управляются внутри своих доменов. Используют airflow для etl задач? Кто пишет джобы? Как делят ресурсы?
Технически мы используем Azure Kusto и его Kql для ETL. Он очень быстрый и нам хватает его возможностей. Данные в Kusto попадают через публикацию сообщений в Event Hub.
4 Почему бы просто не раздать/обучить для каждой команды по data инженеру используя классический data lake подход? Насколько я понял, по сути, к этому все и пришло.
Пока не пришло :) Еще идем. Классический Data Lake подразумевает что есть команда, которая отвечает за всю аналитическую схему данных в компании. Даже если все в итоге будет длится в 1 Mysql (который будет Data Lake) но ответственность за схему будет делится между фичакомандами — это уже Data mesh. Подход не про технологии, а про организацию работы людей.
Но как быть с изменениями в логике данных? Простой пример: раньше в столбце «сумма чека» хранилась сумма без НДС, а потом в операционной системе что-то поменяли и стала храниться сумма уже с включенным НДС. С точки зрения продуктовой команды — это необходимое изменение, но при этом все потребители, которые опирались на этот показатель в data lake, сразу прибегут и скажут что у них сломались расчеты.
Так они у нас и текущим DataMonolith прибегают регулярно. Плюс мы сами чиним переливки в текущее аналитическое хранилище тк фича команда может удалить столбец без объявления войны :) Вообщем с монолитом еще хуже :)
Для написания тестов, которые будут проверять все возможные подобные случаи, надо будет потратить кучу времени — для каждой метрики или атрибута продумать возможные варианты использования, написать тесты, убедиться что они корректно работают при всех возможных раскладах и т.п.
Ну тут наверное подход будет похожим на TDD — сначала пишем тесты на требования, при нахождении багов — тесты на баги. Так хотя-бы не будем чинить одно и то-же дважды.
Мы понимаем что нет серебряной пули, но нам кажется что эти инструменты упростят нам жизнь.
Я искренне желаю чтобы у вас все получилось :) но из моего опыта часто при разделении ответственности за данные между разными командами начинается хаос. В основном потому, что каждой команде проще встать в позицию «моя хата с краю» и не думать про последствия изменений, которые они вносят.
Спасибо за теплые пожелания :) Мы приложим все силы что-бы получилось. Ну а хаос будет всегда — в наших силах только попытаться минимизировать ущерб от него через инструментарий и процесс :)
Распределенные транзакции — это все-таки про операционную деятельность. В аналитической мы стараемся иметь дело с набором случившихся фактов. Так что пока мы не видим необходимости в транзакциях. Хотя факты конечно могут (и будут) разезжаться если сопоставлять их по времени. Так что мы сейчас думаем как сопоставлять факты по foregin key.
Возможно вы правы. Но честно говоря я не вижу сильных проблем в дублировании, если оно не несет за собой проблемы другого рода (рассинхрон данных например). Если будет нести — придется наверное выделить НСИ в отдельный домен. В принципе за НСИ в операционной системе сейчас отвечает отдельный микросервис. Так что выделение их в отдельный домен вполне возможно.
Но есть ощущение, что не полностью раскрыт рабочий процесс при использовании нового подхода с data mesh.
Ну поскольку мы только начинаем его строить — раскрыть полностью процесс очень сложно в одной статье. Очень сложно раскрыть то, что полностью пока не сформировалось :) Сейчас мы итеративно выстраиваем процесс работы с данными внутри команды Data Engeneering, что-бы потом переносить его (естественно адаптирую) на всю компанию.
А в любой крупной компании таких зависимостей между данными разных систем будет очень и очень много, соответственно и разделить ответственность между продуктовыми командами будет непросто — все равно нужен «надсмотрщик», который будет разруливать зависимости и контролировать изменения.
На мой взгляд тут ситуация похожа с API микросервисов. Если API опубликован — в нем нельзя делать breaking changes. То же самое с опубликованными схемами данных. Как это форсировать и контролировать? Мы сейчас думаем про автоматические тесты, которые не дадут накатить миграцию если в ней есть breaking changes.
Да очень много дает.
Я ходил недавно на собеседование и как раз писал код на бумажке. Никаких проблем забываниями сигнатур API функций у интервьюверов не было. Достаточно примерно помнить что функция есть в стандартной библиотеке. А вот практические навыки твои видно просто прекрасно.
Например:
Решаем простую алгоритмическую задачку на java, которая свелась к fold (свертке списка). Ну я пишу 2 решения — одно циклами, другое на Stream API. Меня спрашивают — а как бы нам это сделать параллельно. Я отвечаю — можем использовать AsParallel в Stream API, но в общем это может быть медленнее(из-за кривизны Stream API), так что обязательно надо бенчмаркать. Просто смотря на код — фиг поймешь быстрее будет или медленнее.
Интервьювер сразу видит что я и код написать могу 2х стилях (функциональный и императивный) и то что неплохо знаю стандартную библиотеку java и границы применения ее API
Ну и если вы дете в команду интервьювера -ему же интересно как вы там КОД писать будете. Как переменные назвать (a, b, c или что-то более осмысленное), как методы. Насколько легко ему будет понять — что вы пишете.
Так что — имхо писать код на бумаге во время собеседования — одна из самых логичных практик.
Я всетаки отвечу.
Вот пришел я к вам в команду и вижу что вы используете DyUser. Это DynamicUser ( ну какой-то может быть очень активный) или DynamoUser — структура записи пользователя в DynamoDB? Часто бывает что из контекста это не понятно. В лучшем случае — я час проведу изучая код и пытясь понять что такое Dy, в худшем — пойду пытать вас. А у вас релиз завтра и пара противных багов висит. Но это еще «хорошие обревиатуры». Предположим что у нас есть еще бизнес обьекты типа Route и класс DyRoute — и это как раз тот самы Dynamic Route — он вообще относится к инфраструктуре и определяет куда нужно сейчас оправлять ваш запрос в зависимости от загрузки нижележащих сервисов. И ваще жопа — тк какого художника одна и таже обревиатура в разных кусках одного проекта означает соовсем не связанные между собой вещи.
Когда я был маленький, деревья большие и code-competion был только в emacs и контекстный — тогда сокращения имели смысл. На текущем витке развития software development — это примерно такой-же атавизм как и Go-To. Лучше про него просто забыть.
PS: Я не считаю что имена классов, обьектов или методов должны быть длинными. Совсем наоборот — они должны быть максимально корткими — но при этом читаемые. Такая вот задача минимизации — как не выплеснуть ребенка читаемости вместе с водой.
public final class App {
public static void main(final String... args) {
new FtBasic(
new TkFork(
new FkRegex("/robots.txt", ""),
new FkRegex("/", new TkIndex()),
new FkRegex(
"/xsl/.*",
new TkWithType(new TkClasspath(), "text/xsl")
),
new FkRegex("/account", new TkAccount(users)),
new FkRegex("/balance/(?<user>[a-z]+)", new TkBalance())
)
).start(Exit.NEVER);
}
}
FtBasic — что это???
TkFork — что это???
Что такое Ft или Tk? Зачем эти префиксы из аббревиатур?
Этот код читаем только потому что там есть пути к ресурсам. Количество WTF на момент прочтения readme зашкаливает. Я очень надеюсь что мы не будем писать код с таким именованием классов больше никогда.
Хмм можно разбирать вычисления из лямбд и по ним генерировать подписку.
interface IDisposableSupplier<T> : IDisposable {
T Supply();
}
class ViewModel : BaseViewModel {
public int A {get; set;}
public int B {get; set;}
private readonly IDisposableSupplier<int> cSupplier;
public int C {get{ return cSupplier.Supply(); }}
public ViewModel(){
cSupplier = this.CreateSubcription(() => A + B);
}
}
static class ProppertyChangedHelper {
public static<T> IDisposableSupplier<T> CreateSubcription(this BaseViewModel vm, Expression<Func<T>> callable) {
//AST parsing and subscriptions here.
}
}
Ну а Linq в вашей команде используют — если что это монада List. Async/Await — тоже монада(название у нее разное в разных языках). Даже null value (использование null вместо значения по ссылке) — тоже монада.
Ну и самый главный прикол что просто последовательное исполнение кода в C# это тоже монада — в хаскеле ее называют IO.
Все пользуются монадами — не все об этом догадываются :)
К сожалению скандал не про выбросы. Volkswagen слишком быстро начал становится производителем машин #1 в мире (по количеству). Сейчас посмотрим как ребята из дружественных VAG партии зеленых в Германии начнут проверять пепелацы GM. Вот там смеху будет.
А если серьезно — причина не VW, а совершенно идиотские экологические нормы. Велосипедист который едет со скоростью 30-40 кмч дает больше вредных выбросов чем разрешено автомобилю в Калифорнии. Про стадо коров я вообще молчу. Но почему-то все привязались к автомобилям.
Проблема в том что весь мир живет по одним стандартам (MasterCard + Visa) а Германия по своему собственному (EC), карточку которого фиг получишь если ты не житель Германии. В этом и проблема, для тех кто в Германии не живет, а просто приезжает в гости.
Вы сравниваете совсем разные вещи.
Как минимум используя Linq можно писать запросы и к удаленному хранилищу и к любой локальной структуре данных в едином виде. Это очень полезно.
Jooq и querydsl — это возможность строить запросы к базе.
Тк я работал только с Jooq, то могу сказать только за него — синтаксис менее понятный чем у Linq.
Ну и с linq вся фишка в поддержке рантайма, а именно в том что вы можете получить доступ к AST лямбд которые вы передаете в Linq методы. Это позволяет писать куда более простой и читабельный код.
Вопрос - а зачем тут
IMediator
? Можно же вот так написать:В таком виде мы явно видим что вызываем, понятны параметры вызова. Намного проще переходить по коду. Я честно не могу понять какую пользу приносит именно
IMediator
в реализацию такого хендлера. Да я понимаю что есть валидация, транзакции, логирование в пайплайне. Если именно для этого - то понятно. Но если без пайплайна - то зачем?Вкурсах. По этому пытаются перевести Blazor под wasm-unknown toolchain (через WASI-Libc) вместо emscripten. Только вот проект очень медленно стоит на месте. Emscripten - это 18й век, который нужен что-бы запускать сужествующие С приложения на wasm без особых изменений. Wasm-unknown - куда более нативный и быстрый. Ну и основная часть работы над wasm вне браузера (WASI) ведется как раз на Rust. Так что выбор очевиден. Для браузерных API поддержка в Rust тоже прекрасна.
#режим зануды включен
Сори но ваш процесс разработки в ветках это не Github-flow. Github-flow это хорошо описанный легковесный процесс для разработки. Процитирую автора:
Anything in the
master
branch is deployableTo work on something new, create a descriptively named branch off of
master
(ie:new-oauth2-scopes
)Commit to that branch locally and regularly push your work to the same named branch on the server
When you need feedback or help, or you think the branch is ready for merging, open a pull request
After someone else has reviewed and signed off on the feature, you can merge it into master
Once it is merged and pushed to 'master', you can and should deploy immediately
То есть как минимум в нем просто не может быть релиз бранчей - тк master по сути и есть релиз бранч.
#режим зануды выключен.
Мы понимаем DevOps как набор практик, с помощью которых фичакоманда может доставить свой продукт до конечного потребителя. Если кто-то делает это через зоопарк велосипедов (и это работает) — кто мы такие что-бы запрещать ковыряться в носу :)
У нас самих зоопарка если что нет :) k8s — наше все :)
Мы пока думаем как это сделать. И надо ли это делать вообще. Ведь вполне можно создать домен для ad-hook аналитики, с помощью которого можно решить 80% вопросов. А если задача не попадает под 80% стандартных — ну что-ж надо создавать узкий домен.
Это тоже Data Mesh в нашем понимании. Основная идея для нас — чтобы не было господа-бога-данных, без которого нельзя решить ни один вопрос, касающийся данных.
Почитав ваши вопросы, мне показалось, что вам кажется что все что описано — внедрено внутри компании. Это пока не так :) Сейчас мы на примере одной команды разрабатываем процесс и инструменты для внедрения Data Mesh в Додо. Так что мои ответы будут основываться на том, как мы видим конечный результат внедрения сейчас, а не на рабочем процессе.
Никак. У нас нет такой задачи. Если это будет неоптимальным в будущем — будем думать. Как вариант — выносить в отдельный домен данных которым будет владеть команда Data Engeneering.
Не совсем. Например уже на этапе проектирования нам понадобился датасет который включает факты опубликованные несколькими сервисами. В данном конкретном случае — логика мерджа была сложная и использовалась в нескольких отчетах. Мы вынесли ее в отдельный домен.
Технически мы используем Azure Kusto и его Kql для ETL. Он очень быстрый и нам хватает его возможностей. Данные в Kusto попадают через публикацию сообщений в Event Hub.
Пока не пришло :) Еще идем. Классический Data Lake подразумевает что есть команда, которая отвечает за всю аналитическую схему данных в компании. Даже если все в итоге будет длится в 1 Mysql (который будет Data Lake) но ответственность за схему будет делится между фичакомандами — это уже Data mesh. Подход не про технологии, а про организацию работы людей.
Так они у нас и текущим DataMonolith прибегают регулярно. Плюс мы сами чиним переливки в текущее аналитическое хранилище тк фича команда может удалить столбец без объявления войны :) Вообщем с монолитом еще хуже :)
Ну тут наверное подход будет похожим на TDD — сначала пишем тесты на требования, при нахождении багов — тесты на баги. Так хотя-бы не будем чинить одно и то-же дважды.
Мы понимаем что нет серебряной пули, но нам кажется что эти инструменты упростят нам жизнь.
Спасибо за теплые пожелания :) Мы приложим все силы что-бы получилось. Ну а хаос будет всегда — в наших силах только попытаться минимизировать ущерб от него через инструментарий и процесс :)
Ну поскольку мы только начинаем его строить — раскрыть полностью процесс очень сложно в одной статье. Очень сложно раскрыть то, что полностью пока не сформировалось :) Сейчас мы итеративно выстраиваем процесс работы с данными внутри команды Data Engeneering, что-бы потом переносить его (естественно адаптирую) на всю компанию.
На мой взгляд тут ситуация похожа с API микросервисов. Если API опубликован — в нем нельзя делать breaking changes. То же самое с опубликованными схемами данных. Как это форсировать и контролировать? Мы сейчас думаем про автоматические тесты, которые не дадут накатить миграцию если в ней есть breaking changes.
Я ходил недавно на собеседование и как раз писал код на бумажке. Никаких проблем забываниями сигнатур API функций у интервьюверов не было. Достаточно примерно помнить что функция есть в стандартной библиотеке. А вот практические навыки твои видно просто прекрасно.
Например:
Решаем простую алгоритмическую задачку на java, которая свелась к fold (свертке списка). Ну я пишу 2 решения — одно циклами, другое на Stream API. Меня спрашивают — а как бы нам это сделать параллельно. Я отвечаю — можем использовать AsParallel в Stream API, но в общем это может быть медленнее(из-за кривизны Stream API), так что обязательно надо бенчмаркать. Просто смотря на код — фиг поймешь быстрее будет или медленнее.
Интервьювер сразу видит что я и код написать могу 2х стилях (функциональный и императивный) и то что неплохо знаю стандартную библиотеку java и границы применения ее API
Ну и если вы дете в команду интервьювера -ему же интересно как вы там КОД писать будете. Как переменные назвать (a, b, c или что-то более осмысленное), как методы. Насколько легко ему будет понять — что вы пишете.
Так что — имхо писать код на бумаге во время собеседования — одна из самых логичных практик.
В Java луше тк простой мапинг данных сделать в C# сложно
что-то из серии
В C# будет выглядеть как
Ну и в Java версии явно видно — может быть пустое значение или нет
Вот пришел я к вам в команду и вижу что вы используете DyUser. Это DynamicUser ( ну какой-то может быть очень активный) или DynamoUser — структура записи пользователя в DynamoDB? Часто бывает что из контекста это не понятно. В лучшем случае — я час проведу изучая код и пытясь понять что такое Dy, в худшем — пойду пытать вас. А у вас релиз завтра и пара противных багов висит. Но это еще «хорошие обревиатуры». Предположим что у нас есть еще бизнес обьекты типа Route и класс DyRoute — и это как раз тот самы Dynamic Route — он вообще относится к инфраструктуре и определяет куда нужно сейчас оправлять ваш запрос в зависимости от загрузки нижележащих сервисов. И ваще жопа — тк какого художника одна и таже обревиатура в разных кусках одного проекта означает соовсем не связанные между собой вещи.
Когда я был маленький, деревья большие и code-competion был только в emacs и контекстный — тогда сокращения имели смысл. На текущем витке развития software development — это примерно такой-же атавизм как и Go-To. Лучше про него просто забыть.
PS: Я не считаю что имена классов, обьектов или методов должны быть длинными. Совсем наоборот — они должны быть максимально корткими — но при этом читаемые. Такая вот задача минимизации — как не выплеснуть ребенка читаемости вместе с водой.
FtBasic — что это???
TkFork — что это???
Что такое Ft или Tk? Зачем эти префиксы из аббревиатур?
Этот код читаем только потому что там есть пути к ресурсам. Количество WTF на момент прочтения readme зашкаливает. Я очень надеюсь что мы не будем писать код с таким именованием классов больше никогда.
Ну и самый главный прикол что просто последовательное исполнение кода в C# это тоже монада — в хаскеле ее называют IO.
Все пользуются монадами — не все об этом догадываются :)
А если серьезно — причина не VW, а совершенно идиотские экологические нормы. Велосипедист который едет со скоростью 30-40 кмч дает больше вредных выбросов чем разрешено автомобилю в Калифорнии. Про стадо коров я вообще молчу. Но почему-то все привязались к автомобилям.
Как минимум используя Linq можно писать запросы и к удаленному хранилищу и к любой локальной структуре данных в едином виде. Это очень полезно.
Jooq и querydsl — это возможность строить запросы к базе.
Тк я работал только с Jooq, то могу сказать только за него — синтаксис менее понятный чем у Linq.
Ну и с linq вся фишка в поддержке рантайма, а именно в том что вы можете получить доступ к AST лямбд которые вы передаете в Linq методы. Это позволяет писать куда более простой и читабельный код.