Tag: Software Craftsmanship

A gentle introduction to Domain Driven Design

Domain Driven Design (DDD), first described in Eric Evans’s so-called “Blue Book” is a diverse set of practices. Because these practices are loosely associated and not tied to any specific tool, it can sometimes even be unclear whether you are in fact doing DDD or something else.

There are, however, some core practices in DDD which are worth understanding and doing. The goal of DDD is to put the focus of developers on the domain by removing so-called “accidental” complexity (a key goal for any software craftsperson). Some of the DDD ideas and practices can also be viewed as bringing some of the benefits of functional programming to the object-oriented world.

Key ideas:

Ubiquitous language

The idea of ubiquitous language is simple: The code is developed to solve a problem for some people, so developers and their code should use the same terms as the people for whom they are solving the problem.
This seems like common sense, except that it’s rare in practice for institutional/organizational reasons. Developers are off in their cloister building stuff using the language of developers and architects, and they end up having to translate between what they are building and what the domain experts and end users are expecting. This is accidental complexity which increases the likelihood of and the difficulty of correcting specification problems.

Object types:

DDD divides objects into several categories. Objects which fall clearly into one of these categories are easier to understand and work with in the context of a business domain…

  • Value objects

A value object represents a piece of information in the domain which does not change but which could be replaced. For example, a bank account could contain $55. The value object is a currency object with a numeric value of 55 and a currency type value of “USD”. It could be replaced by a value of $85 if a deposit of $30 is received.
A value object can normally be immutable (which makes it easier to do functional-style processing with no confusing side effects). If a value object is replaced by another value object of the same type with identical values, no one notices or cares.

  • Entities

An entity has identity and state. A customer is a good example of an entity. The customer might have a customer id. Unlike value objects, entities are not interchangeable. An entity will often have “invariants” which must be enforced (do not expose any public methods, including constructors, which could allow violation of an invariant, unless it’s absolutely required by a framework you need to use). An invariant is a logical condition which applies to an entity (for example, an order always has a product ID and a customer ID and an order date, or a Flight always has a departure airport code and an arrival airport code).

  • Aggregates

An aggregate is a cluster of associated objects with a “root”, which acts as a façade – objects outside the aggregate interact only with the root. The aggregate root is responsible for assuring in each of its methods that by the end of the method call all invariants are satisfied within the aggregate (within a single transaction, generally). An example of an aggregate root can be found in this article by Julie Lerman.

  • Domain Events

A domain event encapsulates an event which could potentially trigger actions in various components of your system.  The use of domain events is a kind of decoupled publish/subscribe design pattern (similar to Observer) which allows code to emit events which are handled without being responsible for how and by which components they are handled.

Modules

You already know what a module is in general. In DDD, according to Eric Evans, modules should “tell the story of the system and contain a cohesive set of concepts”, and their names should be part of the ubiquitous language and “reflect insight into the domain”.

Repositories

Repositories are objects which allow retrieval of entities, aggregate roots. In DDD a repository serves as an adapter between the domain object model and the persistence model.

Bounded contexts

A complex application may have to solve different problems for different people. Sometimes the problems are similar enough to each other that you’re tempted to solve both using the same objects and paradigms. Don’t. It’s been drilled into most of us that you need to reuse objects (and database tables) as much as possible to reduce the amount of code (DRY, which is a useful practice in general), but DDD optimizes above all to minimize confusion and cognitive load rather than minimizing lines of code. A bounded context means that you solve problem A with one set of classes using one set of terms and approaches and you solve problem B with a separate set of classes using distinct terms and approaches. Even if subsystems A and B have to communicate with each other, it’s generally easier in the long run to translate between A objects and B objects for communication than to mix A objects into the B implementation or vice-versa.

Shared Kernel

Speaking of our bounded contexts A and B, there can be a core domain which is used in both context A and context B. This is called a shared kernel.
In practice, a shared kernel is a set of interfaces and objects (typically in its own library, such as a jar file in Java) which allow code outside a bound context to interact with the context. This could be service interfaces, aggregate interfaces or DTO’s (data transfer objects – generally behavior-free objects used to pass entity or aggregate data to and from a service implementation). Since the shared kernel can be used in many different places by different teams and products, it should be as stable as possible.

Supple Design

Supple design is a set of patterns/practices, some borrowed from functional programming, which make it easier to reason about behavior of a part of the system without worrying about what the rest of the system is doing.

This includes:

  • Intention-revealing interfaces
    The idea is that an interface (via method names, signatures, etc.) reveals what it does, not how it’s done.
  • Side-effect-free functions
    If a method never changes the state of anything, other than perhaps creating one or more completely new objects, then it won’t cause deadlock or change the behavior of other methods being executed simultaneously. And if called again with the same inputs, you get the same result. It’s easy to verify with unit tests that there are no bugs.
  • Standalone classes
    Reduce coupling between different classes to reduce unnecessary complexity.
  • Assertions
    The idea is to enforce invariants and post-conditions of operations either in the implementation code or with unit tests (or both).

