Статика в С#

Добрий день еврібаді!

Люди добрі допоможіть розібратися в темі.

Вивчаю самостійно С# і багато разів чув, від різних авторів відео по шарпу в ютубі, шо статика це погано ,а деколи навіть зло , і краще не юзати. Але аргументації чіткої і зрозумілої не було , а статичні методи і класи я зустрічаю часто і в голові дисонанс тепер.

Буду дуже вдячний за лінк на джерело істини в цьому питанні.

Бережіть себе!

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Статика это плохо, когда есть риски, связанные с многопоточным доступом либо с утечкой памяти. Extension-методы/хелперы вполне норм.
t.me/ TvpQn1N6oPV256S8
залетай в наше комьюнити, спрашивай если что

Погано саме статичні змінні:
1) вони створюються при запуску программи, що робить запуск довше + займають память навіть якщо ніколи не використовуються
2) вони не thread-safe, якщо спеціально не зроблено інакше
3) важко відслідкувати хто може їх змінювати
тобто більш-менш беспечно використовувати readonly static змінні, інакше це буде ад з якимось періодичними багами із-за concurrency які дуже важко відслідити і протестити.

Статичні методи на мій погляд як раз хороший паттерн, якщо звичайно вони мають сенс для класса якому належать. Альтернатива зазвичай — це такі кілометрові статичні класси Helper з сотнями статичних методів на всі випадки життя, що не є гуд.

Тепер модно Dependency injection, і статичні класи заміняються на singleton. Це краще тому що є менша прив’язка до реалізації, ти можеш сінглтон по інтерфейсу зареєструвати. І не треба менеджити його залежності.

Ну і Артем про глобал варіаблс написав. Я навіть і не залумовувався про них, бо для мене статичний клас за визначенням не має мати стану, чисто хелпер функції.

«а статичні методи і класи я зустрічаю часто і в голові дисонанс тепер.»

Хм, приватні чи публічні? Приватні ок, як хелпери до основного класу. І це чисто по оптимізації краще не дублювати ці члени класу при кожному створенню обєкта, якщо вони не звертаються до стану обєкта.

Статичні класи також використовують для extension methods, або для якихось там конвертеров чи маніпуляторов

Тільки екстеншн методс не замокаєш.

Во-первых, не все в мире нужно мокать.

Во-вторых, оратор ниже уже все рассказал — мокаешь поинтером и вперед.

А навіщо їх мокати, коли їх чудово можна тестувати окремими юніт тестами?

Для контролю того що вони повертають, щоб затестити більше кейсів робочого методу.

Щось у вас занадто складні extension methods :)

Та я нуб. Не так багато тестів переписав, просто зустрілася така проблема.

Так і сам сінглтон, методологи вже давно обісрали, тепер це антіпаттерн.

Також: класс, зареєстрований як singleton не буде антипатерном, якщо його призначення — лише обробка даних або виконування якихось запитів до API, та він не зберігає у собі ніякий state. Просто такий собі worker — отримав дані, обробив, передав далі.

Я тільки так їх і юзаю. Це ж піпець зберігати стейт в об’єкті який не оновлюється хоча б при кожному реквесті.

Ну я мав на увазі клас Math і йому подібні.
І на рахунок dependency injection зустрічав відео про «service locator» . Де прогер інжектив залежності через статичні властивості через гет.

static ExampleClass createExampleClass{ get => new ExapleClass();}

«Ну я мав на увазі клас Math і йому подібні.»

Це ліба мови. Воно було написано дуже давно, коли були інші стандарти. Ну і інджектити кожну стандартну лібу в конструкторі створювало б багато шуму через який би губилися власні депенденсі.

«І на рахунок dependency injection зустрічав відео про „service locator“ . Де прогер інжектив залежності через статичні властивості через гет.»

Сервіс локейтор це антипатерн. Старайтесь використовувати лише від безвиходності.

static ExampleClass createExampleClass{ get => new ExapleClass();}

Це гівнокод.

А можна пояснити в чому гівнокодість? Тому шо все одно залежність від класу? Вибачте шо задовбую)

Тому що сервісні класи мають реєструватися в Inversion of control контейнері, тобто фреймворку який реалізує Dependency injection можливості. Це може бути стандартний нет корівський вбудований в фреймворк, або сторонній.

В даному ж випадку робиться велосипед, при чому без такого контейнера, без life cycle management і без можливості зареєструвати сервісний клас через інтерфейс для кращої відвязаності реалізації. Також пряме використання сервіс локейтору як я вже писав є поганою практикою, бо залежності в сервісному класі куди інджектиться сервіс локейтор стають неявними, їх не видно в конструкторі сервісного класу. Це також робить автоматичне тестування такого класу дуже важким, бо потрібно будувати і передавати цілий сервіс локейтор замість того щоб передати моки або стаби конкретних залежностей. І знову ж таки в наведеному коді навіть не повноцінний сервіс локатор а примітивне велосипедщина яка утримує в собі лише єдиний обєкт. То прийдеться тепер кожній залежності робити сервіс локейтор типу.

