Okay, let's talk about a nice illustration of resisting primitive obsession. Gotta break this writing drought. I'mo freestyle this muse, and I'm rusty, so bear with me.
Before we start. I want you to know how important it is to me that we keep working on change outside the monitor. Please know how proud I am of *every* *little* *thing* you do to help address this world's equity problems. Every little thing helps. Keep it up.

Black Lives Matter.
So, a few months back, my Friday night geek group -- we meet on Tuesday's -- spent a lot of time and had a lot of fun generating random dungeon maps based on the idea of a grid of tiles, each representing a floor, or a wall, or a door, or what-have-you.
Our mission was to make "interesting" maps, and we left "interesting" as an exercise for the coder. We had a blast showing off our stuff, arguing about definitions, playing with code. It's a *terrific* source problem, cuz there's no right answer, just lots of cool puzzles.
In a system like this, where we're messing endlessly with these grids, the absolutely most natural thing in the world is to think of a literal 2-dimensional array of cells, and to address that array by simple 2-integer pairs, the traditional x and y.
Now, recall, we're randomly generating these dungeon maps, so there's lots and lots of inspection going on as it forms. You have to keep things from overlapping, you have to decide where hallways go, where doors go, so and so forth.
And so you write all these functions, and they each typically all have the same first two arguments, an 'x' and a 'y'. (Or a 'row' and a 'column', but never ever mix those two ideas in the same environment or you'll just absolutely hate yourself.)
And two patterns quickly emerge. 1) You're constantly wanting to know what's next-door from cell[x,y] in direction d. 2) You're constantly writing code that switches on direction, N, S, E, W, and does little tweaks to input values x and y. I mean, *constantly*, both things.
So these values, x and y, and also d, are primitives. You might dress up d with your languages way of enumerating constants, but still, they're primitives.
And working this way creates three problems. 1) It makes you duplicate the little coord-tweaking stuff. 2) It adds *tons* of signal-hiding noise. 3) It forces you to test coordinate-logic when you wanted to be testing "dungeon creation logic".
So now I have four ideas for you to ponder. An opening thought, about listening to your own sullen resentment. Two alternative ways to handle this. And a final consideration of how you might decide to use one alternative or the other, or mix them somehow.
Sullen resentment: Everyone who tries this will, a certain number of times, add or subtract 1 from either the right or the wrong values of x and y based on d. But the reaction to this for a noob or even some intermediate programmers is different than it is to a bitter old geek.
You see, a noob is liable to take the feeling they get when this happens and *accept* it. "Oh well, just part of my miserable job in my miserable life, fixing this same stupid mistake over and over all day long. That's why they pay me. Gotta do the time."
But the bitter old geek? She says -- lean in with me here, you need to say this in your strongest midwestern accent to get the right feel -- "THIS IS BOOLSHIT, MAYAANN."
If you're a junior geek, or even a moderately intermediate one, you need to *respect* that feeling of sullen resentment. It's Mother Silicon's way of telling you there's something wrong, something you can do something about.
You know how I'm always saying "The code works for you, you don't work for the code"? This is what I'm talking about. The old hardened geek listens to sullen resentment and says we gotta do something about this.
Thing one to do: De-primitive those damned coordinate pairs. Make a class, I call mine Coordinates. Start by just making all those parameter lists take a Coordinates instead of a pair of integers. Put the two integers in the class, and get them from the class when you need 'em.
And you snarkily ask me what good will that do? (Oh yeah, I know you.) Here's the thing. Now that I have a Coordinates object, I can teach it how to do stuff having to do with Coordinate calculations.
Wanna look at the North neighbor of Coordinates c? Say grid[c.north()]. Ho ho hooooo. And south, and east, and west. Wanna see what's 5 cells north? How about grid[c.north(5)]? Uh-huh. That's what I'm talkin' about.
Wanna know the distance between two coords? c.distanceTo(d) will do it. And the list of these utility operations just goes on and on, area calcs, line extensions, even right-angle plotting.

Now, what do you get from all this?
You get to test it without testing your stupidly complicated dungeon-generation logic, for one thing. You get take 100% of your +1's and your -1's and put them behind the wall of a simple well-understood well-tested function AND NEVER MAKE THOSE MISTAKES AGAIN.
Want to check all four neighbors in a loop? c.orthogonals() will give you an iterable. Want all *eight* directions? c.neighbors() sounds right. Because none of this has to do with dungeon generation logic. All of it has to do with how coordinates work.
Client code gets simpler, bugs get fewer, noise goes down, and at the end of the day it took you something like half-an-hour to do all this.
Thing Two To Do: And this heads in a different direction, we'll talk about that to close the muse. Instead of putting that behavior on Coords, you can put it on a full-scale Direction class instead of that stupid constant int you've been passing around.
north.next(coords) gives the coords of the next cell north, and so on. Now, at first blush, this may not seem quite the same or quite as cool, but it is. It's 1) killing primitive obsession, and 2) creating a Strategy class.
You know all those places where you're switching on direction to decide what orientation of door or wall to put on the screen? Instead of switching over and over around an int, make the code ask the Direction what kind of door/wall it should render.
Your client code, you'll discover over time, can become entirely direction-agnostic. It doesn't care what direction you give it, it just tells that particular direction what it wants.
Instead of conceiving Direction as a simple enum, we're now conceiving of it as a bundle of little strategies for handling various routine operations in your code.
Nearly everywhere in the code that you're switching on Direction to guide your algorithm, you can use *one* algorithm and just let Direction handle steps 3a and 5c *for* you.
And once again, client code gets simpler, bugs get fewer, and noise goes down, and it really didn't take very long to do.
So. The final part: if you're on your game today, you'll notice that conceiving of Direction this way and conceiving of Coordinates this way actually creates a tension. I explicitly defined Coords.north and I also defined Direction.next() and they do the same thing.
Which one is "right"? Which one is "best"? Is there some scheme where we can do both?
Here's the thing. Neither answer is best or right. There probably *is* some scheme where we do both, or where the lines between them become crystal clear to you.

