Java

Building Enterprise Frameworks – Data and Domain

0

In the previous blog entry “Thinking Enterprise Architecture”, I presented the background for a series focusing on Enterprise Architecture. Previously, we discussed the core design principles for software development. We also introduced several design patterns to satisfy the core principles. The concepts were applied to several technologies and demonstrated using Inversion of Control (IoC), Model-View-Controller (MVC) and Windows Communication Foundation (WCF). Since the core design principles and design patterns are not framework or language specific, the “Part VI: Brick Design – How to design and build better software for tomorrow?” article was a Java implementation of the Contact Manager application.

In this entry, I will provide the preliminary enterprise framework core components supporting the domain model and data tier. I will emphasize the word preliminary, because the framework will evolve and refactoring will be required to satisfy our objectives. I will loosely base the framework on the design built by the team introduced in the background entry, since they prefer not to share all design and implementations. The project will be based on my standard Contact Manager application. Basically, we are separating the common components and establishing a framework to build enterprise applications.

First, we create a new project as a class library for the common enterprise framework. The project contains the Data and Model root folders, which are collections of interface and abstract classes. These are not our concrete implementations, but the shared objects that our enterprise projects reference.

The Domain folder includes the IEntity interface and the abstract EntityBase class. All domain model concrete classes should implement IEntity. The interface is our contract, so this should drive the implementations within an interface-based system. The interface includes the Id property, which is the only domain object property that should be common for all concrete implementations.

1
using System;
2
 
3
namespace Joemwalton.Framework.Domain
4
{
5
    public interface IEntity<TId>
6
    {
7
        TId Id { get; set; }
8
    }
9
}

We elected to create a Generic interface, so we can define the types at run-time and not design-time. In this case, our Id property type is unknown. The implementation will define the type, so we are not forced to commit in the contract.

The EntityBase is an abstract class, which serves as a base class to define shared behavior for an implementation to inherit. This class is providing the implementation for the common entity Id property and validation logic. In this domain-driven design, we are encapsulating the business rules for validating the domain object. The Validate method is abstract, since only the concrete implementation would be aware of the validation logic required for the domain object. As we refactor the framework classes, the following will change to reflect our technical design.

01
using System;
02
using System.Collections.Generic;
03
 
04
namespace Joemwalton.Framework.Domain
05
{
06
    public abstract class EntityBase<TEntity,TId> 
07
        : IEntity<TId>
08
        where TEntity : IEntity<TId>
09
    {
10
        public  TId Id { get; set; }
11
 
12
        private List<string> _failedValidations = new List<string>();
13
        protected List<string> FailedValidations 
14
        {
15
            get { return _failedValidations; } 
16
        }
17
 
18
        public List<string> GetFailedValidations()
19
        {
20
            _failedValidations.Clear();
21
            Validate();
22
            return _failedValidations;
23
        }
24
 
25
        protected abstract void Validate();
26
    }
27
}

The next step is the skeleton design for the data tier, which includes the data access tier or repository. The repository is a memory-based domain collection, which is responsible for persisting and retrieving the domain objects. We will also build an interface and base class to support the concrete repository implementations. The IRepository interface is the contract, which includes methods for the standard Create-Read-Update-Delete (CRUD) operations. At this point, we would like all repository implementations to support the basic operations – Save, FindById, FindAll, Update and Delete. The concrete implemenations could include additional methods, which provide additional operations.

01
using System;
02
using System.Collections.Generic;
03
using Joemwalton.Framework.Domain;
04
 
05
namespace Joemwalton.Framework.Data.Repository
06
{
07
    public interface IRepository<TEntity,TId>
08
        where TEntity : IEntity<TId>
09
    {
10
        void Save(TEntity entity);
11
        void Remove(TEntity entity);
12
        TEntity FindById(TId id);
13
        List<TEntity> FindAll();
14
    }
15
}

Since our domain object type is unknown at design-time, we use generics to allow run-time assignments. The where clause is included as a contraint, so the run-time type must be IEntity. The TEntity represents the run-time domain object. The following RepositoryBase abstract class is a placeholder, so this will also be refactored as our design evolves.

01
using System;
02
using System.Collections.Generic;
03
using NHibernate;
04
using Joemwalton.Framework.Domain;
05
 
