3

I've been trying to learn domain-driven design (and similarly Onion Architecture) the last week or so. I think I've got an understanding of it, but like math, I suck at extracting all of the details...

So, I'm designing/building an ASP.NET MVC application (building a site to promote game jams), applying DDD to the project. I've read all of Vaughn Vernon's essay (just discovered the book).

However, I'm a bit hung up about my particular project's domain model. Conceptually, I think I have one bounded context within my domain. I'm not sure if you include web users (ASP.NET Identity I plan on using).

Here's my current (prototype) model (currently one bounded context):

DDD Prototype Model

Another bounded context I can foresee later, but I think it's more in-tune with the infrastructure (thinking Onion here), is the User (linked with 'Developer' on the above bounded context) authentication. I have two 'value objects' ("Developer" and "Description"). I'm unsure whether "Description" should be just a simple string on the entity "Project" though.

Thinking about my invariant behaviors, I've come up with the following:

  1. An event is created by a Developer (using a role for this) with a start and end dates.
  2. Teams are created a Developer for an event.
  3. A team creates a project for an event
  4. Developers sign-up for an event through a project(s) by applying
    • Developers can join multiple projects
    • applying: providing the team leader with a developer's name and role in which they are seeking on a project.
  5. Teams can be created as either open (Developers can apply to join) or closed (team leader must invite a Developer to the team/project)

For my aggregates, what do I do here? Do I write a "service" class like "TeamProjectService" with methods such as "CreateTeamProject"? Or what?


Am I going about this the right way? Or am I maybe over-complicating it or missing something?

  • I often have services which I call from controllers, and then use the entity framework as the model layer. I wouldn't have description as its own table. I'd keep it simple until you get problems and then refactor to keep it clean. Don't over complicating it initially. – Tom Aug 28 '15 at 15:23
  • I guess one thing that confused me about the Vernon's essay was what appeared to be an entity and an aggregate combined. Are they/can they be the same thing (depending upon the domain)? – Zack Aug 28 '15 at 15:41
  • @Tom: I thought so, updated my question with what I originally thought, based upon your reply. – Zack Aug 28 '15 at 15:41
2

Am I going about this the right way? Or am I maybe over-complicating it or missing something?

I think you have a start of a design; you are teasing out the concepts and their basic relationships and the constraints on the relationships, which is a great start.

For me, what I like to do is before I do any real detail on classes and operations (e.g. what methods, where business logic goes), I like to lightly enumerate the concepts and relationships in the business terms that create the ubiquitous language for a domain model. The concepts that have business identities (e.g. plane ticket with record locator, user having unique user name or id, etc...) will probably end up being aggregate roots. Ideally, these concepts and relationships are already known in the business and one doesn't have to try reinvent them as part of design. (And of course, iteration, improvements, refactoring, etc... will occur.)

Next, for me personally, having a good start at the concepts and relationships, I like to do application design from the ends toward the middle. I think of it a bit like designing a bridge. I like to have a design for the embankments first, then the middle (the span). In this analogy one embankment end is the persistence implementation, where I'm thinking about modeling concepts and also their relationships and some of their constraints with SQL using tables. The other end is the externally exposed interface, where I'm thinking about a REST API using OData principles.

I then design the classes, methods, and operations as a bridge that spans between the two, now-known embankments. Also note that we have many choices when it comes to class design (e.g. to use ORM or not, which classes get which methods and where business & application logic go), as the classes in the middle are closer to internal implementation and farther from externally exposed API.


I think you will want a formal notion of different kinds of Users (in addition to Developer), such as Business Stake Holder -- they might be the ones to initiate Projects.

The term event is overused in our business, so I try to use it only in a narrow way (my opinion is that an "event" is something that happened, once, either just now or in the past, and events can fire, be subscribed to, etc...). So, you might choose a more specific name within your business domain for what you are calling event. On the other hand, I'd probably move in the direction of more general recursively composed projects, so projects can compose/decompose into any number of other projects. You already have several specific layers of composition: Event, Project, Application, why not get more general? Yet still, recursive composition may not suffice, you may also need to track dependencies between projects (e.g between peer sub projects, or independent project that are not composed). I might try to formalize the notion of schedule along with notions of dependency.

For my aggregates, what do I do here? Do I write a "service" class like "TeamProjectService" with methods such as "CreateTeamProject"? Or what?

I have two comments here.

First, I would tend to think about the items you list in bold as aggregate roots as they probably have solid identities externally referable from outside the aggregate. Aggregate roots can be related to other aggregate roots (and for NxM relations I would model persistence for each of those with their own first-class table). The way you are using the term aggregate above makes me think about the relationships between aggregate roots more than the entities within the aggregate.

Second, I would probably do relationship creation via an operation attached to one or both of the aggregate roots being related. For example, a team entity might be able to create a project, or the project collection could create a project though requiring a team as a parameter.


These days, I like to use OAuth2 (e.g. Windows Live, Facebook, Google+, Twitter, Stackoverflow) for authentication (I do OAuth2 directly but perhaps Azure ACS can help abstract this across the variety of OAuth2 providers).

  • 1
    Thanks for the response. I read it, and will re-read it overtime as my application develops. :) – Zack Aug 30 '15 at 2:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.