Pull to refresh
4
0
Валерий Реуцкий @benjik

User

Send message

Ну до появления этих постов с телегой в конце я пропускал 50-100 статей в день, чтоб прочесть 1-2. Теперь пропускаю 51-101, делов-то.

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

В этих микрообзорах линукс-ноутов нехватает информации о работе от батареи. Мой xps 9570 после покупки работал от батареи 6-8 часов на свежеустановленной винде, и 2-4 на убунте без твиков. Собственно, линукс ставится почти на любой современный ноут, а вот как он батарейкой пользуется - обычно большой сюрприз.

Крутая штука!

Жаль, что репозиторий уже больше года не обновляется ?

Это у вас прошлогодняя статья из черновиков, с вкраплениями свежего макбука?

Почти все модели с intel-процами уже есть с 13 поколением.

  1. Не "я не понимаю проблему", а вы её не можете правильно сформулировать. Я прошу MyServiceProvider создать мне класс Client1, как-то самостоятельно выбрать для него реализацию IFoo и подставить её в конструктор клиенту, с чем он прекрасно справляется. Так же точно, в конструктор контроллера подставится ровно то, что я укажу в GetService. А настройки для GetService я могу прочитать хоть из .txt, хоть из БД, хоть из ChatGPT.

  2. Вы хотите странного, и хотите этого от Microsoft. Они уже сделали достаточно абстракций и точек расширения: не устраивает родной DI - используйте ninject/autofac/lightinject/etc или пишите свой.

Нет такого условия в задаче (во всяком случае, на момент написания комментария).

Если не хочется менять классы-клиенты, то можно реализовать собственный IServiceProvider.GetService(Type serviceType), который всё это делает, и подменить им нативный:

вот так
void Main()
{
    var builder = Host.CreateDefaultBuilder();
    builder.UseServiceProviderFactory(new MyServiceProviderFactory());
    builder.ConfigureServices(services =>
    {
        services.AddTransient<IFoo, DefaultFoo>();
        services.AddTransient<Foo1>();
        services.AddTransient<Foo2>();
        services.AddTransient<Client1>();
        services.AddTransient<Client2>();
    });

    var provider = builder.Build().Services;

    var client1 = provider.GetRequiredService<Client1>();
    var client2 = provider.GetRequiredService<Client2>();
    IFoo defaultFoo = provider.GetRequiredService<IFoo>();
    defaultFoo.Bar();
}

public class MyServiceProvider : IServiceProvider
{
    private readonly ServiceProvider _nativeServiceProvider;
    public MyServiceProvider(ServiceProvider sp)
    {
        _nativeServiceProvider = sp;
    }

    public object GetService(Type serviceType)
    {
        return serviceType switch
        {
            Type _ when serviceType == typeof(Client1) =>
                ActivatorUtilities.CreateInstance(_nativeServiceProvider, serviceType, _nativeServiceProvider.GetRequiredService<Foo1>()),
            Type _ when serviceType == typeof(Client2) =>
                ActivatorUtilities.CreateInstance(_nativeServiceProvider, serviceType, _nativeServiceProvider.GetRequiredService<Foo2>()),
            _ => _nativeServiceProvider.GetRequiredService(serviceType)
        };
    }
}

public class MyContainerBuilder
{
    public IServiceCollection Services { get; set; }
    public IServiceProvider ServiceProvider => new MyServiceProvider(Services.BuildServiceProvider());
}

public class MyServiceProviderFactory : IServiceProviderFactory<MyContainerBuilder>
{
    public MyContainerBuilder CreateBuilder(IServiceCollection services)
    {
        return new MyContainerBuilder { Services = services };
    }

    public IServiceProvider CreateServiceProvider(MyContainerBuilder containerBuilder)
    {
        return containerBuilder.ServiceProvider;
    }
}

public interface IFoo
{
    void Bar();
}

public class DefaultFoo : IFoo
{
    public void Bar() => Console.WriteLine(nameof(DefaultFoo));
}

public class Foo1 : IFoo
{
    public void Bar() => Console.WriteLine(nameof(Foo1));
}

public class Foo2 : IFoo
{
    public void Bar() => Console.WriteLine(nameof(Foo2));
}

public class Client1
{
    public Client1(IFoo foo)
    {
        Console.WriteLine(nameof(Client1));
        foo.Bar();
    }
}

public class Client2
{
    public Client2(IFoo foo)
    {
        Console.WriteLine(nameof(Client2));
        foo.Bar();
    }
}

Client1
Foo1
Client2
Foo2
DefaultFoo

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

Например так:

void Main()
{
    var services = new ServiceCollection();
    services.AddTransient<DefaultFoo>();
    services.AddTransient<Foo1>();
    services.AddTransient<Foo2>();
    services.AddSingleton<FooFactory>();
    services.AddTransient<Client1>();
    services.AddTransient<Client2>();
    var provider = services.BuildServiceProvider();
    
    var client1 = provider.GetRequiredService<Client1>();
    var client2 = provider.GetRequiredService<Client2>();
    IFoo defaultFoo = provider.GetRequiredService<FooFactory>().GetFoo(null);
    defaultFoo.Bar();
}

public interface IFoo
{
    void Bar();
}

public class DefaultFoo : IFoo
{
    public void Bar() => Console.WriteLine(nameof(DefaultFoo));
}

public class Foo1 : IFoo
{
    public void Bar() => Console.WriteLine(nameof(Foo1));
}

