John DeFalco, SR Software Engineer
March 8th, 2021
I like to cook. Well, the truth is, I like to eat! From an early age my mother instilled in me that if you want to eat, learn to cook, don’t wait for someone else to cook for you. So I did! This lesson extends beyond the kitchen to our software and certainly other places as well.
The way I like to cook is by adequately preparing to make each recipe. There is a French cooking term called “mise en place” that I subscribe to which means “everything in its place”. Before I cook something, I like to read the recipe several times to get a feel for the ingredients and techniques I’ll be employing. Next I measure out the ingredients. Lastly, I take out the tools I’ll be using such as whisks, saucepans, spatulas. Only now is it time to cook.
In my opinion, software development is very analogous to food preparation. You start with a recipe (feature), you review it’s ingredients (requirements), understand the cooking techniques to be employed (technologies) and then you cook (code) it. Typically, when cooking you taste (unit test) the recipe as you go and do a final tasting (functional testing) to adjust seasoning levels before plating it up (delivery to the customer).
It sounds obvious to say but understanding what you are developing in its entirety before starting to code is extremely important. Read the user story or requirements, understand what the customer is asking for from a business perspective and then think about if anything has been left out. This is an important step in the process that relates to design of any technical solution. If you picked up a recipe for Beef tacos and halfway through making them you realized it doesn’t mention chili powder anywhere, you may want to understand why. Was it just missed or is there something else you aren’t understanding about the recipe? Ask questions up front. Throughout my career, more times than I can count, I’ve seen customers appreciate a developer requesting more information before they start coding. It shows initiative and that you are thinking about the feature from their perspective and doing so before you start down the development path, which could cause rework.
Another solid practice is using the language of the domain. In cooking, there is a well known lingua franca. You wouldn’t tell someone that you were heating up some cow in a metal cylinder when you mean roasting a beef roast in a dutch oven. Using different words and phrases than the stakeholders to describe business objects and processes within the solution space may sound just as nonsensical to the subject-matter experts with whom you are working. This does not mean suggestions as to the naming of those objects and processes within your solution space can’t be negotiated before being committed to. If you and your business partners agree that “sauté” and “pan fry” have the same meaning then agree to call it “pan fry” throughout the domain’s ubiquitous language.
Once you have a handle on the language and feature criteria in the problem space, start designing for the solution space. Assess whether the change will require database schema updates, UI changes, server setup, configuration changes, encryption of sensitive data, and on and on. Which one of these changes can or should be done first? How will you deliver testable business value in chunks to your QA team? Do you need to speak to someone on your team to “pick their brain” regarding a technology or technique? Sometimes I stumble across a recipe that calls for a technique that I’ve never done before, such as using a culinary torch to melt raw sugar on top of crème brûlée. YouTube to the rescue! Identifying these gaps in knowledge up front and resolving them helps to keep the feature train moving as you’re coding along and to design a more complete solution for the customer.
Speaking of coding, the use of TDD (test-driven development) to write unit and use case-level spec tests along the way ensures you design and develop the absolute best solution. This is exactly the same as tasting a dish as you are cooking it. Over-seasoning a recipe all at once is a bad technique, so you should season over time in layers and sample the dish along the way. Writing unit tests for small portions of the overall solution and testing your code is very similar to this practice. If you wrote an entire solution then decided to test your logic paths, you may find that you’ve made some terrible decisions along the way. Again, this is a sure sign of rework and wasted time and effort. After developing discrete pieces of functionality into a cohesive feature you functionally test it from the perspective of the end-user. Voilà, your recipe is done. Now it’s ready for plating!
In restaurants, plating is the process of putting prepared food to plate. Sure, you can sloppily throw down a ladle or portion of something onto a plate and send it out to the customer. Doing this will appear as if you don’t care about the dish and even less about the customer. Wiping down the dish so droplets of food aren’t sprayed all over the sides, dusting the top and sides with parsley or cheese or setting a sprig of rosemary over the top all go to great lengths to show that you care about the final product and give a great first impression to the customer. Driving home the analogy, maybe you don’t like exactly where that input field is on the screen or how your color choices mesh together on the page. Add a little more salt, drizzle on some olive oil or sprinkle some parmesan cheese into it. Work to perfect the presentation of your feature before releasing it to QA and the users for testing.
Up your software development game by employing mise en place to give order and structure to the process. I just gave you the recipe. Now, get in the kitchen and make something great!