Project Naming Convention Feedback Please
I am creating a ASP.NET MVC 3 application using Entity Framework 4. I am using the Repository/Service Pattern and was looking for feedback.
I currently have the following:
MVC Application (GTG.dll)
- GTG
- GTG.Controllers
- GTG.ViewModels
Business POCO's (GTG.Business.dll)
- This contains all business objects (Customer, Order, Invoice, etc...)
EF Model/Repositories (GTG.Data.dll)
- GTG.Business (GTG.Context.tt) I used the Entity POCO Generator Templates.
- GTG.Data.Repositories
Service Layer (GTG.Data.Services.dll)
- GTG.Data.Services - Contains all of the service objects, one per aggregate root.
The following is a little sample code:
Controller
Namespace Controllers
Public Class HomeController
Inherits System.Web.Mvc.Controller
Function Index() As ActionResult
Return View(New Models.HomeViewModel)
End Function
End Class
End Namespace
Model
Namespace Models
Public Class HomeViewModel
Private _Service As CustomerService
Public Property Customers As List(Of Customer)
Public Sub New()
_Service = New CustomerService
_Customers = _Service.GetCustomersByBusinessName("Striano")
End Sub
End Class
End Namespace
Service
Public Class CustomerService
Private _Repository As ICustomerRepository
Public Sub New()
_Repository = New CustomerRepository
End Sub
Function GetCustomerByID(ByVal ID As Integer) As Customer
Return _Repository.GetByID(ID)
End Function
Function GetCustomersByBusinessName(ByVal Name As String) As List(Of Customer)
Return _Repository.Query(Function(x) x.CompanyName.StartsWith(Name)).ToList
End Function
End Class
Repository
Namespace Data.Repositories
Public Class CustomerRepository
Implements ICustomerRepository
Public Sub Add(ByVal Entity As Business.Customer) Implements IRepository(Of Business.Customer).Add
End Sub
Public Sub Delete(ByVal Entity As Business.Customer) Implements IRepository(Of Business.Customer).Delete
End Sub
Public Function GetByID(ByVal ID As Integer) As Business.Customer Implements IRepository(Of Business.Customer).GetByID
Using db开发者_StackOverflow社区 As New GTGContainer
Return db.Customers.FirstOrDefault(Function(x) x.ID = ID)
End Using
End Function
Public Function Query(ByVal Predicate As System.Linq.Expressions.Expression(Of System.Func(Of Business.Customer, Boolean))) As System.Linq.IQueryable(Of Business.Customer) Implements IRepository(Of Business.Customer).Query
Using db As New GTGContainer
Return db.Customers.Where(Predicate)
End Using
End Function
Public Sub Save(ByVal Entity As Business.Customer) Implements IRepository(Of Business.Customer).Save
End Sub
End Class
End Namespace
The separation of your project is very good and contains exactly the layers it should. The problem is that you have a strong coupling between your layers making your code impossible to unit test.
Examples:
Your view model is strongly coupled to a specific implementation of the service:
_Service = New CustomerService
Your service is strongly coupled to a specific implementation of the repository:
_Repository = New CustomerRepository
To improve this code and weaken the coupling you should consider using constructor injection and a DI framework.
So for example have your service constructor would take a ICustomerRepository
argument and assign the private field to it instead of hardcoding a new instance manually. Also have your service implement an interface and do the same constructor injection in your HomeController
constructor so that it has access to the service.
精彩评论