Code Generate Often with Moz
Code generation with Annotation
Moz is a project I built out of the need to easily generate code for projects by utilizing simple source markers that can be used to create other structures easily.
More so, the project was also a means of providing more simple structures that wrap the Go template system with usable structures to allow quick scaffolding of source lines.
This post is less an introduction to Moz and more of a short reflection of what I learned while building Moz, which I hope inspires you to code generate more, either through Moz or through custom solutions.
One of the major issues that formed the need for Moz was cases where we had developers do repetitive tasks within our source lines that could easily be done with a little code generation, such as:
- Creating interface mock structures for testing
- Creating struct skeleton code from interfaces
- Generating structures for custom types without using
- Creating triggers for structures using annotations
- Writing more readable code for source line generations.
The above are just a short list, but consider having written a Go-based command line tool for generating a project's startup and asset files, and the many, sometimes unmaintainable, code that evolves from such projects, or how a single change within a template file can reverberate to affect the way the CLI tool renders it.
Why with Moz
I constantly faced the above issues when working on projects, so I wanted a means of generating Go-based source snippets that could be placed within projects with ease, without creating unmaintainable messes with files.
Moz solves all of these issues by allowing me to use very simple functionally composed structures that can be used to generate skeleton source lines for a Go snippet or an entire package.
More so, Moz extends the idea by providing annotation markers like
@mockitup, which allows for the ability to create new source code for different structures and types with ease, simplifying the way code generation works. This, in effect, allowed a simple but flexible ability where a package or a type can easily, using custom functions, create different sources files as desired, for example:
- Creating new structures for different types without relying on
- Mocking up structures for tests
- Creating a whole
Each simplified the development process and increased the flexibility and maintainability of the project.
Challenges Building Moz
Moz provided a few challenges due to the desired goals of simple code generation.
These were the following questions that came about during its development:
- What type of structures fit developers' thinking in writing source lines?
- How do we parse comments in Go source lines to generate with annotations?
- What approach would best suit us in using annotations for code generation?
- How do we write these to the filesystem with enough flexibility for the developer?
Each question provides its own series of challenges. For example, while developing Moz, I had to learn a lot about the internal
go/token packages, which allowed parsing of Go package files. This also expanded to understanding exactly how these structures provided by these packages represented different information from the different structures within the Go language.
More so, I had to create higher level structures that already contained extracted information that simplified the functions that would be used in generating the code.
All in all, I would say the Go language provides a high level of flexibility in its usage, and reflection is not the only means of achieving a little generics. Code generation also provides quite a powerful technique.
Lessons Learned with Moz
Moz was a project that broadened my view of how code generation can really affect the development process for a project and the power that comes with it. I think if one were to summarize, then the following would be most suitable:
- Code generate often.
- Always never assume and always verify.
- Go internal packages for parsing Go source files are powerful for use.
- Generics not in Go are not a loss, but an opportunity.
- Always code generate mocks and structures in projects to reduce repetitive tasks.
A lot can be said about Moz in and of itself, but for a reflection post, I find that it's better to talk about that in another post. If I can give any advice from my experience, it would be that code generation provides a power means to address how we as developers work, and Go, as a language, has already provided the tools. We just need to use them.
Projects Using Moz
After Moz came to be, I happy have used its internal packages in a few other projects of mine, which I felt should be shared to showcase real-world usage.
Gu is a project that builds on top of GopherJS to create front-end applications and uses Moz to generate project and assets files easily.
Dime is an experiement in channel based streaming, and uses Moz to generate different channel implementations for different core Go types (e.g
Shogun is a CLI generator that allows exported functions to be executed through the command line to provide lambda like binaries that can be used for function-based APIs, or for building a project instead of make.
Moz is on going and would greatly benefit from the thoughts and ideas you may have. I equally hope it inspires you and you find it useful during development.