Content by Category
.NET 1.x
.NET 2.0
.NET 3.0
.NET 3.5
.NET 4.0
.NET 4.5
.NET Assemblies
.NET Framework
.NET Getting Started
Accessibility
ADO.NET
Advertorials
Agile Development
AJAX
Amazon Web Services
Analysis Services
Android
Architecture
Arduino
ASP .NET Web API
ASP.NET
ASP.NET MVC
ASP.NET WebForms
Azure
B2B (Business Integration)
BDD
Big Data
Bing
BizTalk
Book Excerpts
Build and Deploy
Business Intelligence
C#
C++
ClickOnce
Cloud Computing
Code Contracts
CODE Framework Info - non Technical
CODE on the Road!
COM+
Community
Conferences
Continuous Integration
Crystal Reports
CSLA.NET
CSS
Data
Debugger
Design Patterns
Development Process
Display Technologies
Distributed Computing
Document Database
DotNetNuke
DSL
Dynamic Languages
Dynamic Programming
Editorials
Enterprise Services ("COM+")
Entity Framework
Events
Expression Blend
F#
Fox to Fox
Frameworks
Functional Programming
Git
Graphics
HTML 5
Internet Explorer 8.0
Interviews
IOS
iPhone
Iron Ruby
Java
Java Script
JavaScript
jQuery
JSON
Lightswitch
LINQ
Linux
LUA
Mac OS X
MDX
Messaging
Metro
Microsoft Application Blocks
Microsoft Business Rules Framework
Microsoft Dynamics
Microsoft Expression
Microsoft Office
Mobile Development
Mobile PC
Mono
MsBuild
MVVM
MySQL
Network
NHibernate
node.js
NOSQL
Nuget
Object Oriented Development
Objective C
Odata
OLAP
Open Source
Opinion
Opinions
Oracle
ORM
Other Languages
Parallel Programming
Patterns
PHP
Podcasts
Post Mortem
PowerPoint
Print/Output
Prism
Product News
Product Reviews
Project Management
Prolog
Python
Q&A
Rails
Rake
Razor
Reporting Services
REST
RIA Services
Ruby
Ruby on Rails
Scheme
Search
Security
Services
SharePoint
SignalR
Silverlight
SOA
Social Networks
Software & Law
Software Business
Source Control
Speech-Enabled Applications
SQL Server
SQL Server 2000
SQL Server 2005
SQL Server 2008
SQL Server 2012
SQL Server CE/AnyWhere/Mobile/Compact
SSIS
Subversion
Sync Framework
Tablet PC
TDD
Team System
Techniques
Testing and Quality Control
TFS
Tips
TypeScript
UI Design
UML
User Groups
VB Script
VB.NET
Version Control
VFP and .NET
VFP and SQL Server
Virtual Earth
Vista
Visual Basic
Visual Basic 6 (and older)
Visual FoxPro
Visual Studio .NET
Visual Studio 11
Visual Studio 2005
Visual Studio 2008
Visual Studio 2010
Visual Studio 2011
Visual Studio 2012
Visual Studio Tools for Office
VSX
WCF
Web Development (general)
Web Services
WebMatrix
WF
Whitepapers
Windows 7
Windows 8
Windows Azure
Windows Live
Windows Phone 7
Windows Phone SDK
Windows Server
Windows Vista
WinForms
WinRT
Workflow
WPF
XAML
Xiine Documentation
XML
XNA
XSLT



LearnNow


XAMALOT
 


SSWUG


Reader rating:
Click here to read 8 comments about this article.
Article source: CoDe (2007 - May/Jun)


Article Pages:  1  2 3 4 - Next >


Layered Architecture, Dependency Injection, and Dependency Inversion

Building loosely coupled application architectures requires more than just separating your application into different layers. In this article, I’ll take a project that was built using techniques that result in fragile, hard-to-test code and introduce some principles, techniques, and refactorings that will help you realize flexibility and testability in your applications.

Most developers understand the value of the layered approach to architecture. The main principle behind layered architectures is that of “separation of responsibility”. Each layer is responsible for a finite amount of work. Any work that cannot (read should not) be done by a particular layer gets delegated to a layer more appropriate for handling the task.

Unfortunately, people using layered architectures can often run into a scenario where they introduce an unnecessary amount of coupling between layers of their application. A high degree of coupling is one factor that can lead to fragile application architectures that are difficult to change or extend.

The first part of this article deals with introducing a design principle that will enable you to take advantage of layered architectures in a much cleaner fashion, and then demonstrates how introducing dependency injection into the mix can help you realize your goals for pluggable application architectures.

The Case at Hand

Assume for a moment that Figure 1 is a screen that I am developing for viewing information on Employees that work with my company. Being that it’s such a “simple” screen, I dive in and quickly hammer out the code shown in Listing 1. (In case anyone asks, I would never do this!)

Click for a larger version of this image.