06
namespace Joemwalton.Framework.Data.Repository
07
{
08
    public abstract class BaseRepository<TEntity,TId> 
09
        : IRepository<TEntity,TId>
10
        where TEntity : IEntity<TId>
11
    {
12
        public void Remove(TEntity entity) { }
13
 
14
        public void Save(TEntity entity) { }
15
 
16
        public TEntity FindById(TId id)
17
        {
18
            return default(TEntity);
19
        }
20
 
21
        public List<TEntity> FindAll()
22
        {
23
            return new List<TEntity>() { default(TEntity) };
24
        }
25
    }
26
}

Next, the Data.NHibernate folder contains the NHibernateRepositoryBase abstract class. This class contains NHibernate implementation code including the SessionFactory. Since we also selected Spring.NET, the Spring framework Object-Relational Mapping (ORM) modules provides the plumbing for this support. The IoC container provides the features to simplify the configuration, NHibernate session and enterprise transaction management. This class will also require refactoring as the features and implementations are discovered, but the following is a start.

01
using System;
02
using NHibernate;
03
using Joemwalton.Framework.Data.Repository;
04
using Joemwalton.Framework.Domain;
05
 
06
namespace Joemwalton.Framework.Data.NHibernate
07
{
08
    public abstract class NHibernateRepositoryBase<TEntity,TId> 
09
        : BaseRepository<TEntity,TId>
10
        where TEntity : IEntity<TId>
11
    {
12
        private ISessionFactory sessionFactory;
13
 
14
        /// <summary>
15
        /// Session factory
16
        /// </summary>
17
        public ISessionFactory SessionFactory
18
        {
19
            protected get { return sessionFactory; }
20
            set { sessionFactory = value; }
21
        }
22
 
23
        /// <summary>
24
        /// Get current active session
25
        /// </summary>
26
        protected ISession CurrentSession
27
        {
28
            get { return sessionFactory.GetCurrentSession(); }
29
        }
30
    }
31
}

In summary, the above are the draft enterprise framework classes and refactoring will be required in the future installments of the series. In the next entry, we will build tests including the mock objects for our abstractions. Once the enterprise framework is established, we will create a Contact Manager application. So…stay tuned for the next article in this series!

Next: Building Enterprise Frameworks - Testing and Mock Objects

Previous: Thinking Enterprise Architecture

Thinking Enterprise Architecture

0

I recently met a friend and fellow software engineer to discuss his current project. We met earlier this year during my .NET Code Camp presentation. I appreciate his candid feedback and suggestions for future articles, since he is a very talented developer and fanatical baseball fan. Although I really enjoy baseball, I am more of a seasonal fan in October. He is also an advocate of the same software design principles and supporting design patterns outlined during the presentation, which I also featured in “How to design and build better software for tomorrow?” multi-part series.

The Project

The project entailed building three major back-office applications, so he assembled a development team for each application. The teams were instructed to follow the software design principles, which they all agreed were important. After several weeks, he was surprised that each team presented such different solutions. The data access layer choices were NHibernate, Linq2Sql and Entity Framework. Although all teams built web solutions, two teams selected Model-View-Controller (MVC) and the third team Model-View-Presenter (MVP). The teams also selected different Inversion of Control (IoC) frameworks, which included Spring.NET and Microsoft Unity. They also followed different validation and exception handling strategies. After he summarized the current status, he expressed his disappointment and frustration. He was obviously directing some of the blame at me. I apologized and sympathized with his frustration. After a brief baseball playoffs and politics conversation, I suggested we work together to rectify the current situation and develop a plan to get the projects back on track. He recognized the long-term impact would be detrimental to the organization, since they would be forced to maintain so many competing technologies, tools and implementations.

I am not surprised that three teams delivered three different solutions. The core principles provide guidance and promote well- designed software, which all three products exhibited. They encourage a design that meets the objectives of the organization and project, but not tightly coupled to any implementation. Change is expected. The ”How to design and build better software for tomorrow?” multi-part series demonstrated a variety of presentation, business and data access layer implementations. The same principles and design patterns were applied to console applications, WinForms and MVC. We developed concrete data access implementations using pure ADO.NET and LINQ. The core software design principles and patterns are also platform independent, so we built working .NET and Java applications.

