KISS, an acronym for "Keep it simple, stupid!", is a design principle first noted by the U.S. Navy in 1960
Speak to a senior ProCode developer and you will often talk about the importance of KISS. When coding solutions it is very easy to over engineer solutions, by either flexing (showing off the cool stuff you know) or by not planning.
Yet KISS is rarely spoken about when developing in LowCode and especially in Power Automate, with the most likely explanation being "Its LowCodeNoCode so it's already Simple", but that isn't the case. In fact it's more important in Power Automate then ProCode because:
- Varied skills base of developers (most developers self-taught)
- Simplified tool set (Less flexibility in the solution can cause complexity)
- Costs (Limited API calls/Premium licenses)
So when you build your next flow keep it simple, easy, but what is simple?
It could simply be:
- Less Actions
- Less Expressions
- Less Complex Actions
- Less Premium Actions
- Less Branches
- Less Loops
but some of them will contradict each other, e.g. less expressions = more actions, and what about:
- Less Environment Variables
- Less Connections
- Easy Deployment
- Configurable Outside of the Flow
- Easy to Scale
What drove me to write this blog was a recent automation I was developing, the basics were:
- MS form gathers data
- Flow selects Word Template based on inputs,
- Updates template with inputs
- Sends template
At first it sounded relativity simple, until you added in the detail:
- 20 Input fields
- Each template has unique combination and naming of its variables
- 20 Templates
- More Templates will be added in the future
I had 2 options,
- Simple Logic
1. Simple Logic
Using a Switch I branch the flow into each template, then hardcode the inputs (as the Word Connector reads the template Schema making it a lot easier).
This is simple because:
- Each Path is only 6 steps
- Only uses 6 API calls
- There are only 25 actions in the flow
- Its easy to follow, and if you need to add a new template just add a new branch.
But is it really that simple because:
To keep the simple inputs in the Word connector you must select the template file. So no environment variables for different templates for Dev/Test/Prod. That means added complexity in how to manage the templates and any development work.
Updates to the process could potentially mean updates in 20 places (e.g. add new variable to template).
It may be easy to add a new branch and template, but that means development which means:
- Developer Time
- Change Requests
That doesn't sound simple.
My second approach was to have a list of templates and variables. When the flow ran it would filter list to return correct template name, then loop over all the variables from the variables list and add in the inputs from the MS forms.
Quick Note - If you pass dynamic schema into the Word Connector you have to pass in the variable ID, not the Variable Name/Tag. Also you can pass anything in, and as long as it's a valid JSON the connector will accept it and use any valid keys/IDs and ignore the rest.
So this is more complex because:
- It has 9 actions in the main branch
- With over 20 variables in uses 208 API calls
- It uses SharePoint connector as well
- Requires 2 lists to be maintained
But when it comes to maintaining the flow in future it is a lot simpler. New templates can be added by anyone without developer time. It's a lot more stable and scalable, as additional templates do not add complexity.
The key thing to understand is simple does not = quicker/easier and at the same time complexity does not = benefits. As a developer our design review is key, as it allows us to identify our bare bones design (If unsure then a spike should be done to find it). From there we build out, it's easier to add the complexity after, then remove it.
My approach is:
A robust set of Non-Functional Requirements is what everything should be built on, this complexity can't be removed as its value is added after development, this includes basic things like:
- Naming convention
- Environment Variables
- Connection References
- Exception Handling
Next is to create the process as simple as possible, this needs to be relatively quick and focusing on pure functionality (though still includes our NFR's).
Finally we enhance our process, swapping out simple techniques for improved (e.g. an expression replaces a condition action). Re-ording the process can often improve efficiency by removing duplication.
The above are easy as they are often don't add real complexity, the balancing act is future proofing. Here we add complexity to make the future simpler. This one is very much intuition, the developer has to make the call based on likely hood of growth, added complexity and how much simpler it will be in the future.
So what did I go with in the case study, well in the end I went with the Simple Logic, this was because:
- The mapping process was too complex
- Low volume of new templates
- The dynamic was overly complex
My friend gave me a great line of advice:
It will be like we own this if we go with complex
And he was right, the more complex it is the smaller the developer pool to maintain it, the more likely you will own it for ever, and that adds up to a lot of baggage.
But that doesn't mean I went full simple, some of you may ask why there was a
Composein the process, well that was because a wanted to add all the branches outputs and pass it as a single input to the
Send Email (the nulls corrupt if passed directly into file content).
That way I didn't have to have 20
Send Email's, it's adding complexity but making it simpler 😎
Update: the images above are out of date, the compose should base64(all word outputs) then on the File Content bas64toBinary(compose). Though also learned in meantime the coalesce(all word outputs) selects just the non null values, so a lot better way to do it