Issue #10

It’s February! Sorry month’s newsletter this is a little later than normal.

Love is in the air (well for some of us anyway) and spring is on its way! Here’s hoping the weather improves soon!

If this newsletter has been forwarded to you and you like what you see and you’d like to see more please subscribe at https://impractical-engineer.beehiiv.com/subscribe. It’s free and it’s very simple to unsubscribe should you decide it’s not for you. And if you subscribe please drop me a note. I always love to talk to other software developers!

Reviews Dept.

A Review Of:

Brian Beckman: Don’t Fear The Monad

This is a video that was originally created for Microsoft’s training/video channel, Channel 9. It’s not exactly brand new (in fact it was created back in 2012) but there is nothing in this video that has aged at all. In fact I’ve bookmarked it on YouTube and I’ve rewatched it probably 7 or 8 times and each time I learn a bit more from it.

Back in the halcyon days of 2012 it looked as if functional programming was poised to take over the world of software development. Of course things look a bit different now but the ideas he covers in this video are still just as relevant. And it’s worthwhile to recall that there’s a difference between a concept and the implementation of a concept. For example the concept of data hiding long precedes the private keyword in C++/Java/C#. Data hiding is the concept and the private keyword is the implementation. There are other ways that data can be hidden—different implementations of the same idea.

This is worth bearing in mind because as Dr. Beckman points out all of the notions of a Monad while generally associated with functional programming can be implemented equally well in an imperative language. In fact his discussion often touches on Linq and the fact that Linq is, in fact, monadic.

So why should you Joe or Jane Developer bother to watch this video—especially if you have no interest in learning what monads are? You should watch it because the ideas he discusses are essential to tackling the central issue of software development—controlling complexity. One reason I am such a fan of functional programming is the fact that it emphasizes composing sets of small functions into a larger whole to accomplish a given purpose. Testing several small functions that have very well defined purposes is a heck of a lot easier than testing one large function that does 12 different things.

A word of warning—this video does introduce some category theory. Not a lot and not anything rigorous but it is there. I have found that it often happens (in many disciplines) that what sounds quite fancy is, in fact, pretty obvious and no big deal once someone who understands it explains it to you. For example, in this video he covers what he calls a “unit function”. In plain English a unit function is simply a function that returns whatever argument is given to it. If you recall your high school algebra a unit function is effectively x(y) = y. Unit function sounds quite daunting (or maybe it only sounds daunting to me) but it’s really pretty simple. Many of the things he discusses sound very daunting but they’re really very straightforward once you understand them.

Dr. Beckman does a very good job of explaining step by step how we get from the idea of functions to monoids (which are certain subsets of “things”) to monads.

4 out of 5 Stars

Puzzle Dept.

Solution For January’s Puzzle:

Consider the following chords on a circle:

As you can see, in drawing 1 I have chord from a to b. Then in drawing 2 I add a chord from c to d. Now in drawing 3, add a line connecting e and f without crossing ab and cd.

You’ll note that at no point do I say that the line connecting e and f has to be a chord. That is, it does not have to be inside of the circle. So the answer (at least the one I came up with) is draw a line around the circumference from e to f.

Solution To January Puzzle

This is another one of those puzzles in the classic nine dots puzzle tradition where it’s only hard if we add an implied (but not stated) constraint. If other folks came up with other solutions I would be happy to hear about them!

February’s Puzzle:

What is the significance of this set of numbers:

-2100, -900, -522, -19, 1025

Since this is a bit harder puzzle than I have customarily shared, here’s some clues to help:

1.) The negative numbers are not numbers we usually think of as negative.

2.) All the numbers are heroic.

Learn Software Engineering Dept.

Dealing With Errors

One thing that this new and magical AI coding paradigm will not do for us--it won't figure out how to deal with errors in a graceful way. No AI in the world is smart enough to tell us whether or not we should

a.) Throw an exception

b.) Return a known-to-be-bad value

c.) Do nothing and carry on because the error isn't going to stop things from working

But we as developers need to determine how to best deal with these things. So let's talk a bit about them and maybe we can find some helpful thoughts from the conversation.

Since it's hard for me to discuss a topic intelligently as a total abstraction let's consider something unlikely to actually come up in practice and how we'd handle it. Pretend we're building a calculation and in the calculation we need to return the dividend of two integers as an integer. For example I need to return 8 divided by 3 and since it doesn't divide evenly I need to return the whole part of the answer--2 in this case.

Of course no one will ever call our code with a 0 divisor but let's just pretend that's something that may happen and ask ourselves--how should we deal with it?

Throw An Exception

For a lot of languages this has become the de facto error handling mechanism. I personally think this particular way of dealing with errors is not our best approach but I can understand why it's popular.

Let's consider our "divide by 0" error case. There are a few ways we could proceed.

1.) We can check our divisor; if it's 0 then throw an exception to tell the calling code that the divisor cannot be 0.

2.) We can try to perform the calculation and check for an exception getting thrown by the library. When we see the exception we catch it ourselves and decide what to do from there. But if we "swallow" the exception how do we return a value?

The problem with both of these approaches (at least to my mind) is that they assume developer discipline. Don't misunderstand--developers are usually a very persnickety bunch of human beings (and I mean that in the best possible way--I'm a bit of a stickler for details myself). But we get under deadlines and all our persnickety personality is jettisoned in the name of meeting a deadline. People who should certainly know better will suddenly forget to add code to test for an exception getting thrown--not because they're not aware but because they have someone asking them why the job they (the developer) estimated for three days of work isn't done 20 minutes after they were asked to estimate it.