After this explanation, he better understood the objective of the software design principles and patterns. We agreed all teams were successful and accomplished the objectives. What went wrong? How do we fix it?

Enterprise Architecture

The enterprise architecture is an organization-wide framework containing a collection of collaborating modules to support the organization’s needs, which is the foundation for a unified platform. This requires establishing the common infrastructure or framework promoting the same core software design principles and design patterns. I would also include the supporting processes.

The logical approach is building a common framework before launching the development of the domain-level modules, but we now have three working applications and no enterprise architecture. After reviewing the three applications, we noticed the teams built similar interfaces and abstract classes. They also share many common services and concrete implementations. These are all common framework candidates, but we were still faced with many decisions as the enterprise evolves. In the end, we decided to apply basic project management techniques and invite the three teams to participate in the sessions. We referred to the three applications as “prototypes” and discussed the technical merits of each including risk, cost and schedule assessments. The teams prepared demonstrations and discussed the technical design. Although the teams initially lobbied for their design, the project management techniques reduced the probability of a biased decision.

The following is a summary of the major decisions and foundation for building the framework.

  • Presentation/User Interface - MVC3 and Razor using view models
  • Business - service objects acting as the entry points coordinating the exchanges between presentation, other service objects and the data access layers
  • Domain – a rich domain-driven design (DDD) supporting enterprise validation
  • Data Access – persistence using NHibernate to SQL Server
  • IoC – Spring.NET

After a few weeks, the enterprise team started building the common framework based on the agreed technical design. Once the framework is complete, the team will refactor the three applications to integrate the common framework. Since the team followed the core software design principles and design patterns, this task will require much less work. The Dependency Injection (DI) pattern and IoC will simplify this process, so the team can focus on building the domain modules to satisfy the needs of the organization. The project schedule was pushed slightly to the right resulting in a delay, but all is not lost. The team is confident the common framework and wealth of reusable components will enable them to accelerate the schedule and deliver the products on time. They also agree the quality will be much improved. Maybe you did not notice, but I no longer refer to them as teams. The experience not only produced a unified enterprise framework, but they are now a unified team.

In the majority of my engagements, we always plan and build a common framework. If you do not have a dedicated team to maintain the common framework then appoint members from all project teams to participate. In both cases, the enterprise team should act as the change control board (CCB) to approve or deny change requests. It is critical to ensure changes do not break existing features or modules, so following the best testing practices is essential.

When the team extended an invitation to participate in this process, I could not decline the offer. They also agreed to allow me to blog about the experience and share with the community. So…I plan to chronicle the journey and decisions along the way including plenty of code examples. Please visit again soon…

Building Enterprise Frameworks – Data and Domain

Building Enterprise Frameworks – Testing and Mock Objects

Part VI: Java Brick Design – How to design and build better software for tomorrow?

0

Since the “How to design and build better software for tomorrow?” series, I received a few requests from members and colleagues in the Java community. Although the concepts and techniques can be applied to all OO languages, the code examples are C# .NET. Since the majority of my recent projects have been .NET, I just naturally start thinking and writing .NET. So…this post will be a port of the Brick Contact Manager .NET project to Java. If you did not follow the series then I encourage you to read the 4 previous entries as background. If you found this post and prefer the .NET flavor then click here.

In Part IV, we refactored our prototype design and introduced the Stick Contact Manager. We applied several design patterns, which established a solid foundation for well-designed software. The design patterns and principles include Dependency Injection Principle (DIP), Separation of Concerns (SoC), Dependency Injection (DI) and Single Responsibility Principle (SRP).

The following are the classes of the common library, which are referenced by the Brick Contact Manager console application. They have been refactored to follow the above design patterns, which were discussed in the previous entries of the series.

The Contact class is a POJO representing the model or domain object for our contact information. The IContactRepository is the interface or contract for our implementation of the data layer responsible for persistence of the contact information. The ContactRepository represents our concrete implementation.

01
package contactmanager.common.model;
02
 
03
import java.io.Serializable;
04
 
05
/**
06
 * Domain Object
07
 *
08
 */
