Pull to refresh

Comments 20

В контексте статьи было бы интересно собрать статистику по языкам программирования и вирт машинам :)
> Тем не менее, в то время как этот подход выглядит как некоторое хакерство, он все же лучше чем альтернатива — код, полный ошибок

Разве не работают другие, вроде бы менее замороченные альтернативы?

1) Не создавать циклических зависимостей:
Можно выносить общий функционал в отдельный тип. В данном случае очевидно, что Gamma можно вынести в новый тип Third. Об этом же так много писали. Параллели с математикой помогут понять, что это можно всегда сделать — любая теория строится на наборе аксиом, из которых все последовательно вытекает без циклических зависимостей.

1) вместо статической инициализации использовать Dependency Injection, например, IoC-контейнеры
Так в общем-то он об обоих случаях избавления от этой проблемы и написал.
Да, точно. Я остановился, когда увидел, что для «юнит-тестов» идет работа с AppDomain и прочим. Тогда это можно оформить в виде автономной программы или плагина для подключения к общему комплексу проверок кода.

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

А использование IoC-контейнеров также решит эту проблему автоматически — циклические зависимости нельзя будет задать в схеме зависимостей.
Я рассматриваю циклические зависимости как Code Smell. Сигнал, что пора подумать об изменении дизайна.
-> В прошлом, я «исправлял» порядок инициализации типов просто перемещая по коду поля.
Вопрос такой:
А как расположение полей влияет на порядок инициализации? Они в обратном порядке инициализируются или в прямом? По тексту «как происходит на самом деле» получается, что в обратном.

А если инициализировать эти поля не при объявлении, а в конструкторе? Вроде как сам задаешь порядок действий, так же как и при написании любых других функций сам отвественнен за избежание зацикливаний.
Будет так работать? То есть, я скомпилировал, выдает 5 вместо нуля, но вообще теоретически, так правильно?

class First
{
public static readonly int Alpha;
public static readonly int Beta = Second.Gamma;
static First()
{
Alpha = 5;
Beta = Second.Gamma;
}
}

class Second
{
public static readonly int Gamma;
static Second()
{
Gamma = First.Alpha;
}
}

ЗЫ где то читал, что инициализироваться в конструкторе вообще кошернее и феншуйнее, чем при объявлении полей.
Что то теги не работают…
Порядок инициализации типов определяется порядком их запроса программой. А порядок полей — порядком их описания в тексте программы. Соответственно, меняя местами строчки можно получить баг (либо, соответственно, его исправить).Статический онструктором, да, можно скорректировать порядок вызовов на правильный
А, понял, такое написание работает только если к First обратиться к первому, лучше чем было, но не фикс. То бишь тут либо код усложнять, либо…
А как обстоит дело с partial–типами?
Тут мне кажется, что порядок их описания будет уже случайным (в смысле зависить от чего-то ещё).
Кстати, да. Потому, все таки, наверное, лучше либо вообще отказаться от взаимного использования стат полей разных классов, либо переходить на свойства
имхо, завязывать логику на статических классах в принципе плохо. из-за них код становиться сильно связанным.
не представляю как создавать моки для юнит-тестов для статических классов.
Есть фреймворки, позволяющие делать моки на статические классы. Например, TypeMock Isolator или Moles.
Но они провоцируют плохой дизайн, потому их надо использовать осторожно.
Китайский коммунизм. Сначала создаем проблемы, а затем героически их решаем.

Когда вы описываете статическую конструкцию вы отказываетесь от контроля времени жизни. Как только у вас возникает в нем необходимость надо убирать слово статик — проблема исчезнет сама.

По поводу оптимизации: глобальная видимость и оптимизация, немного разные вещи. Можно запросто использовать единственный экземпляр объекта и не обращаться к его глобальному носителю где не попадя (статическому полю класса). ИМХО, статических полей инициализируемых статическими полями быть не должно — это абсолютно бессмысленно.

Тестирование в отдельном домене, то что не работает в отдельном домене тоже сомнительно. Уберите статики и проблема исчезнет.
В статье не сказано что надо использовать статики, в статье описано что существует проблема. И если она встретилась, то как ее решать. Например, в Джаве такое поведение отсутствует. В CLR есть
Но в ней и не сказано, что это проблема решается путем отказа от статиков.

Еще раз — это проблема времени жизни объекта (или метаобъекта, если хотите) и решается она явным его определением. Все остальное — это нейтрализация тонких особенностей с помощью других тонких тонких особенностей функционирования CLR.

Не жалко себя, подумайте обо мне. Прихожу я завтра в вашу организацию и получаю код, который работает только потому, что статическое поле «abc» находится в классе «def». Если перенести его в «ghi» все разваливается. Как вы думаете, долго будет спасать вас дверь туалетной кабинки?
Статья о том, как вместо того чтоб выйти из жопы, обустроиться там поудобнее…
По мне так это типичный пример плохой архитектуры.
Если у вас такое случилось, то надо сесть и подумать над сутью своих классов, возможно у них есть что-то общее.

Вот если бы компьютеры были бы аналоговыми — и вычисления производились «решением дифферециальных уравнений», то такие связи были бы уместны…
Хочу отметить, что статические поля, копирующие свои значения из статических полей используемых библиотек, можно писать спокойно, так как подобная зависимость никогда не станет циклической.

Это да. Просто библиотека автора весьма специфична и своими решениями обязана в первую очередь желанием сделать ее максимально быстрой. Люди много критикуют рискованные подходы, однако на мой взгляд при принятии решений важно продумать, какая архитектура будет наиболее подходящей под данные задачи. Например, то что все сейчас так любят — IoC, DI, фабрики, в этой библиотеке будут абсолютно лишними, т.к. понизят производительность… Циклические зависимости не так и плохи, если они оправданы. По аналогии — презрение к опратору goto. Этот оператор усложняет жизнь программисту тем что он создает сложный для восприятия код, и при не аккуратном использовании может случайно создать ошибки. Однако это зачастую единственный способ сделать какой-то алгоритм простым. В общем ответил немного не по теме… ))
Sign up to leave a comment.