0

Based on the project structure below i will have some questions

  • Domain Layer

1) MyApp.Domain.Entities (DLL)

Product.cs

PagedResult.cs

Referentes

No References

2) MyApp.Domain.Interfaces (DLL)

IUnitOfWork.cs

IProductRepository.cs

Referentes

MyApp.Domain.Entities

3) MyApp.Domain.Common.Interfaces (DLL)

IClock.cs

ICryptography.cs

ILogging.cs

Referentes

No References

  • Infrastructure Layer

1) MyApp.Infrastructure.Logging

Will implement the interface ILogging

Referentes

MyApp.Domain.Common.Interfaces

2) MyApp.Infrastructure.Cryptography

Will implement the interface ICryptography

Referentes

MyApp.Domain.Common.Interfaces

4) MyApp.Infrastructure.Data

Will implement the interface IUnitOfWork.cs e IProductRepository.cs

Referentes

MyApp.Domain.Entities

MyApp.Domain.Interfaces

------------------------------ Questions ---------------------------------

A) In my Domain Layer I have MyApp.Domain.Common.Interfaces that will keep interfaces that can be used for all project, this interfaces will represent common elements that whole project can use and will be implemented at Infrastructure Layer.

Am I breaking some Onion Architecture rule having it in my Domain Layer?

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Harry Axl
  • 11
  • 6
  • Common libraries live outside of the domain of the onion architecture, and are treated the same way as they are in any other application. The trick is to respect the boundaries of each layer and their purpose. See [here](http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) for advice on how to manage the layer boundaries. – Robert Harvey Dec 18 '18 at 17:48
  • See also https://softwareengineering.stackexchange.com/q/360850 – Robert Harvey Dec 18 '18 at 17:53
  • Robert Harvey, After reading the links you sent i think i'm at the correct way! Thank you so much for your attention! – Harry Axl Dec 19 '18 at 17:45

1 Answers1

1

I had the same problem with my app and from my investigation, it seems that most people think that this is a bad idea:

  1. When Entities make use of Repositories, ie: here
  2. When Entities make use of Services, this could be avoided by simple refactors, ie: here

In your case, it seems that the IClock and ICryptography is part of the delivery mechanism, not a domain and therefore they should live in the infrastructure layer. It is not clear why your Entities should depend on these. If they do not depend on that infrastructure then you shouldn't keep it in the Domain layer even if this is a common code for all project.

As for ILogging you can solve it by logging domain events produced by your Entities. This way the logging can be a part of a Repository that lives in the infrastructure layer. See here and here

  • Thank you so much for your attention grzegorz.kosciolek, I read the links you sent, below i highlight some points that can clarify doubts 1) I`m not working with DDD, what my MyApp.Domain.Entities has are several POCO entities that i got from Reverse Engineer Code first because i`m creating a new system based on a database created 15 years ago – Harry Axl Jan 07 '19 at 16:16
  • 2) In MyApp.Domain.Common.Interfaces I have the interfaces below A) "ICryptography" is extremmely important to my application, but after rethinking some points I only use "ICryptography" when i compose some objects at User Interface before sending them to my Service Layer. It will contain several methods thare are responsible for encrypt and decrypt information used for some specific entities and is extremely important – Harry Axl Jan 07 '19 at 16:16
  • B) "IClock" was removed from several places of my application and I concentrated everything in my context before saving, like shown in detail below It will contain a method that will return the current time based on some local time rules, and several entities of my domain use it, but after a refactory i only use it in my context like i show below – Harry Axl Jan 07 '19 at 16:17
  • public override int SaveChanges() { IClock i_Clock = new Clock(); foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("RegisterDate") != null)){ if (entry.State == EntityState.Added){ entry.Property("RegisterDate").CurrentValue = i_Clock.CurrentTime(); } if (entry.State == EntityState.Modified){ entry.Property("RegisterDate").IsModified = false; } } } – Harry Axl Jan 07 '19 at 16:17
  • C) "IValidation" i use only to verify User Input in my User Interface, but is also extremmely important to my app, because without it, my application will save invalid information I Kept the interfaces above in my MyApp.Domain.Common.Interfaces because they are extremely important to my Business, even if they are not used in all layers – Harry Axl Jan 07 '19 at 16:17
  • 3) In MyApp.Infrastructure.Utility I have interfaces and concrete implementations of them A) "IFileManagement": Saves and retrives files stored at disk associated with some entities. I only use it at User Interface because when i compose some objects i only send them to my service layer with the location of the file at disk B) "IEmailManagement": Send Emails in case of Server errors, only used at User Interface C) "ILogging": Log actions, only used at User Interface when data is committed – Harry Axl Jan 07 '19 at 16:18
  • 4) In MyApp.Infrastructure.Common I have the concrete implementations of MyApp.Domain.Common.Interfaces – Harry Axl Jan 07 '19 at 16:18
  • -> Summing up: **Domain Layer** _MyApp.Domain.Common.Interfaces (DLL)_ ICryptography; IClock; IValidation **Infrastructure Layer** _MyApp.Infrastructure.Common (DLL)_ Cryptography: ICryptography Clock: IClock; Validation: IValidation; _MyApp.Infrastructure.Utility (DLL)_ FileManagement: IFileManagement; EmailManagement : IEmailManagement; Logging: ILogging; – Harry Axl Jan 07 '19 at 16:29
  • Any criticism or suggestion will be very welcome and respected – Harry Axl Jan 07 '19 at 16:29