, 20 tweets, 3 min read
My Authors
Read all threads
TDD Pro-Tip: I suspect sentinel returns, and though I still use them, it's generally because I haven't found the right formulation yet.
I'm working on the TSD project today, and I've got a nasty little chunk of code I wish weren't nasty.

(It's in this file, and of course, you're welcome to grab the whole repo, which will enable you to *really* make fun of me.

github.com/GeePawHill/tsd… )
You don't have to look at the code, I'm not going into it, but as I glance at it, I notice there's an awful lot of sentinel returns.
A sentinel return is a place where you call a function, and it gives you an answer of some type X, unless there's a problem, in which case you *still* give me an answer of some type X, but the answer isn't *the* answer, it's an object of type X that means "no love here".
Most sentinel returns involve looking for things, again, of type X. If the thing is found, return it. If it's not found, return a borked instance of type X. The grandaddy of all sentinels is the bog-standard "tell me the position of this character in that string".
If you find that character, return its index. If you don't find that character, return -1.

-1 is not a valid position. It's never a valid position (in most programming languages). It's a *sentinel*. It's telling you "there is no answer".
Now, there are no bad dogs. Sentinel returns aren't inherently evil: there are two reasons why they're ubiquitous down there at the bottom of your stack, a cut or two above the metal.
First, for performance. Sentinels combine two answers in one, which can be more efficient than asking two questions.

Second, for full control. By providing those two answers, we provide maximum info for the coder to decide what does and doesn't matter.
But every sentinel return in your code is a guaranteed explicit branching construct in that code. In the string find case, for instance, you can never use the answer blindly. You *have* to branch around the possibility of the sentinel saying "no love here".
I don't desire explicit branches. They make me think, and mama dint raise no thinkers. When I *can* find a way around them, I do.
The trick, as with most coding constructs one's unhappy with, is to see if you can wrap it so that it works in your context but so the branch is effectively hidden from view almost immediately, level-wise.
That is the immediate caller of the sentinel return has the branch, but its callers in turn, don't branch explicitly at all.
A simple case of this: in kotlin maps there's a .getOrDefault(key,default) method. It gets the value associated with the key, or it returns a default answer if there's no value already associated. Internally, it branches, but externally, none the wiser.
(There's also .getOrElse(key) { lambda }, where the lambda can do cool things like go ahead and put the key in the map if its the first de-reference, useful when you're using the map to increment key counts.)
Another case: a method that's supposed to find things and return them, in a naive implementation might return the thing or a null. But you could also make it return a list. If the thing isn't found, the list is empty. This lets callers iterate blindly, hiding/killing the branch.
Another case that's easy to write in kotlin, a findAnd(target) { lamda } that executes the lambda iff target is found.
The thing you notice when you do these sorts of things: the question in the coder's mind changes from "what do I want to know?" to "why do I want to know it?" You can't choose one of these mechanisms w/o a context to suggest which one works best.
Anyway, I'm looking at this ugly code, and there's several things I don't like about it, but nearly all of them are the operational result of code-tweaking to go green-to-green test-wise. At the time I wrote the sentinel-return stuff, I just didn't have enough context.
Now, though, my test set is as complete as I can make it. The current algorithm, branching all over hell's half-acre, will hopefully give me the context I need to come up with a simpler and more expressive way to do this w/o all those sentinel returns.
(BTW, the TSD is the subject of the first Real Programming video season, so if I do bring this bad boy under control, you'll be able to see & hear how I managed it. The series launch is planned for December!)
Missing some Tweet in this thread? You can try to force a refresh.

Enjoying this thread?

Keep Current with GeePaw Hill

Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!