09
public class Contact implements Serializable {
10
 
11
    private Integer id;
12
    private String name;
13
    private String emailAddress;
14
    private String mobilePhone;
15
 
16
    public Contact() {
17
    }
18
 
19
    public Contact (String Name,
20
                    String EmailAddress,
21
                    String MobilePhone) {
22
        this.name = Name;
23
        this.emailAddress = EmailAddress;
24
        this.mobilePhone = MobilePhone;
25
    }
26
 
27
    public Integer getId() {
28
        return this.id;
29
    }
30
 
31
    public void setId(Integer Id) {
32
        this.id = Id;
33
    }
34
 
35
    public String getName() {
36
        return this.name;
37
    }
38
 
39
    public void setName(String Name) {
40
        this.name = Name;
41
    }
42
 
43
    public String getMobilePhone() {
44
        return this.mobilePhone;
45
    }
46
 
47
    public void setModilePhone(String MobilePhone) {
48
        this.mobilePhone = MobilePhone;
49
    }
50
 
51
    public String getEmailAddress() {
52
        return this.emailAddress;
53
    }
54
 
55
    public void setEmailAddress(String EmailAddress) {
56
        this.emailAddress = EmailAddress;
57
    }
58
 
59
    @Override
60
    public String toString()
61
    {
62
        return new StringBuilder()
63
                .append("Name=")
64
                .append(this.name)
65
                .append("\nEmailAddress=")
66
                .append(this.emailAddress)
67
                .append("\nMobilePhone=")
68
                .append(this.mobilePhone)
69
                .toString();
70
    }
71
}

01
package contactmanager.common.repository;
02
 
03
import contactmanager.common.model.Contact;
04
 
05
/**
06
 * ContactRepository contract
07
 * Create one or more implementations.
08
 */
09
public interface IContactRepository {
10
 
11
    void save(Contact contact);
12
}

01
package contactmanager.common.repository;
02
 
03
import contactmanager.common.model.Contact;
04
 
05
/**
06
 * Concrete implementation to persist contact to data store
07
 * I am now separated with a single responsibility to be maintainable,
08
 * reusable and testable!
09
 */
10
public class ContactRepository implements IContactRepository {
11
 
12
    public ContactRepository() { }
13
 
14
    @Override
15
    public void save(Contact Contact) {
16
        System.out.println("ContactRepository.Save: \n" +
17
                Contact.toString());
18
        //TODO: code to persist contact
19
    }
20
}

If we introduce a new technique to persist the contact information then building a new contact repository implementation would be simple. The design patterns will enable us to simplify the process of swapping the new contact repository implementation, so the enterprise application would require no coding changes. This technique is also beneficial for prototyping, so you are not forced to modify your high-level classes. You are creating classes that rely on abstractions or interfaces instead of concrete implementations, so you have the flexibility to swap implementations without significant impact – the ripple effect.

We apply the same technique for the notification services, where the INotificationService is the abstraction/interface and we can create any number of concrete implementations. In our example below, we built the EmailService to provide email capabilities. The same benefits apply as discussed previously, so we can create new concrete implementations for notification services without causing a ripple effect throughout the system. The change is less painful using the design patterns.

01
package contactmanager.common.services;
02
 
03
import contactmanager.common.model.Contact;
04
/**
05
 * NotificationService contract
06
 * Create one or more implementations. Try using an abstract
07
 * class if shared features are beneficial to the implementations.
08
 */
09
public interface INotificationService {
10
 
11
    void send(Contact Contact);
12
 
13
    String getMessage();
14
 
15
    void setMessage(String Message);    
16
}

001
002
/**
003
 * Concrete implementation to send email notifications
004
 * I am now separated with a single responsibility to be maintainable,
005
 * reusable and testable!
006
 */