Associated design practices/architectures:

  • A Hexagonal Architecture makes DDD easier because it further separates the technical infrastructure from the domain.
  • CQRS with or without Event Sourcing is a complementary architecture/practice which simplifies the handling of data.  It’s a big topic beyond the scope of this article, but CQRS is a useful choice for reducing hidden complexity in the spirit of DDD by separating things that do not have to go together (queries and data modification).  Event sourcing is a useful technique for dealing with data that may change over time if you might ever need to know what the state was at a given moment in the past.
  • Behavior-driven development (BDD) is complementary to DDD because it encapsulates the domain in tests based on the ubiquitous language.
  • TDD is a good practice for pretty much any development project, and ensures that DDD assertions are validated early and often.
  • Functional programming (lambdas and streams in Java, for example) works well where supple design is applied.
  • Simple CRUD can coexist with DDD.  Some persisted objects are simple enough that there’s no need for assertions and other domain logic.

Getting started

Well, that’s a lot of interesting ideas, but how to get started using them in development projects? It’s not like a framework where there’s a tutorial that will give you a “Hello DDD” in half an hour.

Some early steps toward DDD are possible, though :

  • Start using value objects.  For example, you can replace numeric dollar amounts by immutable Money objects which have an amount and a currency code.
  • Start using a ubiquitous language.  Align the terminology used in the code and project structure with the domain language.
  • Identify and segregate modules and bounded contexts. You may already have some notion of modules, but maybe you can find that you’re sharing some code between them which shouldn’t be shared.
  • Get started using domain events.  There are some examples on the internet that help you get started, including this C#-oriented article by Udi Dahan.
  • Separate out shared kernels. The flip side of enforcing bounded contexts is sharing precisely what your module needs to share with other modules and the outside world.
  • Use repositories. You may already be doing this.  The key idea is to have domain code using domain storage logic (CRUD and search for entities and aggregates) rather than database logic.

 

Advertisements

Software Craftsmanship and Heroism

A certain restaurant in the Silicon Valley has a sign which says “This is a bad place for a diet. This is a good place for a diet.” There is no contradiction – just 2 different contexts.

So it is with Software Craftsmanship and heroism. The opposite of heroism in software development is a smooth operation high up the CMMI ladder, where everyone knows what to do and no one wastes time or stresses out because the process is moving forward. On the bottom of the CMMI ladder, on the other hand, it’s sometimes chaos, and a developer can be put under pressure to deliver in a hurry because of bad communication or poorly designed and/or poorly tested code encountering demanding clients.

Software craftsmanship is bad for heroism because it reduces the chaos that requires a heroic developer to step in and fix things in a hurry. There’s a software factory pipeline that doesn’t let logic failures reach the client.

Software craftsmanship is good for heroism because sometimes even with a solid agile process and a finely-tuned software factory pipeline and clean, unit-tested code, misconceptions can slip in and a client can do something that the unit tests did not foresee and (rightly) complain about it. And why is craftsmanship good for heroism in this case? Because the code with the error is clean, extensible and unit-testable. If you have an idea for a fix, you can try it out in minutes in a unit test instead of having to code blindly, build, run and test manually and then repeat the process until it’s debugged or you decide to take a different approach. Ultimately, the software craftsperson has to build and run and test manually, but only AFTER the key idea for a solution has been tested and debugged. So with craftsmanship, you may have some shining moments of glory, but the heroic struggle happens gradually, every day, maintaining the quality of the code and the software factory.

“Web Security Basics” on Martin Fowler’s Site

Security should be at the heart of our profession, but I’m not sure it ever has been. Job interview preparation for developer jobs is largely focused on algorithms, API’s and problem-solving. It’s probably happened somewhere, but I’ve never heard of an interviewer asking a candidate for a typical developer job about how to prevent SQL injection or XSS attacks. I’ve never seen a job posting for an ordinary developer job which mentioned OWASP in the list of desired buzzwords.

That may be changing slowly. The value created by software development has attracted the attention of a lot of thieves who would be happy to steal it. The software craftsperson has a duty to produce software which will discourage and repel those thieves, but good learning materials in the field of security have been scarce. The OWASP site has a great deal of info about security best practices, but it’s not organized in a way which makes it easy to learn.

Martin Fowler’s blog is now hosting an evolving document written by two software security experts which gives a lot of good advice which is also well-organized and well-explained. It’s a bit presumptious for them to call the document “Web Security Basics”, since most web sites do not yet follow all of their recommended practices (such as using only https for all connections), but the article may move a lot of companies to better protect their users’ data and information security. It should be required reading for software craftspeople.

They Might be Giants

