Допустим, что есть некая архитектура, в которой пять слоёв:
1) уровень работы с кодировками текста и форматами файлов
2) уровень текстовых операций редактора текстов (добавить отступ для группы строк)
3) уровень элементов и атрибутов xml-формата
4) уровень объектов абстрактного проекта msbuild
5) уровень объектов C# программы в формате .csproj
В каждом слое есть своё API, свои наборы операций, свои структуры данных и константы.
Если хочется иметь полный контроль над всем,
но при этом не давать доступ к нижним уровням на прямую,
то каждый более высокий оказывается объёмнее предыдущего (так как включает всё что уже есть ниже, но по-своему).
Идея такова — разрешить пользоваться API всех уровней, а не только непосредственно нижележащего.
Для того, чтобы при работе с элементами нижнего уровня можно было
делать что-то осмысленное с верхнего уровня должен быть виден контекст,
то есть связи между элементами объектных моделей разных уровней должны быть двухсторонними.
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Дальше мысль не идёт.
Прочитать FDG (доступна в safari books, триала на 10 дней должно хватить). Обязательная штука для человека, который хочет заниматься проектированием API под .net (да и не только под .net).) + architecture guidelines book. В последней вас интересует общий подход, расписан в Chapter 5: Layered Application Guidelines, в первой — умение думать правильно и отлавливать ошибки в рассуждениях до того, как они повлияют на дизайн API.
У вас проблема не в собственно разделении на слои, а в том, что вы пытаетесь это сделать, пропустив все предыдущие этапы, от case study и до выяснения ключевых ответственностей.
Ну и естессно, получается, что "каждый более высокий оказывается объёмнее предыдущего (так как включает всё что уже есть ниже, но по-своему)".
Я просмотрел (не подробно прочитал на запоминание, но всё-таки) советуемое, но не проникся.
Первая предложенная книжка хороша в корпоративных политических войнах,
когда нужно задавить авторитетом — делаем так, потому что так сказано в FDG.
Но не зажигает, ясностью не наполняет.
Видимо мне нужно прочитать дополнительно что-то другое.
S>вы пытаетесь это сделать, пропустив все предыдущие этапы, от case study и до выяснения ключевых ответственностей.
Этапы есть только во втором, но упора на "ответственности" там нет.
Вы что-то такое прочитали про "Key Responsibilities", что Вам очень понравилось, а я не читал.
Здравствуйте, 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 каждого из слоёв.
* суметь разнести ответственности так, чтобы каждый из слоёв не был задизайнен исключительно под нужды следующих.
S>Вот это я называю дизайном здорового человека. Если вдуматься — внушает. Особенно если учесть, что формальных слоёв тут нет (скажем, стек xmlReader и стек xmlWriter друг с другом связаны разве что общим стилем), код отлично работает при использовании функционала с разных слоёв и при этом использование "высокоуровневого" кода остаётся вполне удобным.
S>Возвращаясь к теме — удачный дизайн не по наитию получается. И не как результат попыток сделать всемогутор (скорее наоборот, ни одного удачного не видел). А как результат "находим основные сценарии использования, думаем, как сделать public api с минимумом WTF moments, делаем".
А вот не рановато ли думать о public api до создания самой архитектуры? На мой взгляд, API тогда удачно получаются, когда продиктованы архитектурой, а не наоборот. Т.е. строим дом, потом врезаем окна, а не под сущ. окна строим дом.
На счет fdg я бы поспорил, т.к. интереснее, что читали сами авторы, ибо с первого раза спроетировать api на 15 лет это реально круто. Думается мне с математикой они дружили. Очень интересна с этой точки зрения книга Степанова "Elements of programming". Она вышла позже, но крайне любопытна и полезна ибо при дизайне чего-либо (архитектуры, api) советует смотреть на математику: архитектура должна быть похожа на построение доказательств в математике, только в обратную сторону. Т.е. есть ядро архитектуры (аксиомы), далее создается соотв. функционал (теоремы, леммы). Теорема 1 исп. в теореме 2 и т.д.
Здравствуйте, Sharov, Вы писали:
S>А вот не рановато ли думать о public api до создания самой архитектуры? На мой взгляд, API тогда удачно получаются, когда продиктованы архитектурой, а не наоборот.
Как показывает практика — не рано, если говорить об инфраструктуре, для которой сценарии использования очевидны.
Тут важно само наличие формализованного public api, а не его качество, т.к. мы на самом раннем этапе получаем:
1. Набор ключевых сценариев для фреймворка.
2. Код с примерами использования этих сценариев, он же — готовые интеграционные тесты
3. Возможность проверить архитектуру на адекватность требованиям.
Т.е. на этом этапе public API играет роль спецификации/требований, с учётом которых строится архитектура и пишется реальный код.
В результате мы имеем адекватное представление о проекте в целом буквально с нулевого дня. В твоей аналогии
Т.е. строим дом, потом врезаем окна, а не под сущ. окна строим дом.
делаем модельку, которая прописывает уровень освещённости, вентиляцию и что там ещё по санпину и в процессе собственно проектирования дома постоянно проверяем, что мы в эти требования укладываемся. В общем, речь про подсобный инструмент, а не про замену собственно проектированию.
upd хо, я даже сделал про это оговорку в предыдущем посте. Всё ок короче.
Аналогичный подход работает не только с конкретными типами, но и с инфраструктурой в целом. Только количество сценариев использования заметно больше выходит. Поэтому как правило сначала вчерновую собирают примеры того функционала, который нужно реализовать, а затем уже раскидывают ответственности по слоям, используя простой принцип "ничего не знает о". Ну, т.е. Stream отлично компилируется и работает без StreamReader, StreamReader знает о существовании Stream, но не догадывается о XmlReader и тыды и тыпы.
Как раз на этой идее про постоянную проверку практикой aka
Framework Design Principle
Frameworks must be designed starting from a set of usage scenarios and code samples implementing these scenarios.
вся FDG и построена
S>На счет fdg я бы поспорил, т.к. интереснее, что читали сами авторы, ибо с первого раза спроетировать api на 15 лет это реально круто. Думается мне с математикой они дружили. Очень интересна с этой точки зрения книга Степанова "Elements of programming".
Ну это безусловно да. Проблема в том, что даже FDG осиливают единицы. Поэтому сначала ползать, затем летать
Здравствуйте, Sinix, Вы писали:
S>>На счет fdg я бы поспорил, т.к. интереснее, что читали сами авторы, ибо с первого раза спроетировать api на 15 лет это реально круто. Думается мне с математикой они дружили. Очень интересна с этой точки зрения книга Степанова "Elements of programming". S>Ну это безусловно да. Проблема в том, что даже FDG осиливают единицы. Поэтому сначала ползать, затем летать
Все, что Вы пишете безусловно верно применительно к созданию фреймворка, т.е. набора неких публичных библиотек. Безусловно там надо плясать от public api, но вот, допустим, ТС пишет сугубо утилитарное приложение для своей компании или группы пользователей. Т.е. ни о каких публичных библиотеках речи не идет, конечный продукт. Зачем ему читать fdg? Да для общего развития, да там есть хорошие идеи и замечания, но эта книга вряд ли будет полезной для решения конкретно поставленной задачи. Степанов то с его подходом как раз и будет про "ползать", а fdg уже "летать".
ЗЫ: И все-таки говорить, что парне из мс вот прям молодцы-молодцы тоже не очень справедливо. Ребята не на ровном месте и с нуля все придумывали, а оглядывались (подглядывали) на мир java.
Здравствуйте, Sharov, Вы писали:
S>Зачем ему читать fdg?
Ну блин, это ж очевидно. Ни один софт не является однородной мешаниной из методов и типов, внутри точно так же присутствует разделение на подсистемы-слои-компоненты-хелперы.
Не, в маленьком софте, который разрабатывается парой-тройкой девелоперов ещё можно лениться и развести бардак.
А в средних и уж тем более в крупных проектах любой компонент, которым ваша команда не владеет, вы можете использовать только через его API. Залезая в внутренности напрямую вы неминуемо испортите жизнь всем — от собственно разработчиков, которые теперь не могут чинить ошибки, не сломав ваш код и до других команд, чьи сценарии легко могли поломаться от ваших изменений.
Ну а дальше есть всего два варианта. Или внутреннее API пишется от балды, или учим FDG. Проверено неоднократно, причём сложным способом. В одном из проектов за системную часть и биз-код отвечали две команды, причём общение между ними наладить толком никто не озаботился. В итоге уже через год-полтора 90% системного API было спрятано под хелперами, разработанными второй командой. Потому что всё было в принципе задизайнено правильно, но не было бы ни одного сценария (я серьёзно, от запросов и до создания бизнес-сущностей), который не требовал бы минимум двух-трёх вызовов методов. Не, в итоге получилось даже неплохо, но изначально количество строк, ублажавших инфраструктуру было раз в 5 больше, чем собственно бизнес-логики. Вот такой вот высокоуровневый ассемблер
S>ЗЫ: И все-таки говорить, что парне из мс вот прям молодцы-молодцы тоже не очень справедливо. Ребята не на ровном месте и с нуля все придумывали, а оглядывались (подглядывали) на мир java.
Ну да, согласен абсолютно. Один нюанс: ява — это как раз отличный пример "точно такого же, только без FDG". Серьёзно, фреймворк, который для части элементарщины типа чтения xml требует приседаний в духе
а остальную часть вообще лучше сторонними библиотеками заменить (не будем показывать пальцем, но это был Runtime.exec(). jproc, ещё раз спасибо).
никак не назовёшь вершиной дизайна
Про перевод Document в строку — давайте не будем. doc.toString() — недостаточно энтерпрайзненько.
P.S. Очень-очень подозреваю, что у команды инфраструктурщиков из того проекта за плечами была в основном ява
Здравствуйте, Sinix, Вы писали:
S>>ЗЫ: И все-таки говорить, что парне из мс вот прям молодцы-молодцы тоже не очень справедливо. Ребята не на ровном месте и с нуля все придумывали, а оглядывались (подглядывали) на мир java.
S>Ну да, согласен абсолютно. Один нюанс: ява — это как раз отличный пример "точно такого же, только без FDG". Серьёзно, фреймворк, который для части элементарщины типа чтения xml требует приседаний в духе S>
fdg тогда не было, но вот gof уже начали творить. И в коде выше (да судя по всему и во всей jdk) чувствуется их влияние. А посмотреть на неправильное решение тоже бывает крайне полезно. Как не надо делать почти пол дела.
1) архитектура это сложно-сложно, не лезьте сюда, у нас тут и математики и социология и вообще самим работы не хватает.
2) тысячи классов это нормально, всё равно как уменьшить сложность мы не знаем.
и .Net Framework с его циклическими зависимостями между assemblies — это да, пример для подражания...
3) разрабатывать архитектуры мы не умеем, можем только по тестовым использованиям сказать — удачно вышло или не очень.
кто умел разрабатывать, так это Страуструп, с его CRC-карточками, метод, который никто не вспомнил
но этому итак в русской культуре с детства учат, показывая игру в подкидного дурака с разными возможностями разных персон
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>В каждом слое есть своё API, свои наборы операций, свои структуры данных и константы.
AS>Если хочется иметь полный контроль над всем, AS>но при этом не давать доступ к нижним уровням на прямую, AS>то каждый более высокий оказывается объёмнее предыдущего (так как включает всё что уже есть ниже, но по-своему).
Ну сделайте на верхнем уровне возможность работать с готовыми объектами из уровня ниже. Тогда пользователь всего это API сможет, если захочет, в проект csproj другой форматировщик для отступов, который создаст заранее сам. Все вменяемые библиотеки так устроены.
В чём вообще вопрос? Как ковыряться в xml? Ну способов 10 разных точно есть. По ссылке какая-то тривиальная ерунда, XSLT задействуй, если файлы переписывать хочется. А в рамках идеологии MSBuild вообще решается через переменные (<PropertyGroup/>) и условные выражения в таргетах — подставляешь в нужных местах переменные и меняешь их значения в зависимости от каких-то условий.
Вот пример из CSPROJ — генерация разных подключений к бд в зависимости от выбранной конфигурации (переменная Configuration):
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild" Condition="Exists('ConnectionStrings.$(Configuration).config')">
<!--Generate transformed config in the project directory, because Web apps pick files from there-->
<TransformXml Source="ConnectionStrings.config" Destination="ConnectionStrings.config" Transform="ConnectionStrings.$(Configuration).config" />
</Target>
Здравствуйте, Arsen.Shnurkov, Вы писали:
V>>>> Все вменяемые библиотеки так устроены. AS>>> Покажите мне это на примере Roslyn V>> В чём вообще вопрос?
AS>Рослин устроен не так.
Рослин — это компилятор в дотнетовский байт-код, а вопросы касались XML для файлов проектов, не исходного кода. AS>Нельзя управлять с уровня приложения тем, как будут отформатированы пробелы.
Рослин помогает генерировать код, пробелы и отступы в котором именно такие, какие установил пользователь сам для себя. Rак они это делают не выяснял, но это самый разумный подход — я как пользователь лучше знаю какие пробелы и отступы мне нужны в моём коде. AS>Вы, например, не справились.
Я не волшебник, я только учусь.
AS>А это передовейший проект, написанный архитектурнейшими архитекторами.
Вы определитесь с проектом: https://github.com/dotnet/roslyn https://github.com/Microsoft/msbuild
Здравствуйте, Vladek, Вы писали:
V>Вы определитесь с проектом:
Не, топикстартер в принципе почти по адресу вопросы задаёт, roslyn project system — это будущее API для работы с проектами в следующей студии / VS Code. Один подвох: на сегодня это не public API, оно не закончено и оно не рассчитано на работу в отрыве от хоста.
В теории надо исходную задачу озвучить, с вероятностью процентов в 80 там даже код писать не потребуется. Но учитывая, что ув Arsen.Shnurkov умудряется фразы
речь про подсобный инструмент, а не про замену собственно проектированию.
воспринимать как
разрабатывать архитектуры мы не умеем, можем только по тестовым использованиям сказать — удачно вышло или не очень
а вы почитайте доку на msbuild, он не работает с конкретными видами проектов, только с обобщёнными MsBuild Item
S> я могу только помахать рукой и пожелать удачи
я так и сказал. Могли бы что-то ещё, дали бы ссылку на книжку с методикой.
Угу. И ещё надо учитывать, что помимо csproj нужны sln , т.к. в них прописывается порядок сборки (отдельные гении добавляют ссылки на сборки не как project reference, а как ссылку на собранную библиотеку в общей папке bin).
Кроме того нужно учитывать conditional build symbols, всевозможные извращения в виде targets include а также мегатонны приседаний с ссылками на библиотеки из нюгета с адскими хаками в виде перенаправления версий через app.config.
В общем тут всё очень печально и очень сильно завязано на легаси, чтоб делать что-либо с наскока. Особенно если не дай бог речь про мерж нескольких солюшнов. В общем случае только застрелиться можно.
Если речь про утилиту под себя, то я бы решил дело простым парсером sln + csproj-файлов. Делал такое несколько десятков раз, наколеночный вариант обычно укладывается в 1k строк, редко больше.
Если речь про универсальную утилиту — нужно знать, какую проблему вы пытаетесь решить. Потому что легко может оказаться так, что изначальные требования типа манипуляций с зависимостями — только вершина айсберга, тут любая мелочь может подкинуть очень неприятные сюрпризы.
S>> я могу только помахать рукой и пожелать удачи AS>я так и сказал. Могли бы что-то ещё, дали бы ссылку на книжку с методикой.
Ну блин, кто ж знал, что спрашивая про "как сделать слоёную архитектуру" вы на самом деле интересовались, как сделать своё API для правки csproj-файлов?
S> нужно знать, какую проблему вы пытаетесь решить
Вы путаетесь. Сначала вы (ссылаясь на FDG) говорили, что при дизайне фреймворка
нужно рассматривать максимально широкий спектр задач потенциальных пользователей.
А теперь говорите — нужна одна конкретная проблема и вообще поменьше усилий, чтобы обойтись одним изменением в отдельном случае.
С таким подходом вас вообще к проектированию фреймворков подпускать нельзя.
S> я бы решил дело простым парсером sln + csproj-файлов.
Это всё равно что сказать, что компилятор только из парсера состоит, а кодогенерация это фигня.
Парсер теряет информацию о положении токенов в тексте и не содержит модели редактирования
(таким образом, нельзя в дальнейшем анализировать последующие операции преобразования с точки зрения минимизации вносимых изменений в исходник .csproj)
Парсер строит AST, а нужно ещё задизайнить объектную модель, при помощи которой можно этим AST манипулировать.
Q) мне нужен фреймворк.
A) ты дурачок, фреймворки это сложно, тебе фреймворк не нужен, есть полно готовых решений (более 10 способов)
Q) фреймворка нет, пруф
A) ну мы бы не парились
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>нужно рассматривать максимально широкий спектр задач потенциальных пользователей.
Цитату плиз. Проглядел топик — везде не про "максимально широкий", а про основные сценарии использования aka usage scenarios.
AS>А теперь говорите — нужна одна конкретная проблема и вообще поменьше усилий, чтобы обойтись одним изменением в отдельном случае.
Ну так вы определитесь наконец — вы абстрактный фреймворк ваяете, или пытаетесь поверх существующей инфраструктуры и существующих форматов файлов конкретную проблему решить?
И давайте конкретику уже, а то у нас какой-то холивар вместо собственно обсуждения получается
S>> я бы решил дело простым парсером sln + csproj-файлов. AS>Это всё равно что сказать, что компилятор только из парсера состоит, а кодогенерация это фигня.
огосспидя. Жаргонизм это обычный. Название пошло от типового вида API Xxx.ParseYyy(). XDocument.Parse() не смущает же?
S> вы определитесь наконец — вы абстрактный фреймворк ваяете, или конкретную проблему решить?
Так я сразу определился. Мне нужен фреймворк. Интересуюсь, как делают фреймворки вообще, абстрактно. Выяснил, что методики нет.
S> пытаетесь поверх существующей инфраструктуры и существующих форматов файлов
Существующие форматы файлов — это часть требований. Нельзя просто взять их и выкинуть.
Поэтому даже совершенно новый фреймворк всё равно будет дело с этими же форматами иметь.
S> И давайте конкретику уже, а то у нас какой-то холивар вместо собственно обсуждения получается
Да уж куда конкретнее-то? Вся конкретика есть уже в первом посте.
Интересуюсь я не просто так, не на голом месте интерес. И я конкретно расписал, какой мне нужен фреймворк и для чего.
Моя проблема конкретная в том смысле, что В КАЧЕСТВЕ ПРИМЕРА я привел конкретный фреймворк существующий, а мне нужен тоже КОНКРЕТНЫЙ, но с необходимыми мне возможностями.
Существующую инфраструктуру хотелось бы проанализировать на возможность допилки. Потому что в этом случае есть надежда снизить вероятность ошибок проектирования.
Про .csproj вы выше всё сами расписали.
С ошибками правда, указав что бывают Project Reference (в .csproj), Assembly Reference (в .csproj)
и ссылки (dependencies) между проектами в .sln, только вы смешали второе и третье понятие.
Другой коллега не в курсе, что если преобразовывать XML при помощи XSLT, то форматирование слетает.
И вообще XML — это третий уровень, а изменять хочется средствами пятого.
AS>>нужно рассматривать максимально широкий спектр задач потенциальных пользователей. S>Цитату плиз.
2.1 PROGRESSIVE FRAMEWORKS
Designing a single framework for a broad range of developers, scenarios, and languages is a difficult and costly enterprise.
Они не говорят, что нужно делать именно так.
Но указывают, что если фреймворк прогрессивный, то сценариев он покрывает как правило много.
А если он покрывает мало сценариев, то какой же это прогрессивный фреймворк?
Там ещё ниже есть сравнение
multiframework approach
и
progressive framework.
Так вот то, что есть сейчас для обработки .csproj — это гораздо скорее первое, чем второе.
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Интересуюсь я не просто так, не на голом месте интерес. И я конкретно расписал, какой мне нужен фреймворк и для чего.
Гааах. Я правильно понял, что оно нужно для того, чтоб заменить существующую инфраструктуру sln/csproj/msbuild?
А то вопрос пока выглядит примерно так: "я хочу написать фреймворк. Для начала, в нём должна быть своя субд..." и на дальнейшие вопросы — "всё, что мне нужно, я уже расписал", без обид.
Я уже не знаю, как ещё раз намекнуть на очевидный факт, но сделать простенькое API, чтобы удобно было править ссылки в проектах и целиком реализовать поддержку редактирования csproj или разруливание зависимостей внутри солюшна — это таки две большие разницы. И не зная исходной проблемы, которую вы собрались решать этим фреймворком, вам точно ничего хорошего никто не посоветует.
AS>Моя проблема конкретная в том смысле, что В КАЧЕСТВЕ ПРИМЕРА я привел конкретный фреймворк существующий, а мне нужен тоже КОНКРЕТНЫЙ, но с необходимыми мне возможностями. AS>Существующую инфраструктуру хотелось бы проанализировать на возможность допилки. Потому что в этом случае есть надежда снизить вероятность ошибок проектирования.
Ну блин, снова то же самое. "Я хочу сделать автомобиль. У него должна быть дверь и он должен ездить. Хотя допилить готовый меня тоже устроит".
Где, бляха-муха конкретный сценарий? AKA
* У меня есть x
* Я хочу получить y, затратив z1 и с дополнительными условиями z2
* для этого мой фреймворк должен уметь a, b и c.
Вы расписываете только последнюю часть, да и то отдельные частные случаи, из которых первые два пункта не восстановишь.
AS>Про .csproj вы выше всё сами расписали. AS>С ошибками правда, указав что бывают Project Reference (в .csproj), Assembly Reference (в .csproj) AS>и ссылки (dependencies) между проектами в .sln, только вы смешали второе и третье понятие.
Блин, давайте всё-таки читать то, что вам пишут
И ещё надо учитывать, что помимо csproj нужны sln , т.к. в них прописывается порядок сборки (отдельные гении добавляют ссылки на сборки не как project reference, а как ссылку на собранную библиотеку в общей папке bin).
AS>>С ошибками правда, указав что бывают Project Reference (в .csproj), Assembly Reference (в .csproj) AS>>и ссылки (dependencies) между проектами в .sln, только вы смешали второе и третье понятие.
S>Дано: проект A с S>[code] S><Reference Include="somelib.dll"> S> <HintPath>..\proj\bin\somelib.dll</HintPath> S></Reference> S>[code]
S>Как вы правильно определите зависимости (и порядок сборки) без .sln-файла?
Наличие зависимости запросто определю — увижу в .csproj элемент Reference вместо ProjectReference.
Собрать правильно без .sln файла не смогу, но меня это не волнует, потому что задача парсинга .sln проще, чем задача парсинга .csproj,
в ней всего три уровня — нет XML и нет MSBUILD-элементов.
И конкретно у меня задача парсинга .sln уже решена, мне хватает
(это та самая библиотека CWDev.SLNTools которая занимается тем, что мержит солюшены)
То есть для зависимость записана в .csproj для определения наличия зависимости .sln не нужен.
Конечно, хорошо бы и код работы с .sln переписать, чтобы сохранялось форматирование. Но я спрашивал про проектирование абстрактно,
если мне дадут методику для .csproj,
то для .sln, .nuspec, .package и .config я её уже сам применю по-аналогии.
S> Я правильно понял, что оно нужно для того, чтоб заменить существующую инфраструктуру sln/csproj/msbuild?
нет, неправильно. Я согласен и на интеграцию. Просто существующая реализация этой инфраструктуры не решает мои задачи.
А мне надо, чтобы они решались.
S>* У меня есть x S>* Я хочу получить y, затратив z1 и с дополнительными условиями z2 S>* для этого мой фреймворк должен уметь a, b и c. S> Вы расписываете только последнюю часть, да и то отдельные частные случаи, из которых первые два пункта не восстановишь.
Я это делаю СПЕЦИАЛЬНО для того, чтобы акцентировать внимание именно на задаче разработки фреймворка.
Если я опишу общую задачу, разговор уйдет в нейронные сети или ещё куда не туда свернёт.
Скажете, "нет, это слишком сложно" и на этом обсуждение закончится.
С другой стороны, написать технико-экономическое обоснование того,
что мой фреймворк подарит миру больше счастья меньшими суммарными усилиями жителей планеты
чем сушествующий multiple framework от microsoft
мне пока трудновато.
Здравствуйте, Arsen.Shnurkov, Вы писали:
S>>Цитату плиз. AS>2.1 PROGRESSIVE FRAMEWORKS AS>Designing a single framework for a broad range of developers, scenarios, and languages is a difficult and costly enterprise.
Так, давай наконец как-то чётче формулировать свои мысли. А то внезапно
Вы путаетесь. Сначала вы (ссылаясь на FDG) говорили, что при дизайне фреймворка
нужно рассматривать максимально широкий спектр задач потенциальных пользователей.
превращается в цитату, которую я не приводил, и которая ещё и понята неверно.
AS>Но указывают, что если фреймворк прогрессивный, то сценариев он покрывает как правило много.
Гхмм... вообще-то там говорится о переходе от отдельных узкоспециализированных фреймворков (mfc/atl, как пример) к фреймворку как к платформе, которая включает в себя разные наборы API для разных задач.
Т.е. широта охвата — это не отдельное API-всемогутор, а возможность использовать в одном приложении разные API от разных вендоров без особых проблем, т.к. они выполнены в общем архитектурном стиле.
The main drawback3 is that the multitude of frameworks makes it difficult for developers using one of the frameworks to transfer their knowledge to the next skill level or scenario (which often requires a different framework). For example, when there is a need to implement a different application that requires more powerful functionality, developers hit a very steep learning curve, because they have to learn a completely different way of programming,
______ 3Other drawbacks include slower time to market for frameworks that are wrappers on top ofother frameworks, duplication of effort, and lack of common tools.
AS>Итак, текущее состояние обсуждения:
А, как обычно — с каждой стороны выглядит по своему
За всех участников не скажу, но как минимум я точно никаких набросов аля "ты дурачок" делать не собирался, если так было воспринято — мои извинения. Серьёзно, сорри.
Насчёт остального — да, фреймворки это сложно. Не в том смысле сложно, что "не знаешь — не лезь и даже не пытайся", это дурость полная. Тут любой проектировщик API в одинаковых условиях будет. Смысл в том, что на начальном этапе очень легко допустить ошибки, которые потом так и останутся. Или, в лучшем случае, просто сделать кучу работы на выброс.
Поэтому перед тем как "делать что-то" обязательно надо определиться, что именно должно получиться в итоге и провести предварительную разведку. Если такой подход не нравится, то можно посмотреть на альтернативу — проектирование от паттернов — но это уже к яве.
А вот определиться у нас хронически не получается, не в последнюю очередь из-за того, что тебе пишут одно а ты воспринимаешь совсем другое. Серьёзно. Сформулируй наконец ответ на простой вопрос: какие ключевые сценарии использования у будущего фреймворка. Я не про отдельные фичи, а про проблемы, которые с его помощью можно решать, типовой шаблон "что есть-что надо-ограничения" в прошлом посте писал. После этого уже можно будет определиться с тем, что брать за основу — всё с нуля, форк проекта, или просто набор хелперов поверх библиотеки и уже тогда задумываться об архитектуре.
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Наличие зависимости запросто определю — увижу в .csproj элемент Reference вместо ProjectReference. AS>То есть для зависимость записана в .csproj для определения наличия зависимости .sln не нужен.
Подвох не заметили. Имя проекта — B. Имя бинарного файла для этого проекта — somelib.dll, причём у отдельных эстетов оно ещё и от build conditions зависит. Без разбора зависимостей в sln-файлах правильно сопоставить зависимости даже в средних солюшнах из пары сотен пректов — это тот ещё гемморой. В общем .sln надо парсить обязательно. А то на первой же копии проекта, не включённой в солюшн всё обломается.
AS>если мне дадут методику для .csproj, AS>то для .sln, .nuspec, .package и .config я её уже сам применю по-аналогии.
Как охранять форматирование при записи xml-документов? Вот точно помню, что там был какой-то подвох, поищу. Вот это за основу + XmlWhitespace и IXmlLineInfo для форматирования новых тегов / атрибутов.
DO understand and explicitly design for a broad range of developers with different programming styles, requirements, and skill levels.
...
Therefore the Word team puts in many more features that my mom might find helpful rather than the features the development team finds helpful.
Ну вот я и пытаюсь сделать такой фреймворк, чтобы он решал задачи, которые мне кажутся полезными в принципе, а не только те, которые нужны в ближайшие две недели.
Примеры задач, решение которых должен обеспечивать фреймворк:
1) дан .csproj и пожелания по его изменению (в каком-то формате, например как вызовы API).
Нужно сформировать патч в формате RFC 5261 (не помню номер точно, в общем есть RFC на XML Diff) минимального размера с минимальным количеством операций
2) сформировать обычный патч для diff минимального размера
3) просто изменить непосредственно .csproj, породив минимум разницы (а не переформатирвов все отступы во всём файле)
Уже поверх этого я собираюсь навернуть БД nupkg и всю остальную логику по
скачиванию архивов, распаковне, анализу nuspec, скачиванию исходников, дополнительным файлам с метаданными,
изменению и обновлению зависимостей
и это в scope фреймворка не входит.
Текущие инструменты не дают возможностей для точечных изменений. Это раздельные мелкие фреймворки — либо только для XML, либо только для build items и т.д.
S> Имя проекта — B. Имя бинарного файла для этого проекта — somelib.dll
да не парит меня это. И я уже написал почему. Потому что солюшены я и так читаю во-первых,
а во вторых — моя задача разобрать репозиторий на отдельные проекты, а не собрать.
Соберется оно потом само, потому что dll-ки встанут в GAC и найдутся через Reference-ы, которые я пропатчу.
А каждый проект будет собираться независимо от своего .sln
I believe that LoadOptions.PreserveWhitespace and SaveOptions.DisableFormatting only instruct XDocument on how to handle whitespace in terms of indentation and the content of text nodes. It would still normalize the attributes, etc.
You may wish to use an overload where you specify an XmlWriter that is configured to do what you want, and if you can't find a configuration that works with the default XmlTextWriter, you could always create your own XmlWriter.
XDocument.Save has a SaveOptions argument which can be set to disable formatting. This has the same effect as putting the XmlWriterSettings "Indent" property to "false"
У меня мысль была — раз рослин служит для создания редакторов разных синтаксисов,
то научиться описывать синтсаксис .csproj для Roslyn как платформы.
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Примеры задач, решение которых должен обеспечивать фреймворк:
О, ну так гораздо интереснее получается. Забавная штука должна выйти если не секрет, для чего? Это уже не в рамках темы, просто любопытно.
Вот что я точно могу подсказать — это сохранение форматирования при правке. Тут два варианта. Или используем XDocument с preserve whitespace = true + расставляем XmlWhitespace для новых тегов / атрибутов, или, если документ целиком нельзя держать в памяти, городим свой visitor поверх пары xml reader + xml writer, как всё в том же XDocument.
Всё остальное — это уже на ваш выбор. Я бы обратил внимание на следующее:
1. Семантическая модель для csproj и прочих xml-based форматов. Она вам поможет, но не очень сильно, т.к.
* csproj позволяет очень много вольностей, вот это к примеру — валидный файл
* куча зависимостей может быть разобрана некорректно, особенно если они помечены как conditional symbols или спрятаны в Import.
В общем, если делать — посмотрите, как сделаны типизированные теги в OpenXml SDK (наследниками от XElement). Что-то более сложное будет выглядеть оверкиллом
2. Обработка csproj xml-патчем. Будет хорошо работать только при условии, что csproj не правился кардинально. Ну и кроме того, что-то я не припомню готовой реализации этого дела на шарпе.
Может, отказаться от этого функционала и сразу превращать пожелания по изменению проекта в код, который правит xml / семантическую модель?
А это дубовый вариант как раз, без сохранения форматирования. В общем тут три варианта сходу нарисовываются:
* или вообще забить на форматирование атрибутов (ага, именно в этом был подвох, спасибо, что напомнили),
* или делать мегаизвращение — вытаскивать начало-конец элемента через XmlLineInfo и заменять текст между ними новым значением.
* или городить свою логику поверх xmlReader с запоминанием позиций элементов, кавычек (ага, одиночные заменяются на двойные) и кучу других вещей.
UPD ещё модно поспрошать kirill osenkov, он в своё время делал парсер xml на базе рослина
Нам в своё время хватило первого варианта, т.к. csproj-файлы редко форматируются нестандартным способом.
Он может быть и парсер,
но не очень похож на API для изменения. Узлы там поудалять, повставлять я не вижу как с помощью этой библиотеки...
Допустим надо превратить Reference в ProjectReference. То есть один узел удалить, другой (в другое место) вставить. И чего?
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Он может быть и парсер,
Ну так я ж не зря сказал про "поспрошать kirill osenkov" Он по крайней мере подскажет куда копать. В недрах студии xaml lang services точно на roslyn, насчёт xml не уверен.
S> Что-то более сложное будет выглядеть оверкиллом
А сложнее нужно.
Потому что очевидным образом есть два уровня абстракции — просто проекты msbuild
и конкретно шарповые проекты, у них, например, бывают конфигурации с именами. А имена конфигураций — это важно.
AS>Потому что очевидным образом есть два уровня абстракции — просто проекты msbuild AS>и конкретно шарповые проекты, у них, например, бывают конфигурации с именами. А имена конфигураций — это важно.
Конфигурации работают с любыми msbuild-проектов и не является обязательными. Я ж выше приводил пример csproj-файла без конфигураций.
Пропись конфигов ч/з SolutionConfigurationPlatforms и ProjectConfigurationPlatforms в .sln-файле — лишь один из способов.
Microsoft's own recommendation for API developers and developers of third-party libraries is that they use the Collection<T>, KeyedCollection<TKey, TItem>, and ReadOnlyCollection<T>.
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Если хочется иметь полный контроль над всем, AS>но при этом не давать доступ к нижним уровням на прямую,
По-моему, ключевое противоречие зарыто здесь.
Нельзя в одной архитектуре объединить полный контроль всего и абстрагирование пользователей интерфейсов от деталей реализации, т.к. они влекут за собой противоположные решения и последствия.
Здравствуйте, Arsen.Shnurkov, Вы писали:
AS>Итак, текущее состояние обсуждения:
AS>Q) мне нужен фреймворк. AS>A) ты дурачок, фреймворки это сложно, тебе фреймворк не нужен, есть полно готовых решений (более 10 способов)
такое бывает)
Хорошо бы конкретизировать ваш случай деталями, а именно — какие именно есть слои с кратким описанием сути и для какого сценария надо выставить апи более нижнего слоя...