Кажется что ваш интерфейс IModule нарушает ваше же требование ортогональности
Интерфейс — не нарушает.
Ортогональность соблюдена — и внутри, и снаружи модуля может быть что угодно, в отличие от требований фреймворков.
От COM взяли только базовые интерфейсы с GUID и счетчиками ссылок: Delphi в них умеет из коробки.
Реестр и прочее ActiveX барахло не использовалось.
Технологии тут как раз нерелевантны из-за пункта 5.
Изначально делалось на Delhi 2007
Контрактами были COM-интерфейсы (только из-за наличия у них GUID)
Модуль — объект, реализующий интерфейс IModule: GUID модуля, имя модуля, список реализованных интерфейсов, список интерфейсов-зависимостей, методы для инициализации и финализации.
Из набора модулей автоматически строился граф зависимостей.
Из графа автоматически генерировалась диаграмма компонентов на языке PlantUML.
Порядок инициализации и наличие циклов определялось топологической сортировкой.
Композитный модуль строился на основе графа зависимостей подмодулей. Его зависимости — все интерфейсы, которые подмодули не реализовали сами, а реализованные контракты — подмножество таковых у внутренних модулей.
Автор оригинальной статьи демонстрирует главный антипаттерн разработки модульных приложений: представление сложности обеспечения модульности как сущностной (связанной со сложностью задачи) вместо акцидентной (связанной с существующими инструментами и практиками.
Все аргументы сводятся к одному: у нас говнокод и поэтому повторное использование "очень сложно".
У меня есть успешный опыт превращения спагетти-монолита в свободно расширяемый набор модулей за счет правильной методики и созданного в соответствии с ней велосипеда.
Принципы модульности:
Автономность — модули можно создавать, тестировать и эксплуатировать независимо от любого конкретного набора других модулей. Это сразу требует, чтобы все зависимости и вся реализованная функциональность модулей описывались явными контрактами на уровне кода.
Компонуемость — сборка приложения из набора модулей должна быть простой задачей, в идеале — решаемой автоматически.
Рекурсивность — из набора модулей должен легко собираться композитный модуль, неотличимый от обычных модулей снаружи.
Прозрачность — должна иметься возможность сгенерировать актуальную диаграмму компонентов для модулей в работающем приложении.
Ортогональность — инструмент для организации модульности должен быть библиотекой, а не фреймворком. Правки в коде для поддержки модульности должны быть минимально возможными.
В дотнете Fody тоже никого не смущает.
Но никто не делает вид, что вплетение кода заменяет имеющиеся языковые средства задаром.
А котлин мне очень нравится.
Но, возможно, сейчас и тут напишут про проблему с дженериками.
Такова жизнь. В JVM JIT и сборщик мусора лучше дотнетных. Но нет генериков и непримитивных типов-значений.
Искренне хочется расшифровки или пример «сильного страдания»
Практически все функции по ссылке явовские контейнеры не потянут без дополнительных костылей, так как параметры-типы у генериков Lazy, Func, Owned, IList и т.д. после компиляции даже не превратятся в тыкву, а просто исчезнут. На практике я использовал большую часть списка хотя бы однажды, а самые ходовые варианты (Func) — ежедневно
DI от явовских генериков страдает очень сильно.
Оптимизация аллокаций в куче — еще сильнее.
Первое — хлеб любых приложений от среднего размера.
Второе — очень больная тема в нагруженных приложениях..
Потому что инструменты с вплетением байт-кода есть и для дотнета: от Fody до PostSharp.
Для NotNull в дотнете хватает системы типов (благодаря тем самым, не имеющим отношения к вашей личной продуктивности, генерикам и структурам): я, например, просто могу писать NotNull<T> и это будет та же самая ссылка на класс без оверхеда, но с гарантией, что null там нет.
с неплохой ковариантностью-контрвариантностью из коробки
Согласно Джону Скиту, это единственное преимущество языка Java над C#.
в большинстве повседневных задачах он не мешает
Ну да, конечно. Если я в параметре конструктора укажу IEnumerable<TypeName>, то дотнетные контейнеры автоматически подставят мне все зарегистрированные реализации для TypeName.
В яве это не сработает по построению. Именно поэтому явовские контейнеры на фоне дотнетных смотрятся убого.
Если потребуется оптимизация по аллокации памяти в куче, в яве придется делать специальные алгоритмы с использованием только примитивных типов.
Getter/@Setter
В дотнете для этого костыли не нужны — все уже есть прямо в языке.
1. Ни мне, ни моим работодателям, использующим дотнет для разработки самого что ни на есть кровавого энтерпрайза, эта мысль почему-то в голову не приходила. Что мы делали не так?
2. Как будто что-то плохое: в яве очень много сделано в стиле «лебедь щуку раком», когда на каждый чих есть 100500 разных несовместимым между собой библиотек со своими уникальными недостатками.
GUI при этом никуда не делся и прекрасно работает.
Я пользуюсь и тем и другим — смотря что удобнее по ситуации.
Так что у дотнета преимущество в обоих случаях.
постоянно будет ощущение неполноценности разрабатываемого кода
Это не просто ощущения, а суровая реальность.
Контейнеры в яве такие страшные (с засилием аннотаций) как раз из-за генериков.
Нормальных коллекций для типов-значений нет тоже из-за генериков.
Даже если введут кастомные типы-значения толку от них будет мало опять-таки из-за генериков.
Все преимущества в производительности от шикарного оптимизирующего рантайма могут быть сведены на нет теми же генериками.
По ходу автор просто нашел себе нового идола для карго-культа.
Интерфейс — не нарушает.
Ортогональность соблюдена — и внутри, и снаружи модуля может быть что угодно, в отличие от требований фреймворков.
От COM взяли только базовые интерфейсы с GUID и счетчиками ссылок: Delphi в них умеет из коробки.
Реестр и прочее ActiveX барахло не использовалось.
Технологии тут как раз нерелевантны из-за пункта 5.
Сейчас в свободное от основной работы время занимаюсь библиотекой для дотнета: https://github.com/Kirill-Maurin/FluentHelium
Доклад по теме (прошлый февраль): https://www.youtube.com/watch?v=Gd9Ze7-CIb0&t=1005s
DI-контейнеры как есть для модульности пригодны только ограниченно: с прозрачностью и рекурсивностью у них никак.
Надо бы найти время и сделать-таки серию постов.
Автор оригинальной статьи демонстрирует главный антипаттерн разработки модульных приложений: представление сложности обеспечения модульности как сущностной (связанной со сложностью задачи) вместо акцидентной (связанной с существующими инструментами и практиками.
Все аргументы сводятся к одному: у нас говнокод и поэтому повторное использование "очень сложно".
У меня есть успешный опыт превращения спагетти-монолита в свободно расширяемый набор модулей за счет правильной методики и созданного в соответствии с ней велосипеда.
Принципы модульности:
Как не прижились?
Fody жив-здоров, чего и вам желает.
PostSharp на этом вообще деньги зарабатывает.
Ну и масса библиотек над Castle.DynamicProxy
В дотнете Fody тоже никого не смущает.
Но никто не делает вид, что вплетение кода заменяет имеющиеся языковые средства задаром.
А котлин мне очень нравится.
Такова жизнь. В JVM JIT и сборщик мусора лучше дотнетных. Но нет генериков и непримитивных типов-значений.
Практически все функции по ссылке явовские контейнеры не потянут без дополнительных костылей, так как параметры-типы у генериков Lazy, Func, Owned, IList и т.д. после компиляции даже не превратятся в тыкву, а просто исчезнут. На практике я использовал большую часть списка хотя бы однажды, а самые ходовые варианты (Func) — ежедневно
http://autofaccn.readthedocs.io/en/latest/resolve/relationships.html#supported-relationship-types
Один фреймворк для всего?
Спасибо, не надо.
Вдобавок у комментатора с опытом здесь же https://habrahabr.ru/post/352404/#comment_10732666
мнение про Spring слегка отличается от вашего.
Гоферы с тем же успехом ссылаются на прости господи кодогенерацию.
DI от явовских генериков страдает очень сильно.
Оптимизация аллокаций в куче — еще сильнее.
Первое — хлеб любых приложений от среднего размера.
Второе — очень больная тема в нагруженных приложениях..
Вы на редкость самокритичны.
Что характерно, вопросов, причем тут котлин, не возникало.
Потому что инструменты с вплетением байт-кода есть и для дотнета: от Fody до PostSharp.
Для NotNull в дотнете хватает системы типов (благодаря тем самым, не имеющим отношения к вашей личной продуктивности, генерикам и структурам): я, например, просто могу писать NotNull<T> и это будет та же самая ссылка на класс без оверхеда, но с гарантией, что null там нет.
Согласно Джону Скиту, это единственное преимущество языка Java над C#.
Ну да, конечно. Если я в параметре конструктора укажу IEnumerable<TypeName>, то дотнетные контейнеры автоматически подставят мне все зарегистрированные реализации для TypeName.
В яве это не сработает по построению. Именно поэтому явовские контейнеры на фоне дотнетных смотрятся убого.
Если потребуется оптимизация по аллокации памяти в куче, в яве придется делать специальные алгоритмы с использованием только примитивных типов.
В дотнете для этого костыли не нужны — все уже есть прямо в языке.
Именно что у дотнета.
2. Как будто что-то плохое: в яве очень много сделано в стиле «лебедь щуку раком», когда на каждый чих есть 100500 разных несовместимым между собой библиотек со своими уникальными недостатками.
Я пользуюсь и тем и другим — смотря что удобнее по ситуации.
Так что у дотнета преимущество в обоих случаях.
Это не просто ощущения, а суровая реальность.
Контейнеры в яве такие страшные (с засилием аннотаций) как раз из-за генериков.
Нормальных коллекций для типов-значений нет тоже из-за генериков.
Даже если введут кастомные типы-значения толку от них будет мало опять-таки из-за генериков.
Все преимущества в производительности от шикарного оптимизирующего рантайма могут быть сведены на нет теми же генериками.
По ходу автор просто нашел себе нового идола для карго-культа.
Это только до тех пор, пока не покупается решарпер.
У вас устаревшие сведения. cproj нового образца и маленькие, и простые.