webForumDet fria alternativet

Projektuppdelning i Visual Studio

.NET

13 svar · 814 visningar · startad av Lukaspojken

Medlem sedan maj 20011 312 inlägg
Frågan#1

Jag gillar inte när det blir för många projekt i en solution men det är inte lätt :) I detta inlägg skulle jag gärna vilja försöka få fram en bra generell uppdelning av projekt och namespaces. Vad tror ni om följande uppdelning (som är DDD-inspirerat)?

• MyApp.AppData
  - FileUpload
  - Log
• MyApp.Database (Databasen versionshanterad)
• MyApp.Domain
  - MyApp.Domain.Aggregates
  - MyApp.Domain.Entities
  - MyApp.Domain.Factories
  - MyApp.Domain.Repositories
  - MyApp.Domain.Services
  - MyApp.Domain.ValueObjects
• MyApp.Infrastructure
  - MyApp.Infrastructure.Caching
  - MyApp.Infrastructure.DebugUtils
  - MyApp.Infrastructure.ExceptionHandling
  - MyApp.Infrastructure.Logging
  - MyApp.Infrastructure.Security
  - MyApp.Infrastructure.Smtp
  - MyApp.Infrastructure.Sql
  - MyApp.Infrastructure.Utils
• MyApp.Test
  - MyApp.Test.IntegrationTests
  - MyApp.Test.UnitTests
• MyApp.Web
  - ClientScripts
  - Css
  - Images
  - MyApp.Web.DebugUtils
  - MyApp.Web.MasterPages
  - MyApp.Web.UserControls
• MyApp.WebServices

Är det något projekt som bör läggas till? Tas bort? Bytas namn på? Något sub-namespace som ni brukar ha?

En snarlik uppdelning finns i detta blogginlägg:
http://andreasohlund.blogspot.com/2008/02/structuring-of-projects.html

Medlem sedan aug. 20003 575 inlägg
#2

- MyApp.Domain.Entities
Hade jag lagt direkt under MyApp namespace direkt.
Då slipper jag använda using i varje klass där jag arbetar med min modell som är den jag arbetar med mest.

MyApp.Core
- MyApp - namespace
- MyApp.Repositories - namespace (inte nödvändigtvis ett eget namespace, beror lite på storlek, kan lika gärna ligga direkt under MyApp).

ValueObjects hade jag inte sorterat in i ett eget namespace utan tycker att det lika gärna kan ligga med entiteterna, samma sak med Aggregates.

Medlem sedan maj 20011 312 inlägg
#3

Om jag förstår dig rätt så skulle du också vilja ändra på MyApp.Domain till MyApp.Core. Är det så du tänker?

Medlem sedan aug. 20003 575 inlägg
#4

Nej MyApp.Core är assembly namnet (bara ett namn inget viktigt), men jag tycker man kan skippa att ha namespace domain eftersom jag anser att domänmodellen är kärnan av allting och bör därför ligga i rootnamespacet där alla namespace under domänmodellen automatiskt känner till rootnamespace't.

Medlem sedan maj 20011 312 inlägg
#5

Men tycker du att assemblynamnet MyApp.Core är bättre än MyApp.Domain. Jag har sett på vissa ställen där man använder sig av Core. Vad tycker du?

Angående namespacet skulle du vilja ha det så här istället, dvs använda mappar och utan namespace. Jag förstår ditt argument för det men jag är osäker på om det är rekommenderat att göra så här.

• MyApp.Domain
  - Aggregates 
  - Entities
  - Factories
  - Repositories
  - Services
  - ValueObjects

Jag har funderat lite på detta med Aggregates och jag kanske skulle kallat det för EntitySets istället. Jag skulle nog kunna gå med på att lägga det under Entities-mappen men jag skulle nog inte vilja blanda entities och entitisets. (Jag gillar dock mer ordet aggregates än entitysets för det fångar in mer än entitysets känns det som...hmmm).

Det kan inte vara bra att skilja på vad som är ValueObjects och Entities? Jag håller dock med dig om att det blir lite konstigt med strukturen när jag tänker efter. Kanske skulle följande struktur vara bättre:

• MyApp.Core
  - Domain
     - EntitySets
     - Entities
     - ValueObjects
  - Factories
  - Repositories
  - Services
Medlem sedan aug. 20003 575 inlägg
#6

Mm, möjligtvis att man hade gett repositories, services och kanske factories egna namespace att ligga i. Så hade jag gjort det iallfall.

Detta för att undvika för många heirakier med namespace.

Medlem sedan maj 20011 312 inlägg
#7

Ok, alltså så här:

• MyApp.Core
  - Domain
     - EntitySets
     - Entities
     - ValueObjects
  - MyApp.Core.Factories
  - MyApp.Core.Repositories
  - MyApp.Core.Services

Någon som håller med eller har andra tankar?

Medlem sedan aug. 20003 575 inlägg
#8

Lukaspojken skrev:

Ok, alltså så här:

