2

I have been reading a lot about repository implementation. I am confused about which way to implement it for a project I am sure would change its data layer methods because of db migration from MS Sql Server to NoSQL in a couple of years.

Imp #1

  • Implement Rep layer as a completely separate layer. This will have its own interface and conversion methods here. This rep layer has a dependency on DAL and in turn BLL will have a dependency on this layer

Imp#2

  • Implement Repository not as a separate layer but have its interfaces in Business Logic Layer and the methods in DAL.

I am leaning more towards imp #1 since it looks cleaner. However some explanations of experts I have read use imp#2. I think there must be a clear reason to use one over another according to the situation. I would ideally want our switch to a different database be as painless as possible.

  • Thanks for all the replies. These have been extremely helpful in determining which imp I need to adopt – Emma Feb 4 '15 at 17:12
1

The main reason you would have the interfaces for your repositories in your BLL is to avoid having hard references to the separate DAL but instead have your changing DAL reference the stable BLL.

To be able to swap out implementations without changing the stable BLL

On the internet this might not be the main reason in general, but this would be a compelling reason for me to prefer option 2 in your situation.

Let's assume that you are using a DI (dependency injection) container. If you configure this using a configuration file, for example, you would tell the container that the implementations for the repository-interfaces in the BLL can be found in the DAL.Sql project. Once you switch over to a NoSQL solution you would create the DAL.NoSQL project, deploy it and change the DI container configuration to resolve the implementations of the repository from the new project. Your new DAL depends on the stable BLL that does not need to change.

However, if you go with option 1, you might not be able to hot-swap the DAL project. If you use .NET for example you could run into issues where the BLL project depends on a certain version of the DAL dll and you would not be able to swap out the DAL without changing the BLL as well.

Because the repository interface is part of the BLL

A repository is merely a gateway that defines how your application will retrieve data. In that sense it is as much a part of the business logic as your domain objects. The concrete implementations can change, but the interfaces themselves are part of your business logic.

Because it isolates the BLL

Having the interfaces and implementations in the DAL means bringing all of the DAL into the BLL. There is nothing preventing developers from using objects from the DAL project in ways that they shouldn't be used. Having the DAL depend on the BLL means the BLL can only contain the interfaces that it needs.

To avoid a separate project with the domain objects

Your DAL and BLL both depend on your domain objects. If your BLL has a class that uses a repository and a domain object, you cannot put your repository interfaces into the DAL as that creates a circular reference (BLL needs interface for repository in DAL, DAL needs domain objects in BLL). So you would have to split the BLL and the domain objects into two projects so your BLL can reference the domain and the DAL and the DAL can also reference the domain.

  • this is extremely useful. I will definitely go with the imp #2. Although imp#1 made more sense to me before posting this question but I can now see why the second approach is much better...However I am not aware of creating domain objects in a separate project, In fact I am confused about the difference between business entities/objects and domain objects. but I think I will ask this question in a separate post :) Thanks very much! – Emma Feb 4 '15 at 17:25
  • Business entities or domain objects are pretty much the same thing: the central objects that represent the problem you are working. Customers, Orders, Products, etc... I'm used to thinking in term of Domain Driven Design so I call those things domain objects but I guess the terms are interchangeable. – JDT Feb 4 '15 at 20:09
  • Aha! That's what I was thinking when I posted this programmers.stackexchange.com/questions/272121/… "To me they seem to be a fancy name for business classes however more modelled towards your application domain but then most programmers I have worked with create business object/entities and try to model it as closely as possible to the actual application objects." – Emma Feb 5 '15 at 0:11
2

Sticking to option 1 will allow you to change the least amount of things when you switch from one database to another, thus the change should have the least impact on your application since only the files concerned with the database will need to be changed.

The business layer and any other layer which does not deal with the database should not care, nor know any implementation details. Thus, when you mention that ...and in turn BLL will have a dependency on this layer I am assuming that you would have a series of interfaces, such as IUserRepository or something like that which will define methods such as GetUserByName(string name), etc.

Layers on top of the repository will then consume these interfaces to suit their data needs, this would allow the business layer to know what the repository layer provides, but it will not include any implementation details. Thus, when you make the change, as far as the business layer is concerned, nothing is changed (assuming that you do not make any changes in the functionality provided by the repository layer).

  • Agreed completely and I would also recommend to pay attention to the design of persistence layer in regards to implementation (I know it sounds weird). NoSQL solutions are sometimes completely different beasts and you may be surprized, for example, by the lack of transactions or by the unability to construct a really complex condition which you did before with 50-lined SQL statement or by persisting data and then querying and finding out, that you've received old data instead of fresh. – Vladislav Rastrusny Jan 31 '15 at 20:01
1

@JDT's answer is correct. Imp#2 is the better option. The dependency inversion principle (DIP) as described by Robert C. Martin implicitly demands that if you have two modules A and Band an interface IB which is implemented by B and injected into A the definition of IB should be within the context of A.

Actually it's the second clause of the DIP that demands this:

Abstractions should not depend on details. Details should depend on abstractions.

In the case of BLL and DAL the BLL is the high level module und the DAL is the low level module. If the abstraction (the interfaces for the repositories e.g.) would be definied within the DAL then the abstraction (the interfaces) would depend on the details (the implementation). If the details change (e.g. when you swith to the NoSQL DB implementation) the abstraction/interfaces will also change and the high level module (the BLL) will have to be changed as well. And this is not desired. So clearly the answer to your question is Option #2.

Looking briefly for some sources to back this up I found this on Wikipedia on the DIP:

The interfaces defining the behavior/services required by the high-level component are owned by, and exist within the high-level component's library. The implementation of the high-level component's interface by the low level component requires that the low-level component package depend upon the high-level component for compilation, thus inverting the conventional dependency relationship.

  • Sadly I haven't got the necessary reputation points otherwise I would have definitely upvoted your reply. It has been helpful in making up my mind especially from DI perspective :) – Emma Feb 4 '15 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.