Ответы пользователя по тегу Проектирование программного обеспечения
  • Как организовать принцип передачи данных между клиентом и сервером?

    Стоит разобраться с RESTful(REST-like) HTTP API как с подходом, который заходит в большем числе типовых задач, и разобраться с OpenAPI, и решатся все ваши проблемы про стандарт и про OSI. А уже потом, если вдруг увидете что RPC поверх какого-нибудь Protocol Buffers вам действительно нужнее - тогда и будете делать

    Вы сейчас находитесь в вакууме относительно используемых технологий клиент-серверного взаимодействия, вам нужно из этого вакуума выходить. Про ту же авторизацию/регистрацию уже столько всего наделано, и протоколов (вроде OpenID Connect) и фреймворков (вроде поддержки в ASP.NET всех типовых сценариев), что аж есть из чего выбрать.
    Ответ написан
  • Как организовать архитектуру взаимодействия микросервисов?

    Не нужно делать бложик на микросервисах, что для учебных целей, что для боевых.
    Всё что вы описали о бложике - комменты, юзеры, посты - это всё достаточно сильно связанные данные, и их нет смысла обрабатывать в разных сервисах. В том решении, что вы предложили всё будет отлично, если заменить "микросервис" на "контроллер" (который из MVC), будет классическое решение учебной задачи.

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

    Об аутентификации можно тоже говорить много и долго, обычно чтобы жить некоторое время без сервиса аутентификации её делают по токенам (JWT например). Тогда целевой сервис сам может проверить, авторизован человек или нет.

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

    Вот уже что-то будет интересное. Обратите внимание, что пожалуй все из этих трёх сервисов могут работать без основного, и наоборот - основной сервис может класть сообщения в очередь для других сервисов (1-го и 2-го), и сервисы будут разгребать эту очередь пока работают.
    Ответ написан
  • В чём причина постоянного переделывания кода?

    Заказчик хочет чтобы разработчик сделал сложное приложение.

    Причина 1: обычно заказчик хочет, но не знает чего конкретно. Фишка в том, что разработка приложения, у которого ещё нет аналога - это... не только разработка приложения. Это ещё и выяснение того, что действительно нужно, начиная с пожеланий по UX, и заканчивая оптимизацией бизнес-процессов во всей компании (это когда заказчик внезапно говорит "слушайте, и правда, на кой чёрт мы печатаем эту накладную каждый раз").

    КПД получается крайне низок.

    Причина 2: вы не учитываете причину 1 при расчёте КПД и думаете, что проделали мало работы. Да, приложение ещё не готово или делается очень долго, но это не потому что вы мало работаете, а потому что работы намного больше, чем казалось.

    но идёт на удаление или переделку из-за того, что что-то не так.

    Причина/особенность 3: иногда это неизбежно: бизнес меняется, потребности - тоже.
    Иногда этого можно избежать, не заводя требования слишком "далеко" - очевидно, нет смысла реализовывать то, что УЖЕ СЕЙЧАС кажется неподходящим под требования, НО это далеко не всегда вовремя замечают. Над проектом работает много людей, у всех немного разные представления о задаче, или ещё хуже: не все и далеко не всегда говорят о проблемах с системой, которые уже виднеются "на горизонте", говоря что "в ТЗ всё написано, а мы делаем по ТЗ". Можете погуглить статьи о стоимости ошибок на разных этапах разработки.

    Причина 4: заказчик, разработчики или и те и другие не умеют останавливаться и выбирать необходимый и достаточный функционал для первого или очередного релиза. Я в последнее время убеждаюсь, что это целая наука - вовремя остановиться и не расширять список "супернужных" фич, из которых треть окажется почти невостребованными. Особенно часто это бывает, когда бизнес уже работает как-нибудь (например, на экселевских табличках или Access-овских базах), а теперь пришла пора автоматизации, но релиз постоянно откладывается, потому что "и это хочется, и то бы сразу сделать". Иными словами, иногда нужно решиться на гарантированные переделки в будущем ради релиза сейчас. Оценка возможности и стоимости таких "переделок" - т.е. подождать и переделать сейчас или зарелизиться и переделать потом (соответственно, с удорожанием "переделок") - и есть та самая наука. Разработчик обычно видит только архитектуру, и раньше понимает её недостатки/ограничения, ему сложно решиться на релиз того, что не будет идеально решать поставленную задачу.
    Ответ написан
  • Как организовать хранилище пакетного менеджера?

    Я бы не взялся отвечать сколь либо конкретно на ваши вопросы, т.к. всё это очень сильно зависит от конкретных задач, которые будет решать ваш пакетный менеджер. Непонятно, системный ли это пакетный менеджер, вроде RPM или Windows Installer, или это пакетный менеджер для языка/экосистемы вроде NPM.

    Также непонятно и о каком хранилище вы говорите. Вероятно ваш пакетный менеджер будет клиент-серверным комплексом. Ваши вопросы касаются хранилища для сервисного компонента или способ хранения/установки пакетов на той машине, где они "потребляются" вас тоже интересует?

    Что для вас безопасность? Доступ к каким операциям и ресурсам в вашем программном комплексе вы хотите ограничить?

    Вам следует задать гораздо более узкий вопрос, а для этого сначала нужно продумать задачу самостоятельно. Если вы не знаете с чего начать - тогда либо ваши цели вам поставил другой человек, и нужно уточнить у него, либо, если эти цели вы сами себе поставили - вам надо понять, что вам хочется/нужно. Начните с изучения существующих решений, хотя бы чтобы понять, что "пакетный менеджер" - слишком шиорокое понятие, чтобы рекомендовать что-то конкретное.
    Ответ написан
  • Как лучше организовать структуру и связь между проектами?

    Nipheris
    @Nipheris Куратор тега C#
    Какая версия VS? Какой тип проекта? Есть возможность использовать новую проектную систему? Если да, то PackageReference и вперёд.

    Если нет - то через packages.config, как и всегда. Собирать нюгет-пакеты, если есть зависимости между солюшенами - правильная мысль. Нужны ли вам несколько солюшенов - сходу не скажешь, Payments выглядит адекватно как самостоятельный солюшен, Data - непонятно что это.
    Ответ написан
  • Как правильно создать архитектуру БД для нескольких сервисов?

    Если бы в тегах у вас не стоял MySQL, я бы сказал - "используйте схемы". В нормальных СУБД "база данных" - это единица администрирования, а "схема" - это пространство имён, т.е. как раз то, что вам нужно для различных сервисов и подсистем.

    Судя по тому, что вы описали, сервисов у вас несколько, но предметная область одна и та же, верно? т.е. эти сервисы всё-таки связаны, и возможно (даже вероятно) вам пригодятся связи между таблицами разных сервисов. И тут я бы тоже вам сказал "используйте схемы".

    В разных БД желательно хранить абсолютно несвязанные данные, такие, что можно взять одну из БД и спокойно перекинуть на другой сервер, или вообще на другую СУБД. Например, в одной БД у вас CRM-система, а в другой хранит данные ваш почтовый сервер. А в третьей данные для промо-сайта.

    Но т.к. вы указали MySQL, я говорю вам "используйте префикс к таблицам".

    К ответу Александр : как раз таки если это всё сервисы одного предприятия, то и авторизация лучше будет отдельным сервисом, наравне с остальными. Также со своей схемой/префиксом.
    Ответ написан
  • Как автоматически привязывать товары к категориям?

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

    Ваши категории - это по сути множества/классы, заданные при помощи предиката. Каждый ваш фильтр - это предикат вхождения товара во множество. Иерархия категорий - это обычное наследование классов. Для реализации наследования вам нужно про проверке предиката для категории-наследника проверять еще и все предикаты в родительских категориях. Тогда в категории "2016" вы запишите условие "год = 2016", а в дочерней категории женские напишите "пол = ж", и оба условия следует проверять для каждого товара.

    Таким образом, вам нужен какой-то простой язык или способ записи предикатов (возможно, вам захочется логических операторов и/или/не), иерархия категорий, где к каждой категории привязан предикат на вышеуказанном языке, и движок, который будет выполнять привязку товаров к категориям, или даже, если товаров немного, запрашивать их на ходу, транслируя предикаты в SQL-фильтры (ну или другой язык запросов для базы, в которой у вас товары). У нас был проект - агрегатор товаров из интернет-магазинов, мы примерно так категории и делали. Даже успели впилить поддержку некоторых встроенных функций в предикатах, чтобы например можно было по части названия товара определять его в ту или иную категорию (или наоборот, исключать из категории, чтобы сантехнические прокладки отличать от всяких других).
    Ответ написан
  • Какие существуют архитектуры взаимодействия с базой данных?

    А вы по какому признаку хотите классифицировать? Я вот могу назвать такую архитектуру клиент-серверной, а еще многослойной.
    Какие альтернативы? Ну, во-первых сам WCF может быть очень разный, и SOAP, и REST. Во-вторых, некоторые клиенты (например, административного характера) могут цепляться напрямую к базе (к примеру, они имеют доступ к серверу по VPN), и тогда веб-сервиса между БД и клиентом нет.
    Также, приложение может работать не сразу со веб-сервисом/БД, а к примеру складировать данные в локальную базу (какой-нибудь SQLite), а потом её синхронизировать с основной БД - также через сервис или напрямую (зависит от доверия к клиентскому приложению) - это сложнее с точки зрения наладки всего процесса, но иногда просто необходимо, если связь с центральным сервером БД не гарантирована (иногда приложения на мобильных устройствах должны работать и вне большого города и толстого 4G канала).

    WCF-служба может пользоваться ORM или программист может заранее составить все SQL-запросы.
    WCF-служба может хоститься и на IIS, если это удобно. Хотя, если она выполняет в БД фоновые операции, то вполне правильно и логично хостить её в Виндовом сервисе.

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

    Вас что конкретно интересует? Нужно хотя бы говорить о клиенте или сервисе отдельно, т.к. это сами по себе крупные компоненты со своей архитектурой.
    Ответ написан
  • Как кратко назвать RESTful API, которое, оказывается, никакое и не RESTful, ибо возвращает JSON/XML, кодов HTTP-ошибок не использует, да и URLы не те?

    вижу какие-то статьи, где пишут, будто если с JSON, то это вообще не REST API!

    если REST API - это когда без JSON и XML (т.е. на HTML), то какое же оно тогда API?!

    Ссылки на статьи пожалуйста. Там либо автор фантазирует, либо его неправильно понимают. Единственная причина, по которой автор мог так заявить, это то, что большинство современных RESTful API не гипермедийные. Но это не значит, что не стоит в принципе использовать тот же JSON, это лишь значит, что нужно стремиться включить в него гипермедийные возможности (см. JSON-LD, HAL, Siren) и сам API также строить на этой идее, которая заключается в том, что у вас есть одна "точка входа", а на все остальные ресурсы, имеющиеся в API, вы попадаете, переходя по ссылкам внутри других возвращаемых ресурсов, точно также как вы заходите на сайт, зная его доменное имя, и дальше ходите по ссылкам.

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

    не использующее (или почти не использующее) HTTP-кодов ошибок

    А вот ошибками все-таки стоит пользоваться.

    какие-то паттерны URL наподобие /images/ и /images/1, про какие-то PUT и DELETE, про коды ошибок...

    RESTful API и MVC — что это?
    Основной посыл использования RESTful API - применение основной идеи Паутины для взаимодействия автоматических агентов (приложений), а не только людей.

    Основная идея Паутины - построение распределенной информационной системы путем публикации неких абстрактных ресурсов, выдачи им идентификаторов (в сегодняшнем вебе - иерархических), определения ряда простых и широко известных операций над ними, не зависящих от содержимого ресурса (те самые GET, POST, PUT и т.д.), и связывания этих ресурсов ссылками (это называется гипермедиа, и в частности, гипертекст, если речь идет о текстовой информации).

    Таким образом, если вы хотите какую-то информацию опубликовать как RESTful API, вам необходимо представить ее как набор ресурсов, а все операции над этой информацией выразить через набор предопределенных операций. Фишка в том, что во многих задачах этих предпопределенных операций вполне достаточно, главное правильно определить ресурсы.

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


    Видел слово "JSON-pure API"

    Это уже вкусовщина. Люди не любят XML в API за то, что его модель подходит для описания иерархических данных и документов, но не для привычных объектно-ориентированных отношений между сущностями (он-то и создавался для представления документов, а не для веб-сервисов). Поэтому популярность JSON растет до упора. Многие старые API до сих используют XML, и JSON-pure - способ похвалиться, что ваше API полностью JSON. Сама идея RESTful ничего не говорит о форматах ответа, за исключением того, что формату желательно быть гипермедийным.
    Ответ написан
  • Как организовать обработку сообщений от нескольких серверов?

    Nipheris
    @Nipheris Куратор тега C#
    Общая концепция и модель: раз и два.
    Конкретные реализации и протоколы: обмен сообщениями в чистом виде, независимо от платформы: AMQP, ZeroMQ; также, если речь про дотнет, можно попробовать WCF.
    Ответ написан
  • Как правильно обрабатывать ошибки в C#?

    Nipheris
    @Nipheris Куратор тега C#
    Т.е. нужна некая философия

    А какие книги вы уже пробовали читать, раз такое спрашиваете?

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

    Все это дает вам набор простых правил:
    1) выбрасывать исключение нужно тогда, когда вы не собираетесь обрабатывать возникшую ситуацию в рамках текущего алгоритма. Иными словами, для работающей в данный момент функции эта ситуация - "исключительная". Пример: вы пишете функцию для чтения GIF-файла в Bitmap, и по ходу чтения проверяете соответствие получаемых данных формату GIF-файлов (например, убеждаетесь в наличии GIF89a в начале файла). Если вдруг вы видите, что формат файла нарушен, то вам ничего не остается кроме как выбросить исключение, т.к. вы не можете продолжить выполнение основного алгоритма - считывание файла. Внутри функции считывания вы не знаете заранее, как вызывающий код захочет обработать эту проблему, вам и не нужно это знать;
    2) перехватывать исключение конкретного типа нужно тогда, когда в задачу текущего кода входит и обработка ошибок тоже. Иными словами тогда, когда исключение в вызванном коде - лишь один из вариантов нормальной работы вызывающего кода. Вернемся к примеру с GIFками: если для библиотечной функции чтения файла нарушение формата - это критическая проблема, то для вызывающего эту функцию GUI-приложения это нормальная ситуация - ее можно и нужно обработать, выдав пользователю соответствующее сообщение, или просто пропустить файл, если обрабатывается сразу несколько картинок. Или например, если вы пишете веб-сервис, вы врядли хотите, чтобы весь сервис прекратил работу из-за ошибки при обработке какого-то одного запроса. Поэтому в веб-сервере, раздающем файлы вы, к примеру, можете перехватывать все FileNotFound исключения, и выдывать ошибку 404, а на все остальные исключения внутри обработчика запроса - ошибку 500 и в обоих случаях писать в error.log.

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

    Отличный пример разных подходов - методы Parse/TryParse у числовых типов в дотнете. Первый возвращает значение и выбрасывает исключение, второй записывает значение через выходной параметр, возвращает bool и НЕ выбрасывает исключение. "Try" в названии второго метода подчеркивает, что для этого метода неудача при попытке распарсить число из строки - НОРМАЛЬНАЯ ситуация, и метод в этом случае вернет false. Для метода Parse напротив, такая ситуация будет исключительной, т.к. ему просто-напросто нечего будет возвращать, и дальнейшая нормальная работа кода, в том числе вызывающего, невозможна.
    Поэтому метода TryParse чаще используют тогда, когда вероятность ошибки высока и ее обработка - одна из ветвей алгоритма. Например при считывании пользовательского ввода мы сразу можем попросить пользователя исправить введенное значение.
    С другой стороны, Parse применяется если ошибка маловероятна, мы не готовы ее обработать и лучше прервать всю операцию целиком. Например если мы получили от сервера невалидный ответ, мы не попросим его исправить этот ответ. Дальнейшее общение с сервером лучше прервать, т.к. имеет место нарушение протокола и можно наломать дров.
    Ответ написан
  • Чем отличается архитектура приложения от его алгоритмов?

    Архитектура - это про то, из каких элементов ("черных ящиков") собирается система/подсистема.
    Алгоритмы - это про то, как наиболее низкоуровневые элементы ("черные ящики") и выполняемые ими функции реализованы с помощью последовательности действий.

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

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

    Точное определение алгоритма можно найти в других источниках.
    Ответ написан
  • Как объяснить девушке что такое "некрасивый" код?

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

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

    Молодые люди с ясными и последовательными мыслями, насколько мне известно, пользуются успехом у девушек.
    Ответ написан
  • Как правильно передавать объекты в N-layer архитектуре?

    Nipheris
    @Nipheris Куратор тега C#
    GenericRepository и его метод GetAll - это ни о чем. В том смысле, что вам такой репозиторий не нужен - он ничего не делает и ничего не абстрагирует. Вы выставляете IQueryable - и получаете проблемы на свою голову. Да, это очень соблазнительная штука, но таки репозиторий для того, чтобы все возможные запросы оставлять там, иначе они уходят далеко в логику приложения. Вам нужен конкретный репозиторий (интерфейс GenericRepository может и пригодится) с конкретными запросами, возвращающими IEnumerable. В этом и его суть - на уровне репозитория делается ПЕРВИЧНАЯ выборка (с помощью IQueryable), которая по сути есть запрос к БД и материализация всех НУЖНЫХ объектов, а потом уже мелкую фильтрацию можно делать с объектами в IEnumerable коллекции.

    Как организовать передачу сложных объектов (НЕ СУЩНОСТЕЙ) с уровня DAL на уровень BLL?

    Я бы сделал свой репозиторий для каждой такой вещи. Он будет ОТЛИЧАТЬСЯ от репозитория для сущностей, т.к. там не будет, например, Update. Это будет репозиторий ЗАПИСЕЙ, не объектов. В остальном все также - все возможные запросы нужно постараться собрать там. И класс тоже можно и нужно завести вроде BookReport, только он будет immutable, т.е. будет вести себя как запись. А дальше уже делайте с ним что пожелаете.

    Но если такая выборка находится в репозитории, получается метод репозитория должен возвращать List и уровень DAL будет связан с уровнем BLL.

    Вот тут не понял. Ну пусть возвращает List или IEnumerable, в чем тут вы связь видите?

    Вообще, возможно вам нужно поменьше париться о разделении DAL и BLL. Как правило это приводит к anemic data model, и ничего кроме вреда это вам не принисет. Вообще не знаю откуда эта мода пошла, у меня всегда получалось 80% логики оставлять в самих классах сущностей, и все было ок.
    Ответ написан
  • Какой должна быть ORM?

    > И меня несколько удивило отсутствие каких-либо наработок в этой области в Rust (хотя бы начальных версий).
    1) язык в релизе несколько месяцев, чего вы хотите-то;
    2) не во всех языках ORM смотрится естественно. В C++ нормальной ORM нет до сих пор, есть некоторые библиотеки на базе Qt, но де-факто стандарта нет просто потому, что в языке недостаточно силен уровень метаданных. Но в этом нет проблемы просто потому, что на плюсах редко пишутся приложения, где нужен такой уровень;
    3) А может повсеместное использование ORM это только удел web?
    Я бы сказал что ORM это удел бизнес-приложений и языков высокого уровня (Java/.NET/Ruby). Другое дело, что веб-приложения в 99% случаев пишут на всяких asp.net и Рубях, а не на плюсах, поэтому и такая корреляция. Внутрикорпоративных десктопных приложений по прежнему достаточно, и как раз там ORM тоже любят.

    > Подскажите, на сколько высокоуровневой должна быть ORM?
    Это вам решать, ORM-ки разные бывают, кто-то где-то используют потолще, кто-то - потоньше. Лично я особого смысла в тонких не вижу для большинства задач, поэтому на мой вкус в ORM обязательно должны быть следующие вещи:
    1) martinfowler.com/eaaCatalog/identityMap.html
    2) martinfowler.com/eaaCatalog/unitOfWork.html
    3) martinfowler.com/eaaCatalog/inheritanceMappers.html

    Вообще, озакомьтесь для начала со всеми Object-Relational паттернами: martinfowler.com/eaaCatalog, а то наверняка напишете парк велосипедов.
    Ответ написан
  • Какова должна быть структура проекта на Qt?

    Nipheris
    @Nipheris Куратор тега C++
    Я думаю структура проекта мало определяется самим Qt, и будет такая же, как и других C++ - проектов. Однако положить файлы в подпапку вам никто не запрещает.
    Ответ написан
  • Возможно ли создать интерфейс для списка следующих классов?

    Nipheris
    @Nipheris Куратор тега C#
    Тут нужно оставить один вариант из двух: либо у вас все-таки есть общий интерфейс, через который вы будете работать с объектом любого класса, и тогда вам нужно решать задачу создания экземпляра, для чего можно применить либо упомянутую Фабрику, либо рефлексию. Если же вы твердо уверены, что интерфейс вам неизвестен, значит вы решаете мета-задачу - вам нужно сделать что-то с заранее неизвестными полями/методами заранее неизвестных классов (как например, при сериализации объектов в общем случае), тогда вам не обойтись без рефлексии/кодогенерации. Вы только четко для себя выясните, что вам известно о ваших объектах, а что нет.
    С советом Oxoron пожалуй не соглашусь, т.к. если интерфейс пустой, значит он служит исключительно для целей добавления доп. информации о классе (ну т.е. вот у нас есть классы, реализующие его, а вот тут - не реализующие), а эта задача решается гораздо логичнее с использованием атрибутов - они для этого и были созданы.
    Ответ написан
  • Как представить иерархию элементов?

    Nipheris
    @Nipheris Куратор тега C#
    class Obj { }
    class Collection : Obj
    {
       private List<Obj> items;
    }
    class Item : Obj { }


    паттерн называется Компоновщик. Можно начать с википедии.
    Ответ написан