Tuesday, February 8, 2011

UX is everywhere!

I overheard a conversation today about gas stations and it made me think about why I keep filling gas at same company for the last couple of years. As a bike owner I don't really feel the rising prices of gas so my main consideration isn't money - what then makes me come back?

Oddly enough, the reason is User Experience. You see, I don't like to move my fat buttocks more than I have to, that's why I prefer using a credit card – I don't even need to get off of the bike thanks to the gas station's self-service user terminal. Yey.

The only thing I do need to do is enter my ID number and license plate number. While my ID number is obviously critical when paying with a credit card, the license plate should be optional since it's up to me to limit my card to specific vehicles, right? Well, most gas station companies don't think so since it's a required field! I bet it means nothing for most users… (either that, or I'm the proud owner of a vehicle licensed 11-111-11 for some time now).

My favorite gas station company is different because the terminal's user interface instructs me to enter my license plate number or press 'Enter' to continue. Silly as it may be, they get my money – others don't.

When designing a good UI don't make the user think – make him experience. Try to make that extra step forward in figuring out what he may want at any point, without clutter and noise. Definitely not an easy task, but if you won't take it somebody else will – and that might be a good enough reason to choose a competing product.

Wednesday, February 2, 2011

Introduction to Domain Driven Design

I’ll try to explain what DDD is all about in a nutshell as explained more broadly in this great free online pdf (a must read for every system architect IMHO), which in itself is a nutshell of this (so I‘ve heard) great book about DDD. It also includes other topics I figured I should add. If you find yourself dozing off while reading, feel free to jump straight to the Summary for a quick reference. Put yo’ helmets on.

What, Why and How?

Let’s start with a confusing diagram that sums it all up, yet means nothing at this point:

ddd

Confused? Let’s try and put some sense into it.

Developing a business application is all about increasing that business’ productivity by solving a real-world problem or automating a real-world business process, either way we’re dealing with a real-world Domain of entities, data and processes.

Domain Driven Design is in it’s core an approach to software design, which emphasizes the need to focus on the business domain in which the software operates, and model our software as a reflection of the real world. Why? because software is eventually made up of code, and the bigger the problem you’re trying to solve the more complex and messy it can get. Staying true to the “real world” keeps our software understandable, cohesive, easy to change in respect to the target domain and most importantly – do what we expect it to do, as it imitates reality. OO languages are best for this design method since they allow us to define entities and processes in an intuitive, language natural way.

Now, while the development team consists of experts in many technical areas, they are usually not experts in the business domain. Since you can’t produce a good solution to a problem you don’t fully understand we can conclude that In order to produce good quality software you must involve an expert of the business domain in the development process. (On a side note, agile mythologies also advocate for client involvement and frequent feedback, another aspect where agile and software design come together naturally).

Let’s take for example a simple domain, that of a restaurant’s shifts management – the manager plans the following month’s shifts and publishes them as drafts to his employees which fill out their preferences and constraints. The manager then assigns employees to shifts according considering their input and republishes the final schedule. Our mission – take that process online and automate whatever is possible.

While the team speaks in terms of classes, database and builds, the manager speaks in terms of waiters, bartenders and schedules. The first step then is to create a common domain language between the domain expert and the team, a language that will be used throughout the development process.

To start modeling your domain, ask the expert some guiding questions. Identify your entities with verbs being their behaviors (/ methods) and nouns being their attributes (/ properties). For example, we’ll ask the manager of the restaurant to describe his process from end to end, which may be something like:

“A manager publishes an empty schedule with shifts in it so that employees can fill our their constraints and preferences until a given deadline. After the deadline, the manager assigns employees to shifts with respect to those preferences, and publishes the following weeks’ schedule.”

From that sentence alone we can probably understand that we have an entity called manager and a process that includes that manager assigning employees to shifts according to their constraints and preferences. We’ll name that process “Planning”. We also have an entity called schedule, with a one-to-many relation to an entity called shift, which itself has a many-to-many relation with an entity called employee. The employee has a one-to-many relation to constraint and preference. The employee also fills out his constraints and preferences in a process we can name “Submitting”.  We can also infer that a schedule is attributed with a start date, an end date and a deadline. All that from a single sentence – its objects, nouns and verbs.

