Building .NET Enterprise Applications with Patterns: Part I - Introducing Enterprise Development



Today, I have a lot of free time. So, I decided to write a series of short articles about building enterprise applications using proven patterns. This is a very interesting topic that I think every developer should be aware of. With my knowledge and experience from reading books as well as struggling with some projects, I will try to provide what I understand in this field as much as possible. Because I am a .NET developer I will use a small application built on .NET as an illustration for my pages. Also, because of a limitation of time, I will just focus on what to do and how to do them through a case study. However, I will try to provide some explanation of why we should do that at somewhere.

That's enough for now. Let's begin with the first article of the series. In this article, I will explain the following:

  • What are enterprise applications
  • How to build an enterprise application
  • A case study (introduction)
What Are Enterprise Applications ?

Enterprise applications are software which has the following characteristics:

  • First, most of them are line of business (LOB) applications. LOB applications have often been used in organizations, companies or governments where they effectively service user's demands in their business.
  • Second, they are quite large and complex programs because they are used by many users who might work at many geographic locations and use many devices.
  • Third, an enterprise application must fulfill 4 core quality attributes: reliability, flexibility, reusability, and maintainability.

Reliability is the ability to guarantee that the application is always running properly in all use cases. In other words, the application works in the manner the user expects and never works in unexpected ways for the user for any failure. Obviously, this is a must have requirement. Additionally, there are no ways other than testing the program against all use cases that have been identified to make sure it is reliabile. Because of this, many experts exchange the term reliability with testability.

Flexibility is the ability of changing core features without violating unrelated features or components. This is a prevalent requirement from stakeholders, especially at the phase we are building application. It originates from the fact that application's requirements usually change because we might not grasp all business processes at the initial phase of the project. Many people misunderstand the flexibility with the interoperability. Although flexibility can help us to achieve interoperability easily but the opposite is not true. For example, a program might run on multiple platforms, contain logic for many scenarios but that wouldn't mean it was flexible if it forces us rewrite code in all components when we just want to change some aspects of a feature it had.

Reusability is the ability of sharing one or more program's components in another program or system. It is very useful and makes sense in many aspects such as it makes consistent code that improves performance, increases maintainability, and reduces cost of development. A note when we try to make reusability in our code is that we should just open a component's reusability on the context in which it is used. For example, we write classes that implement UI logic and deliver that behavior to only classes that implementing UI. The reusability is an especially important factor when rating if an application is a true enterprise design.Maintainability is the ability of adding or removing features to an application after it was released to users without giving up the existing core framework of the application. As a user, we often see this capacity in the form of auto-update or auto-upgrade feature of software. As a developer, we know that the maintainability consists of many factors such as readability, analyzability, extensibility therein extensibility is critical. Maintainability requires us to write code that is longer and more complex than normal but the result is decreasing the cost and effort of maintenance and increasing the stability of the program. However, maintainability doesn't mean we introduce unnecessarily complex code. We always try to make our code clear and transparent to everyone.


How To Build An Enterprise Application ?

Building an enterprise application is trying to create software that fulfills the four requirements stated earlier.

We can achieve reliability through testing. Particularly, we need to test each smallest unit of function defined in our application. To do so, we must have a framework that supports unit testing and a methodology for building test driven applications that we call test driven development (TDD). However, TDD and unit tests would be possible only if we architected our application following a model that enables us to create components working independently.

We can achieve flexibility, reusability, and maintainability altogether by applying object-oriented design principles defined by Robert C. Martin (also well- known as SOLID principles). I will explain each principle briefly and how it impacts our requirements.

The first principle is Single Responsibility Principle (SRP that is represented by S in SOLID). This principle says that each object should have only a single responsibility or reason to change. Obviously, SRP is a best fit for flexibility because if you change code of a class that is designed following SRP then you don't have to worry about code contained in other classes. That class is also fit for reusability because you just provide only one responsibility to others without concern for unexpected operations that could be called by external systems.