• MyApp.Core
  - Domain
     - EntitySets
     - Entities
     - ValueObjects
  - MyApp.Core.Factories
  - MyApp.Core.Repositories
  - MyApp.Core.Services

Någon som håller med eller har andra tankar?

haha nej, glöm Core när det gäller namespace.

MyApp
Här ligger alla entiteter, valueobjects samt collections.
MyApp.Factories
MyApp.Repositories osv...

om applicationen inte är så stor så tycker jag det kvittar att dela upp det i olika namespace t.ex. om repositories är färre än 3-4 st.

Sedan kanske MyApp skall vara

Företagsnamn.ProjektNamn men det kan vara en nackdel om företaget senare byter namn osv.

Medlem sedan maj 20011 312 inlägg
#9

Jag är lite osäker på om det kvittar :) För applikationener har en tendens att växa så det är lika bra att göra uppdelningen direkt så slipper man lägga tid på refactoringen sedan. Fördelen med att göra det direkt är också att de olika projekt man jobbar i har en och samma struktur.

Jag var i ett projekt där vi delade upp till och med entities för att det var så många. Det såg ut ungefär så här:

MyApp.Domain
 - Entitities
    - Containers
    - Resources

På detta sätt blev det lättare att ha koll på vilken basklass och subklasser som hörde till tex Containers m.m.

Jag är inte för Företagsnamn.ProjektNamn utan enbart Applikationsnamn. Oftast finns det ingen vinst att ta med företagsnamnet och jag har varit med om de tillfällen då man haft denna struktur och varit tvugna att byta för att man fått ett nytt företagsnamn.

Jo, en sak till :) När du säger: "Här ligger alla entiteter, valueobjects samt collections." Vill du inte ha några mappar heller utan lägga allt i rotkatalogen för MyApp.Domain (jag förstår dock att du inte vill ha namespace)?

Medlem sedan aug. 20003 575 inlägg
#10

Hmm hur skall jag förklara det bra :).

Jag anser i att de flesta fall så blir inte domänmodellen så jättestor utan i större projekt kanske du har flera olika domänmodeller. för en 20 entiteter fungerar detta sättet utmärkt.

ApplicationName.Core (Assembly namn dvs *dll)
  Collections (mapp och namespace)
      - OrderCollection.cs
      - CustomerCollection.cs
   Repositories
      - ICustomerRepository (brukar lägga implemmentationen av repositoryn i en annan dll.)
      - IOrderRepository
  - Order.cs (ligger under rooten)
  - Customer.cs

http://www.webforum.nu/attachment.php?attachmentid=19780&stc=1

Untitled.jpg
Medlem sedan maj 20011 312 inlägg
#11

Jag gillar inte det där med rotkatalogen (jag får tänka på saken) :)

Sedan har du en mapp för Collections som jag inte har. Jag antar att när du tex hämtar en orderkollektion så returnerar du OrderCollections. Hur kommer det sig att du inte returnerar tex IList<Order> istället? Med hjälp av genererics så slipper man skapa egna kollektionsklasser.

Jag har pratat med lite folk och utifrån dessa diskussioner så ser uppdelningen ut så här för tillfället:

• MyApp.Web
  - ClientScripts
  - Css
  - Images
  - MyApp.Web.DebugUtils
  - MyApp.Web.MasterPages
  - MyApp.Web.UserControls
• MyApp.ApplicationData
  - FileUpload
  - Log
• MyApp.Test
  - MyApp.Test.IntegrationTests
  - MyApp.Test.UnitTests
• MyApp.WebService.X
• MyApp.Batch.X
• MyApp.Service.X
• MyApp.Core.X
  - MyApp.Core.X.Domain
     - Classdiagrams (Katalog för klassdiagram)
     - MyApp.Core.X.Domain.EntitySets
     - MyApp.Core.X.Domain.Entities
     - MyApp.Core.X.Domain.ValueObjects
  - MyApp.Core.X.Factories
  - MyApp.Core.X.Repositories
• MyApp.Infrastructure
  - MyApp.Infrastructure.Caching
  - MyApp.Infrastructure.DebugUtils
  - MyApp.Infrastructure.ExceptionHandling
  - MyApp.Infrastructure.Logging
  - MyApp.Infrastructure.Security
  - MyApp.Infrastructure.Smtp
  - MyApp.Infrastructure.Sql
  - MyApp.Infrastructure.Transaction
  - MyApp.Infrastructure.Utils
• MyApp.Database.X (Databasen versionshanterad)
Medlem sedan aug. 20003 575 inlägg
#12

Lukaspojken skrev:

Jag gillar inte det där med rotkatalogen (jag får tänka på saken) :)

Sedan har du en mapp för Collections som jag inte har. Jag antar att när du tex hämtar en orderkollektion så returnerar du OrderCollections. Hur kommer det sig att du inte returnerar tex IList<Order> istället? Med hjälp av genererics så slipper man skapa egna kollektionsklasser.