Manager, Employee, Planning, Submitting and the rest of the underlined words are now added to our domain language. By keeping the conversation active, we can find out more and refine our model and our language - maybe constraints and preferences are the same entity with a different attribute? Maybe the schedule’s start and end date shouldn’t exist and are only defined by the first and last shift in that schedule? and so on…

In these sessions with the domain expert, be as creative as you’d like and use whatever makes you communicate the best – diagrams, white boards and drawings. Make sure to sum it all up and keep an updated domain language reference.

Since I’d like to keep this post at a “readable” size, I’ll divide it into a series of posts (soon to be actual links):

  • Entities vs. Value Objects
  • Architecture – Separation and Interaction
  • Services, Aggregates, Factories and Repositories
  • Refactoring - Constraints, Processes and Specifications
  • Distillation and Generic Subdomains

Summary

When implementing DDD, make sure to:

  1. Identify your domain expert, involve him in the process and create a common domain language (The “Ubiquitous Language”).
  2. Model you domain into Entities and Value Objects according to the target domain, using:
    1. Aggregates to concentrate groups of entities and value objects under a single root entity.
    2. Services to implement stateless operations on multiple entities.
      1. Not to be confused with Web \ Wcf Services, we’re talking about Domain Services.
    3. Factories to separate creation of complex entities and their dependencies.
    4. Repositories to abstract the access to the data layer and stay loosely coupled from your implementation.
      1. Personally, I’m not sure that abstracting your data access framework is always a right decision, for example I do think that Service classes should include a property of ISession when using NHibernate, since the abstraction hides important features and it’s a price to pay, while OR/M isn’t something that you replace that quickly and may not need an abstraction.
  3. Separate a big project into smaller modules, each with it’s own domain model, and try not to overlap. Where you can’t avoid overlapping, communicating between teams is the key, along with automatic integration tests and a CI server.
    1. Define the relationship between you different models (Shared Kernel \ Customer-Supplier \ Anticorruption Layer \ Open Host Service) and make sure your teams act accordingly.
    2. An updated and publicly displayed context map helps to see the big picture and keep in mind the connections between the different modules’ contexts.
  4. Try to extract your core domain out of the entire domain and put you best people on it, that is what separates your application from the rest and that’s where your specialty should shine. for the other generic subdomains use one of the following:
    1. Off the shelf solution
    2. Existing model with an appropriate wrapping
    3. Outsourcing
    4. An in house implementation with lesser focus
  5. Avoid common pitfalls:
    1. Modelers should also code – keeping your hands dirty keeps you in tune.
    2. Don’t over-abstract, talk in real life scenarios – implement the next step ONLY while keeping in mind the following ten steps.
    3. Apply DDD only when it fits – it’s perfectly Ok to use DDD on one module and not on another, all in the same global domain, as long as the communication between you domains

 

Few technical tips

  1. Use an IoC framework, such as Castle WIndsor, Autofac or Spring.Net, after a small learning curve it’ll enhance your code’s maintenance.
  2. Inject dependencies as high as you can in the application, to make you code suitable for as many contexts as possible (NH Session management is a good example for why dependencies should be injected and not created).
  3. Use an OR/M framework and make sure that only the required project reference it and only the required classes use it.
  4. Separate your code into projects, make sure to stay on “need to reference” bases only, to make sure you’re classes aren’t being abused.
  5. Refactor, and then refactor again – if you’re afraid to refactor legacy code, write tests to cover it’s specs and then try again – it’ll even help you to better understand the requirements you’re implementing.
  6. Use TDD to think before you code, starting is hard but it’s addicting.
  7. Prototype anything you’re not sure of – performances, solution structure, etc..
  8. Define a set of contracts and DTO’s as a single point of interface between two modules, don’t reference the other module’s core – it’s not yours!
  9. COMUUNICATE – talk to you team, talk to you client, talk to your mother, just talk.

Want to know more?

Read this or this, or visit the DDD group at: http://groups.yahoo.com/group/domaindrivendesign

Phshewwww, that was long, but now that we’ve armed ourselves and laid down our design principles let’s get practical – in the next couple of posts we’ll be applying those tools and principles on our own application, using frameworks and tools like WCF, FubuMVC, NHibernate, Automapper and more.

For now, happy modeling.