Saturday 21 January 2017

On Programming and Pragmatism

You know when someone wants to invoke feelings of humility and humbleness they show you that graph. You know the one, it shows that Dinosaurs lived for ages in comparison to us and how we are merely an insignificant blip on our planet's mammoth (geddit!) timeline. Well we can see the software industry in a similar position to man in this example, being about sixty years old and fledgling in comparison to traditional engineering. Take the Institute of Civil Engineers in the UK, two centuries old, with established practices and a commitment to professional review, conduct, and a collective commitment to studying and analysing past works. Morality is a seperate topic, but just imagine if we as a community of engineers had reached the maturity whereby we saw each failure as a learning opportunity and seriously analysed case studies.

I have always found that there is comfort in tradition, I think that this partly explains a few bizzare ongoing phenomena and anachronisms such as constitutional monarchy. There is comfort in tracing an unbroken line back, and knowing that your ancestors encountered similar difficulties yet persevered. However this is a comfort that the software industry is visibly bereft of. Perhaps this goes some way to explaining our identity crisises, the continual rocking of the boat every few years when 'THE NEXT BIG THING'TM comes along and all those goddamn wood-working craftsman metaphors that everyone is so fond of. I think that it is a sign of industrial immaturity that a dogmatic view that the next big thing will solve all our problems is so alive and well. New technologies have pros and cons and are designed for certain use cases over others, we should be able to evaluate their merits level headedly.

There is that constant desire to seek that silver bullet, OOP, functional programming, test-driven development, agile methodologies, they all promise to cure all ills yet come with their own set of potential abuses and weaknesses. I read a Steve Yegge post where he compared a programmer's progression to that of a child. At first the bewildering exploration of the early years, then the overconfidence of adolesence, followed by the humility of adulthood, admitting that complexity and flaws exists and always will. I see the software industry as in those heady teenage years, still chasing absolute truths.

'I know that I know nothing' - Socrates

I think that some of the best programmers are the ones who realise their limitations and check overconfidence. They program defensively, realise the human brain will never be up to the task of perfectly modelling and building these complex systems, these castles in the sky, and don't try and solve that problem by weaving more layers of abstraction, UML and object hierarchies. They behave conservatively and understand the importance of testing and don't overreach.

Have you ever found some code and thought, this is crap, who wrote this? ... git blame, oh, me? This is evidence that we are constantly improving and as we do we realise that our formerselves were misguided in some way, this is an endless path, we do not one day become enlightened and get bestowed a halo and aura by Richard Stallman. It stands to reason that there are always flaws in our understanding, this realisation is one of the humbling and empowering truths of programmer adulthood. If we had limitless understanding tests would be redundant and refactoring rare.

As developers we like to imagine ourselves as omniscient and infallable and don't like putting our mistakes on show, we lean on git rebase. This fallacy is propagated by many solutions presented in blog posts or code samples that exclude the context of their genesis and teetering development. For code review, fine, but in general there is no point in fixing up your version control history so it looks like you are some zen programming god. Improvements come in increments, everything won't be solved in the 'BIG REWRITE'TM. I'm not sure if its a cultural thing, but there is this Japanese concept in japan of 'kaizen', continuous, iterative improvement, I think this a healthier philosophy, than I am going to fix everything in one highway to the danger zone themed montage.

We have to be pragmatic lest we become lost in the complexity of our work, software is hard and stable optimal solutions take time, good engineering and clean coding can help but we have to be careful not to overreach or become swept up in heady currents of new trends

Sunday 8 January 2017

On Golang and Exceptions

I have been programming professionally in Golang for a couple of years now and I have to say that I really like the language. My first experience of Golang was a bit of a drop in the deep end, coming into a new job where I would be using Golang as my main language with no real experience. Yet, despite this, it did not take very long before I became productive. I believe that this is partly due to the simplicity of golang and its density/ economy of language features.

Golang was designed to be a small, strict and opinionated language. The small size reduces the required learning time, strictness ensures users do not form harmful habits such as ignoring warnings or leaving unused variables lying around and its opionatedness puts an end to bikeshedding about things like brace placement. This is in contrast to a language such as C++, massive and sprawling and certainly intimidating to a newcomer. The size and complexity of C++ provides many places for the concealment of pitfalls. And an effective understanding of the quirks and gotchas of the lanugage is deservedly highly valued in the corporate world. The problem with giving you this much rope is that it is long enough to hang yourself many times over. Sure, it is powerful but it is shows little respect for your sanity if you are not well directed in your work. Golang also tries to avoid introducing magic where possible. By magic I mean, a feature that hides a sufficient amount of complexity so as to appear 'magic' to the uninformed.

'Any sufficiently advanced technology is indistinguishable from magic' - Arthur C Clarke

One of the magical language features that got the chop in Golang is exceptions. Recently, when doing some work in Python I noticed that I didn't really miss exceptions, they complicated the control flow a lot and caused me much fear and consternation. This is because exceptions are magic, they can cause unexpected jumps in your code based on non-local conditions and inject complexity. They are another thing that you constantly have to think about when writing code. I find that multiple return values, available in both Python and Golang, is a much more intuitive and useful feature that largely subverts the need for exceptions.

'But it doesn't even have exceptions' - reaction of an old workmate when I told him I was now working in Golang.

I see how exceptions can be useful in standardising error reporting, which is great. We've all had to deal with a function with obscure error reporting, that say returns an int value, and we end up asking, does 0 denote an error, what do negative values mean? etc. However Golang also standardises this by providing the error type and interface providing a standard with room for extensibility.

I understand that not allowing exceptions complicates the success case code as often 'if err != nil {...)' is liberally applied. However one really needs to consider if these minor gripes are worth adding extra complexity to the language and burdening the programmer with as an extra concern.