Я разрабатываю библиотеку для своего приложения, которая обертывает подсистему смарт-карт Windows.
Физически существует смарт-карта, которая подключена к устройству чтения смарт-карт, а устройство чтения - к ПК.Существует много типов смарт-карт (например, карты Javacards и .NET).Одна из идей для разработки этого заключается в следующем:
TReaderListBase <- TReaderListJavaCard </p>
TReaderBase <- TReaderJavaCard </p>
TSmartcardBase <- TJavaCard </p>
Список читателей Get() метод возвращает считыватель по индексу или по имени, а метод Connect () считывателя возвращает экземпляр объекта карты для работы с ним.
Проблема в том, что хотя существуют физически действительно разные типы смарт-карт, существуетна самом деле только один тип читателя, который может прочитать их все.TReaderListJavaCard предназначался только для выполнения функций поиска с использованием определенных атрибутов Javacard.И TReaderJavaCard существует только для того, чтобы возвращать экземпляр класса TJavaCard вместо TSmartcardBase, возвращаемого TReaderBase в методе Connect ().
Также в этом дизайне есть некоторые логические дыры, например, когда вы подключаете смарт-карту из устройства чтения, может показаться логичным, что экземпляр потомка TSmartcardBase немедленно уничтожается, потому что имя класса говорит, что он олицетворяет собой саму карту, и этой карты больше нет.
Tt работает точно.Но кажется ли эта схема логичной?
У меня было предложение от моего друга изменить структуру системы следующим образом:
Пропустить считыватели, создать класс TSmartcardProxyObjectBase, спуститься с него TJavaCardProxyObject и добавить все методы впоиск и подключение к ним карточек.Что-то вроде пакета «все в одном».Эта абстракция выглядит хорошо, потому что CardProxyObject действительно может что-то искать, подключаться к чему-либо, находиться в автономном режиме (если удалена карта, к которой он подключен) и т. Д. Но этот дизайн нарушает SRP, потому что один класс выполняет поиск связи и поиск объектов.Если я захочу отсоединить функции поиска от него и получу ту же схему, что и в первом случае (он просто добавит что-то, что может работать с читателями).
Мой друг говорит, что мы на самом деле не работаемнепосредственно с читателями, и основная цель библиотеки - работать с карточками, поэтому мы должны скрывать читателей от пользователя библиотеки.
Поскольку такие проекты - это то, из чего можно научиться проектировать ООП, я заинтересован в нахождении чрезвычайно красивого решения.;)
Надеюсь, я объяснил все понятно;)
Есть третий способ сделать это.Пусть это будут финальные классы ReaderList и Reader.Но в читателе не должно быть метода Connect ().Вместо этого я могу реализовать метод Use () или PutOnline () в классе смарт-карт, чтобы использовать этот конкретный ридер для связи, эффективно скрывая низкоуровневый вызов SCardConnect от пользователя.Функции поиска могут быть перемещены в некоторый вспомогательный класс (например, TJavaCardLocatorService).Или я должен сделать их статическими членами класса TJavaCardProxyObject?Что-то вроде TJavaCardProxyObject.AttachToCardWithAID (ReaderList), но имя выглядит также нелогичным и, опять же, кажется, нарушает SRP.
Что вы думаете?В любом случае, важно ли иметь хорошую архитектуру в реальных проектах, или я просто теряю время, пытаясь научиться чему-то неважному?