Figure 1: This looks like a pretty simple screen to build, right?

I’ll pause for a second to allow the utter travesty of that code to truly sink in! The code breaks several application architecture rules:

  • Hard-coded connection strings.
  • User interface has intimate knowledge of database tables.
  • User interface is responsible for mapping database data into domain objects.
  • Coding to implementations not abstractions.
  • Forget about that last bullet point for a little while. I can start to remedy the first three items by introducing a layered application architecture.

Separating Responsibilities with a Layered Architecture

One of the main issues with the code in Listing 1 is that it takes the single responsibility principle and throws it completely out of the window. The single responsibility principle simply states that “every object should have a single responsibility and therefore only a single reason to change.” If you are already familiar with the term cohesion, you can quickly identify that a component that follows this principle can often be described as a “highly cohesive” component.

If I took a moment to ask the question, “What should the main responsibility of the View Employees Web page be”? The simple answer is that it should only be dealing with the rendering of a set of employees to the user. However, if I take a look at the code-behind, the reality of the situation is quite different. Instead of methods focused around the rendering of employees to the user, the component is currently responsible for:

  • Creating a connection to the database.
  • Creating a SQL statement to pull the appropriate information from the database.
  • Disposing of expensive resources (connection, reader, etc.).
  • Mapping the database information to a domain representation of the data.
  • Rendering the information to the user.

As you can see from this short list, this component has far too many responsibilities. To make matters worse, not all (most) of the responsibilities have anything to do with “rendering” a list of employees to the user. If this does not smell of low cohesion, I don’t know what does.

For a long time people have been realizing the value of introducing the concept of n-tier/layered architectures into their applications to address this very issue. In short, the introduction of a layered architecture can ensure that each layer (as pragmatically as possible) can adhere to the single responsibility principle. Figure 2 shows a proposed high-level diagram for the separate layers that will make up the application. I am going to tackle refactoring this application by going from the top down. I can first make use of the “passive view” variant of the “model view presenter” design pattern to deal with the abuse of responsibility in the code-behind for the Web page. I will not dive into the details of this pattern in this article; you can take a look at an article I wrote last year that talks about the pattern in more detail: http://msdn.microsoft.com/msdnmag/issues/06/08/DesignPatterns/)

Click for a larger version of this image.

Figure 2: A proposed high-level diagram for the separate layers.

The first refactoring I will tackle is to pull out code not directly related to the responsibility of “rendering employees” (read: pull pretty much all code from the code-behind!). Listing 2 shows the resulting code for the code-behind of the Web page. Compared to Listing 1, the difference here is night and day. If you are not familiar with the passive view pattern, here’s a quick description:

  • View implementation (Web page) implements an interface that is consumed by the presenter.
  • The View interface exposes events that are implemented by the View (Web page) and subscribed to by the presenter.
  • The View raises events in response to events that occur on itself (for example, Button is clicked, Load is happening), these events are in turn handled by the presenter.
  • The presenter processes the event accordingly and may push information back to the view by means of using the View interface.
  • Using the View interface allows the presenter to remain loosely coupled to any particular UI technology (for example, ASP.NET).

Listing 3 shows the first iteration of the presenter class.

From the looks of Listing 3 all that I have managed to accomplish is to push the messiness that was originally located in the code-behind for the Web page and move it into another class. However, with the introduction of the interface for the view, I have introduced a concept that is critical in creating flexible layered architectures: the dependency inversion principle.

&

By: Jean-Paul S Boodhoo

Jean-Paul Boodhoo

bitwisejp@gmail.com

(403) 560-3590

Jean-Paul S. Boodhoo is a .NET delivery expert who has been working with the .NET Framework since beta 1 of .NET 1.0. He has over seven years of experience in architecting, designing, and developing applications. He spends his days working as an independent consultant; helping teams realize success through agile practices and pragmatic Behavior Driven Development (BDD) techniques.

He has a passion for sharing information on applied behavior-driven development with .NET, and has written articles for Visual Studio Magazine, DevX, and MSDN that utilize BDD to pragmatically apply .NET. Jean-Paul has presented on the popular podcast/screencast .NET Rocks! and DNRTV and has delivered Webcasts for Microsoft on the topic of design patterns in the real world. He is a member of the MSDN Canada Speakers Bureau and a Microsoft Most Valuable Professional (MVP).

You can reach Jean-Paul at bitwisejp@gmail.com and he makes continual efforts to update his blog at http://www.jpboodhoo.com/blog.

bitwise@memlane.com

Fast Facts

Software developers use the term cohesion to describe the relation and focus of a particular component.



Listing 1: First attempt at UI
public partial class ViewEmployeesTightlyCoupled : Page
{
   private const string ConnectionString = "data 
   source=(local);Integrated Security=SSPI;Initital
   Catalog=NorthWind";
   private SqlConnection connection;

