top of page

Engineering decisions

Writer: The MainesThe Maines

Decisions are a key feature of logic. Making those decisions easy for a human to understand is of paramount importance when it comes to software development. Let’s spend some time looking at various decision strategies and how we can improve upon them.


Decisions


Well first, I guess we should clarify what a decision is. A decision takes a course of action based on the evaluation of a condition or a set of conditions. Let’s look at an example.


// Python
def main():
  outcome = “”
  if 1 == 1:
    outcome = “they are equal”
  else:
    outcome = “they are not equal”
  print(outcome)

main()

The decision is whether or not 1 is equal to 1. If 1 is equal to 1, it sets the outcome to “they are equal”. If 1 is not equal to 1, it would set the outcome to “they are not equal”. In this case, the program will always print “they are equal”. Can we clean this up a bit? Absolutely:

// Python
def main():
  outcome = “they are not equal”
  if 1 == 1:
    outcome = “they are equal”
  print(outcome)

main()

We removed two lines of code. Instead of defaulting the outcome to an empty string “”, we defaulted it to the value that the else statement would have evaluated. This allowed us to remove the else portion of the condition. That saves some processing time, making our application a little more efficient. This technique can’t always be used, but you should definitely consider it when you’re just setting variable values and not nesting into other logical flows.


Unix has a philosophy of doing one thing and doing it well. Let’s look at this in the context of decision statements. It becomes extremely difficult when you have multiple pieces of a decision jammed together on one line. Looking at a simple example here:



// Python
def main():
  listOfRoles = ["editor", "public"]
  userName = “joe@domain.com”
  userRole = “editor”
  if len(userName) > 0 and (userRole in listOfRoles or userRole == “admin”):
    print("User %s does have access as an %s" % (userName, userRole))
    return
  print("User %s does not have access" % userName)

main()

Our decision requires that the length of the userName variable is greater than 0 and that the userRole is within the listOfRoles array or that the userRole is equal to “admin”. This isn’t an excessive example and I would actually just go with it as is. However, when you have conditions that become excessively long, it really does become hard to follow. Try breaking out the related components of the decision into small, one line functions that clearly evaluate only that particular element or set of related elements. Let’s rewrite the above code and make it a little more clear:


// Python
def main():
  userName = "joe"
  userRole = "editor"
  if len(userName) > 0 and userRoleHasAccess(userRole):
    print("User %s does have access as an %s" % (userName, userRole))
    return
  print("User %s does not have access" % userName)

def userRoleHasAccess(userRole):
  listOfRoles = ["editor", "public"]
  return userRole in listOfRoles or userRole == "admin"

main()

What did we change? Functionally, nothing. However, from a readability standpoint, we condensed the decision into a two component decision. It is much easier for your brain to keep track of smaller pieces when it’s clear what each piece is there to accomplish. We moved the check for the userRole into its own function and allowed that function to keep track of the listOfRoles. The userRoleHasAccess method does one thing, and does it well. This frees up the main function from keeping tabs on that information and cleans up the decision quite a bit. Further, we have a function that is easy to write unit tests against.


That’s all I really wanted to throw out there for decisions at this point. You don’t have to break out every single decision into a function, but you should start to consider it after you reach three conjunctions. I do want to revisit this idea for switch cases, but I think I’ll save that for a post on design patterns. I hope this helps you in writing better decisions for code clarity and easier maintenance.

Recent Posts

See All

How to engineer good function names

Continuing on our journey for clean and self-documenting code, we are now turning the focus to function names. We just talked about...

How to engineer good variable names

Let’s look at some techniques that will help make your code more readable, maintainable and ensure you don’t look back at it in 3 to 6...

Comments


bottom of page