On Friday, it’s exactly one month since we gathered in my basement to take the first stumbling steps laying out the plan and starting to build Our Machinery. The beginning of an ambitious project like this can be a bit scary; just the sheer amount of code you know you will need to knock out through your fingers can sometimes feel overwhelming. And on top of that, the first code produced has the tendency to form and shape the entire code base as it grows. So it becomes very important to “get it right”. But what does that really mean; getting it right?
For a lot of programmers getting a piece of code right equals a long design phase, trying to think of every possible problem and solutions to those before even writing a single line of code.
For us it is the total opposite,
in fact we even forbid ourselves thinking about a design problem for more than a day before we start writing some code. Our reasoning is that if you can’t wrap your head around the design of a system in a day, you probably know too little about the problem domain to come up with a good design on paper even if you spend a week thinking about it. In those scenarios we always favor moving on doing some exploratory coding to get a better understanding of the problem domain, and usually the code produced at this stage eventually forms the design and foundation for the new system.
This methodology has been very successful for us; it helps us to keep on moving forward and not getting stuck in endless design discussions. In the rare occasions where the exploratory coding stage still doesn’t answer enough questions to unblock us, we usually context switch and take on a different task while digesting the problem in the back of our heads, and then after some time we go back to it.
We originally started practicing this methodology more than ten years ago when working in the games industry. Back then the reasons for doing so were different though. In games you rarely have enough time to solve a problem cleanly or design a system properly, the next payment milestone is always around the corner and you simply cannot fail shipping a promised feature. This is both the strength and weakness of the games industry; a lot of cool tech gets built and adopted fast, but usually at the price of buggy and hacky code, poor tools and frustrated and burned out co-workers.
When we sat out to build Bitsquid we wanted to maintain the fast development speed we knew from the games industry but without jeopardizing life and code quality. Turns out it was actually easier than anticipated, at least in a small development team. This is how we approach it:
- Decide that your private life is at least equally important as work, don’t do overtime unless absolutely necessary.
- Set some ridiculously ambitious short term development goals that forces you to stay focused.
- Practice to have your mind processing at least two tasks at the same time to reduce the mental burden of context switching if you get stuck on what you are currently working on.
- Trick your mind into believing that nothing is very hard or complicated. Even if you know that something is far from trivial from prior experience, convince yourself that there must be some other way to go about it that makes it more manageable.
- Try to avoid code complexity at all costs.
Let me elaborate a bit on the last point; Dumb and easy to read code that clearly reflects the design philosophies of a project is king. Getting everyone on the same page about what’s important and why in a project saves tons of time and increases efficiency, as it enables developers to more quickly grasp different parts of the code base. Even if this makes you write some overly verbose code compared to using some fancy language feature that allows you to express a solution to hairy problem in a more compact (but often less clear) form.
At Our Machinery we have a single design mantra: “Do more with less”.
We hope to echo this mantra not only through our own code base but also throughout the entire product. Our goal is to build a few powerful but minimalistic building blocks that, if put together smartly, can express almost anything. On top of that we want to make it natural and very simple for our users to extend the system with more building blocks.
The core is a minimalistic foundation library (memory, threading, OS, logging / error handling, etc) together with a centralized data model. Everything else will be built as plugins. What forms the final product depends on what plugins our users choose to activate.
While it’s too early to say if this will become a successful product structure, it so far feels very promising.
I’m currently working on getting some basic rendering up and running, in a future post I will go through the plugins involved. For now I will just leave you with this, the first triangle rendering through our Vulkan rendering backend.