Пространства имен и структуры папок в решениях С#: как должны быть организованы папки на диске?
Прежде всего, давайте соглашаемся с тем, что пространство имен должно соответствовать структуре папок и что каждый артефакт языка должен находиться в собственном файле.
(см. Если папки в решении совпадают с пространством имен?).
Следующий вопрос заключается в том, как папки на самом деле должны быть организованы на диске.
Предположим, что у меня есть ClassC в пространстве имен A.B.C и ClassD в пространстве имен A.B.C.D.
Также предположим, что каждое пространство имен встроено в собственную сборку (проект) и что пространства имен имеют зависимости справа налево в соответствии с принятой наилучшей практикой (A.B.C.D может зависеть от A.B.C, которая может зависеть от A.B, которая может зависеть от A). Я понимаю, что каждое пространство имен не должно быть в отдельной сборке, но в общем случае у нас будут отдельные пространства имен в отдельных сборках, и мой пример иллюстрирует это.
Я вижу (по крайней мере) два способа создания дерева папок - которые я вызываю "вложенные папки" и "плоские папки":
1 - Вложенные папки:
а
--A.csproj
-В
---- A.B.csproj
---- C
------ A.B.C.csproj
------ classC.cs
------ D
-------- A.B.C.D.csproj
-------- classD.cs
ИЛИ
2 - Плоские папки:
а
--A.csproj
A.B
--A.B.csproj
A.B.C
--A.B.C.csproj
--classC.cs
A.B.C.D
--A.B.C.D.csproj
--classD.cs
Вы увидите, что Ive сделал несколько предположений:
- Каждый файл проекта имеет полное имя (FQN) на основе пространства имен.
- Каждый файл класса использует не-FQN
Вложенные папки кажутся более естественными (все мы похожи на иерархии), но может быть немного сложнее ориентироваться в больших решениях:
Когда вы смотрите на свое решение в VS, он показывает плоский список проектов, а не вложенное представление. Это больше похоже на "плоские папки", поэтому может быть полезно организовать папки на диске в соответствии с представлением в VS.
Если вы посмотрите в каждой папке на диске, вы увидите артефакты папки для этого проекта плюс подпапку для пространства имен: в качестве примера возьмем C:
C
--bin
-D,
--obj
--Properties
--A.B.C.csproj
--classC.cs
В зависимости от реального имени Ds может быть не очевидно, что D является папкой пространства имен, а не организационной папкой в пространстве имен C.
Я знаю, что у weve были папки и пространства имен с первого дня в .NET(8 или 9 лет назад) и Java до этого, но, лично говоря, мы, похоже, не пришли к консенсусу в отношении лучшей организации проекта для крупных решений, Мне действительно интересно узнать, что вы все думаете.
Спасибо
Майкл
Ответы
Ответ 1
Я использую плоский подход. Я считаю, что вложенную иерархию слишком сложно поддерживать. Я группирую свои проекты в несколько решений, с максимальным повторным использованием и перекрестными ссылками, и всегда считал это удовлетворительным. Пример (с отступом):
CompanyName
CompanyName.Core
Class1
Struct2
Enum3
CompanyName.Data
CompanyName.Web
CompanyName.Projects
CompanyName.Projects.Core
CompanyName.Projects.ProjectX
CompanyName.Projects.ProjectX.Core
CompanyName.Projects.ProjectX.Website
CompanyName.Projects.ProjectX.ToolY
и т.д.. и др.
Изменить: удалить замечание о бессмыслице
Ответ 2
Я не большой поклонник вложенных проектов, поскольку он зарывает проекты глубоко внутри структуры, и если вам нужно повторно использовать этот проект в другом приложении, то что вы делаете, скопируйте/вставьте код?
Мне нравится следовать некоторой плоской структуре, но организованной пространством имен.
Вот как я это делаю:
- DataHelpers\
---Factory\
---DataAccess\
---...
- Components\
--- EmailProcessor\
--- ErrorLogger\
- Desktop\
--- WindowsApp1\
- Services\
--- WindowsService1\
--- WindowsService2\
- WebApps\
--- WebApp1\
--- WebApp2\
Теперь, внутри каждого основного приложения у меня есть, например:
- WindowsService1\
--- WindowsService1\ (this contains all *.cs, bin, obj, etc and .csproj file)
--- Solution\ (this contains the .sln file where you link to other projects like ErrorLogger, etc)
Надеюсь, это имеет смысл!
Ответ 3
"Прежде всего, давайте соглашаемся с тем, что пространство имен должно соответствовать структуре папок и что каждый артефакт языка [sic] должен быть в собственном файле."
Забавно, что пакеты работают на Java. Я всегда думал, что нарушение связи между пространствами имен и структурой каталогов считается одним из улучшений, внесенных С#. Разве это не так? (Простите мое невежество, я человек Java.)
Ответ 4
Я всегда делал вложенную иерархию. Это становится болезненно очевидным, когда добавлять новые проекты к существующему решению и сохранять ваши пространства имен хорошо организованными на диске. Это также делает очерчивание пространства имен по сравнению с проектом более очевидным.
Ответ 5
Если вы используете вложенные проекты, вы рискуете попасть в окна MaxPath.
Это огромный инструмент для прерывания работы, когда-либо использующий вложенные структуры. Представьте себе, что встретите этот маленький Gem на полпути, хотя проект Dev, который должен назвать проекты VS с 3-буквенными аббревиатурами, чтобы не попасть в MaxPath. Ошибка MS заканчивается как вдохновение для имен ваших сборок. Какая шутка. Работа с плоскими структурами намного лучше вокруг.
-SouceControlFolderName
-Project1
-Src
-Main
-Company.Project1.AppName
*Company.Project1.AppName.sln
*Company.Project1.AppName.Tests.sln
-Company.Project1.AppName.Common
-Company.Project1.AppName.Common.Tests
-Company.Project1.AppName.Entities
-Company.Project1.AppName.Entities.Tests
-Company.Project1.AppName.Security
-Company.Project1.AppName.Security.Tests
-etc.
Вы можете создать отдельный каталог для тестовых проектов или, как указано выше, и объединить их все вместе, что легче управлять при добавлении в исходный элемент управления, т.е. Subversion (TFS лучше во многом сэкономить на том, что ему нужна интеграция с Explorer не только VS интеграции и надлежащего офф-лайн истории)
Ответ 6
Я думаю, вам нужно определить точку отсечения, где плоский подход больше не работает. Например, если у вас типичная трехуровневая архитектура в небольшом проекте, отсутствие трех проектов на внешнем уровне не представляет проблемы. Однако, если у вас есть несколько десятков, то какая-то группировка помогает сегментировать функциональность и делает все решение более понятным.
Ответ 7
Я предпочитаю плоскую структуру с проектами в корне.
- MyCorp.Core
- MyApp.Domain
- MyApp.Datali >
- MyApp.UI
- MyApp.Test
Внутри них у меня есть разные папки и пространства имен. Я создаю разные сборки для развертываемых устройств. У небольших приложений даже не будет такого разделения. ИМО все это упрощает. Если я когда-либо решаю, что код, который мне нужен, должен использоваться в другом месте, достаточно легко разбить его на сборку, если это необходимо, если я соблюдаю хорошие методы управления именами.