Updated on February 28th, 2017
This post is part of a series of posts designed to make you think about your own design philosophy on different topics. If you haven’t read these posts yet, please do so first:
Develop Your Design PhilosophyDesign Philosophy On Packaging
Package Oriented Design allows a developer to identify where a package belongs inside a Go project and the design guidelines the package must respect. It defines what a Go project is and how a Go project is structured. Finally, it improves communication between team members and promotes clean package design and project architecture that is discussable.
Package oriented design is NOT bound to a single project structure, but states that a project structure is paramount to applying guidelines for good package design. Moving forward, I will present one possible project structure and the guidelines to follow based on the design philosophies presented earlier.
I believe that every company should establish a single Kit project and then multiple Application projects for the different sets of programs that get deployed together.
Think of the Kit project as a company’s standard library, so there should only be one. The packages that belong to the Kit project need to be designed with the highest levels of portability in mind. These packages should be usable across multiple Application projects and provide a very specific but foundational domain of functionality. To this end, the Kit project is not allowed to have a vendor folder. If any of packages are dependent on 3rd party packages, they must always build against the latest version of those dependences.
A typical Kit project might look like this:
Note: There is nothing wrong with breaking each of these Kit packages into their own repository. I don’t do this because it creates more work managing all these packages. Vendoring tools that exist today let you cherry pick the packages you need to vendor from a repository. This feature allows you to manage a single repository for Kit packages.
Application projects contain the set of programs that get deployed together. The set of programs can include services, cli tooling and background programs. Each Application project is bound to a single repo that contains all the source code for that project, including all the source code for the 3rd party dependencies. How many Application projects you need is up to you, but always take a less is more approach.
Each Application project contains three root level folders. These are cmd/, internal/ and vendor/. There is also a platform/ folder inside of the internal/ folder, which has different design constraints from the other packages that live inside of internal/.
A typical Application project might look like this:
│ ├── servi/
│ │ ├── cmdupdate/
│ │ ├── cmdquery/
│ │ └── servi.go
│ └── servid/
│ ├── routes/
│ │ └── handlers/
│ ├── tests/
│ └── servid.go
│ ├── attachments/
│ ├── locations/
│ ├── orders/
│ │ ├── customers/
│ │ ├── items/
│ │ ├── tags/
│ │ └── orders.go
│ ├── registrations/
│ └── platform/
│ ├── crypto/
│ ├── mongo/
│ └── json/
│ ├── ardanlabs/
│ ├── golang/
│ ├── prometheus/
Good documentation for the vendor/ folder can be found in this Gopher Academy post by Daniel Theophanes. For the purpose of this post, all the source code for 3rd party packages need to be vendored (or copied) into the vendor/ folder. This includes packages that will be used from the company Kit project. Consider packages from the Kit project as 3rd party packages.
All the programs this project owns belongs inside the cmd/ folder. The folders under cmd/ are always named for each program that will be built. Use the letter d at the end of a program folder to denote it as a daemon. Each folder has a matching source code file that contains the main package.
Packages that need to be imported by multiple programs within the project belong inside the internal/ folder. One benefit of using the name internal/ is that the project gets an extra level of protection from the compiler. No package outside of this project can import packages from inside of internal/. These packages are therefore internal to this project only.
Packages that are foundational but specific to the project belong in the internal/platform/ folder. These would be packages that provide support for things like databases, authentication or even marshaling.
An important aspect of package oriented design is the ability to validate the design of packages. This is possible because of the guidelines that are associated with a package based on its location inside the project. There are seven validation steps that will help you identify design problems.
Here is a quick example of how we can review the Application project to understand how the project is put together and validate the dependency choices for each package.
Package Oriented Design fosters conversations and review to make sure packages maintain the best possible purpose, usability and portability. This drives clean package design for any package across the entire project. For package oriented design to be effective, you need strong rules about project structure. The project structure I have shared has been developed over the past three years and has been working effectively on multiple projects. Other project structures could be just as effective and I expect over time to continue to refactor my project structure and guidelines.
My goal in everything I teach is to get you to start thinking about what you are doing and why. To have you start asking questions and validate everything you are doing. I hope you start to think about package oriented design and begin to formalize how you structure projects and design packages for the projects you work on.
Get your team up to date with best practices & customized curriculum.
We help you evaluate your architecture, design, structure, tech-debt and human capital.
Learn at your own pace!
Special offers on upcoming training events & our latest blog posts.
Valid email required.
Submit failed. Try again or message us directly at firstname.lastname@example.org.
Check your email for confirmation.
We've built our reputation as educators and bring that mentality to every project. When you partner with us, your team will learn best practices and grow along the way.
Years in Business
Please fill out the form below, and we'll get back to you soon.
Check your email for confirmation of your sent message. We'll get back to you shortly.
Ardan Labs Copyrights © 2023