Don’t let’s start. This is not an article about music from back in the day, but about the elusive “20X” developer who is 20 times as productive as “normal” engineers.

I recently read the recently blogged guide Recruiting Your Next Anakin by “The Sith” Recruiting Training and Retaining Giants (pdf file) whose author (who calls himself “The Saint”) has earned a fair amount of bad buzz on the web. The TLDR is that you should look to hire people with “a calling” who don’t want “balance” in their lives and then work them 80 hours a week to “season” them (i.e. accustom them to working 80-hours a week for less salary than they’re worth). The guide comes out of the video game sector, where there seem to be a number of horror stories of exploitation. It’s a sector which attracts some programmers who have more talent and passion than maturity and who are thus easy prey for exploitation. I’ll leave it to others to criticize the guide in detail – for a sane perspective on recruiting talented engineers, I recommend Joel Spolsky’s approach.

Here I would rather discuss one of the ideas behind the article in question. The article states: “GIANTS can be worth 10X-20X ordinary engineers”. This is not a new idea, and it sounds very “truthy”, but has it really been scrutinized?

When I think of a GIANT who might be worth 20-times the ordinary people in his profession, rather than any software developer, I tend to think of this tall gentleman:

Madison Bumgarner
In software development, while I’ve seen some great engineers, the paradigm does not seem to apply well.

For the sake of argument, though, let’s assume that there’s some objective measure of individual developer productivity and worth in the context of software teams (I doubt it), that it can’t be “gamed”, and let’s assume there are some 20X giants and that there’s way to hire them, and that (as the afirementioned pdf guide seems to assume) 20X giant-ness is an inherent quality of a young developer which can’t be taught to “normals”.

Imagine that you in a team of “normals” and you are then joined by one 20X giant.

Imagine the sprint planning. The first 200 sprint points go to the giant and then everyone else gets 10.

It’s as if your cellar-dwelling adult-league basketball team just got Stephen Curry. You’re no longer playing basketball – on offense you just give the ball to Steph and maybe (if you get past half-court before he’s drained a three) set a pick or box out in the low post. If you play any defense at all, it’s a box-and-Steph.

Imagine the daily stand-up meeting. The part which gets everyone’s attention is when the giant has an obstacle (probably caused by one of the “normals”).

Kind of demoralizing for everyone, but the assumption inherent in the thinking around 20X giants is that developers, once hired, can’t be improved (except by making them work longer hours if they’re willing and able to).

Fortunately, this is a ridiculous fantasy. In reality, with some effort and intelligence, teams and individual developers can improve. And in reality, if someone in your team is accomplishing 20 times as much as anyone else in the team, something is horribly wrong. Maybe the others are busy cleaning up messes left by the “giant” or decrypting unreadable code written by the “giant” at 3 a.m. when the effects of the energy drinks have worn off.

The software craftsmanship movement embraces the idea that not all developers are at the same level, but part of a software craftsperson’s job is to help the rest of their team to improve. We value the quality of our work as much as the quantity, because software is never really done, and going too fast now will force us to go much slower later. We strive not to be giants among Liliputians but highly competent professionals on teams of profesionals and in a larger community of professionals.

TDD is our friend, but…

“Animals are our friends!!”, comedian Bob Goldthwait used to shout, adding “But they won’t lend you money.”

One famous definition of legacy code (from Michael Feathers) is “code without tests”. I would extend that definition to say that it’s code which does not have tests for the behavior you want to have. TDD will get you code that is well-tested for the behavior you want when you develop it. If your code does anything innovative, some of the behavior you want will almost certainly change over time.

So TDD is our friend, but it won’t eliminate all legacy code. What it will do is make it easier to know when we accidentally change behavior. It doesn’t necessarily make it easy to change our code’s behavior, either, but it gives us confidence to tackle the change because we know that tests will catch and allow us to fix any little mis-steps before they become more difficult and time-consuming to find and fix, and, importantly, it nudges us constantly to design our code in a way which allows it to be refactored with less trouble and risk.

Quick thoughts about Seth Godin’s article “Our Software must get better”

I’m a long-time Seth Godin fan, so I read with interest his recent article about software quality.

With the examples he gives of inadequacy in software – iTunes user experience, the Macintosh’s built-in address book’s slowness and difficulty with importing and exporting data, and general unreliability and lack of Macintosh-compatibility of stamps.com – he’s focused mostly on the user experience aspects of software, which I think misses a key point. I think the biggest problems for software users these days are not slowness, confusion, frustration and extra clicks – though these can be real problems. The big issue for software users today, IMHO, is in the realm of data security, transparency and privacy.

Software in general is getting really good at collecting data profiles of the people who use it. I think this can be done in an ethical, transparent and generally secure way which generates value for the software’s creator in a fair and honest exchange for the user experience that consumers want. Is that what’s happening now? Not enough to satisfy European governments, who are taking action on this issue.

