The Power of Bounded Contexts in Software Development: A Journey of Discovery

Mike HoganMike Hogan
3 min read

In the realm of software development, one of the most impactful discoveries in any build is identifying the right bounded contexts. This approach allows developers to focus on excellently implementing each concern with a model fully germane to that specific context. The mistake lies in trying to find one model to rule them all - or refusing to split models once a bounded context reveals itself.

A Real-World Example: Booking and Appointments

In my current domain of booking and appointments on breezbook, I've discovered several distinct bounded contexts:

1. Availability Checking

2. Pricing

3. Payment

Initially, I attempted to service all these concerns with a single model consisting of:

- Service (name, description, price, duration, resource requirements)

- Resource (name, description, type, capacity, available hours)

- Booking (service, location, start time, end time, customer, payment)

- Business configuration (opening hours, coupons, discounts, refund policy, locations)

However, this approach quickly revealed its limitations. Availability checking had no interest in price, customer, or payment details. Payment didn't need to know about resource requirements. As more bounded contexts emerged and each became more complex, increasing data demands were placed on Service, Resource, and Booking, causing them to become bloated.

The Evolution of Models

Availability Checking

When I started modeling availability checking as its own domain, I found it was only concerned with:

- Resource (type, available hours)

- Existing appointments (start time, end time, assigned resources, capacity)

- Availability request (start time, end time, resource requests, party size)

This model is dramatically different from the original Service, Resource, and Booking entities, offering much more flexibility and focus.

Pricing

Similarly, my initial pricing implementation worked with Service, but when split into its own pricing context, it was found to deal only with:

- Pricing factors

- Pricing rules

- Pricing engine

This new model uses a completely different language, resulting in a clean, coherent, well-tested, and quite generic pricing package. You can find test cases for it here.

Indicators of Boundary Crossing

Finding these bounded contexts has been a slow and sometimes painful process. The principal indicators of potential boundary crossing have been:

1. Setting up dummy data for "pointless" domain model attributes in tests

2. Domain model entities getting increasingly bloated

3. Having to reach hard to get "random" data at the edge of the application (e.g., endpoints)

Reflections on the Process

While techniques like big picture event storming could potentially accelerate the discovery of these boundaries, I've found that "feeling my way across the stones" in the river is more my style. This organic approach has led to some valuable insights:

1. Embracing flexibility: Be open to restructuring your models as you gain deeper understanding of the domain.

2. Focusing on core concerns: Each bounded context should only deal with what's essential to its function.

3. Recognizing the signs: Pay attention to the indicators that suggest you might be crossing boundaries.

4. Iterative refinement: Don't expect to get it right the first time. Continuous refinement is key to finding the optimal structure.

Conclusion

In conclusion, while the journey to discovering the right bounded contexts can be challenging, the rewards in terms of cleaner, more focused, and more maintainable code are well worth the effort. It's a testament to the evolving nature of software development and the importance of staying adaptable in our approach to problem-solving.

0
Subscribe to my newsletter

Read articles from Mike Hogan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mike Hogan
Mike Hogan

Building an open source booking and appointments software stack - https://github.com/cozemble/breezbook