A few weeks ago, I saw a Udemy advert about prices reduction to £9.99 for most courses. I decided then to start a proper Golang course. One that would have cost me £199.99. So £190 saved, or at least not spent for great content. I did go through the Tour of Go about a year ago but then didn’t bother much more with it. After completing the course within ten days, I decided I would write a post with some demonstrable results of what I learned. I figured, algorithms wouldn’t be useful and that should use my next post to learn something. Something like writing the simplest possible web app. But then where do I start? How to structure my project? I figured since I wanted to write about Domain-Driven Design (DDD) for a while but couldn’t figure an angle, now is my chance.
3rd day on that course. Prob won’t spend more than 30mn which is fine. The important bit is consistent repetition l the end just like everything else. #AlwaysLearning@Udemy: Go (Golang) Programming: Mastering Google’s Go Programming https://t.co/HYE2lpRS4T pic.twitter.com/PBaZ8aNrX6— Jean-Dominique Nguele (@CodingNagger) August 21, 2020
What to build?
I am going to write a very simple todo-list web app, super original I know. Think I can’t get any lazier than that? I will use in-memory storage for my items. I just wanna show off my new Go toy and sneaking some Domain-Driven Design. Let’s jump into it!
What is Domain-Driven Design?
According to Martin Fowler, Domain-Driven Design is an approach to software development that centers the development on programming a domain model that has a rich understanding of the processes and rules of a domain. At the heart of this was the idea that to develop software for a complex domain, we need to build Ubiquitous Language that embeds domain terminology into the software systems that we build.
Crunching knowledge to define the building blocks
The first part of building software using Domain-Driven Design is to crunch knowledge. If you are trying to build software for architects to help them design buildings, you will need to know enough about architecture to deliver a satisfactory solution. One option would be to study architecture but this might not be the best option unless you want to specialize in that domain. Another option is to talk with the architects that will use the product, understand how they work, what components they use.
Here, I only need to write a todo list for a blog post so there isn’t much knowledge to crunch. The application is the todo list which consists of a list of tasks. We can add new items and we can complete tasks. I want to have the ability to list tasks based on their state which is pending until they are done. Also, I’ll allow for duplicate tasks because, reasons.
Interestingly, when I started writing the post, I used the name “items” instead of “tasks”. I did so because when describing actions related to the tasks, “items” didn’t sit well with me. It felt too generic. That’s an important part, try and pick wordings that apply to your domain in a way that more people understand what you’re referring to with a minimal amount of effort.
Putting this knowledge into a Domain-Driven Design frame
For this part and the next, I took inspiration from Kat Zien’s GopherCon 2018 talk beer review service example. She had a slide presenting a few Domain-Driven Design keywords for a given bounded context, so let’s see what that looks like for our todo list.
- Context: task tracking
- Language: tasks, pending, completion, storage, creation, restful service
- Entities: Task
- Value Objects: N/A
- Aggregates: N/A
- Service: Task creator, Task lister, Task completer
- Events: Task created, Task completed
- Repository: Task repository
How this Domain-Driven Design frame translates into a Go project structure?
Time to write up the code. It took me a few hours as I am still a newbie in Go which is part of why I’m sharpening my Go-skill with this post. Now I got something functioning and there are no tests here. Maybe I’ll write a post later on testing on Go. Makes me more to write about. First have a look at that screenshot then I’ll discuss further what we got here.
I chose to use a screenshot showing the main file that sets up everything alongside the exploded folder structure so that it’s clear what we have here. As you can see here, we got five different contexts. Let’s go through each of them.
- creation: This one contains a creation specific Task which contains only a description which is all we need to create a new Task. From there, we have a service that uses that specific kind of Task in the repository that will need a create method with it.
- completion: We basically have the same shape as the above with the difference that we have a completion specific Task which contains only an ID as it is all we need to complete a task.
- listing: This one contains a specific kind of task where both ID and Description are provided so that we can visualise and complete tasks.
- storage/memory: This context contains methods and structures for storing tasks in memory. It will abide by each of the service interfaces/contracts. It will provide methods to create, complete and retrieve tasks stored in memory.
HTTP rest context
- http/rest: This context will provide endpoints and connect these to the services that will provide answers for each endpoint.
This is the main package where we initialize the application and tie everything together, it contains the application entry point.
As I write this, this is the structure I will go by to develop Go apps in the future. I’m quite excited about the language and the options it offers to separate concerns in a fairly similar way to class Object-Oriented languages. If you want to know more about Domain-Driven Design you can check out that post from Martin Fowler. However, if you are ready to dig deeper, go and get yourself Eric Evans’ Domain-Driven Design book. Now if you want the code is available over there. Thanks for reading and see you next time!