Seth Godin is smart enough and experienced enough to set up a kickstarter for a better Mac address book that is fast and can handle imports. But he would like software users to take ownership of the quality of the software that they use, by explicitly paying for what they use and by insisting on a user experience that meets their needs. On a large scale, that would be a pretty radical change, which would surely have a positive impact.

For the moment, most users either don’t know what “better” is or don’t care enough to pay for it. The trend among the giants of the software industry landscape seems to be that better means “smarter”, which means “knows what you want”, which is a problem in the aforementioned realm of data security, transparency and privacy. If you collect personal information, you must protect it forever and use it in a way which is ethical and transparent. If your smart assistant in the cloud knows that you have an appointment next Tuesday with Doctor So-and-so and the Such-and-such Clinic, who else will know that? The only data which is 100% guaranteed to be private is data which is never collected.

Ironically, the respect for privacy seems to be better in free software (Mozilla, Linux, etc.) than in software which people pay for. Godin alludes to this in his point “C” as to why software is mediocre.

Seth Godin would obviously like us, the software craftspeople of the world, to insist on better user experience, and, ideally, he’s right. It should be part of the software craftsperson’s ethics to improve the user experience. It’s not always clear, though, who should be responsible for defining what constitutes improvement or deciding what time and resources should be allocated for it.

At a minimum, we as developers can strive to create software which is easy enough to change that the user experience can be improved easily once we understand what improvements need to be made. We can also strive to treat the users’ personal data as a precious commodity to be protected, we can sanitize our inputs, and we can use the best encryption techniques available for passwords and other sensitive data.

The Boy Scout Rule vs. the Pottery Barn Rule

Scenario 1 (The Blind Side)

You’re fairly new here, but it you thought it would be a good idea to rename the method “doProcessing” to “updateSalesStatistics”. It’s true, the code is much more readable now. Did you know that our largest paying customer loads our jar file and calls “doProcessing” via reflection? They’re not happy.

Scenario 2 (Danger UXB):

We had to revert your last commit. We’re 2 weeks from code freeze, and you refactored the doProcessing method. That method is 400 lines long and contains little mountains of indentations, and there’s no way to unit test it. It’s too important to risk breaking it now.

With his Boy Scout Rule, Robert C. Martin encourages us as software craftsmen and craftswomen to be brave and clean up the messes we find, at least a little bit at a time. Unless you have a team experienced in and fanatically devoted to clean code, design, and TDD plus a clear shared vision of the functional specifications, technical debt is added to your project on a daily basis. So the Boy Scout Rule proposes that each of us reduce technical debt on a daily basis, hopefully at least as fast as it accumulates.

This excellent approach sometimes runs afoul of its corporate nemesis, which is best summed up as the Pottery Barn Rule: You break it, you own it.

It can create a real dilemma for a software craftsman or craftswoman who wants to do the right thing but can not promise that every improvement poses no risk. We see in the first scenario above that we can be blindsided by undocumented usages of the code which are not enforced by the compiler. This kind of problem is technical debt that keeps on giving. In the second scenario above we see technical debt which protects itself using fear. It’s like an unexploded bomb, but there’s no bomb squad, just you and the people who will blame you if it explodes after you’ve touched it.  If it explodes when left alone, responsibility for the explosion is diffused.

Overcoming these sorts of blockages requires courage, an effective code review process, and what I might call “good management”. According to an extensive internal study done by Google, the number one key to having an effective team is “psychological safety: Can we take risks on this team without feeling insecure or embarrassed?”. That’s partially down to management, but I think it’s also linked to the number 2 key: “Dependability: Can we count on each other to do high quality work on time?” That’s where the developer can make an impact. If most of the time you get it right when you take a risk, the team will likely cut you some slack on the rare occasions when you don’t.

 

Care

With software craftsmanship there’s a lot to say about tools and methodologies, but if I had to sum up in only 1 word what you need to do to be a software craftsman or craftswoman it would be “care”.

As in:

  • care about the people (including your memory-challenged future self) who will have to work with the code you’re writing today – 6 months, 2 years or maybe even 10 years from now
  • care about the people who will be using the software you’re developing today
  • care about the people who have staked their reputation on the product you’re developing today (and about whatever promises you make to them)
  • care about learning to be better at what you do
  • care about what your fellow team members are working on and about being able to give them a hand if necessary
  • care about mentoring your fellow team members and others

Some cynical people think that Software Craftsmanship is a fad to sell training and consulting. There may or may not be a grain of truth to that, but there’s no certificate for caring – either you care, and the results will gradually become evident, or you don’t care, and the results of that will also be evident at some point to somebody. If you do care, there are many free resources, including this blog, which can help you learn about the methodologies and tools you need to become a software craftsman or craftswoman.