П.С. Якщо ви робите у своєму коді отак: new ClassName();, і це не клас моделька для передачі даних, то ви робите погано. Використовуйте IoC контейнер.

Дякую за відповідь . Короче треба менше ютуба дивитись)

Просто не сприймайте кожного професійного програміста за еталон якості. Він в чомусь може бути правий, а в чомусь такий гівнокод генерувати, що джун після прочитання теорії краще напише.

В софтвер розробці купа гівнокодерів.

Я стараюсь все піддавати сумніву але тяжкувато фільтрувати будучи не компетентним . В 2010 коли я вивчав звукорежисуру і саунд дизайн , була проблема того шо інфи не дістанеш бо її нема. І я просто роками набивав шишки . А зараз інфи просто океан і здавалось бери да вчи ,але сміття як я розумію багато. Короче судячи з усього свої шишки знову навчать краще всього 🤣 просто була надія з економити час.

Я цей сайт почитую, тут є приклад статичного методу що створює об´єкт:

deviq.com/principles/encapsulation

 public class Volume
{
  private Volume(double amount, string unitOfMeasure)
  {
    if(amount < 0) throw new ArgumentOutOfRangeException("Volume amount must be non-negative.");
    Amount = amount;
    UnitOfMeasure = unitOfMeasure;
  }
  public static Volume InLiters(double amount)
  {
    return new Volume(amount, "Liters");
  }
  // include other static factory methods here for other units
  public double Amount { get; private set; }
  public string UnitOfMeasure { get; private set; }
  // perhaps include methods here to convert from one unit to another
}

Це стиль як у ліб нетівських, до прикладу TimeSpan.FromSeconds і інші методи. В такому випадку схоже статік норм. Ну але це і клас моделька а не сервіс.

А який сенс в цьому методі якщо можна перегрузити конструктор? Дефолтний робить в літрах , інший би сетив параметр unit of measure?

Хороше питання. При цьому з твоїм варіантом нам би не довелось робити статік метод.

Я б правда не робив дефолтний в літрах а вимагав явно задати юніт через енюм в конструкторі.

Як уже говорили в статичних класах немає нічого страшного. Проблема в статичному стейті. Math — це просто місце куди поклали кучу «чистих» методів. З ними немає ніяких проблем оскільки вони не мають стейту. Просто приймають щось на вхід, думають над цим і повертають результат. Не зачіпаючи нічого іншого взагалі.

Только держим в уме, что Singleton патерн, пожалуй самый распространенный в приложениях, «это другое» ©

Singleton патерн, пожалуй самый распространенный в приложениях

У тебя опечатка в слове «антипаттерн»

Надеюсь в твоем любимом расте, киллера всего "тяжелого наследия С++"© и статику и синглтоны можно добавить теперь _только_ с супер специальными операторами, что окаянный ведает что творит ?

по ряду причин static mut использовать настоятельно не рекомендуется

www.reddit.com/...​is_static_mut_bad_to_use

И как

Singleton

корреклирует с твоим утверждением

«антипаттерн»

если тебе нужно всеголишь заинжектить какую-то фабрику, которую видят все (например провайдер доступа к субд)

и это не

static mut

?

ЯННП. Переформулируй вопрос, чтоб было понятно что ты пытаешься спросить.

Вопрос простой. Почему ты считаешь

Singleton

антипаттерном, если его имплементация на уровне одного из трех типов инжекта встречается у всех видов DI контейнеров (AddTransient, AddScoped, AddSingleton) во всех языках ?

Можно считать сигатеры и алкоголь отравой, если они продаются в каждом магазине?

Можно ли считать ЗОЖ разработчика, кто собрался пересоздавать постоянно какой-то инстанц фабрики напр. (AddTransient, AddScoped), где хватит всего одной копии инстанца (AddSingleton) ?

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

Я щось туплю. В чому проблема мокати сінглтон якщо він по інтерфейсу реалізований?

У мене нема проблеми мокати — перезавантажуєш його поінтером на мок і робиш тести

:D
Якщо у тебе нема зірочки перед варіаблєй — то у тебе нема лише зірочки, а поінтер може усе одно бути під капотом

Можливо, як «зло» мали на увазі статичні змінні? Які дійсно, можуть бути злом в деяких випадках.
Бо статичні методи та класи взагалі, за їх доречного використання, є корисна реч.
docs.microsoft.com/...​-and-static-class-members

деяких

Якщо це не рідонлі, я навіть не уявляю в яких випадках вони можуть бути «добром». Нерідонлі статичні змінні, як і глобальні мають використовуватись лише у виключних випадках.

Підписатись на коментарі