Либо ваш пакет полезен, либо нет, какая разница, сколько строк?
А вообще, честно говоря, проще Unity выкинуть, тогда и вопроса, делить на отдельные пакеты или нет, не будет.
400-800-1000 строк скучного, повторяющегося кода, который всегда вызывает конфликты при merge :)
Не вызывает ни в жирном монолите на несколько сотен проектов, ни в нескольких сотнях микросервисов, и это мы ещё не очень большая компания. Где-то используется Microsoft DI, где-то Autofac, в котором вы тоже регистрируете сервисы вручную, просто с другим синтаксисом. И нет никакой проблемы с конфликтами.
а я вполне себе делаю Metadata-Driven Framework-и в DDD/CleanArchitecture
При этом не понимаете, что писать в <TargetFramework>. Поменяв net7.0 на netcoreapp2.0, вы сделали хуже, потому что если у .NET 7 поддержка закончилась в мае 2024, у .NET Core 2.0 - в октябре 2018.
При этом не настроили .gitignore, чтобы не тащить в репозиторий мусор.
Вам бы основам сначала уделить внимание, а потом уже хвастаться Metadata-Driven фреймворками. И нет, у меня нет цели вам нахамить или обидеть.
Мне проще делать 1 nuget проект для 10 популярных контейнеров, чем разбивать все на RegisterByAttributes.Abstractions, RegisterByAttributes.Unity и прочее
Если вы хотите, чтобы ваш пакет был полезен другим людям и им пользовались, то как проще вам - не так важно, как проще вашим потенциальным пользователям. А пользователям проще не нести в проект мусор. Даже если 20 кб.
Да, нужно разбивать на несколько пакетов. Unity отдельно, Microsoft DI отдельно. Нет, разбираться в 3+ пакетах никому не придётся. Кому нужен RegistrationByAttributes для Microsoft DI, те по-прежнему поставят один пакет.
Если же вы сделали пакет для себя, то это уже другой вопрос. Как говорится, хозяин - барин. Но тогда не удивляйтесь фидбеку :)
И еще 150+ человек, у которых ушел BoilerPlate регистраций,
Во-первых, не ушёл. Посмею предположить, что самой частой ситуацией у разработчиков является зарегистрировать некий Service как реализацию некого IInterface. В случае Microsoft DI мне нужно написать одну строку (пусть будет синглтон):
services.AddSingleton<IInterface, Service>();
В случае RegisterByAttributes, как ни крути, вам тоже придётся эту одну строку где-то написать, ну только выглядеть она будет атрибутом. Ну и где выигрыш?
Если у вас вдруг на один интерфейс есть 4 разных сервиса - да, окей, вы выиграли и сэкономили 3 строки. Стоило ли оно того? Моё мнение - нет, потому что есть такой принцип наименьшего удивления, которому почему-то редко учат в умных книжках про принципы программирования. Суть в том, что про Microsoft DI - что это такое, как он выглядит и как им пользоваться - знает любой опытный разработчик на .NET, вы простейший web проект не сможете сделать, не наткнувшись на него. Я могу скинуть свой проект коллеге, а он уже заранее будет знать, как в него добавлять новые сервисы. А что такое RegistrationByAttributes? Какая существует веская причина, чтобы заставлять вашего пользователя разбираться в новом пакете, реализующим такую фундаментальную вещь как регистрация сервисов?
Во-вторых, лично я с возрастом начал ценить простоту. Я выберу 200 строк скучного, повторяющегося, но понятного как пять копеек кода, нежели магический чёрный ящик на 20 строк.
Все популярные либы уже поддерживают добавление конфигураций\реализаций и контроллеров БЕЗ ЛИШНИХ ДЕЙСТВИЙ. (AutoMapper, MVC, etc.)
Ну есть Scrutor на худой конец, если очень хочется автомагических регистраций.
Ну и к коду есть вопросы.
case LifetimeManagementType.Singletone:
container.AddSingleton(baseType);
Неужели ничего не щёлкает от Singletone, когда буквально на соседней строчке находится корректный вариант?
case LifetimeManagementType.PerThread:
container.AddScoped(baseType);
PerThread != Scoped, это разные вещи. К слову, это дополнительный довод почему пытаться натянуть один пакет на разные библиотеки DI, - не очень хорошо.
Про написание (в C# все методы пишутся в PascalCase, даже приватные) и в целом неопрятность кода уже упоминали.
в java в finaly можно получить исходное искоючение и что-то сделать (не перехватить но обработать).
А можно пример этого чуда?
В C# не так. Чтобы получить исключение, нужно его перехватить. Перехватывать исключения, не перехватывая их (без catch), нельзя.
я не понимаю как try finaly решает проблему "нужно вывести ошибку в том ui компоненте, откуда пользователь кнопку нажал, а catch у нас где угодно но не там"
Это try-catch:
private void button1_Click(object sender, EventArgs e)
{
try {
throw new InvalidOperationException("The answer to the ultimate question was not 42");
}
catch (Exception ex) {
// Вывести ошибку в том ui компоненте, откуда пользователь кнопку нажал
button1.Text = $"The exception was: {ex.Message}";
// Пробрасываем выше по стеку в "где угодно"
throw;
}
}
У таких конструкций и паттернов есть фатальный недостаток,
Сильно зависит от языка. Например, в Rust есть discriminated unions, #[must_use] и try operator. Вместе они делают работу с results удобной и одновременно убирают заботливо разложенные грабли (например, случайно проигнорировать ошибку нельзя). Win-win.
В C# ничего этого нет, вот и выходит, что работать с исключениями гораздо проще. Но в целом, это не вина паттерна.
Как идея - можно попробовать добавить honeypot в виде какой-нибудь скрытой ссылки, которую живой человек не увидит, а бот попытается соскрапить.
Чтобы говорить, что суп пересолен, шеф-поваром быть не нужно.
Вот я тоже в первую очередь подумал про первую циву. То ли мы с вами динозавры, то ли автор слишком молод ;)
Вот прямо на любом? И на Air?
Порошок не входи
Вам нужен netstandard2.0.
Я объяснил зачем.
Либо ваш пакет полезен, либо нет, какая разница, сколько строк?
А вообще, честно говоря, проще Unity выкинуть, тогда и вопроса, делить на отдельные пакеты или нет, не будет.
Не вызывает ни в жирном монолите на несколько сотен проектов, ни в нескольких сотнях микросервисов, и это мы ещё не очень большая компания. Где-то используется Microsoft DI, где-то Autofac, в котором вы тоже регистрируете сервисы вручную, просто с другим синтаксисом. И нет никакой проблемы с конфликтами.
Ладно, я искренне попытаюсь.
При этом не понимаете, что писать в
<TargetFramework>
. Поменяв net7.0 на netcoreapp2.0, вы сделали хуже, потому что если у .NET 7 поддержка закончилась в мае 2024, у .NET Core 2.0 - в октябре 2018.При этом не настроили
.gitignore
, чтобы не тащить в репозиторий мусор.Вам бы основам сначала уделить внимание, а потом уже хвастаться Metadata-Driven фреймворками. И нет, у меня нет цели вам нахамить или обидеть.
Если вы хотите, чтобы ваш пакет был полезен другим людям и им пользовались, то как проще вам - не так важно, как проще вашим потенциальным пользователям. А пользователям проще не нести в проект мусор. Даже если 20 кб.
Да, нужно разбивать на несколько пакетов. Unity отдельно, Microsoft DI отдельно. Нет, разбираться в 3+ пакетах никому не придётся. Кому нужен RegistrationByAttributes для Microsoft DI, те по-прежнему поставят один пакет.
Если же вы сделали пакет для себя, то это уже другой вопрос. Как говорится, хозяин - барин. Но тогда не удивляйтесь фидбеку :)
Во-первых, не ушёл. Посмею предположить, что самой частой ситуацией у разработчиков является зарегистрировать некий
Service
как реализацию некогоIInterface
. В случае Microsoft DI мне нужно написать одну строку (пусть будет синглтон):В случае RegisterByAttributes, как ни крути, вам тоже придётся эту одну строку где-то написать, ну только выглядеть она будет атрибутом. Ну и где выигрыш?
Если у вас вдруг на один интерфейс есть 4 разных сервиса - да, окей, вы выиграли и сэкономили 3 строки. Стоило ли оно того? Моё мнение - нет, потому что есть такой принцип наименьшего удивления, которому почему-то редко учат в умных книжках про принципы программирования. Суть в том, что про Microsoft DI - что это такое, как он выглядит и как им пользоваться - знает любой опытный разработчик на .NET, вы простейший web проект не сможете сделать, не наткнувшись на него. Я могу скинуть свой проект коллеге, а он уже заранее будет знать, как в него добавлять новые сервисы. А что такое RegistrationByAttributes? Какая существует веская причина, чтобы заставлять вашего пользователя разбираться в новом пакете, реализующим такую фундаментальную вещь как регистрация сервисов?
Во-вторых, лично я с возрастом начал ценить простоту. Я выберу 200 строк скучного, повторяющегося, но понятного как пять копеек кода, нежели магический чёрный ящик на 20 строк.
Ну есть Scrutor на худой конец, если очень хочется автомагических регистраций.
Ну и к коду есть вопросы.
Неужели ничего не щёлкает от
Singletone
, когда буквально на соседней строчке находится корректный вариант?PerThread != Scoped, это разные вещи. К слову, это дополнительный довод почему пытаться натянуть один пакет на разные библиотеки DI, - не очень хорошо.
Про написание (в C# все методы пишутся в PascalCase, даже приватные) и в целом неопрятность кода уже упоминали.
А если все полки уже заняты другими крупногабаритными украшениями для фанатов?
И тумбочки тоже.
А ещё в роутере за 1000 руб. не будет блока Security.
Многие современные ядра Intel идут без SMT.
Если эти ваши соседские мальчишки способны получить доступ к сети zigbee, я бы дал им помигать лампочками уже просто из чувства восхищения.
"У вас нет ни малейшего ё%^5го понятия" это переводится :)
Так они у вас никуда не делись, только теперь размазаны по всему солюшену.
А можно пример этого чуда?
В C# не так. Чтобы получить исключение, нужно его перехватить. Перехватывать исключения, не перехватывая их (без
catch
), нельзя.Это try-catch:
К сожалению, это не так. NRT - это рекомендация, компилятор помогает как может, но гарантировать не null не может.
Делать так конечно не надо. Но технически возможность есть.
Сильно зависит от языка. Например, в Rust есть discriminated unions, #[must_use] и try operator. Вместе они делают работу с results удобной и одновременно убирают заботливо разложенные грабли (например, случайно проигнорировать ошибку нельзя). Win-win.
В C# ничего этого нет, вот и выходит, что работать с исключениями гораздо проще. Но в целом, это не вина паттерна.
Ну вот потребность выхода из вложенных циклов - повседневная жизнь.
try-finally не ловит и не обрабатывает исключения (в нём нет блока catch).
А в чём принципиальная разница?
Имхо, это сносно работает только для несложных игрушечных примеров. При первых же сложностях вроде
async
/await
читаемость сильно падает.