Architectual Styles - Part Three : Domains

Brian LeGros | August 9th, 2007 | series  

The concept of a custom type is something that is hard to avoid when designing object-oriented software. I’ve always seen custom types as a way to bring organization and semantic meaning to my applications. I find they help me to better describe data, relationships, and behavior especially when implemented in the form of classes. My biggest question, however, when I first began programming was the degree to which I should be utilizing classes. I always end up trying to find a balance between the following two questions:

  • To what extent do I utilize a class for semantic purposes?
  • To what extent do I utilize a class for reuse?

When does the use of a class for semantic reasons become overkill and when am I designing for too much flexibility? I’ve come to favor semantics over reuse, however I feel both are very important in the creation of successful architectural designs.

So let’s talk about domains. What are they and why do I care? Well, for starters, when I refer to a domain, what I’m actually referring to are the identifiable entities based on a “real-world” problem for which a software application needs to be constructed to act as a solution. Put much simpler, a domain can be a collection of objects from the “real-world” recreated in software to solve a problem. Again this is just my definition, so yours may vary.

Please understand that the purpose of this post, is not how to conduct a domain analysis. There are much smarter people in the world with much better ideas than me that can help you in this area. That being said, below is a UML class diagram describing an example domain for a very simple search engine:

Example 1 - Class Diagram

The Search1 class is used to represent a search executed by a user. The SearchCriteria class represents the possible criteria that can be used to execute a search. SearchEngine1 is a very naive approach at representing some type of Fascade which uses an external search engine to execute a search. In this example, let’s say the utlimate goal of a search is to return some type of collection of strings, each of which represents a URI somehow related to the search criteria provided.

Now in this example, I’ve taken what I feel is a very pragmatic approach to representing the search results in my model; I decided to use a generic collection object of type List (arrays, sets, or any other type of generic collection could be used here, I just chose List). Please note, I make the assumption that the caller already has created the Search and SearchCriteria objects and the External Search Engine will return a List. Below is a simple sequence diagram which shows the order of messages sent within the application:

Example 1 - Sequence Diagram

So in Example 1 I have reused a collection object with a stock set of behavior with which I am familiar and can probably be productive with little effort. On the other hand, I have sacrificed the semantics of my domain, because the notion of search results are nothing more than a generic collection. Let’s say that I want to do something more with search results than List provides. What if I want to sort search results? If it’s a simple ascending or descending alphabetical sort, then yeah, my generic collection can probably handle the work, but what about a sort by domain name or protocol? If we were to implement this using the model from Example 1, the Caller actor would have to take the responsibility (assume the behavior) of sorting the search results because we chose to go with a generic collection. Although coupling remains loose because of the flexibility of different classes which may be typed as List, the Caller’s cohesion will be reduced because it’s assuming the behavior of a domain its consuming. What about this design decision from a maintenance POV; will other developers immediately know where to look for the behavior associated with sorting search results? Is the answer still yes if you have multiple Caller actors which call execute() on the Search object?

Example 2 is an alternative to Example 1 where semantics were chosen over reuse:

Example 2 - Class Diagram

Example 2 - Sequence Diagram

In this example, the External Search Engine is still returning a List, but the SearchEngine2 class is digesting that List and converting it into a SearchResults object (SearchResults could even inherit from List). The SearchResults class has behavior associated with it and now has semantic meaning in the context of the domain. From a maintenance perspective, it is also easy for other developers to see where the behavior for sorting search results resides. Additionally, the behavior associated with SearchResults is completely encapsulated from Caller, so cohesion remains high with both the actor and the object. Coupling on the other hand does get tighter, but I see this as a worth-while compromise to obtain a more semantically meaningful domain.

Similar examples where I see myself choosing semantics over reuse are situations such as reporting. I’ve said this in the past, but reports very commonly represent entities within a domain. In fact, I see a very common behavior associated with reports, rendering report contents (not to be confused with how to deliver the rendered contents of a report). If a report is being generated from a database, for example, why should the calling process be subject to having its cohesion reduced so that an abstract data type can be used (e.g. - a RecordSet class or the like)? How maintainable does the notion of rendering a report become when other calling processes have to utilize the behavior; what if we need to render a report in multiple ways instead of one default way (e.g. - fixed length, comma-delimited, XML)?

Please keep in mind, I’ve said that my preference is choosing semantics over reuse when modeling a domain, but I still see this as a preference. I am not saying that I will never use abstract data types when modeling a domain. I am saying however, if the data, relationships, and behavior associated with domain warrant the use of a custom type, I am much more likely to create that type, than look for an opportunity for reuse. I like to use the “pseudo-metrics” of cohesion and coupling as a check and balance to help gauge the trade-offs I’m making in the domain as well. I have begun to use these principles even more with my current employer than every before. I think the fact that we have to live with our code for quite some time (5+ years in some cases) is definitely another driving factor for my preferences.

As I continue this series, please try to keep an open mind and realize that this post will serve as the basis for other posts as well. I have many more styles to talk about. Thanks for reading this far.