Jag har pratat med lite folk och utifrån dessa diskussioner så ser uppdelningen ut så här för tillfället:

• MyApp.Web
  - ClientScripts
  - Css
  - Images
  - MyApp.Web.DebugUtils
  - MyApp.Web.MasterPages
  - MyApp.Web.UserControls
• MyApp.ApplicationData
  - FileUpload
  - Log
• MyApp.Test
  - MyApp.Test.IntegrationTests
  - MyApp.Test.UnitTests
• MyApp.WebService.X
• MyApp.Batch.X
• MyApp.Service.X
• MyApp.Core.X
  - MyApp.Core.X.Domain
     - Classdiagrams (Katalog för klassdiagram)
     - MyApp.Core.X.Domain.EntitySets
     - MyApp.Core.X.Domain.Entities
     - MyApp.Core.X.Domain.ValueObjects
  - MyApp.Core.X.Factories
  - MyApp.Core.X.Repositories
• MyApp.Infrastructure
  - MyApp.Infrastructure.Caching
  - MyApp.Infrastructure.DebugUtils
  - MyApp.Infrastructure.ExceptionHandling
  - MyApp.Infrastructure.Logging
  - MyApp.Infrastructure.Security
  - MyApp.Infrastructure.Smtp
  - MyApp.Infrastructure.Sql
  - MyApp.Infrastructure.Transaction
  - MyApp.Infrastructure.Utils
• MyApp.Database.X (Databasen versionshanterad)

Collections var mer ett exempel på underkategori kan bytas ut mot Factories osv, inte ofta man behöver ha Collections men nej det är inget som en repossitory retunerar utan isåfall något som ligger på domänobjektet då vissa collections kanske har specialmetoder, har dock börjat gå mer åt att entiteten har dessa metoder på sig själv, men som du säger IList<T> är det bästa valet om man inte vill ha specialmetoderna för eventuella utsökningar på listan.

Medlem sedan juni 20003 076 inlägg
#13

Jag skulle vilja lufta en idé om projektuppdelning med er.
Har ett typ av ett cms med ett antal moduler såsom menyhantering, nyheter, forum osv...
Det är placeringen av dessa moduler jag funderar på.
Så här gör jag nu när jag skapar en ny modul:
Entiteterna åker in i entitetsprojektet, affärs/service-koden läggs i serviceprojektet, webbfilerna åker in i webapplikationen osv. dvs allt känns väldigt utspritt och blir ett pussel om jag skulle vilja återanvända modulen till annat projekt.

Nu skriker ni säkert rakt ut men vore det helt galet att stoppa alla filerna i ett eget projekt istället? Det kanske inte ens är möjligt att lyckas kompilera ihop det så!? :q

Medlem sedan feb. 200563 inlägg
#14

Lukaspojken skrev:

Någon som håller med eller har andra tankar?

Jag tycker det är mest naturligt att i stället gruppera domain-modulerna per aggregate, och alltså inte använda några namespaces som heter Aggregates, Entities, ValueObjects, Factories, eller domain.Repositories (med repository-interfacet).
(däremot kan man möjligen använda sig av en persistance-modul persistance.Repositories med implementationerna av repository-interfacen)
Denna grund-strukturen används i DDD sample application, där Eric Evans själv är medlem (därmed inte sagt att han är den generellt främsta experten på struktureringen av alla layers, men inom domain layer är han förstås en tungviktare).
Se även sidan "On layering in DDDSample" som bl.a. skriver så här:

...A pretty obvious decision was to place each aggregate in its own subpackage below domain, so we had domain.cargo, domain.handling and so on...

Här finns ett klassdiagram (dock ej heltäckande med samtliga klasser) för exempelapplikationen:
http://dddsample.sourceforge.net/characterization.html
Som ni ser finns det en Cargo aggregate med en root entity som heter Cargo samt några value objects. Däremot visar inte diagrammet något repository men om man laddar ner koden så ser man att repository-interfacet också ligger i samma paket. Däremot finns det ingen Cargo-factory där men om det hade funnits så hade det varit naturligt att placera den där också i samma paket som repository-interfacet.

Domain services har de placerat i ett eget paket (och ett "paket" är f.ö. java's motsvarighet till .NET namespaces) medan de har alla aggregates i ett "model"-subpaket som är parallell till "services"-paketet, dvs så här ser några av paketnamnen ut:

se.citerus.dddsample.domain.service
se.citerus.dddsample.domain.model.cargo
se.citerus.dddsample.domain.model.handling
se.citerus.dddsample.domain.model.location

När det gäller var implementationen av ett repository ska placeras så är det nog inte lika självklart. De hade placerat den i application layer, vilket jag m.fl. redan har diskuterat på DDD Sverige (i tråden "Paketnamn") så mina synpunkter om detta har jag inte för avsikt att duplicera till denna tråd...

/ Tomas

284 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
127 ms — deklarationer (db)
0 ms — hämta statistik (cache)
154 ms — hämta tråd, inlägg och bilagor (db)
121 ms — ändringar (db)