This question already has answers here:
Ioc/DI - Why do I have to reference all layers/assemblies in application's entry point?
(4 answers)
Closed 6 years ago.
I am trying to learn about DI, to have a better understanding of IoC, and the other benefits.
Pre DI, I have a project that has a UI project (MVC), a BusinessLogic project and a DataAccess project. I also have a SharedLib project. All projects have a reference to SharedLib. UI has a reference to BusinessLogic, and BusinessLogic has a reference to DataAccess.
I want to add the Interfaces now. So I go to my DataAccess, and add an Interface for each class, and populat them with their methods. I do the same for the business logic layer.
But in order to inject the DataAccess class, which I instantiate in the BusinessLogic class in the UI project, I need a reference to my Data project, because the UI project (correctly, I think) has no idea what an 'IDataAccess' interface is. The only fix I can see is to add a project reference in my UI to my DA project - which seems wrong.
And if I try add Unity as my container (One day in the future, once i work out how that all works), and want to initialise my Interface/Class relationships in the UI project - same issue.
Maybe the interfaces must go in some shared project? Or one project up? How should this be handled?
If you don't want the references between projects you could look into factories/abstract factories.
Your UI knows about your business layer, so you want to define a factory in your business layer which knows how to use the data layer. Then you handle all your DI in your composition root (the UI project in this example).
A simple example below using a console app as the UI, sticking to the references you stated in your question
Data layer
public interface IDataAccess
{
string GetData();
}
public class XmlDataAccess : IDataAccess
{
public string GetData()
{
return "some data";
}
}
Business layer
public interface IDataAccessFactory
{
IDataAccess GetDataAccess();
}
public class XmlDataAccessFactory : IDataAccessFactory
{
public IDataAccess GetDataAccess()
{
return new XmlDataAccess();
}
}
public class BusinessLogic
{
IDataAccessFactory dataAccessFactory;
public BusinessLogic(IDataAccessFactory dataAccessFactory)
{
this.dataAccessFactory = dataAccessFactory;
}
public void DoSomethingWithData()
{
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
Console.WriteLine(dataAccess.GetData());
}
public string GetSomeData()
{
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
return dataAccess.GetData();
}
}
UI
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IDataAccessFactory, XmlDataAccessFactory>();
var logic = container.Resolve<BusinessLogic>();
logic.DoSomethingWithData();
string useDataInUI = logic.GetSomeData();
Console.WriteLine("UI " + useDataInUI);
Console.ReadKey();
}
It's a contrived example so it looks like abstraction for nothing, but with a real world example it would make more sense.
e.g. you might have a bunch of different data access classes in your data layer database, xml files, etc. so you might define a factory for each in your business layer.
Using abstract factories
The factory could contain a lot more logic about the nitty gritty of the data layer, or as an abstract factory provide a set of individual factories to the business logic layer.
Business layer
You might instead have an abstract factory in the business layer such as
public interface IPlatformFactory
{
IDataAccessFactory GetDataAccessFactory();
IPricingFactory GetPricingFactory(); // might be in the business project, or another project referenced by it
}
with a concrete factory
public class WebPlatformFactory : IPlatformFactory
{
IDataAccessFactory GetDataAccessFactory()
{
return new XmlDataAccessFactory();
}
IPricingFactory GetPricingFactory()
{
return new WebPricingFactory(); // not shown in the example
}
}
(You might have additional concrete factories such as RetailPlatformFactory, etc.)
Your BusinessLogic class would now look something like
public class BusinessLogic
{
IPlatformFactory platformFactory;
public BusinessLogic(IPlatformFactory platformFactory)
{
this.platformFactory = platformFactory;
}
public void DoSomethingWithData()
{
IDataAccessFactory dataAccessFactory = platformFactory.GetDataAccessFactory();
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
Console.WriteLine(dataAccess.GetData());
}
public string GetSomeData()
{
IDataAccessFactory dataAccessFactory = platformFactory.GetDataAccessFactory();
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
return dataAccess.GetData();
}
}
Data layer
Your business layer no longer needs to provide an IDataAccessFactory to your UI so you can move it into your data layer in this example. So the data layer classes would be
public interface IDataAccess
{
string GetData();
}
public class XmlDataAccess : IDataAccess
{
public string GetData()
{
return "some data";
}
}
public interface IDataAccessFactory
{
IDataAccess GetDataAccess();
}
public class XmlDataAccessFactory : IDataAccessFactory
{
public IDataAccess GetDataAccess()
{
return new XmlDataAccess();
}
}
UI
Now you'd in the UI you'd configure the container and perform similar actions as
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlatformFactory, WebPlatformFactory>();
var logic = container.Resolve<BusinessLogic>();
logic.DoSomethingWithData();
string useDataInUI = logic.GetSomeData();
Console.WriteLine("UI " + useDataInUI);
Console.ReadKey();
}
The UI then knows nothing about the data layer/access, it's just handing off the factory creation to the business layer, which holds the data (and pricing) references.
Some recommended reading:
Composition Root
Implementing an Abstract Factory
Compose object graphs with confidence
Related
This question already has answers here:
How to avoid Dependency Injection constructor madness?
(10 answers)
Closed 7 years ago.
I'm developing an MVC application, I'm using Unity for IoC. My Application basically consists of a UI layer, a services layer and a repository layer.
My typical controller is:
public class TestController : Controller
{
private ITestService testServ;
public TestController(ITestService _testServ)
{
testServ= _testServ;
}
public ActionResult Index()
{
testServ.DoSomething();
return View();
}
}
Nothing out of the ordinary, each of my controllers has a service object injected. So of my service layer objects carry out complex business rules aggregating information from many different repositories. By using IoC I'm finding my constructors look overly complex, but as the service requires access to many repositories I cannot see any way around this.
A typical class in my service layer will look like:
public class TestService : ITestService
{
private ITransactionRepository transRepo;
private IAccountRepository accountRepo;
private ISystemsRepository sysRepo;
private IScheduleRepository schRepo;
private IProfileRepository profileRepo;
public TestService(ITransactionRepository _transRepo;
IAccountRepository _accountRepo;
ISystemsRepository _sysRepo;
IScheduleRepository _schRepo;
IProfileRepository _profileRepo)
{
transRepo = _transRepo;
accountRepo = _accountRepo;
sysRepo = _sysRepo;
schRepo = _schRepo;
profileRepo = _profileRepo;
}
public DoSomething()
{
//Implement Business Logix
}
}
Several of my service layer object require 10 or more repositories. My repository sits is using Entity Framework where each repository class exposes a table in the underlying data store.
I'm looking for some advice on best practice in a situation like described.
You have created a service layer so that it acts as a facade to the underlying repositories. This approach is a good practice to provide a facade to the client with a coarse API. The clients do not have to worry about underlying repositories.
The service themselves have now a complex constructor because of the way the DI is done. The other approach is to use an abstract factory pattern at the Service layer and do a setter injection. This complexity of newing up the repositories are moved into a separate class, a factory of its own.
For example:
You may set the repositories of your test service as follows instead of a constructor
public class TestService : ITestService
{
private ITransactionRepository transRepo = DataAccess.transRepo;
private IAccountRepository accountRepo = DataAccess.accountRepo;
private ISystemsRepository sysRepo = DataAccess.sysRepo;
private IScheduleRepository schRepo = DataAccess.schRepo ;
private IProfileRepository profileRepo = DataAccess.profileRepo;
}
Below is an example of an interface for factory
public interface IRepoFactory
{
ITransactionRepository TransRepo {get;}
IAccountRepository AccountRepo {get;}
ISystemsRepository SysRepo {get;}
IScheduleRepository SchRepo {get;}
IProfileRepository ProfileRepo {get;}
}
Below is an example of a concrete factory that will new up all the repositories.
public class EfFactory : IRepoFactory
{
public ITransactionRepositry TransRepo { return new TransactionRepository();}
public IAccountRepository AccountRepo {return new AccountRepository();}
public ISystemsRepository SysRepo {return new SystemRepository();}
public IScheduleRepository SchRepo {return new SchRepository();}
public IProfileRepository ProfileRepo {return new ProfileRepository();}
}
Below is a factory method that will return the concrete factory (in your case, it would be an EF Factory)
public class RepoFactories
{
public static IRepoFactory GetFactory(string typeOfFactory)
{
return (IRepoFactory)Activator.CreateInstance(Type.GetTypetypeOfFactory)
}
}
The abstract factory with static methods to new up and return the repository objects
//Example: factoryName = MyProject.Data.EFFactory ( This can be added in your web.config or app.config)
Public static class DataAccess
{
private static readonly string DbfactoryName= ConfigurationManager.AppSettings.Get("factoryName");
private static readonly IRepoFactory factory = RepoFactories.GetFactory(DbfactoryName);
public static ITransactionRepositry transRepo
{
get {return factory.TransRepo;}
}
public static IAccountRepository accountRepo
{
get {return factory.AccountRepo;}
}
}
Here are some steps to simplify (and decrease) dependencies:
Split you service into separate services and inject them in your controller. That will decrease number of dependencies of services. The downside is that you'll need to inject more dependencies to your controllers. The next step is split controllers when they become complicated. Remember about Single Responsibility Principle.
Take a look at Bounded Context pattern: you could try to group entities that often comes together in single context and inject that context into a service instead of injecting tens of repositories:
public class TestService : ITestService
{
private readonly ITestData testData; // represents a bounded context
public TestService(ITestData testData)
{
this.testData = testData;
}
public void DoSomething()
{
this.testData.Transactions.Add(...); //It gives you access to Transactions repository
}
}
I want to write tests for a program that is coded by someone else. But I have some problems while writing tests. I can't understand exactly how to fake some objects. I searched and found Unit Test for n tier architecture but It doesn't help me. For example, I want to write a test for code below (I know It is a dummy code for just clarification)
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
DAL customerDal = new DAL();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
I just want to test FetchCustomersByName but there is connection with DAL. I think creating stub class but In this case I have to change my original code. And it was coded by someone else. How can I write a test for this method?
Thanks in advance.
Don't unit test the data access layer. Write integration tests for it.
Mocking the dependencies in the DAL isn't just worth the trouble as it doesn't guarantee anything.
If you think about it, the DAL have dependencies on the SQL dialect and the database schema. Therefore your unit tests might work just fine. But when you run the real solution it can still fail. The reason can be that your SQL queries are incorrect or that the one of the class property types doesn't match the table column types.
unit tests are typically written for business logic. One thing that they catch is errors that doesn't generate exceptions such as incorrect conditions or calculation errors.
Update
Ok. So your example actually contains business logic. The method name fooled me.
You have to change the way you create your DAL classes. But you don't have to use constructor injection like Jack Hughes suggests. Instead you can use the factory pattern:
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
var customerDal = DalFactory.Create<CustomerDal>();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
That's bit easier since now you can just use "replace all" to change all var customerDal = new CustomerDal() to var customerDal = DalFactory.Create<CustomerDal>();
In that factory class you can call different implementations
public class DalFactory
{
public static IDalFactory Factory { get set; }
static DalFactory()
{
Factory = new DefaultDalFactory();
}
public static T Create<T>() where T : class
{
return Factory.Create<T>();
}
}
public interface IDalFactory
{
T Create<T>() where T : class
}
public class DefaultDalFactory : IDalFactory
{
public T Create<T>() where T : class
{
return new T();
}
}
The code isn't beautiful, but it solves your case with minimal refactoring. I suggest that you start with that and then try to change your coding standards so that constructor injection is allowed.
To get it working in your tests you can use the following implementation. It uses [ThreadStatic] to allow multiple tests to run at the same time.
public class TestDalFactory : IDalFactory
{
[ThreadStatic]
private static Dictionary<Type, object> _instances;
public static Dictionary<Type, object> DalInstances
{
get
{
if (_instances == null)
_instances = new Dictionary<Type, Object>();
return _instances;
}
}
public static TestDalFactory Instance = new TestDalFactory();
public T Create<T>() where T : class
{
return (T)_instances[typeof(T)];
}
}
Next in your tests you can configure the DAL factory to return a mock by doing the following:
[TestClass]
public class MyBusinessTests
{
[TestInitialize]
public void Init()
{
DalFactory.Instance = TestDalFactory.Instance;
}
[TestMethod]
public void do_some_testing_in_the_business()
{
TestDalFactory.Instance.DalInstances[typeof(CustomerDal)] = new MyNewMock();
//do the testing here
}
}
Using constructor injection of the DAL would allow you to stub the DAL layer. Ideally you would inject an interface. Mocking concrete classes is a bit of a pain with the tools I've used. Commercial mocking tools may well be better suited to mocking concrete classes but I've not used any of those.
class YourClass
{
private DAL customerDal;
public YourClass(DAL theDal)
{
customerDal = theDal;
}
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
// don't create the DAL here...
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
}
[Test]
public void TestMethodHere()
{
// Arrange
var dalMock = Mock.Of<DAL>();
// setup your mock DAL layer here... need to provide data for the FetchByName method
var sut = new YourClass(dalMock);
// Act
var actualResult = sut.FetchCustomersByName(new CustomerObject());
// Assert
// Your assert here...
}
So. This may be a stupid question, but...
I'm limited to using a database that doesn't support EntityFramework but I'd still like to separate out my data layer into a separate assembly. That means I'd need to share domain object values yet avoid a circular reference between my business and data layers. I therefore wondered whether it would be acceptable to construct a repository of persistence interfaces that could be implemented by the business layer and passed to the data layer independently of each other.
Example as follows:
// Business Layer
public class Customer: IPersistableCustomer
{
private string name;
public string Name{ get { return this.name; } }
public void persist()
{
dataLayer.StoreCustomerInstance(this);
}
}
// DataLayer
public StoreCustomerInstance(IPersistableCustomer persistableCustomer)
{
// Do storage stuff
}
// Interface repository
public interface IPersistableCustomer
{
string Name { get; }
}
I'm almost certain this is a terrible idea but I'm not sure why. I'd be interested to know people's thoughts to see where any potential pitfalls might be.
What you're doing in your example is hide your domain objects behind an interface. What you should do is hide your data layer behind interfaces. This abstraction of the data layer is commonly known as the repository pattern.
In the business layer you define the domain classes and repository interfaces:
public class Customer
{
public Customer(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
public interface ICustomerRepository
{
void Save(Customer customer);
}
Note that the Customer class doesn't have any persistence logic. Neither does the repository interface; it only defines the contract of the data layer.
The implementation of the contract goes in the data layer:
public class SqlCustomerRepository : ICustomerRepository
{
public void Save(Customer customer)
{
// Persistence logic
}
}
At this point the data layer needs a reference to the business layer, but not the other way around.
You tie these two layers together in the application layer:
class CustomerForm
{
private readonly ICustomerRepository customerRepository;
// This class declares a dependency on any ICustomerRepository
public CustomerForm(ICustomerRepository customerRepository)
{
this.customerRepository = customerRepository;
}
public void PersistCustomer()
{
Customer customer = CreateCustomerFromUserInput();
this.customerRepository.Save(customer);
}
}
class Program
{
static void Main(string[] args)
{
// Dependency injection, usually done via a DI container
var customerRepository = new SqlCustomerRepository();
var form = new CustomerForm(customerRepository);
form.PersistCustomer();
}
}
I found the articles on the Onion Architecture very valuable when faced with the same question as you. It explains how to set up your application's architecture in a way that prevents tight coupling to the data layer.
Another advantage of using interfaces for the data layer is that it allows you to unit tests most of your code without having to have an actual database running. You can simply mock the repository interfaces.
I once used interfaces for my domain objects a few years ago. I don't regret it, because it taught me how not to do it. But that's the only good thing; it was a lot of extra work and maintenance without any real benefits :)
I'm currently building the Data Access Layer and Business Logic Layer classes for our new application, and I have a question (obviously). First, here are some details that may help:
Using Entity Framework 5 for Model classes and data access
Each "layer" is separated in different class libraries and namespaces (i.e App.Model, App.DAL, App.BLL)
Starting with the DAL - I decided to write a base class for all DAL classes to inherit.
public abstract class DALBase<T> : IDisposable
{
protected AppEntities context;
protected DbSet set;
public DALBase()
{
context = new OECCORPEntities();
set = context.Set(typeof(T));
}
protected virtual void Save()
{
context.SaveChanges();
}
public virtual void Add(T model)
{
set.Add(model);
Save();
}
public virtual T Get(int id)
{
return (T)set.Find(id);
}
public virtual List<T> GetAll()
{
return set.OfType<T>().ToList();
}
public virtual void Delete(int id)
{
T obj = Get(id);
set.Remove(obj);
Save();
}
public virtual void Update()
{
Save();
}
public void Dispose()
{
context.Dispose();
}
}
As you will see, the base class implements a generic type which should be the type of the model the DAL class is responsible for working with. Using the generic type, in the constructor it creates a DbSet using the type of the generic argument - which is used in the predefined CRUD-like virtual functions below (add, get, etc).
And then I got the idea - wait a minute... since it's generic, I really don't have to implement DAL classes for every single model. I can just write something like this:
public class GenericDAL<T> : DALBase<T>
{
public GenericDAL() : base() {}
}
... that I can use for any of the models. OK, so on to the Business Logic Layer. I created a base class for BLL as well:
public abstract class BLLBase<T>
{
protected GenericDAL<T> dal;
public BLLBase()
{
dal = new GenericDAL<T>();
}
public virtual void Add(T model)
{
dal.Add(model);
}
public virtual T Get(int id)
{
return dal.Get(id);
}
public virtual List<T> GetAll()
{
return dal.GetAll();
}
public virtual void Delete(int id)
{
dal.Delete(id);
}
public virtual void Update()
{
dal.Update();
}
}
... which uses the GenericDAL to do its work. So in a simular fashion, I just wrote a GenericBLL class that looks like this:
public class GenericBLL<T> : BLLBase<T>
{
public GenericBLL() : base() { }
}
And to test it, a simple console application:
class Program
{
static void Main(string[] args)
{
GenericBLL<ADMIN> bll = new GenericBLL<ADMIN>();
List<ADMIN> admins = bll.GetAll();
}
}
... where "ADMIN" is the model type. Works like a charm.
The idea behind this was to avoid having to write DAL / BLL classes for every single model, unless it needed extra functionality. Can someone tell me why I WOULDN'T want to do it this way? I think the generic DAL / BLL classes would get the job done and also save development time.
Thank you for your time.
Well, one drawback is that if you decide to add some business rules later on you would have to switch the type from GenericBLL[Whatever] to WhateverBLL.
An obvious solution to this is to create a class that inherits from GenericBLL[Whatever]. Like:
public class WhateverBLL : GenericBLL<Whatever>
and use this class instead.
Right now, your BLL isn't particularly adding value. Every call is simply a pass-through to another layer. Maybe it's the simplicity of your application (and thank your lucky stars that you are so lucky), or maybe you have what I would classify as the actual business logic living elsewhere.
Business logic to me is everything that is done up to the point of persisting data, everything that is done after retrieving data, and things like that. The decisions, the forks in the road, the actions that are taken. Actually saving and retrieving data is typical extremely trivial by comparison.
So as I look at your generic DAL base class, I think it's a fine start. I would probably extract an interface from it so I could replace it when testing. For now, your class that inherits the base isn't adding any value. Do not create layers and classes simply for the sake of it, be sure it adds value and makes your life easier in some way.
As I look at your generic BLL class, I think you probably have your real business logic tucked away in the codebehind on some form, or inside a class file in a console app. While it's certainly possible that there could be generically applicable functionality that only varies on the type, I don't think one class is where you want to be. My suggestion here is to reconsider what you think is your actual business logic. A simple pass-through layer to the DAL probably isn't it.
How do I unit test a Business Layer method that makes call to WCF service?
example:
public void SendData(DataUnit dataUnit)
{
//this is WCF call
SomeServiceClient svc = new SomeServiceClient();
svc.SomeMethod(dataUnit);
}
Is there a way I can mock SomeServiceClient in my Unit test project?
Your problem here is that you have tightly coupled your Business Layer to your WCF service - you actually create a new instance of the service client within the Business Layer, meaning that it is now impossible to call the SendData method without also calling the service methods.
The best solution here is to introduce dependency injection to your architecture.
At its simplest, all you do is pass an instance of your service class into your Business Layer. This is often done at class construction time using a constructor parameter.
public class BusinessClass
{
private ISomeServiceClient _svc;
public BusinessClass(ISomeServiceClient svc)
{
_svc = svc;
}
public void SendData(DataUnit dataUnit)
{
_svc.SomeMethod(dataUnit);
}
}
Note that the code above is a design pattern, with absolutely no reliance upon any framework like an Inversion of Control container.
If it is your company's policy not to use such frameworks (an insane policy by the way), you can still manually inject your mock instances of the service inside your unit tests.
You should separate your service call from your business layer:
Using the demo below, your Business Layer method that you listed would now look like this:
public void SendData(IMyInterface myInterface, DataUnit dataUnit)
{
myInterface.SomeMethod(dataUnit);
}
Pass in a RealThing if you want to do the service call, pass in a TestThing if you just want to run a test:
public interface IMyInterface
{
void SomeMethod(DataUnit x);
}
public class RealThing : IMyInterface
{
public void SomeMethod(DataUnit x)
{
SomeServiceClient svc = new SomeServiceClient();
svc.SomeMethod(x);
}
}
public class TestThing : IMyInterface
{
public void SomeMethod(DataUnit x)
{
// do your test here
}
}