007
public class EmailService implements INotificationService {
008
 
009
    private String message;
010
    private String subject;
011
    private String sender;
012
    private String smtpHost;
013
 
014
    public EmailService() { }
015
 
016
    public EmailService(String SmtpHost,
017
                        String Sender,
018
                        String Subject,
019
                        String Message) {
020
            this.message = Message;
021
            this.subject = Subject;
022
            this.sender = Sender;
023
            this.smtpHost = SmtpHost;
024
    }
025
 
026
    @Override
027
    public void send(Contact Contact)
028
    {
029
        System.out.println("EmailService.Send: \n" +
030
                toString() +
031
                Contact.getName());
032
        //TODO: email
033
    }
034
 
035
    @Override
036
    public String toString()
037
    {
038
        return new StringBuilder()
039
                .append("SmtpHost=")
040
                .append(this.smtpHost)
041
                .append("\nSender=")
042
                .append(this.sender)
043
                .append("\nSubject=")
044
                .append(this.subject)
045
                .append("\nMessage=")
046
                .append(this.message)
047
                .toString();
048
    }
049
 
050
    /**
051
     * @return the Message
052
     */
053
    @Override
054
    public String getMessage() {
055
        return this.message;
056
    }
057
 
058
    /**
059
     * @param Message the Message to set
060
     */
061
    @Override
062
    public void setMessage(String Message) {
063
        this.message = Message;
064
    }
065
 
066
    /**
067
     * @return the Subject
068
     */
069
    public String getSubject() {
070
        return this.subject;
071
    }
072
 
073
    /**
074
     * @param Subject the Subject to set
075
     */
076
    public void setSubject(String Subject) {
077
        this.subject = Subject;
078
    }
079
 
080
    /**
081
     * @return the Sender
082
     */
083
    public String getSender() {
084
        return this.sender;
085
    }
086
 
087
    /**
088
     * @param Sender the Sender to set
089
     */
090
    public void setSender(String Sender) {
091
        this.sender = Sender;
092
    }
093
 
094
    /**
095
     * @return the SmtpHost
096
     */
097
    public String getSmtpHost() {
098
        return this.smtpHost;
099
    }
100
 
101
    /**
102
     * @param SmtpHost the SmtpHost to set
103
     */
104
    public void setSmtpHost(String SmtpHost) {
105
        this.smtpHost = SmtpHost;
106
    }
107
}

The ContactsService class is our final common library object, which is the called by the Brick Contact Manager user interface to handle our business logic. It is responsible for orchestrating the objects required to perform complete the desired client request, which is add a contact in our example. We do not have logic to email or persist data, since these tasks have been delegated to the appropriate objects. The design is decoupled from the concrete implementations, since the constructors accept abstractions/interfaces instead of concrete types.

01
package contactmanager.common.services;
02
 
03
import contactmanager.common.model.Contact;
04
import contactmanager.common.repository.IContactRepository;
05
/**
06
 * High-level concrete contacts service - called by the client
07
 * I am not married to low-level concrete dependencies, so any
08
 * changes will no longer affect me. I now depend on interfaces
09
 * or abstract classes.
10
 */
11
public class ContactsService {
12
 
13
    private IContactRepository ContactRepository;
14
    private INotificationService NotificationService;
15
 
16
    //dependencies are now injected using the constructor
17
    public ContactsService(IContactRepository ContactRepository,
18
                           INotificationService NotificationService)
19
    {
20
        this.ContactRepository = ContactRepository;
21
        this.NotificationService = NotificationService;
22
    }
23
 
24
    public void addContact(Contact Contact)
25
    {
26
        //code is simple and easy to understand!
27
        System.out.println("ContactsService.AddContact: \n" +
28
                Contact.toString());
29
        this.ContactRepository.save(Contact);
30
        this.NotificationService.send(Contact);
31
    }
32
}

The Stick Contact Manager (see Part IV) scored high marks during our evaluation, although we discovered one frustrating side-effect of the design – the client still must have knowledge of how to create the dependencies. We successfully eliminated the dependency creation throughout the majority of the objects, but we are forced to write significant code to create the dependencies.

The solution is centralizing the object creation or instantiation, so the client can delegate the task and knowledge of all the dependencies to another entity. This can also promote reusability, so the clients or consumers can also delegate this task to the same entity. This would eliminate the need for redundant client code required to create the dependencies.

As discussed previously, the Stick Contact Manager client still must have knowledge of how to create the dependencies. As an alternative, we will introduce Inversion of Control (IoC) for our centralized object creation solution. An IoC container will handle the object creation, so now we can remove the majority of the code and just request the object. In general, IoC inverts the relationship by the client delegating control to the container. In this example, we selected Spring for the job.