So, in sum, nothing wrong with throwing exceptions--we (developers and those who work with developers) need to find ways to ensure exceptions are dealt with--if possible at compile time. Because if they aren't taken care of until run time--well this where those 2 AM "Holy Mother of God, the entire system is down! FIX IT NOW!" phone calls that make developers old before their time--this is how they arise.

Return A Known-To-Be-Bad Value

This is a good practice when it can be employed. Of course it too like "Throw An Exception" relies on developer discipline and that can be a dangerous thing to rely on. But let's talk about what this means.

In untyped languages (think LISP family languages or batch files) any value that's returned is potentially right and we need to designate a "known-to-be-bad" value. In our division example if we set up a constant--like say "-1" as the known-to-be-bad value then when someone hands us a zero we hand back the -1 and the calling code should now know that something's wrong. I can practically hear the gears turning in the heads of experienced developers. "What if I call your division function with 1 and -1? Then -1 is the right answer!" And they'd be 100% correct. This is problematic.

So we say "Hmm. I know let's say that the values passed must be natural (greater than zero) numbers!" That's accomplishing two purposes with one fix. I can't get -1 from dividing two positive numbers and if my numbers have to be greater than 0 then I'll never have to worry about a zero divisor!

The problem is that working code will need to change. In fact the better it's working the more likely it is to have to change. Think on that one for a second. I've delivered some awesome software--the business is thriving and everyone is happily contemplating the beauty of nature. But gosh if you could just have the software do this one more tiny thing--wow it'd be icing on the cake! In fact one sign that people are using your software is requests to change it. If no one asks for changes then no one is using your software!

So inevitably you'll have to change things to allow for all integers (not just natural numbers) and if you forget that you've set aside -1 as an error indicator then you will run into a situation where -1 is the right answer.

Some folks seem to wonder where null came from in software development. The answers pretty simple if you think about it. Using any value that might come up in a set of data (for example -1 in division of integers) will inevitably lead to problems because eventually the code will be changed and what was previously not allowed will have to be allowed. But null by its very nature is not part of any set of data so it's always ok to use. For instance, find a substring in a string: if I use " " to indicate an error eventually someone's going to ask me to find a space. But if I use null--well by definition I can't find null in a string so it's future-proofed. All that has to happen is the developers calling the code need to check for null and I'm good.

By show of hands how many people reading this modest essay have ever had an unhandled null exception thrown in their code? Wow--I can't even count all the hands. And, again, these errors don't arise because developers aren't being careful enough (although some of us are pretty careless); they arise because people get rushed and also because sometimes it's not the code we're calling directly but code that the called code is calling that throws the null. Wow, I just wrote that sentence and it's a bit confusing--so let's say this: I have function a which calls b and b calls c and c calls d. Down in the bowels of d (which I can't even see becuase it's in a library) it gets a null and throws out an exception. Since b and c aren't coded to handle the exception I see it up in a.

Again as with the "Throw An Exception" discussion above any technique that relies on programmer discipline will fail. Maybe not today and maybe not tomorrow but it will fail. So the better answer is to build our defensive code right into the library.

How? Let's say instead of trying to return a known-to-be-bad value we instead wrap the return value inside a container. The container can either have the value or it can have "nothing". Now our calling code has built right into it that it needs to unwrap the returned value. Some of you may recognize the maybe monad (in essence that's what this is) but we can do this in other ways too. If I make my return an object then I can add a class member like "IsValidValue" which the calling code can check before I use it. In some languages it's common to return a tuple; the first element is a signifier--"is this returned value good or not?" and if it is good then the second element contains the actual value. This allows me to use any value as the known-to-be-bad value without worrying about it accidentally being a good value because of changes to the code.

Do Nothing And Carry On

Since this is often the default way of treating errors (because most developers don’t bother to think about all of the possible errors) there’s not a lot to be said here. I do think it is worthwhile to mention that it may be better to let certain errors simply shutdown the system anyway. I mean if you need a certain file to be present and can’t proceed without it (for example, a csv file of transactions) then reporting that you can’t find the file isn’t really a lot of help. So log the error and shutdown gracefully and let the user tell you that the system shutdown.

Humor (We Hope) Dept.

Dating Tips For Nerds

Yes we know it’s an unfair stereotype that nerds are bad at relating to the opposite sex. But it’s not entirely untrue. So in the interests of helping our brothers and sisters who would love to make their best impression on a potential paramour here are some tips on dating:

1.) Do compliment their outfit. Do not compare their outfit to a fractal no matter how much the pattern may resemble one.

2.) Do ask about them. Do not inquire about their favorite bug tracking software (although if it comes up somehow and they mention JIRA, find a way to end the date immediately).

3.) Do ask if they have a pet. Do not ask if they’re aware of the hygenic issues associated with owning an animal.

4.) Do relate amusing anecdotes. Do not relate amusing debugging stories; there are no amusing debugging stories.

5.) Do not ask them about their favorite anime/favorite card in Magic The Gathering/favorite Monty Python sketch (depending on the age of your potential paramour).

6.) Do not spend time pointing out to them how unrealistic the science of Avatar was.

7.) Never ask them “Who would win in a battle between Wolverine and Batman?”

Feedback Dept.

If you’d care to share:

  • feedback

  • suggestions

  • events

  • questions

or anything else, please contact me, Onorio Catenacci, editor of the Impractical Engineer at my email.

If this newsletter has been forwarded to you and you like what you see and you’d like to see more please subscribe at https://impractical-engineer.beehiiv.com/subscribe. It’s free and it’s very simple to unsubscribe should you decide it’s not for you.

And if you’re a subscriber and you’d like to do a small favor for the editor, please share this with your developer friends!

Keep Reading