Quality and Software

My last post and talking about what quality software is reminded me of “Zen and the Art of Motorcycle Maintenance.”

Here is an excerpt from chapter 18:

Phædrus wrote, with some beginning awareness that he was involved in a strange kind of intellectual suicide, “Squareness may be succinctly and yet thoroughly defined as an inability to see quality before it’s been intellectually defined, that is, before it gets all chopped up into words — .We have proved that quality, though undefined, exists. Its existence can be seen empirically in the classroom, and can be demonstrated logically by showing that a world without it cannot exist as we know it. What remains to be seen, the thing to be analyzed, is not quality, but those peculiar habits of thought called `squareness’ that sometimes prevent us from seeing it.”

Please Use Loosely Coupled Pure Subroutines : How To Subdivide Programs

Some people get bent out of shape about superficial style choices in code.  Whenever you work with someone new there is always the “Okay, curly braces should be after a newline” conversation.  I have yet to find someone who writes code in such a way that it makes a difference for me, I don’t care where you put your curlies.  The things we should care about are substantial style choices that make code more reliable and easier to maintain.  For example I think it’s hardly controversial to say that we should name variables so that they match their semantics.  “count” is a better variable name than “c”, just as “widgetCount” is better than “count”.

There is another style consideration in the same vein with which I thought we were all on the same page.  Or at least in short time everyone would be, but it’s been 8 years since I’ve made this revelation and I haven’t seen a change in practices.  So I’m going to cry it out to the world in hopes that people adopt it.  If there was one thing I could tell every programmer that I think would help the State of Software the most, it would be this.

Please use loosely coupled pure subroutines.

Every programming language worth talking about has support for subroutines, all the way down to the assembly level (6502 assembly jsr opcode, c functions, java methods).  We all have to make the decision constantly while programming of when and why to break certain logic into subroutines.  How do you do it?  Let us refer to the Linux Kernel Coding Style document, they have alot of important code with many maintainers, they should have a good idea:

This is more or less the rule I’ve adopted, hopefully you have something similar running through your brain.  Maybe this is controversial, maybe I should be happy stopping here so we can all get on the same page, but no, I’m going to push forward and assume we all agree with some version of this rule.

Different languages have different faculties for limiting scope and mutability, C has Blocks for Structured Programming, Java has Objects with private fields, C++ has ‘const’, etc.  Generally, why do languages have these features?  Because managing context and capabilities in code allows us to work with complex code efficiently by dividing our code into small chunks that are easy to reason about.  When we divide our program into subroutines we can do better by limiting their context and capabilities.  We do this by using loosely coupled Pure Functions.

(For those who don’t know what Pure Functions are, they are functions who given the same input arguments always return the same value no matter the calling context and they cause no side-effect.  Loosely coupled in this context means the subroutines should have the minimal set of information needed to make their calculations, also check out Information Hiding.)

For the purposes of our discussion we’ll say that functions that appear pure by contract are as good as pure.  We don’t care if you have side effects on an object that you created and no one else can see, we aren’t Haskell.

Enough abstract talking, lets bring this principle back to a real language, C#.  C# unlike Fortran or Nim doesn’t have explicit support for pure functions and private methods pass around all the state of the object.  How can we use this principle?  By building our methods from loosely coupled pure static functions:

CalcBar and CalcBaz are loosely coupled pure functions.  What have we gained by dividing our code this way?

  • The temporal coupling between CalcBar and CalcBaz is explicit at the call site in Start, this means Joe Programmer coming back into Start will be less likely to futz that up.
  • CalcBar and CalcBaz can be evaluated on their own merit, all the code and possible data required to understand the code is right between the curlies.
  • CalcBar and CalcBaz are easily and directly testable.  Maybe Foo.Start is difficult to test but there is no excuse not to test CalcBar and CalcBaz if you want to.

Right about now OOP heads are starting to get mad at me.  Cool down my babies, let me explain.  Objects as an abstraction are very stateful, they have public methods with void return types.  If you are working with OOP that’s just how things are done.  I’m not suggesting you write all your code functionally and ditch OOP.  Keep building objects’ public interfaces however you were doing it.  I’m merely suggesting you build those public methods on solid functional footing by dividing them into collections of loosely coupled pure functions.

Now I understand that depending on your situation pure functions might be hard to swing, like I said earlier apparent pure functions are just as good, and loosely coupled functions are better than methods.  You just have to choose the most limiting construct for your subroutine.

If you haven’t read Andrew Hunt’s “The Pragmatic Programmer” I highly recommend it.  It boils down to a list of tips for programming that are useful no matter what tools you are programming with (here is the list tips).  I’m now going to list all of his tips that are apropos to programming with loosely coupled pure functions:

  • DRY—Don’t Repeat Yourself – when you divide your code into loosely coupled pure functions you remove required context which makes your code more reusable
  • Eliminate Effects Between Unrelated Things – this one should be pretty apparent, pure functions are orthogonal by definition
  • Always Design for Concurrency – pure functions factor out state change which makes them easier to reason about in threaded code since they can’t have race conditions
  • Design to Test – public pure functions are easier to test, all you have to do is call them with their input and check the output

If you are already using a functional language, chances are you blew off this article paragraphs ago, but according to TIOBE you probably aren’t.  I honestly think this is the one easiest thing people can start doing to make their code easier to maintain, easier to write, and less buggy.

Automatic F# Compilation in Unity

I was playing around with F# and Unity integration and there are some nice examples out there  but they all relied on compilation systems outside of Unity, build some .dll in Xamarin then drop it into a Unity project.  Cool, but it’s not usable if we don’t hook into Unity’s build system and get a fresh build every time we edit a .fs file.  So, I decided to explore doing just that with UnityEditor.AssetPostprocessor.  When you implement a AssetPostprocessor you get called with a message every time you reimport an Asset.  This happens when the file gets touched on disk.  So what we can do with AssetPostprocessor is recompile a .dll full of F# code whenever a dependent F# file is edited.

Here is example code of that method:

In order to actually use this you’ll need to build a target in MonoDevelop for a .dll that will contain this AssetPostprocessor.  Put that .dll in your project’s Assets.  You’ll also have to make sure that your Unity project has FSharp.Core.dll as an Asset if you want to use your F# code.  I had luck using version 2.3.0.  You can check the version with “monodis –assembly <path to dll>”.  The build rule will have to be made a bit more robust if you wanted to compile something with a more complex dependency tree of course.  If you need help making MonoBehaviours in F#, this will help.

Sorry I didn’t didn’t post this on Github.  There is a considerable amount of work to make this idea handle most cases.  It served my purpose as is, maybe I’ll package it up later.