Software Mise En Place
buttondown.email
buttondown.email
I think Mise en place can mean different things to different people. The way I was taught it was to have everything "in place" before you start. Literally you gather all the ingredients in one place (on a metal tray) before you start cooking. This has three main benefits: 1) you make sure you have everything you need; 2) you don't forget to add anything as you go because at the end your tray should be empty; 3) you don't mess up timings by searching for something while you're cooking that you can't find; Thus I use Mise en place, but I don't chop everything at the start. I chop the onion and then start cooking it, and then chop the other ingredients. Chopping everything else upfront would make the process slower.
Similarly in software development I often save simple tasks for when I need mental relief from a hard task. Working on a simple task can often give you the space you need for your brain to solve the hard task it's working on in the background.
Doing all the simple tasks up front does not seem to me like a good approach to cooking or software development, but making sure you know what all the ingredients are and have them all ready, does.
"I should thus resemble those bad operators who, having neglected their mise en place, are obliged to make it in the course of other work, and thereby not only run the risk of making it badly, but also of losing valuable time which might be used to better advantage.
Elementary preparations consist of those things whereof one is constantly in need, which may be prepared in advance, and which are kept available for use at a moment's notice."
A modern guide to cookery, A. Escoffier 1907"Cooking onions is not downtime" isn't an effective rebuttal of the general point of "I chop things during downtime, for example when cooking onions".
"I only tell the truth, for example when lying" is irrecoverably self-invalidating. There is no second example that could nullify its effects. The argument is made invalid by that example specifically. (Not to mention, it calls into question the claimant's understanding of what it means to tell the truth.)
You have misidentified the fallacy here.
I think this one sentence much better describes what I feel the spirit of mise en place is in regards to software. Things which you need, which may be prepared in advance. When I think of it this way, I am reminded of the many little scripts, aliases, editor plugins, configuration settings, etc. that I have accrued over the course of my day job that make it easy to do the things I have to do many times per day. For example, our product can be launched in several different configurations, so I have a script that takes a build directory and a configuration parameter and sets up everything so it's launched exactly as it should be; I also have a bunch of GDB scripts to set up the environment and to display data in a meaningful fashion; and many more things like that. Unlike in cooking however, once I have set up some aspect of my msie en place, it stays that way forever - it's like if you cut the peppers once and you have an infinite bucket of cut peppers. When looked at that way, I think it makes sense to make your mise en place as you go, since you don't really know what you need before you need it. Obviously a lot of trivial things should be set up beforehand and shared with the team, but every programmer has a slightly different workflow, so it pays to write some simple little tools for yourself when you come to need them and put them in your mise en place.
In a commercial kitchen, you'd better have the peppers (say) chopped and ready so you can use them. Not only for a single serving of one dish, but for all plates you expect to make of any dish with chopped pepper in it.
You cannot pipeline chopping the peppers with frying the onions when you are preparing several dishes at once like you can at home. At home, you have maybe a dish or two, and you know you have time while the onions are frying. You also know that these are the only dishes to be cooked and no one is going to order something else while your onions are frying.
It also applies to software. If you're in a calm, steady development flow, you can pipeline tasks as you need. You can work on the docs while blocking work on the library, it doesn't matter. However, when you'be got periods of high-speed, fast-paced environment with deliverables required right now and bugs flying at you, finding a way to move groundwork out of the stressful time is a good idea.
Obviously, all analogies break down eventually, but I would say something similar to the article: if you anticipate needing to swap some component out, or you are concerned that some activity contains substantial project risk (in the analogy, this is chopping peppers while onions are frying and hoping that no one orders another dish) will be needed during a period of high pressure (lead up to a release, say), try to front-load that effort into a more forgiving timeframe (i.e. chopping peppers before the restaurant starts to take orders). Do the experiments, write the documentation, make sure everyone knows what's going on, then, hopefully, it's less project risk at a time when you can't afford it. You're saving risk, not necessarily time. And you can't eliminate all the risk.
If that's just not possible because you're too busy 100% of the time, you're probably on a death march and it's already too late: once the orders are coming in, if you haven't prepped the peppers, you just have to deal with it, and if that makes any dishes late and customers angry, tough.
I think another important difference is that software is much less predictable. Thanks to low/zero-cost replication, we spend much more time doing something novel than a commercial chef does. If a developer is doing the same thing over and over, that's a an opportunity to extract a service or a framework or a library. Whereas restaurants have much more predictable workloads, making it much safer to, say, chop 100 carrots than to write 100 classes in advance of need.
* Physically clean desk and laptop.
* Commit old code changes before working on new ones.
* Main branch is pulled.
* Fix the build before writing more code.
* Set up tmux or whatever so every terminal is in a convenient place.
* Check that the failing test fails as expected.
* Set up text editor/IDE to have easy access to relevant files and browser to have access to e.g. the relevant JIRA.
* Close irrelevant browser windows and applications.
etc.
Dont think it means "do the easy tasks first", just "prep the environment".
Another good software example is having slack. If you're always busy, you may not be working on the right things.
Mise-en-place is the religion of all good line cooks. Do not fuck with a line cook’s ‘meez’ — meaning his setup, his carefully arranged supplies of sea salt, rough-cracked pepper, softened butter, cooking oil, wine, backups, and so on. As a cook, your station, and its condition, its state of readiness, is an extension of your nervous system... The universe is in order when your station is set up the way you like it: you know where to find everything with your eyes closed, everything you need during the course of the shift is at the ready at arm’s reach, your defenses are deployed. If you let your mise-en-place run down, get dirty and disorganized, you’ll quickly find yourself spinning in place and calling for backup. I worked with a chef who used to step behind the line to a dirty cook’s station in the middle of a rush to explain why the offending cook was falling behind. He’d press his palm down on the cutting board, which was littered with peppercorns, spattered sauce, bits of parsley, bread crumbs and the usual flotsam and jetsam that accumulates quickly on a station if not constantly wiped away with a moist side towel. “You see this?” he’d inquire, raising his palm so that the cook could see the bits of dirt and scraps sticking to his chef’s palm. “That’s what the inside of your head looks like now.”
One thing that makes software different than other jobs is that most of the space in which we work is what we ourselves have built in previous days. A messy codebase makes it hard to have a calm, clear presence. Which in turn leads to a messier codebase. There are whole projects, probably whole companies, where the inside of everybody's head looks like that.
So for me, a key part of developing is creating and projecting the sorts of work that over the long term enable that feeling of "the universe is in order". Indeed, you could write a history of software development in terms of how much progress we're making in that.
I'll have to check this book out!
I used to freak out about not making extra dishes, but who cares. I have a dishwasher. It take 20 seconds to throw 3-5 small bowls on the top rack.
In cooking, you usually know the recipe and have experience before preparing it for many people.
In programming, you often explore and create, trying out new things that you didn't know before.
Mise en place suggests that you know exactly what ingredients and tools you'll need and what to do with them.
Perhaps a woodworking workshop is a better analogy for the creative process:
You're trying out a lot, taking scrap pieces as dummy items to test on, create scaffolding and helper items to get where you want. But afterwards, you clean up the bench and service the tools.
To me, this kind of "explosion first, prune afterwards" process seems more natural/common?
So far this approach seems to be working really well, I'm not getting overwhelmed or bogged down by trying to 'vertical slice' anything, and keeping the end goal very loosely defined means I can easily adopt new gameplay ideas as I come across them in the process of tinkering with the available tools and their interactions.
Once I've figured out all the individual challenges I can begin in earnest to craft the whole.
Im pretty sure that experimentation equally well to cooking.
There is very little reason to write out (say) the same algorithm a hundred times because you have a hundred different users who need it, but a cook can't just ctrl-C ctrl-V a dish.
Mise en place has nothing to do with rigidity, it's the concept of everything in its right place before you start preparing the final assembly of the dish. You can and should practice mise en place when you cook, even if you have no idea what you are making. Preparing food is all about timing and mise en place allows you to focus on the preparation without getting distracted or caught up in chopping onions when your steak is already too done.
I actually do that all the time - different ingredients have different densities and different cooking times, so it makes total sense to start cooking the harder ones while cutting the softer ones (e.g. when making a Minestrone soup). Or you want an onion/garlic/tomato base to break down before inserting other ingredients that should only cook shortly and retain their texture.
It's not really that hard to get it right though, just by touching it it's easy to see that a zucchini will cook faster than fennel.
This is why wine was invented.
Not really, cooking is not baking (where you need to control the process tightly), you always have much more leeway (except for marginal conditions like things burning). Especially with harder vegetables, which have a long range from hard over al dente to soft but still nice. Unless you have to fulfill some Michelin style quality control, you won't have that problem.
Any time I'm developing a feature there's usually a bunch of supporting research: how does the existing code work and where is it located? Are there any supporting open source packages I need to add? How do those work, and where is their documentation? Any good examples out there?
I gather all of this research in issue comments - sometimes working on my mobile phone.
Once that's all gathered, the actual coding work (on my laptop) often takes significantly less time then the research did.
Wrote a bit about my process here: https://simonwillison.net/2022/Jan/12/how-i-build-a-feature/
This one is a bit more involved: https://github.com/simonw/shot-scraper/issues/18
There are a few good examples linked to at the very bottom of https://simonwillison.net/2022/Jan/12/how-i-build-a-feature/
> What does mise in place tell me? Separate the tasks. Find a way to prep just the action file, then just the credentials, then the idiosyncrasies of my projects. After that I can integrate the pipeline with the documentation proper.
The problem I find is that unless you've done something very similar before (and recently, because services and APIs are always in flux), what can happen is you complete a few tasks, then on a later task you find some gotcha that means your original approach isn't going to work, so you come up with a workaround which requires you to redo/change the earlier tasks. Development whack-a-mole.
So what I tend to do is take the riskiest task first, do just enough to convince myself it can be finished, then move on to the next task etc. and then iterate back around filling in the gaps until I'm done.
By the way, I recently did some GitHub Action automation and it was super frustrating. There's no official way to run/test this locally (there's https://github.com/nektos/act which doesn't replicate a lot of features) so you end up editing-saving-pushing-waiting-diagnosing (e.g. even just for basic syntax errors) in this painfully slow feedback loop until it eventually works and hope it doesn't break later. I'd rather just stick to the simplest single script I can come up with than use GitHub Action features because of this.
Never again.
How are people able to piece together such complex GitHub Actions? Does GitHub have to deal with this internally as well or they just haven't gotten around to releasing dev tools yet?
If it’s a web service, set up a hello world / health check to auto-deploy with migrations if applicable, after automatically running the build.
If it’s a library, set up a build and CI, and any version bumping and release scripts, docs autogeneration.
Basically set yourself up for success and handle a lot of the non-project related heavy lifting. That makes a great foundation off which to launch and iterate quickly.
https://www.amazon.com/Work-Clean-life-changing-mise-en-plac...
The reason is that it’s very easy to get started again - the test is broken, so the next task is to fix the test.
A good “add-on” read to this is Essentialism. I felt like it complemented Working Clean very well.
https://www.amazon.com/Essentialism-Disciplined-Pursuit-Greg...
"Clean as you go" is apparently much harder with software. :)
- graduellement
- progressivement
- petit à petit
--------
side note: for some reason I find the use french words, terms, and expressions in English (and there are a lot, in a strict technical sense almost every french word is a valid English word) somewhat annoying because they usually diverge with time in ways that are important enough to change meaning but not enough for the sense to be inferred just from local context alone. given how prevalent anglicisms are in french this make for more confusing and verbose conversations.
--------
Ex: "mise en place" just mean setup, so image two french software engineers talking about software "setup", one that has in his mind the meaning/philosophy meant here and the other using the more generic meaning.
I don't think intensity or difficulty is the key differentiator between preparation and the actual work. To me, it's mainly about separating tedious and repetitive tasks from the ones that require attention and creativity.
Prep work means that you perform something that you have done many-many times before and it feels automatic. Prep can be also harder and more intense in many ways than the actual work itself.
If a piece of code combines data from three systems, then maybe first fetch it from each one (maybe in parallel), then "wash" it (check preconditions, normalize, etc.)
Then you hopefully have data which is ready for doing the core work without the code being muddled with fetching missing stuff and cleaning it.
I can obviously find counterexamples when it is not so easy but I think I can also find functions which unnecessarily mix fetching stuff, checking it and the core logic.
fetch A
wash A
fetch B
wash B
in terms of being easier to read. Of course sometimes there are performance benefits to firing off all the requests right at the start.Anyway I definitely agree that not separating the core logic out from the data fetching/cleaning is a bad idea.
carrot = fetch carrot
onion = fetch onion
celery = fetch celery
clean(carrot)
clean(onion)
clean(celery)
cook(carrot, onion, celery)
The way I think about it is, how would I write it if performance didn’t matter? And then from that point I think about what compromises I can make that improve performance at the expense of something else (readability, etc)
Disclaimer: I’m not trying to argue that my preference is _better_.
One of the things that I like to do, is create multiple reusable, standalone repos of tools that can be integrated into larger, aggregate, projects. Works a charm. That’s sort of a mise en place.
But the trap is that we can spend so much time on prep and infrastructure, that we don’t have time for the project, itself. I’ve done that.
There was an SNL character (Phil Hartman played it), called “The Anal-Retentive Chef.” The gist was, that he often spent so much time on prep, that he couldn’t make the meal.
At least when it comes to a ssmall-ish feature.
For larger systems, the typical aechitecture/urbanism analogy is probably more suitable.
Nevertheless, I will reuse it in my teams.
“Test first” still feels like a bridge to far to me (my programming is usually more exploratory than that), but with the mis en place framework it’s easier to see why people might like it so much.
It involves 'getting out all the tools' - the local development server, opening up my notes, a terminal window running the virtual environment, etc.
An equally important part though is clearing away the things I won't be using.
The test environment is the isolated place where I can quickly stand up individual parts and then later, assemble them into larger chunks of value.
Prep the shit outa everything requirement and design wise, then make it in sequential fashion?
I don't think so, because the article is talking about prepping up the tools and infrastructure needed for the project, not the requirements and design needed for the program's business logic.
The Practice of Programming(Kernighan and Pike 1999) https://www.cs.princeton.edu/~bwk/tpop.webpage/ goes into much better details of the iterative development that is actually being done by the author. If you know the overall design of your program, you build out the skeleton with everything stubbed out. As you iterate through development, those stubs are fleshed out into fully working components.
The analogy of mise-in-enplace works if you have a ready for reusable components (COTS, FOSS, or personal) that you quickly pull off the shelf and combine into the larger product. Mise means having everything ready to go; you have your set of reusable components and subsystems that you can quickly pull together to make a new product.