<< Part 2 : Cohesion and Coupling

Architectual Styles - Part One : Introduction

Brian LeGros | July 21st, 2007 | series  

Just recently for my job, I completed a training packet for new hires that will hopefully aid us in an internship program we’re hoping to start. In part of the packet I try to expose our new developers to architectural tools, concepts, and styles. This is meant to empower them to understand the designs they’ll be asked to work with and begin to brainstorm about possible ways that we can improve our own process. What I’d like to do for my blog in this series of posts is go over those conversations and talk about the paths I choose to follow architecturally and why.

So as an introduction, let’s talk about the types of software I build so my mindset can be understood. Web applications are obviously first on my list. The context in which I usually build these applications is to expose new or existing business processes via the web. Integration is a big issue I have to be address on a daily basis, not only with third parties, but internally with other teams in the department. These applications are usually written with a common subset of web technologies (XHTML, CSS, JavaScript, Flash) and then I usually find myself using some combination of ColdFusion, Flex, and/or Java. Typically these applications are constructed for an audience of users external to company, but more recently I am building “intranet” based applications as well. The other type of software I find myself building is that of components. Usually these components are constructed as services later to be integrated with an ever evolving SOA. I usually find myself using Java because of the cool stuff that the JEE world can provide with some pretty descent maturity (i.e. - JTA, JMS, JPA, etc). I really like to use Spring as a container for these JEE tasks as well rather than something like EJB. The intended audience for these components are usually developers within the same or other teams of the department.

With that being said, this is how I will be presenting this series of posts:

  1. Introduction
  2. Coupling and Cohesion
  3. Domains
  4. Layering
    1. Business
    2. Integration
    3. Presentation
  5. Styles
    1. Light-weight Design
    2. Heavy-weigh Design
  6. Preferences

Please understand that I’m taking an object-oriented approach to design in this series. I am also taking the approach of an upfront design rather than something like TDD/BDD which jumps right into code (that’s a discussion for another day). I will use UML to help represent my thoughts (as best as possible) and will attempt to approach this from a language agnostic perspective. Look for more posts over the following weeks. I hope you enjoy the series!

NOTE : Please take what I have to say as my opinion and nothing else. Recently, my readership has spiked, so the last thing I want anyone to think is that I’m telling them how to design their software. These are practices that worked well for me and the last few companies that have employed me and I want to share them with the community.

Part 2 : Coupling and Cohesion >>

cf.objective() 2007 : Object Oriented Modeling

admin | May 7th, 2007 | conferences  

Let me start out by saying, I had little to no expectations about this talk whatsoever. In fact, I bought Internet at the conference for one day to specifically, at this talk, update my blog. Well I was very happy that my expectations were not correct. Wow, Hal Helms hit the nail on the head in terms of explaining object oriented concepts, UML, and dynamite examples. He was able to associate terminology with concepts I had yet to formalize in my head. His slides referred to a few OO books which I may buy just because of how his presentation went. Hal basically focussed on how to design the domain model associated with an application. He addressed what I’ve been calling light-weight designs, but he calls service-level designs, and how common it is that people will place their application business rules into service-level APIs, even mistake them for service-level business rules.

Overall, Hal’s talk was a great and I am happy I went and kinda disappointed I missed his Large Scale Architectures talk. Supposedly, his talks should be up on the cf.objective() site soon, so I’ll try to link to them soon.

cf.objective() 2007 : ColdBox Re-design Discussions

admin | May 6th, 2007 | conferences  

This wasn’t a session at the conference, but it caused me to miss a few sessions today. I wasn’t that impressed with the topic selection today anyway so this was more fun and more educational. I was able to catch up with Luis Majano for almost 4-5 hours today. I interviewed him at my previous job and really got a chance to know him better today. He humored me and gave me a full walk-through of ColdBox over an espresso. Wow, he has really found a good balance between convention and configuration I think. I really think that ColdBox has the ability to do for ColdFusion what Rails did for Ruby, or least to certain degree. Luis has built-in more tools than I can think of to help with productivity and debugging. ColdBox has framework configuration options available in XML, but the bulk of the work done by the application programmer is done by using convention. ColdBox has tools to generate a working application skeleton, a robust caching mechanism, and an amazingly sexy debugging utility. What even crazier is that ColdBox gains most of its power from the massive number of plug-ins available for the framework and the ease in which they can be created. ColdBox comes with support for Java localization and layout management out of the box and even better, if you want they can be turned off. There are tons of things I’m leaving out but I would definitely suggest checking it out. I’m seriously considering it over Fusebox after talking to Luis.

In an effort to better understand how the framework works and to help Luis with the 2.0 release, we sat down and did a domain model analysis to see if we could develop a more descriptive domain model. We made some good progress and will hopefully pick back up tomorrow.

The sheer amount of work that Luis has put into this framework is amazing. With the current documentation available for the project and Luis’ robust approach to product management, this framework is not going away. The tools alone make it worth using this framework. Definitely check it out.