Domain-Driven Design and MVC Architectures

According to Eric Evans, Domain-driven design (DDD) is not a technology or a methodology. It’s a different way of thinking about how to organize your applications and structure your code. This way of thinking complements very well the popular MVC architecture. The domain model provides a structural view of the system. Most of the time, applications don’t change, what changes is the domain. MVC, however, doesn’t really tell you how your model should be structured. That’s why some frameworks don’t force you to use a specific model structure, instead, they let your model evolve as your knowledge and expertise grows.

Domain-driven design separates the model layer “M” of MVC into an application, domain and infrastructure layer. The infrastructure layer is used to retrieve and store data. The domain layer is where the business knowledge or expertise is. The application layer is responsible for coordinating the infrastructure and domain layers to make a useful application. Typically, it would use the infrastructure to obtain the data, consult the domain to see what should be done, and then use the infrastructure again to achieve the results. Srini Penchikala explains this in more detail here: “Domain Driven Design and Development In Practice“.

Object-oriented programming is the most important element in the domain implementation. Domain objects are designed using classes and interfaces, and take advantage of OOP concepts like inheritance, encapsulation, and polymorphism. Most of the domain elements are true objects with both State (attributes) and Behaviour (methods or operations that act on the state). Entities and Value Objects in DDD are classic examples of OOP concepts since they have both state and behaviour.

Terminology used by Domain-driven design

  • Entity: An object which has a distinct identity. For example, a User entity has a distinct identity with an ID.
  • Value Object: An object which has no distinct identity, like numbers and dates. For example, if two Users have the same date of birth, you can have multiple copies of an object that represents the date 16 Jan 1982.
  • Factory: Used to create Entities. For example, you can use a Factory to create a Profile entity from a User entity.
  • Repository: Used to store, retrieve and delete domain objects from different storage implementations. For example, you can use a Repository to store the Profile your Factory created.
  • Service: When an operation does not conceptually belong to any object.

The purpose of this post was to provide a brief introduction to Domain-driven design.

Part 2: Domain-Driven Design: Data Access Strategies

Links

If you’re interested in learning more about Domain-driven design or Model-driven design, I recommend the following articles:

Favour object composition over class inheritance

What does “favour composition over inheritance” mean, and why is it a good thing to do?

Object composition and inheritance are two techniques for reusing functionality in object-oriented systems. In general, object composition should be favoured over inheritance. It promotes smaller, more focused classes and smaller inheritance hierarchies.

Troels Knak-Nielsen wrote:

Class inheritance is a mix of two concepts. The extending class inherits the parents implementation (functions/methods) and it inherits the parents type. In a statically typed language, the latter is fairly important, since you can’t freely mix types. So if some method expects an argument of a given type, you might use inheritance to satisfy this. In a dynamically typed language that is a non-issue. You can simply implement the expected behaviour and that’s all there is to it. If you need a more explicit contract, you can document it or – since PHP has sort of a middle-way on this matter – you could use a statically typed interface (Eg. implements Person, rather than extends Person) to do the same thing. Since PHP is dynamically typed, this (slightly more verbose and restrictive) solution is purely optional. You can just use an implicit contract (duck typing).

The other use of class inheritance is to reuse implementation. If your abstract class Person is extended by a subclass Employer, you would have access to the same code in Employer as you do in Person. You could achieve code-reuse with composition as well, but it takes a bit more work. Employer would have to implement a wrapper that delegates control to a Person instance in this case. Eg.:

class Person {
  function sayHello() {
    echo "Hello, World!";
  }
}
class Employer {
  protected $person;
  function __construct() {
    $this->person = new Person();
  }
  function sayHello() {
    $this->person->sayHello();
  }
}

rather than:

class Person {
  function sayHello() {
    echo "Hello, World!";
  }
}
class Employer extends Person {}

As you can see, slightly more work to do, which is why people often use inheritance in these cases. The cost however, is that the Person-Employer relationship is now set in stone; It can’t be changed or intercepted at runtime. There is also the matter of clarity. While the compositional code is more verbose, it is also very clear about what it does. You can look at the code and know what it does. With the inheritance version, you need to look at the superclass to find out what it does. Some times there are multiple levels of inheritance, making you trace up and down the chain to figure out exactly what code is available in the concrete class. Finally, there is the problem of multiple inheritance. In PHP, you can’t. You only have one shot at inheritance, so if you want to reuse code from two places, well, you’re out of luck.

Source: SitePoint Forums

10 concepts that every software engineer should know

In this post, Alex Iskold discusses the top 10 concepts software engineers should know.

A successful software engineer knows and uses design patterns, actively refactors code, writes unit tests and religiously seeks simplicity. Beyond the basic methods, there are concepts that good software engineers know about. These transcend programming languages and projects – they are not design patterns, but rather broad areas that you need to be familiar with. The top 10 concepts are:

  1. Interfaces
  2. Conventions and Templates
  3. Layering
  4. Algorithmic Complexity
  5. Hashing
  6. Caching
  7. Concurrency
  8. Cloud Computing
  9. Security
  10. Relational Databases

Read more: 10 concepts that every software engineer should know

The best code is very shy

The best code is very shy. Like a four-year old hiding behind a mother’s skirt, code should not reveal too much of itself and should not be too nosy into others affairs. But you might find that your shy code grows up too fast, shedding its demure shyness in favor of wild promiscuity. When code isn’t shy, you’’ll get unwanted coupling.

The Pragmatic Programmers, Andy Hunt & Dave Thomas.

Getters and setters create unnecessary coupling

Every getter and setter in your code represents a failure to encapsulate and creates unnecessary coupling. A profusion of getters and setters (also referred to as accessors, accessor methods, and properties) is a sign of a poorly designed set of classes.

“Getters and setters should be avoided because they break the encapsulation OOP offers”, says Greg Jorgensen.

A long time ago programmers discovered that reducing the scope (visibility) of data as much as possible led to more reliable and maintainable code. Before programming languages supported encapsulation or objects, programmers who cared to write better code followed best practices and idioms (what would be called patterns today) that encouraged limiting scope and data hiding. Back in the old days these ideas were discussed in terms of module strength and coupling. To learn the concepts without the distraction of OOP and “design patterns” terminology see Glenford Myers’ books “Reliable Software Through Composite Design” and “Composite/Structured Design”.

Read the rest of the article

Working Effectively with Legacy Code

Is your code easy to change? Can you get nearly instantaneous feedback when you do change it? Do you understand it? If the answer to any of these questions is no, you have legacy code, and it is draining time and money away from your development efforts.

In the book Working Effectively with Legacy Code, Michael Feathers offers start-to-finish strategies for working more effectively with large, untested legacy code bases. This book draws on material Michael created for his renowned Object Mentor seminars: techniques Michael has used in mentoring to help hundreds of developers, technical managers, and testers bring their legacy systems under control.

The topics covered include

  • Understanding the mechanics of software change: adding features, fixing bugs, improving design, optimizing performance
  • Getting legacy code into a test harness
  • Writing tests that protect you against introducing new problems
  • Techniques that can be used with any language or platform—with examples in Java, C++, C, and C#
  • Accurately identifying where code changes need to be made
  • Coping with legacy systems that aren’t object-oriented
  • Handling applications that don’t seem to have any structure

The book also includes a catalogue of twenty-four dependency-breaking techniques that help you work with program elements in isolation and make safer changes.

More about Michael Feathers.

Articles he wrote:

Emergent optimization in test-driven design (PDF)

The humble dialog box
(PDF)
The self-shunt unit testing pattern (PDF)