Israel
Marching in the streets.
Never thought I’d see the day –
Brown shirts.
Stop.
Listen.
Look.
Fight back!
Israel, Israel, we belong to you.
Israel, Israel –
To God Most High.
Stand and Fight!
The other day when I was scrolling LinkedIn, I found a post arguing that exceptions are not the best way to handle errors. Most languages don’t force you to handle or re-throw exceptions at each level of the call stack, which means that it can be difficult to track down the source of a given exception when it bubbles up to the top level. In addition, exceptions should only ever be used to address situations that are, well, exceptional, and not situations that can easily be anticipated – say, a record not being found in a database.
Error Statuses in JSON Data
I’ll share the solution that was suggested in the post momentarily, but first, I’d like to share an old solution from the days before I knew much about the REST maturity model. In those days, an “Ajax” request was just a POST with a uniform JSON response. Since it hadn’t occurred to me to use HTTP response codes, I needed to indicate success and error statuses in my JSON, so my responses usually ended up looking something like this for a “failure”:
{ error: "User not found" }
And something like this for a “success”:
{ result: { name: "Bob", password: "oops, we shouldn't be sending this to the front end!" } }
In other words, successful calls populated the “result” field, and unsuccessful calls populated the “error” field. It was easy enough to check for the existence of an “error” or “result” on the front end, and proceed accordingly.
Returning a Result Object
The aforementioned LinkedIn post inspired me with an idea: if an API endpoint can return this type of response, why can’t a function? Couldn’t we have our functions return an object, like this:
type Error = object
message: string
# The Nim language uses the [T] syntax for generics
type Result[T] = object
value: ref T
error: ref Error
# A Nim 'proc' is just a function, and the equals sign
# at the end of this line works like '=>' in other languages.
proc isSuccess[T] (this: Result[T]): bool =
this.error == nil and this.value != nil
proc isFailure[T] (this: Result[T]): bool =
not this.isSuccess
proc failure[T] (error: Error): Result[T] =
result.error = new Error
result.error[] = error
proc success[T] (value: T): Result[T] =
result.value = new T
result.value[] = value
… instead of throwing an exception? Then we could check the results, like this:
proc getUsernameFails (_: int): Result[string] =
result = failure[string](Error(message: "User not found."))
proc getUsernameSucceeds (_: int): Result[string] =
result = success[string](Error(message: "User not found."))
var usernameResult = getUserNameFails(999)
# [] is Nim's dereference operatorif usernameResult.isSuccess: echo usernameResult.value[]
else: echo usernameResult.error[]
usernameResult = getUserNameSucceeds(999)
if usernameResult.isSuccess: echo usernameResult.value[]
else: echo usernameResult.error[]
Of course, maybe you’ve already noticed the potential issue with this approach. Accessing the error
field of a Success result, or the value
field of a Failure result, without first checking for isSuccess or isFailure, will result in a null pointer exception (hardly ideal, considering the point of this exercise is to do away with exceptions!), or worse, a buffer overflow.
Discriminated Unions
Instead of a Regular old, Unassuming Result Objects (RUh-ROh’s…), the suggestion on LinkedIn involved a Union of two types. One type contains a value
field, and the other contains an error
field. The Union can exist in either a Success or a Failure state, and, depending on which state it’s in, it will contain one or the other field.
The Nim language accomplishes something similar by allowing you to use a case statement within an object declaration, to determine what fields the object should have. Think of it as syntatic sugar for the abstract factory pattern:
type ResultKind = enum
Success,
Failure
type Result[T] = object
# Nim infers from this case statement that a Result object has a
# ResultKind enum field, called 'kind' case kind: ResultKind:
of Success:
# a Result object will only have this field when its kind field is set to ResultKind.Success
value: T
of Failure:
# a Result object will only have this field when its kind field is set to ResultKind.Failure
error: Error
Then, a function can indicate success or failure by returning one or the other variation of the Result object:
proc getUserById(id: int): Result[int] =
if database.getUser(id) == nil:
result.kind = Failure
result.error = Error(message: "User not found")
else:
result.kind = Success
result.value = user.id
However, there’s an issue with this approach, as well. It’s true that you’re no longer dealing with null pointer access when you try to inspect the value
field of a Failure object, or the error
field of a Success object. But the determination as to which fields of a given Result object are currently available can only be made at run-time; so, when the user tries to access a non-existent field, it throws an exception.
And so we’re back where we started.
Multiple Return Values
What we really want is a way to force the user to check the success status of a function call before trying to use the result. Go and React both come really close, by returning multiple values (Go), or an array (React). In Go, you do something like this:
error, result := myLib.DoAThing()
if !error {
doSomethingWith(result)
}
While in React, you do something like this:
let [error, result] = doAThing()
if (error) console.log(error)
else doSomethingWith(result)
In Nim or Python, you can accomplish the same result using a tuple:
let (error, result) = doAThing()
if not error: doSomethingWith(result)
else: echo error
(Okay, so my example only works in Nim. But why would you use Python anymore, when you can get the same expressiveness from a language that also allows you to write compilers and OS kernels, and that also cross-compiles, at your option, to Javascript?)
A common complaint I see with this approach, especially in Go, where it is used most often, is that now you have to do an if !error check for nearly every line of code you write, which is tedious and ugly. To be fair, the LinkedIn solution – using discriminated unions – has the same issue.
… and that’s when I realized why Nim’s readLine
function works the way it does. And was reminded of a best practice my dad (- another programmer -) told me about from back in the days before C++ and Java had unseated C as the only reasonable choice for Serious Programmers –
The Result Argument.
Nowadays, most languages default to pass-by-value arguments, like this:
let manipulateString = (str) => {
str = str.toUpperCase()
}
let myString = "hello"
manipulateString(myString)
console.log(myString) // "hello"
You can try this in your browser’s developer tools. myString
will remain unchanged, because the str
argument contains a copy of the original value. Nim functions (known as “procs” – since Nim is a procedural language) work in a very similar way:
proc maniuplateString (str: string) =
str = str.toUpperAscii() # does not compile - str is an immutable copy
let myString = "hello"
manipulateString(myString)
echo myString # hello
You can give manipulateString the power to modify str, however, by turning it into a mutable reference, using the var keyword:
proc maniuplateString (str: var string) =
str = str.toUpperAscii()
var myString = "hello"
manipulateString(myString)
echo myString # HELLO
The ability to pass by reference means that we can store the result of a successful function call in its last argument, and use the function’s return value to indicate success or failure, like this:
proc getUserName (id: int, username: var string): bool =
let user = database.getUserById(id)
if user == nil:
return false
else:
username = user.username
return true
var username # = ""
if not getUserName(999, username):
return false # pass along the failure status
echo username
Nim auto-initializes all declared variables to sensible defaults; it also does not allow users to ignore a function’s return value – you have to explicitly discard it, with the self-documenting discard keyword:
var username
discard getUserName(999, username)
echo username # ""
This forces you to think about what you want to do with the true/false value returned by getUserName
, and it forces you to think about what – if anything – is being stored in the username variable. If you absolutely refuse to think, and getUserName can’t get the username from the database, then we fall back on an empty string, which follows the principle of least surprise.
The real power of this convention manifests in a loop:
var input = ""
while stdin.readLine(input):
doSomethingWith(input)
Your function can even use an enum value, to indicate exactly what went wrong:
type errno = enum
# "errno" is a callback to that old best practice from C
Success,
InvalidUserId,
UserNotFound,
KeyCollision
proc getUserName(id: int, username: var string): errno =
if id < 0: return InvalidUserId
# ... etc. ...
I’m not sure how I feel about this way of doing things as opposed to exceptions. And I wish Nim had something like C++’ & operator to more clearly signal to the reader when we are and are not passing by reference. But I think I will try this way out for awhile in my side projects, and see how it holds up.
The world is really simple – and that makes everything complicated. Lots and lots – billions – of simple pieces – very simple pieces – all moving around and interacting at the same time. It’s very complicated.
I hate playing chess. I used to think I was smart, but then I realized how simple chess was, and how bad I was at it. I want chess to be something that smart people can just be good at – but it’s a skill, like everything else – so I’m not good at it, which means I’m not a smart as I thought I was, because I can’t just pick it up, look at it, and figure it out. So I hate it.
Everything is like that. The things that were made by smart people, for smart people, usually end up getting mastered – and taken over – by stupid people who want the benefits of playing the same closed games we smart people invented in order to keep them out. And then it isn’t fun anymore, because before long, the stupid people get to be smarter than the smart people, and we have to find something else to do.
It’s like the rubiks cube. I tried to figure out how to figure out how to solve it – without algorithms. I don’t want to memorize a set of steps, I want to see how smart I am. But after I solved it a few times, I started to realize that there are certain sets of steps you can follow that work every time… and then it got boring, because all I was doing, at that point, was memorizing a set of steps.
Everything eventually becomes a science – which means that the more magic you practice, the less magic there is in the universe. At some point, all the magic in the universe will just become science and then life won’t be worth living anymore.
If you really want to be special you have to invent something. A religion, a martial art, a bit of software. A book. To be the first one – but, even then, it’s not guaranteed. Even if you’re the first one, someone else with no talent can come along and sell your thing and take all the credit.
You also have to be careful not to fall into the trap of mass producing other people’s inventions for money – artists end up drawing the same pictures, again and again – software developers inevitably find themselves “specializing” in writing and rewriting the same application, again and again, in different languages and for different companies. At some point, you stop inventing altogether and become a full time salesman – someone with no talent selling other people’s ideas and taking all the credit. But if it puts food on my children’s plates…. ?
Here’s another thing that happens when you are a creator. An idea gets into your head, and it won’t go away. Most of the time you can drink another cup of coffee, or hit the weights again, or watch another YouTube video, or go for another walk, or smoke another cigarette, or… and then, after all that, if the idea still won’t go away, so that you can sit down and get busy doing whatever it is you’re really supposed to be doing, for whoever is paying you to do it, what then?
If I have to write one more paragraph about the election, or one more RESTful CRUD service… draw one more couple holding hands in front of a sunset on the beach… or stand in this horse stance for one more minute…
I had a melt-down last night. They’ve been happening more and more frequently.
Maybe I should stop drinking so much coffee.
Imagine a world where there was a group of people who decided which ideas were “correct,” and made an example out of anyone who expressed dissent.
Imagine a world where people were not permitted to organize around a shared set of spiritual beliefs, or to share those beliefs with others.
Imagine a world where you had to surrender yourself as a slave to those who had access to the goods and services necessary for your survival, instead of engaging with them in an equitable, voluntary system of exchange.
Imagine a world where, once you had spent your time – which is your life – to earn money, that money and the things you bought with it could be taken away from you by people who you had no say in appointing.
Imagine living in a world where others could determine your status as a person, based on arbitrary criteria designed specifically to exclude you.
Being American means being willing to give your life to prevent that from happening.
And being against Israel means support for those who are willing to kill and die to ensure it happens to the Jewish people.
Even the mind has limits. But as soon as I mention “limitlessness,” I create a referent to what is just outside my reach. I capture the unquantifiable inside Christmas wrapping paper. Shake it, feel the packaging with my fingertips. Give myself something to talk about.
The mind isn’t “limitless,” but the mind can contain it; that’s the authority of words.
Today I’m experiencing a sensation I haven’t felt in years. Pain has a way of sweeping a whole rainbow of emotions through you in a single moment. Like trying to remember who it was that enjoyed that song the first time you heard it, or finding that old hoodie at the back of your closet.
What kinds of things do you do to silence your unease? You know it’s going to catch up to you, but you just need a few more minutes. A few more hours. You’re in traffic – much too busy to deal with anything that could rock your world.
It’s time to start a silence habit.
Sensory Deprivation Chamber – 21st century, we call it, “recreation.” A luxury. 1000 years ago, it was a form of torture. Few minds could survive it.
“I will strike you with madness, blindness, and confusion” (Deut. 28:28).
I go for a run, or listen to music. I have a life to live – bills to pay. No time to notice the time I don’t have to notice. No time to realize that time was all I ever had.
“On the day you eat of it, you will surely die.” And I did – and I have been, ever since then.
But enough about me. How cold was it when you first came out that door? Morning joy hurting your eyes; the unceasing tide, blue skies? Living in and preparing for the future – when did it pass you by?
Now I’m hovering over the waves, wings spread. Serenity. Is it the moon, the endless, snow-peaked ranges, dotted with tall, ever-green cliches? Pores open, to let the wind pass through. If you were nothing, invisible, absorbed into nature, then you could continue to ignore all these questions… for just a little while longer.
I just added an object-oriented REST controller and Cypress end-to-end testing to my Node/Express side project. Check it out:
https://github.com/abraham-serafino/simple-security/blob/main/src/User/User.controller.ts
https://github.com/abraham-serafino/simple-security/blob/main/cypress/e2e/User.controller.cy.ts
I just figured out how to do filesystem routing like the kind supported by Nextjs, but for Nodejs API’s implemented in express. Check out the commit on my GitHub:
https://github.com/abraham-serafino/simple-security/compare/main…express-file-path-routing#diff-3b62bfb52c340d82485e1a1712ac89b98c5c8f55499990329997e0c692ac620d
I believe integration tests are the most valuable type of automated test. A linked list is usually part of a standard library, so that makes it a great example of a candidate for integration testing.
My guideline is, “one test per requirement.” For example, for a Linked List, I would probably start with one test for each of the following:
1) Can values be prepended, 2) inserted at a given index, and 3) appended?
4) Can values be removed without compromising the list’s integrity?
5) Can the list be traversed forward and (for doubly linked lists), 6) backward?
7) Are we preventing out-of-bounds access?
8) Any potential type safety requirement
9+) Each potential memory efficiency requirement
…) Each potential runtime requirement