We are working on a Mvc application, where we want to use dependency injection using nInject. Currently we are maintaining entities in different class library "ShopEntities" and in our mvc application we are using this entities.
Let's consider a class in ShopEntities.
namespace ShopEntities
{
public class Customers
{
public int custId {get;set;}
public string custName {get;set;}
public string Address {get;set;}
public string ShippingAddress {get;set;}
}
}
Now when we want to use it in our mvc application, we create an instance and set the properties like below,
public ActionResult Index()
{
ShopEntities.Customers cust = new ShopEntities.Customers();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
}
How to use nInject here to avoid dependency? Further we don't want to create interfaces as this is limited in scope. Thanks in advance.
The way to abstract away the use of the Customer entity from the presentation layer is not to hide the entity itself behind an ICustomer of some sort, nor to let a DI container build it up. Hiding data objects behind an interfaces is typically not useful; interfaces are meant to abstract behavior, not data.
As NightOwl already stated, your Customer entity is runtime data and you should not use a container to build up object graphs containing runtime data.
Instead, you should hide specific business operations behind an abstraction. Such abstraction can be consumed by the presentation layer and implemented by the business layer. For instance:
public interface ICustomerServices
{
void CreateCustomer(string customerName, string homeAddress,
string shippingAddress);
void ChangeShippingAddress(Guid customerId, string shippingAddress);
}
Your controller can depend on this abstraction:
private readonly ICustomerServices customerServices;
public CustomerController(ICustomerServices customerServices) {
this.customerServices = customerServices;
}
public ActionResult Index()
{
this.customerServices.CreateCustomer("Sam", "xyz", "xyz xyz xyz");
}
Now your business layer can create an implementation for this abstraction that uses the entities internally:
public class CustomerServices : ICustomerServices
{
private readonly EntitiesContext context;
public CustomerServices(EntitiesContext context) {
this.context = context;
}
public void CreateCustomer(string customerName, string homeAddress,
string shippingAddress)
{
// NOTE that I renamed 'Customers' to 'Customer', since it holds information
// to only one customer. 'Customers' implies a collection.
Customer cust = new ShopEntities.Customer();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
this.context.Customers.Add(cust);
this.context.SubmitChanges();
}
public void ChangeShippingAddress(...) { ... }
}
Doing this has the advantage that you can keep your presentation layer thin, but there are still quite some down sides to the shown approach, compared to alternatives. One of such alternatives is using a message based approach with SOLID design, as explained here.
If i understand you question, you should create middle business layer to convert ShopEntities to your own Entities:
namespace MyShopEntities
{
public class MyCustomers
{
public int custId {get;set;}
public string custName {get;set;}
public string Address {get;set;}
public string ShippingAddress {get;set;}
}
}
public ActionResult Index()
{
ShopEntities.Customers cust = new MyShopEntities.MyCustomers();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
}
class BussinesModel
{
void Insert(ShopEntities.Customer customer)
{
// use ShopEntities.Customer only in wrapper
// if you later switch to another Customer dependency,
// you just change this wrapper
MyShopEntities.MyCustomers cust = new MyShopEntities.MyCustomers();
cust.CustName = customer.CustName;
cust.IAddress = customerIAddress;
cust.ShippingAddress = customer.ShippingAddress;
InsertInternal(cust);
}
void InsertInternal(MyShopEntities.MyCustomer customer)
{
// use MyCustomer for all your bussines logic
}
}
Related
I have confusion about clean architecture, in my project i have two projects one is Infrastructure where i create database and model entities,i have Core project where i created my interfaces and my models,the interfaces inside core are implemnted inside the infrastructure,for example in my Core project i have IDataHandler class,i put i all the signiture which interact with DB,and i implement those signitures inside DataHandler which is in Infrastructure project..now here is my question,
in my Core IDataHandler looks:
public interface IDataHandler
{
public Task<StudentsModel> GetStudent(string id);
}
in my Infrastructure i have StudensEntity which is the exact copy of the StudentModel,but when i want to implemet the IDataHandler i cant use like this:
public interface DataHandler:IDataHanlder
{
public Task<StudentsEntity> GetStudent(string id);
}
it the return type is not the same as its interface,even thought they have the same properties,i ope you understand what im trying ask,if so,what should i do?
The solution you came up with reflects clean architecture principles, especially in regard to the separation between repository interfaces (IDataHandler) and repository implementations (DataHandler) and between what you refer to as "models" (StudentModel) and "model entities" (StudentEntity).
in my Infrastructure i have StudensEntity which is the exact copy of the StudentModel
In order to make this work, the core model should actually be either an abstract class or an interface, e.g. interface IStudent instead of class StudentModel, and infrastructure model StudentEntity should implement that interface. This may lead to such (simplified) code:
// Core (domain language)
public interface IStudent
{
long Id { get; }
string Name { get; }
}
// Infrastructure
public StudentEntity : IStudent
{
public StudentEntity(long id, string name)
{
this.Id = id;
this.Name = name;
}
public long Id { get; }
public string Name { get; }
}
// Core (domain language)
public interface IDataHandler
{
Task<IStudent> GetStudent(string id);
}
// Infrastructure
public class DataHandler : IDataHanlder
{
public async Task<IStudent> GetStudent(string id)
{
// Construct StudentEntity from database and return it.
}
}
I've been reading about TDD and I've seen a lot of posts about not to do any database transaction because "single, isolated block of code with no dependencies".
So now I have a little bit of dilemma - I want to be able to test if my service layer method called AddNewStudent actually works. This method goes into my DbContext and then add a new record into the database. If database operations aren't recommended for TDD then how else can I test AddNewStudent method aside from just testing my application on a browser?
public class StudentManager : ManagerBase
{
internal StudentManager() { }
public Student AddNewStudent(string fName, string lName, DateTime dob)
{
// Create a student model instance using factory
var record = Factories.StudentFac.CreateOne(fName, lName, dob);
DbContext.Students.Add(record);
DbContext.SaveChanges();
return record;
}
}
And my test looks like this
[TestMethod]
public void StudentManager_AddNewStudent_Test()
{
var fName = "Ryan";
var lName = "Rigil";
var dob = DateTime.Parse("3/1/2006");
var student = Managers.StudentManager.AddNewStudent(fName, lName, dob);
Assert.AreEqual(fName, student.FirstName);
Assert.AreEqual(lName, student.LastName);
Assert.AreEqual(dob.ToShortDateString(), student.DoB.ToShortDateString());
}
Your StudentManager has dependencies buried internally that make it difficult to test. Consider restructuring your design to allow for better testability.
Looking at the StudentManager the following assumptions were derived...
//An assumed abstraction of the ManagerBase
public abstract class ManagerBase {
public ManagerBase(IDbContext dbContext, IFactory factories) {
DbContext = dbContext;
Factories = factories;
}
public IDbContext DbContext { get; private set; }
public IFactory Factories { get; private set; }
}
//An abstraction of what the unit of work would look like
public interface IDbContext {
//student repository
DbSet<Student> Students { get; }
//...other repositories
int SaveChanges();
}
//Just an example of the Student Factory.
public interface IModelFactory<T> where T : class, new() {
T Create(Action<T> configuration);
}
public interface IFactory {
IModelFactory<Student> StudentFac { get; }
//...other factories. Should try to make your factories Generic
}
With that the target class refactors to...
public class StudentManager : ManagerBase {
public StudentManager(IDbContext dbContext, IFactory factories) : base(dbContext, factories) { }
public Student AddNewStudent(string fName, string lName, DateTime dob) {
// Create a student model instance using factory
var record = Factories.StudentFac.Create(r => {
r.FirstName = fName;
r.LastName = lName;
r.DoB = dob;
});
base.DbContext.Students.Add(record);
base.DbContext.SaveChanges();
return record;
}
}
While it may look like much it will greatly help the testability of your code.
A mocking framework like Moq can now be used to create a fake version of the database access and factories...
[TestMethod]
public void StudentManager_Should_AddNewStudent() {
//Arrange: setup/initialize the dependencies of the test
var fName = "Ryan";
var lName = "Rigil";
var dob = DateTime.Parse("3006-01-03");
//using Moq to create mocks/fake of dependencies
var dbContextMock = new Mock<IDbContext>();
//Extension method used to create a mock of DbSet<T>
var dbSetMock = new List<Student>().AsDbSetMock();
dbContextMock.Setup(x => x.Students).Returns(dbSetMock.Object);
var factoryMock = new Mock<IFactory>();
factoryMock
.Setup(x => x.StudentFac.Create(It.IsAny<Action<Student>>()))
.Returns<Action<Student>>(a => {
var s = new Student();
a(s);
return s;
});
//this is the system/class under test.
//while this is being created manually, you should look into
//using DI/IoC container to manage Dependency Injection
var studentManager = new StudentManager(dbContextMock.Object, factoryMock.Object);
//Act: here we actually test the method
var student = studentManager.AddNewStudent(fName, lName, dob);
//Assert: and check that it executed as expected
Assert.AreEqual(fName, student.FirstName);
Assert.AreEqual(lName, student.LastName);
Assert.AreEqual(dob.ToShortDateString(), student.DoB.ToShortDateString());
}
For production you can create proper implementations of the interfaces and inject them into the classes that depend on them. This answer is based entirely on the example you provided in your post. Take some time to understand the concepts used and also do some more research online. You can then apply these concepts with the remainder of your project as you progress with TDD.
Is it considered a good practice to pass the model class from e.g. the DAL to a threaded service class as 'information model'?
Example:
public class CarModel {
public string Name { get; set; }
public int AmountOfWheels { get; set; }
public Engine EngineDescription { get; set; }
}
public class Car {
public CarModel CarModel { get; set; }
public Car(CarModel model) {
this.CarModel = model;
Thread.Start(BrummBrumm);
}
private void BrummBrumm() {
// start the car
}
}
This example is made under the assumption that CarModel is a entity (e.g. to use with Entity Framework or any other repository/DAL) or a model class to use with UI, WebApi, WCF.. and Car is a class that resides as implementation in e.g. a Windows service.
Edit further code
public class CarManager {
public List<Car> Cars = new List<Car>();
public void Add(CarModel model) {
this.Cars.Add(new Car(model));
}
public void Remove(int id) {
...
}
}
... then what's with the example above? What if I don't just have cars, but also motorcycles? Wouldn't the example above create a lot of boilerplate code?
Best practice is to use DTOs while transfering data from/to services. There are also tools to reduce code required to map DTO's from/to business objects. Personally I use Automapper.
There's a good article just in case you want to read up on DTO's - Pros and Cons of Data Transfer Objects
However if your solution is small and is not supposed to grow and your services are not publicly exposed you are good to go with just your business objects to avoid overdesign.
Hope it helps!
I am new to IoC and Repository Pattern. I was able to do some test project and it works. But, I am not so sure if what I implemented is a good practice. The test project I have created have all the repositories in place as well as a working interface with a dummy data. But what I want is that my project should not be able to know the concrete types of my models because the initial version should be implemented using MSSQL, and the second version would be a mix of MSSQL and NoSQL(for reads and logging). The models might have different properties or structures from MSSQL to NoSQL (or whatever i might use in the future)
So I tried to create an interface for each model:
public interface ISearchResult
{
string Id { get; set; }
string Name { get; set; }
string Description { get; set; }
string Url { get; set; }
}
And here's the repository:
public interface ISearchRepository<T> where T: class, ISearchResult
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
And here's the service:
public interface ISearchService
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
Because I want to have a working GUI even without MSSQL or NoSQL entities, I have created a View Model that inherited the ISearchResult:
public class SearchResultViewModel : ISearchResult
{
[Display(Name="Reference Id")]
public string Id { get; set; }
[Display(Name = "Company")]
public string Name { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Website")]
public string Url { get; set; }
}
And here's how it looks on my controller:
[SearchQueryFilter]
[GeoTargetFilter]
public ActionResult Query(SearchQueryModel searchQuery)
{
searchQuery.Results = this._searchService.Search<SearchResultViewModel>(searchQuery.Keyword,searchQuery.Region, new List<string>() { searchQuery.Industries }, new List<string>() { searchQuery.Countries}, new List<string>() {searchQuery.City}, searchQuery.Offset)
.ToList<ISearchResult>();
return View(searchQuery);
}
And my view would look like this:
#foreach (SearchResultViewModel result in Model.Results)
{
//code to display
}
My question is: Is it fine to use this approach? I don't want my web application to be dependent on my data entities so that's why I came up of making my view models inherit an interface. And because I was new to IoC and Repository Pattern and only have a test project, I don't know if my solution would be more of a problem in the long run.
Any advise is highly appreciated.
You shouldn't need to implement an interface in your view model in order to create a separation between your web application and your data entities. Your view model should belong to your web application and should itself be independent of your data entity.
So, instead of:
_searchService.Search<SearchResultViewModel>(x);
You should have, in your controller:
var result = _searchService.Search<SomeEntity>(x);
var model = new SearchResultsViewModel
{
Name = result.Name,
Desc = result.Desc,
Url = result.Url
};
return View(model);
The view model belongs to the web application and is responsible for containing the data passed from controller to view (and back) - it should have nothing to do with your service layer (or any other layer of your application).
SomeEntity is a concrete class, in the form of whatever your search service exposes. Your controller will consume this in the same way as any other application would and then compile a view model for passing to and from views. You might even find that SomeEntity is more or less identical to SearchResultsViewModel initially; however, they are still distinct entities as the requirements of the view might change independently of the search service.
I have an existing bank application classes as shown below. The banks account can be of SavingsBankAccount or FixedBankAccount. There is an operation called IssueLumpSumInterest. For FixedBankAccount, the balance need to be updated only if the owner of the account has no other account.
This demands the FixedBankAccount object to know about other accounts of the account owner. How to do this by following SOLID/DDD/GRASP/Information Expert pattern?
namespace ApplicationServiceForBank
{
public class BankAccountService
{
RepositoryLayer.IRepository<RepositoryLayer.BankAccount> accountRepository;
ApplicationServiceForBank.IBankAccountFactory bankFactory;
public BankAccountService(RepositoryLayer.IRepository<RepositoryLayer.BankAccount> repo, IBankAccountFactory bankFact)
{
accountRepository = repo;
bankFactory = bankFact;
}
public void IssueLumpSumInterest(int acccountID)
{
RepositoryLayer.BankAccount oneOfRepositroyAccounts = accountRepository.FindByID(p => p.BankAccountID == acccountID);
int ownerID = (int) oneOfRepositroyAccounts.AccountOwnerID;
IEnumerable<RepositoryLayer.BankAccount> accountsForUser = accountRepository.FindAll(p => p.BankUser.UserID == ownerID);
DomainObjectsForBank.IBankAccount domainBankAccountObj = bankFactory.CreateAccount(oneOfRepositroyAccounts);
if (domainBankAccountObj != null)
{
domainBankAccountObj.BankAccountID = oneOfRepositroyAccounts.BankAccountID;
domainBankAccountObj.AddInterest();
this.accountRepository.UpdateChangesByAttach(oneOfRepositroyAccounts);
//oneOfRepositroyAccounts.Balance = domainBankAccountObj.Balance;
this.accountRepository.SubmitChanges();
}
}
}
public interface IBankAccountFactory
{
DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount);
}
public class MySimpleBankAccountFactory : IBankAccountFactory
{
public DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositroyAccount)
{
DomainObjectsForBank.IBankAccount acc = null;
if (String.Equals(repositroyAccount.AccountType, "Fixed"))
{
acc = new DomainObjectsForBank.FixedBankAccount();
}
if (String.Equals(repositroyAccount.AccountType, "Savings"))
{
//acc = new DomainObjectsForBank.SavingsBankAccount();
}
return acc;
}
}
}
namespace DomainObjectsForBank
{
public interface IBankAccount
{
int BankAccountID { get; set; }
double Balance { get; set; }
string AccountStatus { get; set; }
void FreezeAccount();
void AddInterest();
}
public class FixedBankAccount : IBankAccount
{
public int BankAccountID { get; set; }
public string AccountStatus { get; set; }
public double Balance { get; set; }
public void FreezeAccount()
{
AccountStatus = "Frozen";
}
public void AddInterest()
{
//TO DO: Balance need to be updated only if the person has no other accounts.
Balance = Balance + (Balance * 0.1);
}
}
}
READING
Issue in using Composition for βis β a β relationship
Implementing Business Logic (LINQ to SQL)
http://msdn.microsoft.com/en-us/library/bb882671.aspx
Architecting LINQ to SQL applications
Exploring N-Tier Architecture with LINQ to SQL
http://randolphcabral.wordpress.com/2008/05/08/exploring-n-tier-architecture-with-linq-to-sql-part-3-of-n/
Confusion between DTOs (linq2sql) and Class objects!
Domain Driven Design (Linq to SQL) - How do you delete parts of an aggregate?
The first thing I noticed was the improper use of the bank account factory. The factory, pretty much as you have it, should be used by the repository to create the instance based on the data retrieved from the data store. As such, your call to accountRepository.FindByID will return either a FixedBankAccount or SavingsBankAccount object depending on the AccountType returned from the data store.
If the interest only applies to FixedBankAccount instances, then you can perform a type check to ensure you are working with the correct account type.
public void IssueLumpSumInterest(int accountId)
{
var account = _accountRepository.FindById(accountId) as FixedBankAccount;
if (account == null)
{
throw new InvalidOperationException("Cannot add interest to Savings account.");
}
var ownerId = account.OwnerId;
if (_accountRepository.Any(a => (a.BankUser.UserId == ownerId) && (a.AccountId != accountId)))
{
throw new InvalidOperationException("Cannot add interest when user own multiple accounts.");
}
account.AddInterest();
// Persist the changes
}
NOTE: FindById should only accept the ID parameter and not a lambda/Func. You've indicated by the name "FindById" how the search will be performed. The fact that the 'accountId' value is compared to the BankAccountId property is an implementation detail hidden within the method. Name the method "FindBy" if you want a generic approach that uses a lambda.
I would also NOT put AddInterest on the IBankAccount interface if all implementations do not support that behavior. Consider a separate IInterestEarningBankAccount interface that exposes the AddInterest method. I would also consider using that interface instead of FixedBankAccount in the above code to make the code easier to maintain and extend should you add another account type in the future that supports this behavior.
From reading your requirement, here is how I would do it:
//Application Service - consumed by UI
public class AccountService : IAccountService
{
private readonly IAccountRepository _accountRepository;
private readonly ICustomerRepository _customerRepository;
public ApplicationService(IAccountRepository accountRepository, ICustomerRepository customerRepository)
{
_accountRepository = accountRepository;
_customerRepository = customerRepository;
}
public void IssueLumpSumInterestToAccount(Guid accountId)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
{
Account account = _accountRepository.GetById(accountId);
Customer customer = _customerRepository.GetById(account.CustomerId);
account.IssueLumpSumOfInterest(customer);
_accountRepository.Save(account);
}
}
}
public class Customer
{
private List<Guid> _accountIds;
public IEnumerable<Guid> AccountIds
{
get { return _accountIds.AsReadOnly();}
}
}
public abstract class Account
{
public abstract void IssueLumpSumOfInterest(Customer customer);
}
public class FixedAccount : Account
{
public override void IssueLumpSumOfInterest(Customer customer)
{
if (customer.AccountIds.Any(id => id != this._accountId))
throw new Exception("Lump Sum cannot be issued to fixed accounts where the customer has other accounts");
//Code to issue interest here
}
}
public class SavingsAccount : Account
{
public override void IssueLumpSumOfInterest(Customer customer)
{
//Code to issue interest here
}
}
The IssueLumpSumOfInterest method on the Account aggregate requires the Customer aggregate to help decide whether interest should be issued.
The customer aggregate contains a list of account IDs - NOT a list of account aggregates.
The base class 'Account' has a polymorphic method - the FixedAccount checks that the customer doesn't have any other accounts - the SavingsAccount doesn't do this check.
2 min scan answer..
Not sure why there is a need for 2 representations of a BankAccount
RepositoryLayer.BankAccount and DomainObjectsForBank.IBankAccount. Hide the persistence layer coupled one.. deal with just the domain object in the service.
Do not pass/return Nulls - I think is good advice.
The finder methods look like the LINQ methods which select items from a list of collection. Your methods look like they want to get the first match and exit..in which case your parameters can be simple primitives (Ids) vs lambdas.
The general idea seems right. The service encapsulates the logic for this transaction - not the domain objects. If this changes, only one place to update.
public void IssueLumpSumInterest(int acccountID)
{
var customerId = accountRepository.GetAccount(accountId).CustomerId;
var accounts = accountRepository.GetAccountsForCustomer(customerId);
if ((accounts.First() is FixedAccount) && accounts.Count() == 1)
{
// update interest
}
}
Things that strike me as weird:
Your IBankAccount has a method FreezeAccount, but I presume that all accounts would have quite similar behavior? Perhaps a BankAccount class is warranted that implements some of the interface?
AccountStatus should probably be an enum? What should happen if an account is "Forzen"?