The second principle is Open/Closed Principe (OCP that is presented by O in SOLID). This principle says that software entities (classes, modules, functions, etc) should be opened for extension but closed for modification. We apply this principle in practice by creating contract-based design. The OCP is especially fit to maintainability because you can add or remove features without changing existed code. All you need to do is create new classes implemented using exiting interfaces or create new interfaces inherited from old interfaces and add more features.

The third principle is Liskov Substitution Principle (LSP that is represented by L in SOLID). This principle says that super types can be replaced by their sub types without altering the correctness of a program. LSP principle is also inspiration for creating contract-based design and therefore, it's also good for maintainability. Both OCP and LSP also help reusing components safely because components talk each other through interfaces.

The fourth principle is Interface Segregation Principle (ISP that is represented by I in SOLID). This principle says that one general purpose interface should be divided into many client specific interfaces. This principle is similar to SRP because it also supports easy modification of code without affecting unrelated code. So, the ISP principle is good for flexibility.

The fifth principle is Dependency Inversion Principle (DIP that is represented by D in SOLID). This principle provides a dependency relationship among using modules (high-level modules) and used modules (low-level modules) and provides a solution by reversing that dependency. Because of this, it was called Dependency Inversion or Inversion of Control. DIP is a critical mechanism to create extensible applications where it is used to enable writing an application's plug-ins or extensions. Obviously, it is useful for maintenance and testing.

So far, these principles I introduced have the same goal; that is help us to create loosely-coupled components. In other words, they were inspired from a generic philosophy called Separation of Concerns (SoC). SoC is a progress of separating a computer program into distinct features that overlap in functionality as little as possible. Typically, concerns are synonymous with features or behaviors. At a low-level, SoC can be achieved through encapsulating concerns in classes and modularizing classes in components. At a high-level, SoC is interpreted in layered designs of applications. So, what are layered designs? They are designs that require our applications to be divided into layers and tiers. The term layer has a logical meaning while the term tier has a physical meaning. For example, you are required to build an application that allows user access to data stored at a remote database. Applying SoC, you decided to divide your application into three subsystems: a database installed on a centre server, a program installed on another server and that provides services for clients, and each UI application installed on each client's computer.


Untitled.png

What you have just done is divided the applications into three tiers: UI tier, application tier, and data tier. Dividing an application into tiers has many benefits. For example, if you want to change or update data on a database, you just work on the database without preventing the application from running continuously. Next, you decided to arrange components or classes into logical containers put on a communication stack in your application. Each such logical container is called a layer. Typically, an enterprise application would be divided into 5 layers as illustrated in the following figure:


Untitled1.png

Details of each layer will be explained mentioned in future articles. For now, we should keep in mind two things:
  • Each layer (except Infrastructure Layer) can call the layer below it and answer the layer above it.
  • All layers can call the Infrastructure Layer.
Introducing a Case Study

TechCorp is a fictional domestic company which is a major distributor of technology devices such as smartphones, laptops, tablets, and computers. With the fast growth, it has a wide range of agencies in many locations. Normally, it requires each agency to use traditional means such as phones, email, or in-person at the company to order products. This cna be inconvenient for the business for the company as well as it's partners. Therefore, the company's CEO had contracted with us developers to build an application for agencies management that we call SmartCM.

After some meetings with TechCorp, we have got requirements as followings:
  • Support ordering products
  • Support submitting claims such as commission claim
  • Support making reports
  • Support offline capacity
  • Support for various devices
  • Support intelligent installation and auto-update features

To address the first three requirements, we will use a method called Domain Driven Design (DDD) to analyze and create a domain model for our application. Although DDD is complex to apply, it is easy for us to maintain and extend features in the future.

To support offline capacity, we will use a local database installed on the client's device as well as a remote database installed on a centre server at the company's office. We also chose SQL Compact Edition (SQL CE) as the local database because it is a lightweight database and can be installed on many devices.

To support various devices, we will build two type of UI, one for the web that is a best fit for mobile devices and one for Windows that is a best fit to desktop computers, laptops, and tablets. We also chose ASP.NET for building the web UI and WPF for building the Windows UI.To support intelligent installation as well as auto-update features, we will employ the One Click feature of .NET. It allows installion of an application by just clicking on a URL and automatic updatie of an application when the update feature and a connection are available.