Archive for the ‘series’ Category

Architectual Styles - Part Four : Layering

admin | October 7th, 2007 | series  

In the fourth part of this series, I’d like to talk about my uses of layering as it applies to architectural styles. In searching for a good explanation of the Layers pattern itself, I stumbled up on this posting which I thought was a good analysis. Although the analysis is done in the context of Visual FoxPro, it gets across the mindset I have when working with the Layers pattern.

In my experience, I find myself consistently implementing layering in my applications as they grow in scale. I try to use layering as means by which to simplify the interactions between objects in my application to somewhat, well-defined levels of abstraction. I find that layering is also a good exercise in following good practices as it applies to cohesion and coupling; without an appropriate use of both, the use of layers may appear more difficult than it should be. In reading this post, please keep in mind that these abstractions are in place to help reduce complexity from the perspective of the developer. Adherence to preserving the integrity of each layer in your architecture is left up to you. In practice, you may come to find that breaking those boundaries every once and while may be more practical, but that is decision you have to come to.

So let’s take a look at an overview diagram that I threw together:

Layering Overview

In the diagram there are few things that I want to point out. Firstly, I chose to show what I commonly refer to as a 3-tier layering scheme: Presentation, Business, and Integration. Semantically speaking, I’ve heard a lot of variations on the naming of these layers (e.g. - Presentation = Interface, Integration = Data), but for the purpose of this series let’s stick with what written. Second, I’ve chosen to identify a few patterns in the given layers based on my previous experience with them. Please note that there are entire disciplines in software engineering devoted to pattern analysis and implementation, these are just a few that I’ve found useful and not a comprehensive or exclusive list. Third, for the purpose of this diagram, I’ve split the Presentation layer into two segments: Application and Service. Each section represents how I use the Presentation layer in the context of constructing an application with a UI or a service API. It should be assumed that the Business and Integration layers have to solve similar problems for each section, so no distinction has been made in the other layers.

With that being said, let’s look at each layer in more detail:

  • Presentation - The Presentation Layer is where I place all of the classes associated with assembling some type of consumable interface for either an application or a service API.

    For an application, the typical interface I expose is a user interface. Web templates, view widgets, and other UI components make up the class types I place into this layer. Typically the Consumer for applications are end-users.

    For service APIs, I tend to expose Service classes which encompass units of work from the API as a whole, usually as methods on an object. The Service class’ responsibility normally does not exceed aggregating functionality from the Business Layer. Based on the approach I’m taking, I may even include input validation as the responsibility of the Service class. Additionally, Facade/Adapter classes can be created to re-expose the functionality identified by the Service class but take only responsibility for the translation of messages to and from the consumer of the API. For example, I may not be able to call the service API by instantiating the Service class in shared memory, I may have to utilize RPC calls over SOAP. A Facade/Adapter class would be helpful for creating an interface to use as a basis for WSDL generation and translation of value objects to domain objects (more on this in a little bit). The Consumer for service APIs could be an application or another service API.

  • Business - The Business Layer is where I place all of the classes associated with the implementation of the business rules, usually as outlined by my use cases. Based on the architectural style you choose to implement (see next post in series), domain classes can potentially play a larger role in the implementations of these rules. Other classes applicable to this layer could be Validators (for business rules not input), Managers, and Unit of Work classes aggregating interactions as they relate to the Integration Layer. Although I consider the domain classes an integral portion of the “glue” between layers, I usually associate them with the Business Layer since its goals relate more directly to the problem domain than functional aspects.
  • Integration - The Integration Layer is where I place all of the classes that act as abstractions for the external resources on which my application is dependent. The responsibility of this layer usually results in classes managing connection and location information as well as domain object mapping. I typically do not find myself creating Transfer classes since most technologies (e.g. - ORM solutions) can work with my domain classes directly. In the diagram you can see some examples of the types of resources and the patterns I use to abstract them. Remember, the Integration Layer is just providing friendly abstractions; the use of those abstractions is dictated by the Business Layer. If multiple classes in the Business Layer need to send an email, both could have a common use of an EmailDelegate, for example, that exposes the basic functionality associated with sending an email. The classes in the business layer care about what’s in the email, the delegate cares about how to send that email and other functional aspects of email.

Hopefully after these brief explanations, it begins to become apparent the crucial role that a domain plays in a layered architecture. The domain pervades into each layer as a contract allowing each to focus on how it can solve the problem using the behavior, or set of behaviors, for which it is responsible. This is yet another reason that semantics play such a large role in the creation of a domain; forming semantically relevant contracts between layers allow you scale your software as the solutions needed for the problem domain scale. From my experience, this turns out to not only be true as it relates to uses cases and business requirements but as it relates to functional requirements as well (e.g. - integrating something like instant messaging into the application).

That’s about all I have on layering, but suffice it to say, I think migitating complexity is always a good thing when you know it will be an issue you have to address in the future. Hopefully I was able to make sense of my perspectives to help you reduce the complexities you encounter. In the next post of this series, we will get more into architectural styles as it relates to the Business Layer as I will try to convey ideas on what I consider light and heavy-weight architectures. I will also try to touch more on the idea of state and what it means for each of these styles.

Thanks for reading.

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 Two : Cohesion and Coupling

Brian LeGros | July 23rd, 2007 | series  

Cohesion and coupling are two terms that I always find myself coming back to when debating (with myself) over approaches to take to OO design. A definition for both cohesion and coupling can be found on Wikipedia. For the purpose of this series, I’m going to focus on each in the following regard:

 

Cohesion

Cohesion is the basic idea that a class has a focussed set of responsibilities, or behaviors, from a particular perspective. I gauge cohesion as an “analog-metric” from high to low. High cohesion implies focus, low implies a blurring of that focus.


Low |——————————–| High

Coupling

Coupling is a representation of a relationship between two classes and the degree to which they are dependent on each other. I gauge coupling as an “analog-metric” from loose to tight. Loose coupling implies easily interchangeable dependent classes, tight implies little to no interchangeability between dependent classes. Statically typed language typically rely on the use of interfaces to achieve loose coupling (segregating a class’ contractual agreement from its implementation of that agreement) where something like duck typing would be more commonly implemented in dynamic languages.


Tight |——————————–| Loose

 

Now Wikipedia probably does much better than I just did with these definitions, but the basic spirit of what I want to get across is in the above. Additionally, when I use the term “analog-metric” what I’m really trying to say is that through exposure to the design process and implementation of those designs, you gain a “code smell” for how a class can equate to one end of the spectrum or the other.

When working with my designs, I always try to keep one key point in my head:

Designing software with cohesion and coupling in mind is considered good practice, but designing for high cohesion and loose coupling in the purest sense can be harmful.

Now this might seem counter-intuitive at first. Why wouldn’t I strive to achieve the purest form of these “metrics” when designing my software? A lot of these reasons will become more evident over the next few posts, but suffice it to say, I feel there is a balance to be maintained when designing your software. Cohesion brought to its extreme may result in a code base that may be hard to maintain due to how large its become. An overly robust adherence to loose coupling could result in added flexibility to portions of a code base that may never be refactored over its lifetime.

I promise I’ll explain my perspective in more detail soon. For now, try to walk away from this post with an understanding of these two concepts and the variance that can exist in how they are gauged.

:)

<< Part 1 : Introduction | Part 3 : Domains >>

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 >>