Re[3]: API и слоёные архитектуры
От: Sinix  
Дата: 13.09.16 06:01
Оценка: 107 (4) +1
Здравствуйте, Arsen.Shnurkov, Вы писали:

S>>У вас проблема


AS>Я просмотрел (не подробно прочитал на запоминание, но всё-таки) советуемое, но не проникся.

Ага, если пролистывать, то как обычный справочник выглядит.

Там вся ценность — не в собственно в правилах, а в подходе к дизайну API и в пояснениях. Как думают товарищи авторы, что для них важно в дизайне API, что нет.
Вдохновлять оно и не должно, но от стандартных проблем типа "дизайним _до_ того, как представляем, как оно будет использоваться" лечит неплохо


AS>Этапы есть только во втором, но упора на "ответственности" там нет.

AS>Вы что-то такое прочитали про "Key Responsibilities", что Вам очень понравилось, а я не читал.
Неа, это уже из опыта. Нет никакого смысла разделять код на слои до тех пор, пока вы не определитесь с ответственностями для каждого из слоёв.


Классический простой пример — работа с XML. Для большинства пользователей достаточно XDocument.Load("SomeFile"), но все остальные сценарии (вплоть до откровенных извращений типа подмены имени кодировки) выполняются через перегрузки одного и того же метода.

В результате с одной стороны — довольно интуитивный код и никакого сфероконизма типа abstractPatternFacadeSingletonFactoryБлаБла (подобного в дотнете вообще не встречается, за этим — к яве).
С другой — под капотом там настоящий слоёный пирог — чтение из потока, чтение текстового потока, токенизация, разбор xml, валидация (ага, мало кто знает, но оно есть) и тыды и тыпы.
С третьей — одна и та же инфраструктура (XmlReader) _без_ изменений переиспользуется как минимум в трёх фреймворках по работе с XML (XmlDocument, XDocument, DataCOntractSerializer), а в последнем — ещё и расширяется кастомными классами (XmlDictionaryReader и наследники). И работает без особых изменений в public api начиная с первого фреймворка. 15 лет спустя, ага.

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


Возвращаясь к теме — удачный дизайн не по наитию получается. И не как результат попыток сделать всемогутор (скорее наоборот, ни одного удачного не видел). А как результат "находим основные сценарии использования, думаем, как сделать public api с минимумом WTF moments, делаем".

Аналогичный подход работает не только с конкретными типами, но и с инфраструктурой в целом. Только количество сценариев использования заметно больше выходит. Поэтому как правило сначала вчерновую собирают примеры того функционала, который нужно реализовать, а затем уже раскидывают ответственности по слоям, используя простой принцип "ничего не знает о". Ну, т.е. Stream отлично компилируется и работает без StreamReader, StreamReader знает о существовании Stream, но не догадывается о XmlReader и тыды и тыпы.

Получается, что каждый из слоёв по умолчанию использует public API предыдущего слоя _и_ каждый слой позволяет при необходимости подкрутить логику нижележащих слоёв, например, передавая правильно настроенный объект. И для дизайна многослойного API нужно
* уметь дизайнить public API каждого из слоёв.
* суметь разнести ответственности так, чтобы каждый из слоёв не был задизайнен исключительно под нужды следующих.


Собственно всё
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.