   protected void Page_Load(object sender, EventArgs e)
    {
        if (! IsPostBack)
        {
         PopulateGridFrom(MapFrom(GetAllEmployees()));
        }
    }

    private DataTable GetAllEmployees()
    {
      using (connection = new 
      SqlConnection(ConnectionString))
        {
            SqlCommand command = 
            connection.CreateCommand();
            command.CommandText = "SELECT * FROM 
            Employees";
            command.CommandType = CommandType.Text;

            connection.Open();


            using (SqlDataReader reader = 
            command.ExecuteReader(
            CommandBehavior.CloseConnection))
            {
                DataTable results = new DataTable();
                results.Load(reader);
                return results;
            }
        }
    }

    private List<EmployeeMapFrom(DataTable 
    employeeData)
    {
        List<Employeeemployees = new 
        List<Employee>();
        foreach (DataRow employeeRow in 
        employeeData.Rows)
        {
            employees.Add(MapFrom(employeeRow));
        }
        return employees;
    }

    private void PopulateGridFrom(List<Employee
    employees)
    {
        this.employeesRepeater.DataSource = employees;
        this.employeesRepeater.DataBind();
    }

    private Employee MapFrom(DataRow row)
    {
        return
            new Employee(Convert.ToInt32(
            row["EmployeeId"]), 
            row["LastName"].ToString(), 
            row["FirstName"].ToString(), 
            row["Title"].ToString(),
            Convert.ToDateTime(row["BirthDate"]), 
            Convert.ToDateTime(row["HireDate"]));
    }
}


Listing 2: Code-behind of Web page with introduction of presenter
public partial class 
ViewEmployeesWithAdditionOfPresenter : Page, 
IEmployeeView
{
    private ViewEmployeesPresenterLowCohesion 
    presenter;

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        presenter = new 
        ViewEmployeesPresenterLowCohesion(this);
    }

    public IList<IEmployeeEmployees
    {
        set
        {
            this.employeesRepeater.DataSource = value;
            this.employeesRepeater.DataBind();
        }
    }

}


Listing 3: First attempt at a presenter
public class ViewEmployeesPresenterLowCohesion
{
    private IEmployeeView view;
    private const string ConnectionString = "data
    source=(local);Integrated Security=SSPI;
    Initital Catalog=NorthWind";
    private SqlConnection connection;


    public ViewEmployeesPresenterLowCohesion(
    IEmployeeView view)
    {
        this.view = view;
        HookupEventHandlersTo(view);
    }

    private void HookupEventHandlersTo(
    IEmployeeView view)
    {
       view.Load += delegate { LoadEmployees(); };
    }

    private void LoadEmployees()
    {
       if (view.IsPostBack) return;
        view.Employees = MapFrom(GetEmployees());
    }

    public DataTable GetEmployees()
    {
       using (connection = new 
       SqlConnection(ConnectionString))
        {
           SqlCommand command = 
           connection.CreateCommand();
           command.CommandText = "SELECT * FROM 
           Employees";
           command.CommandType = CommandType.Text;
           connection.Open();

           using (SqlDataReader reader = 
           command.ExecuteReader(
           CommandBehavior.CloseConnection))
           {
              DataTable results = new DataTable();
              results.Load(reader);
              return results;
           }
       }
   }

   private IList<IEmployee
   MapFrom(DataTable employeeData)
   {
       List<IEmployeeemployees = new 
       List<IEmployee>();
       foreach (DataRow employeeRow in 
       employeeData.Rows)
       {
           employees.Add(MapFrom(employeeRow));
       }
       return employees;
   }

   private Employee MapFrom(DataRow row)
  {
       return
           new Employee(Convert.
           ToInt32(row["EmployeeId"]), 
           row["LastName"].ToString(),
           row["FirstName"].ToString(), 
           row["Title"].ToString(),
           Convert.ToDateTime(row["BirthDate"]),
           Convert.ToDateTime(row["HireDate"]));
   }
}


Article Pages:  1  2 3 4 - Next Page: 'The Dependency Inversion Principle' >>

Page 1: Layered Architecture, Dependency Injection, and Dependency Inversion
Page 2: The Dependency Inversion Principle
Page 3: Putting Dependency Injection and Dependency Inversion through Their Paces in the Service Layer
Page 4: Gluing It All Together

How would you rate the quality of this article?
1 2 3 4 5
Poor      Outstanding

Tell us why you rated the content this way. (optional)

Average rating:
4.2 out of 5

90 people have rated this article.

Instantly Search Terabytes Of Text
“Lightning Fast”
– Redmond Mag
“Covers all data
sources” – eWeek
25+ fielded & full-text search options
dtSearch’s own document filters highlight hits in popular file types
Web Spider supports static & dynamic data
APIs for .NET, Java, C++, SQL, etc.
Win / Linux (64-bit & 32-bit)
www.dtSearch.com
 

      LearnNow

 

SSWUG