BOs are essentially your domain objects, or at least that's my guess. In general, if you are not using a template such as ActiveRecord, these are just state objects. The interface, on the other hand, defines behavior. Not a good concept, out of many “best practices,” to mix behavior and state. Now I’m most likely going a bit, but I think the background can help.
Now, to the question of where the interfaces should exist. There are several options.
- Insert the interfaces into the library to which they belong.
- Create a separate contract library
It’s easiest to stick to them in the same library, but then your layouts rely on the library as well as your tests. Not a huge deal, but it has a slight smell.
My usual method is to create such projects:
{company}. {program / project}. {worry (optional)}. {area}. {subarea (optional)}
The first two or three bits of the name are covered by the word "CentralRepository". In my case, it will be MyCompany.CentralRepository or MyCompany.MyProgram.CentralRepository, but the naming convention is not the main part of this post.
Parts of the "area" are the target of this post, and I usually use the following.
- Setting up a library of domain objects (your BO): CentralRepository.Domain.Models
- Domain Exception Library Configuration: CentralRepository.Domain.Exceptions
- All / most other projects refer to the two above, as they represent the state in the application. Of course, all business libraries use these objects. The sustainability library may have a different model, and I may have a presentation model in the experience library (s).
- Set up the main library as follows: CentralRepository.Core (can have subareas?). this is where the business logic lies (the actual application, because persistence and changes in experience should not affect the core functions).
- Set up a test library for the kernel: CentralRepository.Core.Test.Unit.VS (I have Unit.VS to show this unit tests, not integration tests with the unit test library, and I use VS to indicate MSTest - others will have different names).
- Create tests, and then customize business functionality. Configure the interfaces as needed. Example
- Data from DAL is needed, therefore, for the data used for Core tests, the interface and layout are configured. The name here will be something like CentralRepository.Persist.Contracts (a subarea can also be used if there are several types of persistence).
The main concept here is “Core as Application”, not the n-level (they are compatible, but thinking only about business logic, as a paradigm, allows you to freely combine with perseverance and experience).
Now back to your question. The way to configure the interfaces is based on the location of the "conjugate" classes. So I will probably have:
CentralRepository.Core.Contracts CentralRepository.Experience.Service.Contracts CentralRepository.Persist.Service.Contracts CentralRepository.Persist.Data.Contracts
I am still working with this, but the basic concept is my IoC, and testing should be considered, and I should be able to isolate testing, which is better achieved if I can isolate contracts (interfaces). Logical separation is fine (one library), but as a rule, I do not head this way because there are at least a couple of green developers who find it difficult to see logical separation without physical separation. Your mileage may vary .: -0
Hope this mess helps in some way.