So…let’s refactor the client for the Brick Contact Manager to call the Spring IoC container and request the ContactsService (download source code). The container will instantiate the object and injects all dependencies, so the object is ready to use without additional initialization.

01
package brickcontactmanager;
02
 
03
import contactmanager.common.model.Contact;
04
import contactmanager.common.services.ContactsService;
05
import org.springframework.context.ApplicationContext; 
06
import org.springframework.context.support.ClassPathXmlApplicationContext;
07
 
08
/** 
09
* Simple console application to illustrate the design patterns of ContactManager
10
*
11
*/
12
public class BrickContactManager {
13
 
14
    /**
15
     * @param args the command line arguments
16
     */
17
    public static void main(String[] args) {
18
        System.out.println("*** BrickContactManager ***");
19
        //set reference to IoC container
20
        ApplicationContext context = 
21
                new ClassPathXmlApplicationContext("applicationContext.xml",
22
                BrickContactManager.class);
23
        /* request object from container - client is no longer aware of how
24
           to construct the object and its' dependencies!!! */
25
        ContactsService service = (ContactsService)context.getBean( "ContactsService" );
26
 
27
        service.addContact(new Contact("John Doe",
28
                                       "jwalton@test.com",
29
                                       "0000000000"));
30
    }
31
}

It was just a few lines of code for the client and we significantly reduced the clutter regarding the instantiation of the objects, which has been delegated to the Spring IoC container. How does the container know how to create the objects? Well, we will need to provide the instructions to the container. We will select the xml metadata configuration approach, so the bean definition is contained in an external xml file. So…let’s look at the object definitions in the xml metadata files.

01
<?xml version="1.0" encoding="UTF-8"?>
02
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
03
<beans>
04
    <bean id="ContactsService"
05
          class="contactmanager.common.services.ContactsService">
06
        <!-- inline object -->
07
        <constructor-arg>
08
            <bean class="contactmanager.common.repository.ContactRepository" />
09
        </constructor-arg>
10
        <constructor-arg ref="EmailService" />
11
    </bean>
12
    <bean id="EmailService"
13
          class="contactmanager.common.services.EmailService" >
14
        <constructor-arg value="dummy.com" />
15
        <constructor-arg value="test@dummy.com" />
16
        <constructor-arg value="Hello!" />
17
        <constructor-arg value="Hello Email Contact!" />
18
    </bean>
19
</beans>

The element bean contains the instructions to instantiate and initialize an object. The id or name attribute is the reference name, which is the value that is passed when requesting an object from the IoC container. The class attribute is the namespace qualified class name. The primary bean child elements include the constructor-arg and property, which provide constructor and setter based dependency injection techniques.The value attribute is the static value, expression or placeholder. The ref attribute identifies the name or id of another bean element, so the value is set to this object.

Our Brick Contact Manager xml metadata example is only scratching the surface of the options available for defining your objects. Bean configuration and the popular elements and attributes supporting instantiation, inheritance, lifecycle, scope and the injection types (setter and property) are available.

The following is the output from the NetBeans IDE, where you can trace the calls based on the console writes.

The choice of the dependency injection type (i.e. constructor, setter or method) is sometimes a personal choice. I prefer defining a constructor for mandatory dependencies and setter properties for optional items. If you have too many mandatory items then your constructors become difficult to manage and configure using IoC.

Spring provides a robust set of IoC features that are too many to present in this post. You can download the Brick Contact Manager and review the code. You will find making changes is simple. The NetBeans and Eclipse development environments provide the libraries and templates to support Spring, so this minimizes the learning curve for Spring.

In summary, the Brick Contact Manager complements the Stick Contact Manager and solves the object creation responsibility problem. I have found that following the software design principles we have defined in Part II and implementing the patterns in Part IV are a good defense against premature end-of-life scenario for your applications. The addition of an IoC container will further promote the software design principles and add significant value to your product. You will find maintenance and change requests will be less painful.

I hope you found this series helpful and will be able to follow the concepts presented with your next project. I still receive messages from colleagues of previous projects as they continue to promote the design patterns and practices discussed in this series. If you are currently working a project then take a few minutes and perform an evaluation using our software design principles. Would your project benefit from the design patterns and concepts?

Source Code

Go to Top