It absolutely depends on your actual context for having invented such ideas in the first place.
Coordinates and Direction aren't some exercise in determining the Forms in the Platonic Paradise.

That is not our game, here, that's not what geekery is.

We work for a living. The game is to do the work as effectively as we can.

Ya wanna know how to decide? Lemme tell you.
The way to decide whether to go with the Coordinates approach or the Direction approach or a clever mixture of both is this:

Try one, and listen to your sullen resentment meter.
Thanks for reading. If you like it, gimme love this way:

1) Subscribe. Free, spam-free, includes full-text/audio.

geepawhill.org/subscribe

2) Embrace change, not just in the code, but in yourself and the world.

We can change this, we're all that can.

Black Lives Matter.

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with GeePaw Hill

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!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @GeePawHill

22 Sep
The remote conference scene has been a mixed blessing, but I have to say, it's been truly *mixed*, and there have been some great things about it.
I did a conference this year, and for the first time in 20 years of conferencing, I watched every single session. Because I could fidget, smoke, shake my head when I disagreed, stretch, make noises, go pee, and most of all not be exhausted from too much social interaction.
And, in general, I've been to more events in the past 18 months than I was ever able to manage in the past.
Read 6 tweets
21 Sep
My favorite take/spin on the blind men and the elephant is this stunning take from Peter Vaill. It's nearly a page of text, so I'll gist it here, but spell it out below.

gist.github.com/GeePawHill/9fa…
"The relationality of all experience contains challenges to our understanding of organizations that we have barely begun to come to terms with. I can illustrate this by extending the metaphor of the blind men and the elephant."
"In its conventional telling, each blind man had a grip on a different part of the beast, and they were unable to agree on what it was really, really like, that is, as one of Kuhn's 'fixed and neutral
experiences.'"
Read 13 tweets
20 Sep
Left my phone at the restaurant last night, will pick it up soon. This is always a great social discomfort, because my phone is in horrifying condition.

They will tease me mercilessly.
It is cracked in several places, and the case's seam has split quite a bit, so it looks like the stuffing is coming out of it.
It's a Galaxy S8 Active, and it's been the best phone I've ever had, and I don't want to get a new model, and it wasn't that popular so there aren't millions of old ones laying around for cheap.
Read 7 tweets
20 Sep
Shirley Jones, "Til There Was You".

As with others, as with even Louis Armstrong, I grew up without knowing the past of these people on TV.
Mike Douglas was actually a pretty impressive crooner. Shirley Jones was a gifted soprano. Louis Armstrong was the most influential musician of the 20th century.

But you don't know, right, you're just a kid watching daytime TV.
Read 6 tweets
20 Sep
Coaching Pro-Tip: If your team never makes jokes at your expense, you're either losing outright or you're not quite there yet.
Diet coke, ideally in 20 oz bottles, is part of my several ways of getting through the day. My teams never see me without a Diet Coke cuz I'm never without a Diet Coke. This is, to put it mildly, odd.
About five years ago, I was at a site, sitting in my quarter-cubby, and I reached for my diet coke, and I put it up to my lips, and the soda in the bottle just hung there, stuck in the bottle, like it was some jelly solid.
Read 9 tweets
20 Sep
Man, on *that* topic, I been butt-cheek on phalanges for the last thirty hours, and I'm gonna remain so for at least the next thirty, but I gotta say, in my heart there's a substantial amount of "You best step off, child, cuz you about to be playin' out of your league."
It's not a part of myself I'm proud of, this longing to go the fuck off. I'm a little brother, tho, and when you're a little brother, there's no room for decency or kindness. We don't shoot to wound, cuz wounded big brothers are *dangerous*. :)
I once hit my big brother with a lamp, and it took 14 stitches to fix him up. Sure I felt bad, but not as bad as if he'd gotten ahold of me.

(I can assure you that my mother did not see it that way. Oddly, tho, my brother was cool about it. Desperate times, desperate measures.)
Read 18 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


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

Become a Premium Member ($3/month or $30/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!

Follow Us on Twitter!

:(