public class Foo2 : IFoo
{
    public void Bar() => Console.WriteLine(nameof(Foo2));
}

public class FooFactory
{
    private readonly IServiceProvider _sp;
    public FooFactory(IServiceProvider sp) => _sp = sp;
    public IFoo GetFoo(object client)
    {
        return client switch
        {
            Client1 => _sp.GetRequiredService<Foo1>(),
            Client2 => _sp.GetRequiredService<Foo2>(),
            _ => _sp.GetRequiredService<DefaultFoo>()
        };
    }
}

public class Client1
{
    public Client1(FooFactory fooFactory)
    {
        Console.WriteLine(nameof(Client1));
        IFoo foo = fooFactory.GetFoo(this);
        foo.Bar();
    }
}

public class Client2
{
    public Client2(FooFactory fooFactory)
    {
        Console.WriteLine(nameof(Client2));
        IFoo foo = fooFactory.GetFoo(this);
        foo.Bar();
    }
}
Client1
Foo1
Client2
Foo2
DefaultFoo

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

Про то, что проходить собеседования - это отдельный скилл, отличный от решения реальных задач на работе, и его надо "качать", написано много. Теперь, вот так сюрприз, оказывается, что проводить собеседования - это тоже отдельный скилл, и его тоже надо "качать". Только вот у проходящих собеседование есть хорошая такая мотивация (кушац-то хочется) и скилл качать, и над обратной связью порефлексировать, а у проводящих эта мотивация не очень хорошая (особенно если на собес дёрнули погрязшего в срочно-важных тасках обычного разраба) и цикл обратной связи подлиннее (1-3 мес нанять, 1-3 мес понять что "тянет"/"не тянет"). Вот и имеем что имеем. Как только тимлиду/руководителю разработки припечёт - наймут первого подходящего.

$ winget install -e --id Docker.DockerDesktop
$ docker run --name mysql \
   -p 3306:3306 \
   -e MYSQL_ROOT_PASSWORD=<secret-password> \
   --restart unless-stopped \
   -d mysql:8
  1. ...

  2. PROFIT!

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

Вот инструмент, который решает твою задачу достаточно хорошо. Зачем тратить время на А и Б, когда задача уже решена, и скорее всего был опыт с В и Г в прошлом, отмели Д и Е по каким-то причинам, а Ж была на проекте раньше, и с неё долго и мучительно съезжали?
У архитекторов (не 23-летних) обычно и без этого хватает работы.
Про стеснение вообще не понял - зачем стесняться того, что ты чего-то не знаешь или не смотрел?

Альтернативное название статьи: "За что бить по рукам на Code Review"

Пять лет учишь матан, линал, тервер, матстат, алгоритмы, машоб, распределёнщину, функциональщину.
Два года настраиваешь шрифты в 1С,меняешь картриджи в принтере и предлагаешь выключить и включить.

Адекватные (и объективные) процессы оценки:

  • Мониторить стоимость найма сотрудника (или сотрудников) с аналогичным скиллсетом в данную конкретную контору в данный конкретный проект (а не в среднем по рынку) и стоимость его онбординга. Да, надо собесить людей. Да, первые 1-3-6 месяцев (иногда и больше) он может не приносить особой пользы. Очень дорого, но относительно надёжно и предсказуемо.

  • Смотреть, с каким оффером от условных конкурентов приходит увольняться/просить повышения ваш сотрудник. Дёшево, но внезапно и ненадёжно.

Адекватный процесс мотивации (только денежной):

  • Платить что-то между цифрами из первого и второго процессов оценки.

Т.е. если термины "незаменимость" (или "заменимость") поменять на термин "стоимость замены" - всё становится гораздо проще и для компании, и для сотрудника.

Естественно, всё это работает, если обстановка в компании относительно адекватная. Токсичность, бардак, микро/чайка-менеджмент, задержки ЗП и прочее веселье - и сотрудники будут уходить "в никуда".

На прошлой работе в моей и в соседней командах делали UI для админок продакшн-систем на Blazor+Telerik. В .net 5.0 им уже вполне можно было пользоваться, сейчас (.net 7.0) стало еще лучше.
Выбирали не потому что wasm, а чтобы относительно простой UI мог сделать дотнетчик без привлечения реакто-фронтов.

Какие-то уроки после этого веселья извлекли?
На net 7.0 переезжать будете, или "оно и так работает"?

@Firensis а у вас есть какой-нибудь публичный issue tracker, куда можно слать баг-репорты на PVS-Studio и трекать прогресс их решения? Я не нашел такого, по-этому тут отпишу.

Вот пример, где получаю пару корректных срабатываний, и пару false positive.
Для DTO из классической опердени с кучей полей очень сложно понять, есть там ошибка на самом деле, или нет.

V3005 The 'Text' variable is assigned to itself. Program.cs(20) 
V3005 The 'Number' variable is assigned to itself. Program.cs(21) 
V3005 The 'Text' variable is assigned to itself. Program.cs(25) 
V3005 The 'Number' variable is assigned to itself. Program.cs(26)

Код:

public class Program
{
    public static void Main()
    {
        var obj = new Example
        {
            Number = 1,
            Text = "One"
        };
        _ = obj.CorrectClone();
        obj.IncorrectUpdate();
    }
}
public class Example
{
    public string Text { get; set; } = null!;
    public int Number { get; set; }
    public Example CorrectClone() => new()
    {
        Text = Text,
        Number = Number
    };
    public void IncorrectUpdate()
    {
        Text = Text;
        Number = Number;
    }
}

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity