kait.dev
On the Same Page cover

On the Same Page

by Haley Cass

Must Read

I want to burrow up inside of this book and live there.

Is that a strong enough recommendation?

Serious Haley Cass fans (guilty) will recognize Riley and Gianna from the short story Down to a Science, but it's here in On The Same Page that we learn about the truth and depth of their friendship. The story of how their relationship blossoms and grows is amazing in its own right. You know how sometimes you get jealous of fictional characters? Just me? At any rate, the friendship between these two is absolute goals, and the delightful mix-up that leads to it becoming something more just makes it all the more delicious.

I almost wanted to tag this as enemies-to-lovers, but it's not quite there. Though Gianna is anything but friendly when we first meet her. I don't often feel like the turn from heel character into likeable one is earned in romance novels, but Gianna's transition from damaged/spoiled rich brat to genuinely likeable person is slow and emotionally cogent enough to feel completely honest. And Riley's just a damn delight throughout, though she manages to grow, too.

The only sour note for me in the whole book is Riley's reaction to the Big Revelation, which feels weirdly out of place. Luckily, it's a momentary blip that is entirely ignorable. I mostly just wanted to mention so y'all would know I'm not completely in the tank for this book/author.

If you like queer fiction, especially sapphic, especially especially romance, this one's for you. Read it.

Synopsis

Riley Beckett met Gianna Mäkinen – drop-dead gorgeous influencer, trilingual, daughter of world-famous models, yes, that Gianna Mäkinen – their first year at Boston University, and it changed everything for the both of them. After all, when you find the person who just gets you, nothing feels quite "the same" right? And in the ten years since, Riley has come to depend on Gianna more than anyone else in her life. She knows Gianna just as well as she knows herself – maybe better, some days. She knows Gianna is incredibly sex-positive, she knows Gianna doesn't do romance or relationships, and she knows nothing could ever come between them. This is what makes sense to her, all of this is status-quo. But when a holiday party mix-up sets in motion a domino effect of changes to these previously inalienable truths, Riley has to question everything she thought she knew about their relationship. What, exactly, does Gianna mean to her after all?

In the Long Run cover

In the Long Run

by Haley Cass

Recommended

What does your hometown mean to you? I struck out for college at age 18 and have only returned to my (not-so-quaint anymore) little town maybe 3 or 4 times in the succeeding two decades. It's grown and prospered to the point where it's barely recognizable anymore - sure, I know some of the landmarks, but even those seem to have sprouted the generic "apartments on the top, commercial underneath brick facade" block-length buildings that have come to define 21st century architecture.

But, if asked, I'd still say it's where I'm from. 

That seems odd to me. Your hometown shapes you, in ways good and bad. It provides the backdrop for your early life yes, but it also dictates what types of people and experiences you're exposed to, the values you're inculcated with, and the cast of characters populating your life definitely makes huge impacts on who you turn out to be as a person.

The title of In the Long Run sort presupposes that our hometowns are responsible for the desire paths in our lives, whether we choose to follow the freshly poured sidewalk (main character Brooke) or venture off on our own (love interest Taylor). Brooke is a no-nonsense town manager who gets (adorably) flustered when confronted with things outside her control. She's lived in Faircombe all her life, and has no desire to reach beyond it; wanting to contribute back to the positive feedback loop she feels the town has given her.

Taylor, by contrast, is a free spirit, a travel blogger (this book being released in the depths of Covid is either hugely fortunate or unfortunate, depending on how you look at it) who feels restless whenever it feels like anything resembling roots have started to take hold. Given her upbringing and experience with the town, this diametrically opposed view seems entirely justified.

The same general circumstances, even interactions among the same family, can produce drastically different people. We are not who our history forces us to be, but our history does influence who we decide to become. 

I will admit this story took me a second re-read to really appreciate some of the depth and layering that goes into the character and town. I'm not sure if it's for everybody - there's an awwwwful lot of town business in these pages, and not usually in the fun Pawnee way. But the way these characters interact with one another, grow and change, provides a pleasant perk of perusal. 

Synopsis

Free-spirited and easygoing Taylor Vandenberg left her hometown of Faircombe, Tennessee as soon as she could, and in the twenty-five years since, she has rarely looked back. She wouldn’t change anything about how her life has turned out – having traveled to nearly every country, never staying anywhere long enough to feel stifled. Very few things can hold her attention back in Faircombe: her sister/best friend, her precocious niece, and perhaps the prospect of riling up Brooke Watson. Brooke has known Taylor for her entire life, given that her best friend is Taylor’s younger brother. And a lifelong knowledge of Taylor means that Brooke knows she’s trouble: irresponsible, takes nothing seriously, and is irritatingly attractive. Unlike Taylor, Brooke loves their town so much that she’s spent her adult life dedicated to making sure it doesn’t get swept away like many of the other declining small cities of the American South. Faircombe means the world to her, and she’s willing to do just about anything to make sure it flourishes. Even if it means working with Taylor, whose path seems to continuously be crossing with Brooke’s everywhere she turns…

Down to a Science cover

Down to a Science

by Haley Cass

Highly Recommended

Honestly, I would support buying this book just based on how it came to be, alone. For Pride Month 2022, IHeartSapphFic (best name ever) got 8 authors to contribute novel/las and released them as part of a set. I expected to get some middling short stories the authors had been toying with but weren't good enough to publish on their own.

Instead, they blew me away in their own right. 

Though I will always be grateful to Down to a Science for setting up the characters for On the Same Page, I find myself fiercely protective of both Mia and Ellie, in different ways. Mia's got a somewhat predictably tragic backstory (in the same way no Disney princesses have mothers, most lesbian romance interests have on average 1.4 dead parents), but it feels true to her character both in how it shaped her life in the broad view as well as how it impacts her in the moment-to-moment. 

Ellie, on the other hand, is another neurospicy character who feels authentic, rather than cheaply staged or exploited, which is both helped and made harder by the fact that (as the book is written from her perspective) we get the full breadth of her thoughts and feelings. Having her whirling emotions helps ground the character in reality, but is an authorially bold move given that too often attempts to write neurodivergent characters wind up missing the mark. However, much like Love is for Losers, Ellie felt real to me in a way that's mildly unnerving, given how much I identify with or at least understand her reactions to different situations.

I promise, this is not intended to be a neurospicy queer book website! But it's nice to see the genre widening out to include more diverse perspectives into the lives of queer people, and I want to celebrate when that's done well. Whether it's neurological differences, race, gender, aro/allo, it's a legitimate cause for joy when media is created that allows people to feel seen. And this book has that, well, down to a science. 😉

Synopsis

Ellie Beckett’s life is simple and uncomplicated; she’s on track to become a leading expert in biomedical engineering, she has a pub where she feels comfortable enough to hang out multiple times a week, and, so what if she doesn’t have time for… people? She doesn’t need or want them. Until she meets Mia Sharpe. As it it turns out, maybe Ellie does want at least one person.

Love at First Set cover

Love at First Set

by Jennifer Dugan

Highly Recommended

I so did not expect to like this book! As someone with a definitely not made up allergy to gym equipment and exercise, I was not expecting to like the strong ladies book. But oh my gosh, did you know that the strongest muscle is the heart (it's actually your jaw, or your uterus, or your butt, or your eye, or your tongue, or the heart, depending on your definition of "strongest") and this one's working overtime.

This doesn't really count as a spoiler because it's in the description, but Lizzie's drunken bathroom pep talk is so inspiring, funny and touching I almost went and broke up some weddings myself. It's just that good.

Lizzie comes across as a real person, with lots of insecurities owing to how she grew up that she mostly manages to shove away. Both James and Cara are absolute wankers at times (James early and often, Cara once or twice but at exactly the wrong times), but in Cara's case it's easy to see her redeeming values as to why Lizzie would fall in love with her (and vice versa).

I don't know, y'all, I just love Lizzie's energy. She's a disaster gay, through and through, but because her heart's in the right place (and it's so strong) she always manages to rack 'em after pounding out that last set. You'd have to be a dumb belle not to like this book. Do not weight to pick it up. Alright, much like Lizzie I might be too tipsy for this (despite drinking squat) and need to bail before I (bench) press my luck. It's definitely worth curl-ing up with.

Synopsis

The gym is Lizzie’s life—it’s her passion, her job, and the only place that’s ever felt like home. Unfortunately, her bosses consider her a glorified check-in girl at best, and the gym punching bag at worst. When their son, Lizzie’s best friend, James, begs her to be his plus one at his perfect sister Cara’s wedding, things go wrong immediately, and culminate in Lizzie giving a drunken pep talk to a hot stranger in the women’s bathroom—except that stranger is actually the bride-to-be, and Lizzie has accidentally convinced her to ditch her groom. Now, newly directionless Cara is on a quest to find herself, and Lizzie—desperate to make sure her bosses never find out her role in this fiasco—gets strong-armed by James into “entertaining” her. Cara doesn’t have to know it’s a setup; it’ll just be a quick fling before she sobers up and goes back to her real life. After all, how could someone like Cara fall for someone like Lizzie, with no career and no future? But the more Lizzie gets to know Cara, the more she likes her, and the bigger the potential disaster if any of her rapidly multiplying secrets get out. Because now it’s not just Lizzie’s job and entire future on the line, but also the girl of her dreams.

Maybe a glimmer of recognition in "disaster gay"? WHO CAN TELL

Astrid Parker Doesn't Fail cover

Astrid Parker Doesn't Fail

by Ashley Herring Blake

Recommended, Maybe

Astrid Parker is kind of a bitch.

I'm sorry, she is? I'm understanding about people growing up in bad situations (truly, the overall family dynamic as well as how specifically her mother treats her was and is pretty bad), and needing to grow, but Astrid just ... doesn't?

I mean, we literally spent an entire book blowing up her wedding because she was marrying some (presumably) MAGA chump (forced it into it by her mother) who thought he should buy a house several hours away without telling his fiancee and ... didn't see it? Didn't care? Hard to tell, really.

But that wasn't enough! Even though Astrid Parker has already Failed, she's determined to make her interior design business (forced into by her mother) succeed by renovating a historic old B&B on some home renovation show. But the carpenter/contractor, Jordan, has her own ideas. Better ideas. They're just straight-up better. It took Jordan almost no time to come up with them. Astrid Parker is almost entirely superfluous. But we can't say that because .... reasons?

Look, I know contrivances are part and parcel for genre novels, especially romance. But that on top of Astrid just being a straight-up dick most of the time really made me struggle to finish this book. I have absolutely no idea what Jordan saw in her other than 🔥, and that doesn't always come through in books, y'know?

It's not bad writing! It's just an annoying character. I can recommend this book out of completeness' sake for the Bright Falls series, but otherwise there are plenty of other, better options for your time. And Jordan, you can do so. Much. Better.

Synopsis

For Astrid Parker, failure is unacceptable. Ever since she broke up with her fiancé a year ago, she’s been focused on her career—her friends might say she’s obsessed, but she knows she’s just driven. When Pru Everwood asks her to be the designer for the Everwood Inn’s renovation, which will be featured on a popular HGTV show, Innside America, Astrid is thrilled. Not only will the project distract her from her failed engagement and help her struggling business, but her perpetually displeased mother might finally give her a nod of approval.    However, Astrid never planned on Jordan Everwood, Pru’s granddaughter and the lead carpenter for the renovation, who despises every modern design decision Astrid makes. Jordan is determined to preserve the history of her family’s inn, particularly as the rest of her life is in shambles. When that determination turns into some light sabotage to ruffle Astrid’s perfect little feathers, the showrunners ask them to play up the tension. But somewhere along the way, their dislike for each other evolves into something quite different, and Astrid must decide what success truly means. Is she going to pursue the life that she’s expected to lead or the one that she wants?

Delilah Green Doesn't Care cover

Delilah Green Doesn't Care

by Ashley Herring Blake

Must Read

I think I have abandonment issues with really good books. Think about it! Every book you've ever loved, ever craved to wedge yourself between the lines and live among the fictional world, is finite. Even as part of an ever-sprawling series, inevitably you get to the last page of the last chapter of the last page ... and it's over. 

Both the titular Delilah Green and her love interest, Claire, seem to have (justifiable) abandonment issues of their own. Delilah (dead parent alert!) hasn't had any family to rely on since she was young, so she books it to NYC as soon as she can and stays there. She's only brought back by the lure of much-needed cash from wicked stepsister Astrid Parker, but she's coming and going just as fast as she does in any relationship - quickly, and without remorse.

That is, until she meets one of Astrid's BFFs, Claire. Suddenly she's consumed by the thoughts of this girl and her manic pixie dream daughter, and just mayyybe it's enough to keep her sticking around ...  

Isn't it useful how the Lothario, only-in-it-for-themselves types always turn out to have secret mushy hearts that just need the right queer person unlock them?

I jest! Things can be tropes simply because they happen often, not because they were written to follow said trope. Delilah is a wonderfully fleshed-out character, and the progression in all the relationships feels justified and well-earned. And hey, who can blame Delilah? I'd stick around and shack up with Claire if only I knew she wouldn't leave me before the acknowledgments.

Oh, Claire. We could have been so good together. Instead, I'll just have recommend others spend their time with you and hope that can satisfy your insatiable craving.

Synopsis

A clever and steamy queer romantic comedy about taking chances and accepting love—with all its complications—from the author of Astrid Parker Doesn't Fail. Delilah Green swore she would never go back to Bright Falls—nothing is there for her but memories of a lonely childhood where she was little more than a burden to her cold and distant stepfamily. Her life is in New York, with her photography career finally gaining steam and her bed never empty. Sure, it’s a different woman every night, but that’s just fine with her.     When Delilah’s estranged stepsister, Astrid, pressures her into photographing her wedding with a guilt trip and a five-figure check, Delilah finds herself back in the godforsaken town that she used to call home. She plans to breeze in and out, but then she sees Claire Sutherland, one of Astrid’s stuck-up besties, and decides that maybe there’s some fun (and a little retribution) to be had in Bright Falls, after all.    Having raised her 11-year-old daughter mostly on her own while dealing with her unreliable ex and running a bookstore, Claire Sutherland depends upon a life without surprises. And Delilah Green is an unwelcome surprise…at first. Though they’ve known each other for years, they don’t really know each other—so Claire is unsettled when Delilah figures out exactly what buttons to push. When they’re forced together during a gauntlet of wedding preparations—including a plot to save Astrid from her horrible fiancé—Claire isn’t sure she has the strength to resist Delilah’s charms. Even worse, she’s starting to think she doesn’t want to...

Iris Kelly Doesn't Date cover

Iris Kelly Doesn't Date

by Ashley Herring Blake

Highly Recommended

Y'all, I struggled with this one a bit. There are so many conflicting emotions going on in my brain right now.

Looking at it holistically, it's the third in a series. Delilah Green was excellent, Astrid Parker didn't really do it for me. Iris Kelly is sort of inbetween, leaning toward Delilah, a bit?

I'll say this, Blake can write characters. I loved Iris Kelly, the bold and brassy lass of Irish descent whose temper is as fiery as her passion. Her family is ... verging on unbelievable? I don't know that there's a likable older parent in this series, but Iris' mom is almost worse than Astrid's and Delilah's. This all actually would cohere a lot better if I believed that we were supposed to be filtering our perceptions through Iris' slanted, tempestuously-colored eyes, but I don't get that sense. I think we're supposed to take literally that her mom is condescending to the point of seeming like a negging pick-up artist, and her family is just a ball of uncontrollable.

And Stevie is wonderful, too, in her own way. But also just this side of realistic? I truly don't know how one could exist as a successful actor being that much of a doormat to everyone around them. Flaws are fine, but enough cracks in the mirror and it's a bit hard to actual understand what's being reflected back.

But they make sense together. Maybe the trick is to not assume this is set in our universe, but in one slightly removed. If you can put aside the absurdity of nearly every situation our fierce females face, their story and connection is one that can make your heart sing (or get up on stage and prance around in a donkey's head, as required). I think most people can suspend their disbelief to get to the goodness at the core of the novel, but I won't pretend it comes without effort.

Synopsis

Everyone around Iris Kelly is in love. Her best friends are all coupled up, her siblings have partners that are perfect for them, her parents are still in marital bliss. And she’s happy for all of them, truly. So what if she usually cries in her Lyft on the way home. So what if she misses her friends, who are so busy with their own wonderful love lives, they don’t really notice Iris is spiraling. At least she has a brand-new career writing romance novels (yes, she realizes the irony of it). She is now working on her second book but has one problem: she is completely out of ideas after having spent all of her romantic energy on her debut. Perfectly happy to ignore her problems as per usual, Iris goes to a bar in Portland and meets a sexy stranger, Stefania, and a night of dancing and making out turns into the worst one-night stand Iris has had in her life (vomit and crying are regretfully involved). To get her mind off everything and overcome her writer's block, Iris tries out for a local play, but comes face-to-face with Stefania—or, Stevie, her real name. When Stevie desperately asks Iris to play along as her girlfriend, Iris is shocked, but goes along with it because maybe this fake relationship will actually get her creative juices flowing and she can get her book written. As the two women play the part of a couple, they turn into a constant state of hot-and-bothered and soon it just comes down to who will make the real first move…

When You Least Expect It cover

When You Least Expect It

by Haley Cass

Must Read

It sounds like the cheapest of plot devices - divorce attorney meets latebian with asshole ex-husband. And wouldn't you know it, the ex-hubby used to work at the same firm! 

But oh my gosh, it goes beyond the tropes and the clichés. It's a slow-burn love story where, yeah, you can tell that Caroline (the main character) has a crush on Hannah. She admits it to herself at first, but then they build an honest friendship and (slight spoilers) even a little family, as Caroline met and charmed Abby (Hannah's little girl) when she was stuck at the office on weekends.

It's just so charming and endearing I want to completely melt every time I read it.

The slowest of slow burns? Absolutely. But it feels so earned and so, so rewarding when she finally gets her gal.

Legitimately the best way to impart how much I thoroughly enjoy the book is to admit that I own on Kindle, in paperback and audiobook - and I've read/listened to all of them more than once. Per year.

It's the best of what romance has to offer, whether in literary or real-world form. Did I mention it's also a CHRISTMAS romance? Seriously, this book is everything you'd want in a romance novel. Deep, abiding friendship; mutual respect; an all-encompassing love that suffuses both of their lives. I promise you'll find yourself striving to reach the warmth you'll find within.

Synopsis

Caroline Parker knows three things to be true. First, she is going to be Boston's most sought after divorce attorney by thirty-five. Second, given how terrible her romantic track record is, falling in love isn't in the cards for her. And third, Christmas only brings her bad luck - being broken up with not once, not twice, but three times during the holidays is proof enough of that. When she runs into Hannah Dalton on Christmas Eve, she has no reason to believe her luck will change. After all, though Hannah is probably the most gorgeous woman she’s ever seen, she’s also straight. And married to Caroline’s work rival. While being hired by Hannah throws her for a loop, winning a divorce case and sticking it to her ex-colleague should be enough of a thrill. But as the months slip by, bringing her closer to both Hannah and her adorable daughter Abbie, the lines between attorney and client begin to blur. And she could have never predicted just how much she wants them to.

The Ride of Her Life cover

The Ride of Her Life

by Jennifer Dugan

Recommended

Look, "disaster queer" is a real-life trope we all know and probably embody to some extent, but it exists for a reason. And boy, "hot mess" does not even begin to describe what goes down in this book. Every character has more issues than your average grandparent's National Geographic collection ("it'll be worth something someday!"), to the point of you might find yourself wishing for appendices to keep everything straight.

If I'm being honest, I felt more than a little personally attacked by some of the problems plaguing Molly McDaniel. Her biggest issue, as the book memorably puts it, is that Molly "makes someone else her IPA" - that is, she transforms herself in order to fit neatly into the life of whomever she's dating at the time (in the case of the IPA, Shoni, the love interest, bought a home-brewing kit to impress her IPA-loving lady friend). 

So I can't really fault the realism there! The sheer depth of the characters drew me in certainly, but I will say at times it left me flailing my arms trying to stay afloat. Like, it's mildly difficult to keep track of everyone's issues? If every wall is an accent wall, you're actually lacking a primary color. Similarly, if every character is presented as a prickly patch of insecurities, it makes it more difficult to savor or even appreciate the juicy, fruity parts. And with so many unresolved issues just hanging off everyone's shoulders, the book's ending feels a bit rushed and left far too many burdens on my poor little brain and heart.

All that being said, it's a very emotional, complex novel that demands you sit with it for a bit. You can rush through it, of course, but I think you'll feel better afterwards if you pace and give it the time it deserves. I don't know that I'd recommend it for those looking for lighthearted romantic fare, but it's a solid work that should manage to hit you in the feels.

Synopsis

Molly McDaniel's life is falling apart. Between her day job as a barista, her night job at a call center, and her crushing student loans, she's barely getting by. And that dream she has of starting a wedding event planning business? The dream that led to all those student loan in the first place? She can feel it slipping farther and farther out of reach every day. So the absolute last thing she needs is to discover she's inherited a run-down, struggling horse barn out of the blue, courtesy of her estranged late aunt. Molly is so ill-equipped to run the barn, it's laughable. She certainly doesn't have the money, time or knowledge needed to save it, no matter how much faith everyone who loved her aunt has that she will. But the more Molly gets involved, the more she starts to wonder: maybe the barn is a blessing in disguise. If she can sell the land, the profits could be the small-business seed money miracle she's been waiting for. So what if she's starting to love everyone in the mismatched family she's found here? Well, everyone except Shani, the resident farrier and family friend who took care of Molly's aunt in her last days. Judgmental, grouchy Shani, who refuses to give up on the barn; who walks around like she so much better than Molly; who's actually really good with the horses...and kind of thoughtful. And obnoxiously hot. And unfailingly loyal. And suddenly, Shani has become an entirely different kind of problem, one Molly can't possibly solve, not without risking her whole future, no matter how much her heart wishes she could.

Boys Don't Dance cover

Boys Don't Dance

by Ivy Whitaker

Recommended

**There are so many expectations bound up in this book. **

From a plot standpoint, our author heroine (Lyra, a name I absolutely love) flees sunny California for the rundown mid-Atlantic foothills of Pennsylvania when her sister falls victim to a stroke. Lyra tries to meet the expectations of being a devoted sister as best she can, while also trying to stave off what's expected of a multiple-time best-selling author after a flop (namely: Write more, better).

This, of course, is complicated when she runs into her childhood best friend/love, Alex. Alex has not only felt the weight of the expectations of others, she has flat-out surrendered to them. Her mother expected her to marry a man and live the life of a stay-at-home mom, and only upon reacquainting herself with the force that is Lyra does she start to realize the crushing burdens of those expectations. 

This book felt challenging - In a good way, mind you! But by no means an easy or breezy read.

Part of that, I think, lay in the expectations on my part. Expectations affect everything we do, from consuming media to consuming food to how we relate to other people. If we have an expectation, even if we don't realize it ourselves, failing to have that expectation met can leave you feeling off-kilter, or disappointed.

To put it bluntly, I expected a simple sapphic romance. It's more than that! Better in many ways, with lyrical prose and extremely vivid depictions of emotions and connection. And certainly much deeper in terms of the difficult subject matter it deals with.

But in its (successful, in my eyes) aspirations to literary fiction, the novel's insistence on hitting some of the simplistic romance tropes felt forced. I think the book would have worked much better had it simply shed its romance-constrained plot points and just kept exploring and exposing its beating heart, which was otherwise mesmerizing.

Expectations are a double-edged sword. I've no doubt "sapphic romance" has some advantages for marketing purposes, and with that designation comes certain expectations. I just think this book is better than that, and I'm only sorry it seems to try shape itself to a form it has clearly outgrown. 

All that said, this book is a lovely, wonderful piece of work. And I truly can't wait to see what the author will do next.

This review is for an advanced reader copy of the book, provided by the publisher.

Synopsis

Lyra Moreno's life has fallen apart. Her latest book was a literary flop, and her on-again-off-again relationship was, again, off. When her sister suffers a stroke, Lyra returns to her small hometown to temporarily run her sister’s dance studio. Lyra hopes the familiar setting will help heal her wounds and distract her from the pressures of a relentless agent, hungry publicists, and the curious public. It might have worked if she hadn’t run into an old flame—Alexis Marsh, now Alexis Cole. Alexis’s worst fear was coming true—turning out like her mother. She followed the tried and true formula to happiness a handsome husband with a great job, two kids, a beautiful house, and a homemaker lifestyle. She should be happy. She is happy. Her carefully curated reality begins to crumble when a ghost from her past breezes Lyra Moreno. Her high school sweetheart and first love—a person she had convinced herself had been little more than a minor character in a passing phase. So why does she feel the need to prove she’s happy?

An image promoting my improv for developers workshop at Beer City CodeI'm headed back to the Midwest to do some speakerizing again in August 2024.

Beer City Code 24**** is in Grand Rapids, MI, on Aug 2-3. I'm super excited to present a workshop, Improv for Developers, which is where we'll do actual improv training and then talk about how those skills translate to software development. It's 6 hours (!!), but it should be a lot of fun!

I'll also talk about greenfield development: specifically, that it doesn't really exist anymore. There are always preexisting considerations you're going to have to take into account, so I'll give some hard-won tips on sussing them out.

DevUp will be held in St. Louis on Aug. 14-16. I'll be talking about greenfields again, as well as reasons scrum-based development tends to fail, and how we can measure developer productivity.

Hope to see you this summer!

YES, AND you also have to write documentation or no one will know what the hell you were thinking when you wrote it.

Though I am no great fan of AI or its massively over-hyped potential, I also do not think it's useless. As Molly White put it:

When I boil it down, I find my feelings about AI are actually pretty similar to my feelings about blockchains: they do a poor job of much of what people try to do with them, they can't do the things their creators claim they one day might, and many of the things they are well suited to do may not be altogether that beneficial.

I wholeheartedly agree with those claims, and don't want to get into the specifics of them too much. Instead, I wanted to think out loud/write about why there's such a wide range of expectations and opinions on the current and future states of AI.

To get the easy one out of the way: Many of the most effusive AI hype people are in fit for the money. They're raising venture capital by saying AI, they're trying to get brought in as consultants on AI, or they're trying to sell their AI product to businesses and consumers. I don't think that's a particularly new phenomenon when it comes to new technology, though perhaps there is some novelty in how many different ways people are attempting to get their slice of the cake (companies cooking up AI models, apps trying to sell AI generation to consumers, hardware and cloud providers selling the compute necessary to do all of the above, etc.).

But once we take pure profit motive out of the way, there are I think two key areas of difference in people who believe in AI wholeheartedly and those who are neutral to critical.

The first is software development experience. Those who understand what it actually means when people say "AI is thinking" tend to have an overall more pessimistic view of the pinnacle of current AI generation strategies. In a nutshell, all of the current generative models try to ingest as much content of whatever thing they're going to be asked to output. Then, they are given a "prompt," and they are (in simplistic terms) trying to piece together an image/string of words/video that looks most likely based on what came for.

This is why these models "hallucinate" - they don't "know" anything specifically in the way you know that Washington, DC is the capital of the United States. It just knows that when a sentence starts "The capital of the United States is" it usually ends with the words "Washington, DC."

And that can be useful in some instances! This is why AI does very well on low-level coding tasks - a lot of the basics of programming is pretty repetitive and pattern-based, so an expert pattern-matcher can do fairly well at guessing the most likely outcome. But it's also why AI developer assistants produce stupid mistakes, because it doesn't "understand" the syntax or the language or even the problem statement as a fundamental unit of knowledge. It simply reads a string of text and tries to figure out what would most likely come next.

The other thing you learn from experience are edge cases, and specifically what doesn't work. This type of knowledge tends to accumulate only through having worked on a product before, and understanding how different pieces come together (or don't). AI lacks this awareness of context, focusing only what immediately surrounds the section it's working on.

But the other primary differentiator is for the layperson, who can best be understood as a consumer and it can be condensed to a single word: Taste.

I'm reminded of a quote from Ira Glass I heard on some podcast:

... all of us who do creative work … we get into it because we have good taste. But it’s like there’s a gap, that for the first couple years that you’re making stuff, what you’re making isn’t so good, OK? It’s not that great. It’s really not that great. It’s trying to be good, it has ambition to be good, but it’s not quite that good. But your taste — the thing that got you into the game — your taste is still killer, and your taste is good enough that you can tell that what you’re making is kind of a disappointment to you ...

I think this is true, and I think it's the biggest differentiator between people who think what AI is capable of right now is perfectly fine and those that think it'll all wind up being a waste of time. People who can't or are unwilling create text/images/videos on their own think that AI is a great shortcut. This is either because the quality of what the AI can produce is better than what they can do unassisted, or they don't have the taste to see the difference in the first place.

I don't know that I think there's a way to bridge that gap any more than there is to explain to people who think that criticism of any artform is "unfair" or that "well, could you do any better?" is a valid counterpoint to cultural criticism. There are simply those people whose taste is better than that what can be created only through an amalgamation of data used to train a model, and those who think that a simulacrum of art is indistinguishable (or better) than the real thing.

It's amazing how short my attention span for new fads is anymore. I don't want to blame Trump for this one, but my eagerness to ignore any news story he was involved in definitely accelerated the decline of my willingness to cognitively engage with the topic du jour significantly.

Software requirements are rather straightforward - if we look at the requirements document, we see simple, declarative statements like "Users can log out," or "Users can browse and create topics." And that's when we're lucky enough to get an actual requirements document.

This is not legal advice

None of the following is intended to be legal advice. I am not a lawyer, have not even read all that many John Grisham novels, and am providing this as background for you to use. If you have actual questions, please take them to an actual lawyer. (Or you can try calling John Grisham, but I doubt he'd pick up.)

But there are other requirements in software engineering that aren't as cut-and-dried. Non-functional requirements related to things like maintainability, security, scalability and, most importantly for our purposes, legality.

For the sake of convenience, we're going to use "regulations" and other derivations of the word to mean "all those things that carry the weight of law," be they laws, rules, directives, court orders or what have you.

Hey, why should I care? Isn't this why we have lawyers?

Hopefully your organization has excellent legal representation. Also hopefully, those lawyers are not spending their days watching you code. That's not going to be fun for them or you. You should absolutely use lawyers as a resource when you have questions or aren't sure if something would be covered under a specific law. But you have to know when to ask those questions, and possess enough knowledge when your application could be running afoul of some rule or another.

It's also worthwhile to your career to know these things! Lots of developers don't, and your ability to point them out and know about them will make you seem more knowledgeable (because you are!). It will also make you seem more competent and capable than another developer who does not – again, because you are! This stuff is a skillset just like knowing Django.

While lawyers may be domain experts, they aren't always (especially at smaller organizations) and there are lots of regulations that specifically cover technology/internet-capable software that domain experts likely would not (and should not) be expected to be on top of. Further, if you are armed with foreknowledge, you don't have to wait for for legal review after the work has been completed.

Also, you know, users are people, too. Most regulations wind up being bottom-of-the-barrel expectations that user data is safeguarded and restricting organizations from tricking users into doing things they wouldn't have otherwise. In the same way I would hope my data and self-determination are respected, I also want to do the same for my users.

Regulatory environments

The difference in the regulatory culture between the US and the European Union is vast. I truly cannot stress how different they are, and that's an important thing to know about because it can be easy to become fluent in one and assume the other is largely the same. It's not. Trust me.

United States

The US tends, for the most part, to be a reactionary regulator. Something bad happens, laws or rules (eventually) get written to stop that thing from happening again.

Also, the interpretations of those rules tend to fluctuate more than in the EU, depending on things seemingly as random as which political party is in power (and controlling the executive branch, specifically) or what jurisdiction a lawsuit is filed in. We will not go in-depth into those topics, for they are thorny and leave scars, but it's important to note. The US also tends to give wide latitude to the defense of, "but it's our business model!" The government will not give a full pass on everything, but they tend to phrase things in terms of "making fixes" rather than "don't do that."

Because US regulations tend to be written in response to a specific incident or set of incidents, they tend for the most part to be very narrowly tailored or very broad ("e.g., TikTok is bad, let's give the government the ability to jail you for 20 years for using a VPN!"), leaving little guidance to those of us in the middle. This leaves lots of room for unintended consequences or simply failing to achieve the stated goals. In 2003, Congress passed the CAN-SPAM Act to "protect consumers and businesses from unwanted email." As anyone who ever looks at their spam box can attest, CAN-SPAM's acronym unfortunately seems to have meant "can" as in "grant permission," not "can" as in "get rid of."

European Union

In contrast, the EU tends to issue legislation prescriptively; that is, they identify a general area of concern, and then issue rules about both what you can and cannot do, typically founded in some fundamental right.

This technically is what the US does on a more circumspect level, but the difference is the right is the foundational aspect in the EU, meaning it's much more difficult to slip through a loophole.

From a very general perspective, this leads to EU regulations being more restrictive in what you can and can't do, and the EU is far more willing to punish punitively those companies who run afoul of the law.

Global regulations

There are few regulations that apply globally, and usually they come about backwards - in that a standard is created, and then adopted throughout the world.

Accessibility

In both the US and the EU, the general standard for digital accessibility is WCAG 2.1, level AA. If your website or app does not meet (most) of that standard, and you are sued, you will be found to be out of compliance.

In the US, the reason you need to be compliant comes from a variety of places. The federal government (and state governments) need to be compliant because of the Rehabilitation Act of 1974, section 508. Entities that receive federal money (including SNAP and NSF grants) need to be compliant because of the RA of 1974, section 504. All other publicly accessible organizations (companies, etc.) need to have their websites compliant because of the Americans with Disabilities Act and various updates. And all of the above has only arisen through dozens of court cases as they wound their way through the system, often reversing each other or finding different outcomes with essentially the same facts. And even then, penalties for violating the act are quite rare, with the typical cost being a) the cost of litigation, and b) the cost of remediation and compliance (neither of which are small, but they're also not punitive, either).

In the EU, they issued the Web Accessibility Directive that said access to digital information is a right that all persons, including those with disabilities, should have, so everything has to be accessible.

See the difference?

WCAG provides that content should be

  • Perceivable - Your content should be able to be consumed in more than one of the senses. The most common example of this is audio descriptions on videos (because those who can't see the video still should be able to glean the relevant information from it).

  • Operable - Your content should usable in more than one modality. This most often takes the form of keyboard navigability, as those with issues of fine motor control cannot always handle a mouse dextrously.

  • Understandable - Your content should be comprehensible and predictable. I usually give a design example here, which is that the accessibility standard actually states that your links need to be perceivable, visually, as links. Also, the "visited" state is not just a relic of CSS, it's actually an accessibility issue for people with neurological processing differences who want to be able to tell at a glance what links they've already been to.

Robust - Very broadly, this tenet states you should maximize your compliance with accessibility and other web standards, so that current and future technologies can take full advantage of them without requiring modification to existing content.

Anyway, for accessibility, there's a long list of standards you should be meeting. The (subjectively) more important ones most frequently not followed are:

  1. Provide text alternatives for all non-text content: This means alt text for images, audio descriptions for video and explainer text for data/tables/etc. Please also pay attention to the quality – the purpose of the text is to provide a replacement for when the non-text content can't be viewed, so "picture of a hat" is probably not an actual alternative.

  2. Keyboard control/navigation: Your site should be navigable with a keyboard, and all interactions (think slideshows, videos) should be controllable by a keyboard.

  3. Color contrast: Header text should have a contrast ratio of 3:1 between the foreground and background; smaller text should have a ratio of 4.5:1.

  4. Don't rely on color for differentiation: You cannot rely solely on color to differentiate between objects or types of objects. (Think section colors for a newspaper website: You can't just have all your sports links be red, it has to be indicated some other way.)

  5. Resizability: Text should be able to be resized up to 200% larger without loss of content or functionality

  6. Images of text: Don't use 'em.

  7. Give the user control: You can autoplay videos or audio if you must, but you also have to give the user the ability to stop or pause it.

There are many more, but these are the low-hanging fruit that lots of applications still can't manage to pick off

PCI DSS

The Payment Card Industry Data Security Standard is a set of standards that govern how you should store credit card data, regulated by credit card companies themselves. Though some individual US states require adherence to the standards (and fine violators appropriately), federal and EU law does not require you to follow these standards (at least, not specifically these standards). However, the credit card companies themselves can step in and issue fines or, more critically, cut off access to their payment networks if they find the breaches egregious enough.

In most cases, organizations offload their payment processing to a third party (e.g., Stripe, Paypal), who is responsible for maintaining compliance with the specification. However, you as the merchant or vendor need to make sure you’re storing the data from those transactions in the manner provided by the payment processor; it’s not uncommon to find places that are storing too much data on their own infrastructure that technically falls under the scope of PCI DSS.

Some of the standards are pretty basic - don’t use default vendor passwords on hardware and software, encrypt your data transmissions. Some are more involved, like restricting physical access to cardholder data, or monitoring and logging access to network resources and data.

EU regulations

GDPR

The EU's General Data Privacy Regulation caused a big stir when it was first released, and for good reason. It completely changed the way that companies could process and store user data, and severely restricted what sort of shenanigans companies can get up to.

The GDPR states that individuals have the right to not have their information shared; that individuals should not have to hand over their information in order to access goods or services; and that individuals have further rights to their information even once it's been handed over to another organization.

For those of us on the side of building things, it means a few things are now requirements that used to be more "nice-to-haves."

  • You must get explicit consent to collect data If you're collecting data on people, you have to explicitly ask for it. You have to specify exactly what information you're collecting, the reason you're collecting it, how long you plan on storing it and what you plan to do with it (this is the reason for the proliferation of all those cookie banners a few years ago). Furthermore, you must give your users the right to say no. You can't just pop up a full-screen non-dismissable modal that doesn't allow them to continue without accepting it.

  • You can only collect data for legitimate purposes Just because someone's willing to give you data doesn't mean you're allowed to take it. One of my biggest headaches I got around GDPR was when a client wanted to gate some white papers behind an email signup. I patiently explained multiple times that you can't require an email address for a good or service unless the email address was required to provide said good or service. No matter how many times the client insisted that he had seen someone else doing the same thing, I stood firm and refused to build the illegal interaction.

  • Users have the right to ask for the data you have stored, and to have it deleted Users can ask to see what data you have stored on them, and you're required to provide it (including, again, why you have that data stored). And, unless it's being used for legitimate processing purposes, you have to delete that data if the user requests it (the "right to be forgotten").

And all of this applies to any organization or company that provides a good or service to any person in the EU. Not just paid, either – it explicitly says that you do not have to charge money to be covered under the GDPR. So if your org has an app in the App Store that can be downloaded in Ireland, Italy, France or any other EU country, it and likely a lot more of your company's services will fall under GDPR.

As for enforcement, organizations can be fined up to €20 million, or up to 4% of the annual worldwide turnover of the preceding financial year, whichever is greater. Amazon Europe got docked €746 million for what was alleged "[manipulation of] customers for commercial means by choosing what advertising and information they receive[d]" based on the processing of personal data. Meta was fined a quarter of a billion dollars a few different times.

But it's not just the big companies. A translation firm got hit with fines of €20K for "excessive video surveillance of employees" (a fine that's practically unthinkable in the US absent cameras in a private area such as the bathroom), and a retailer in Belgium had to pay €10K for forcing users to submit an ID card to create a loyalty account (since that information was not necessary to creating a loyalty account).

Digital Markets Act

The next wave of regulation to hit the tech world was the Digital Markets Act. which is aimed specifically at large corporations that serve a “gatekeeping functionality” in digital markets in at least three EU countries. Although it is not broadly applicable, it will change the way that several major platforms will work with their data.

The directive’s goal is to break up the oversized share that some platforms have in digital sectors like search, e-commerce, travel, media streaming, and more. When a platform controls sufficient traffic in a sector, and facilitates sales between businesses and users, it must comply with new regulations about how data is provisioned and protected.

Specifically, those companies must:

  • Allow third parties to interoperate with their services

  • Allow businesses to access the data generated on the platform

  • Provide advertising partners with the tools and data necessary to independently verify claims

  • Allow business users to promote and conduct business outside of the platform

Additionally, the gatekeepers cannot:

  • Promote internal services and products over third parties

  • Prevent consumers from linking up with businesses off their platforms

  • Prevent users from uninstalling preinstalled software

  • Track end users for the purpose of targeted advertising without users’ consent

If it seems like these are aimed at the Apple App Store and Google Play Store, well, congrats, you cracked the code. The DMA aims to help businesses have a fairer environment in which to operate (and not be completely beholden to the gatekeepers), and allow for smaller companies to innovate without being hampered or outright squashed by established interests.

US regulations

The US regulatory environment is a patchwork of laws and regulations written in response to various incidents, and with little forethought for the regulatory environment as a whole. It’s what allows you as a developer to say, “Well, that depends …” in response to almost any question, to buy yourself time to research the details.

HIPAA

Likely the most well-known US privacy regulation, HIPAA covers almost none of the things that most people commonly think it does. We'll start with the name: Most think it's HIPPA, for Health Information Privacy Protection Act. It actually stands for Healthcare Insurance Portability and Accountability Act, because most of the law has nothing to do with privacy.

It is very much worth noting that HIPAA only applies to health plans, health care clearinghouses, and those health care providers that transmit health information electronically in connection with certain administrative or financial transactions where health plan claims are submitted electronically. It also applies to contractors and subcontractors of the above.

That means most of the time when people publicly refuse to comment on someone's health status because of HIPAA (like, in a sports context or something), it's nonsense. They're not required to disclose it, but it's almost certainly not HIPAA that's preventing them from doing so.

What is relevant to us as developers is the HIPAA Privacy Rule. The HIPAA privacy rule claims to "give patients more control over their health information, set boundaries on the use of their health records, establish appropriate safeguards for the privacy of their information."

What it does in practice is require that you have to sign a HIPAA disclosure form for absolutely every medical interaction you have (and note, unlike GDPR, that they do not have to let you say "no"). Organizations are required to keep detailed compliance policies around how your information is stored and accessed. While the latter is undoubtedly a good thing, it does not rise to the level of reverence indicated by its stated goals.

What you as a developer need to know about HIPAA is you need to have very specific policies (think SOC II [official link] [more useful link]) around data access, operate using the principle of least privileged access (only allow those who need to see PHI to be able to access it), and specific security policies related to the physical facility where the data is stored.

HIPAA’s bottom line is that you must keep safe Protected Health Information (PHI), which covers both basic forms of personally identifiable information (PII) such as name, email, address, etc., as well as any health conditions those people might have. This seems like a no-brainer, but it can get tricky when you get to things like disease- or medicine-specific marketing (if you’re sending an email to someone’s personal email address on a non-HIPAA-compliant server about a prostate cancer drug, are you disclosing their illness? Ask your lawyer!).

There are also pretty stringent requirements related to breach notifications (largely true of a lot of the compliance audits as well). These are not things you want to sweep under the rug. It’s true that HIPAA does not see many enforcement acts around the privacy aspects as some of the other, jazzier regulations. But health organizations also tend to err on the side of caution and use HIPAA-certified hosting and tech stacks, as any medical provider will be sure to complain about to you if you ask them how they enjoy their Electronic Medical Records system.

Section 230 of the Communications Decency Act

Also known as the legal underpinnings of the modern internet, Section 230 provides that "No provider or user of an interactive computer service shall be treated as the publisher or speaker of any information provided by another information content provider."

In practice, this means that platforms that publish user-generated content (UGC) will not be treated as the "publisher," in the legal sense, of that content for the purposes of liability for libel, etc. This does not mean they are immune from copyright or other criminal liabilities but does provide a large measure of leeway in offering UGC to the masses.

It's also important to note the title of the section, "Protection for private blocking and screening of offensive material." That's because Section 230 explicitly allows for moderation of private services without exposing the provider to any liability for failing to do so in some instances. Consider a social media site that bans Nazi content; if that site lets a few bad posts go through, it does not mean they are on the hook for those posts, at least legally speaking. Probably a good idea to fix the errors lest they be found guilty in the court of public opinion, though.

GLBA

The Graham-Leach-Biley Act is a sort of privacy protection policy for financial institutions. It doesn’t lay out anything particular novel or onerous - financial institutions need to provide a written privacy policy (what data is collected, how it’s used, how to opt-out), and provides some guidelines companies need to meet about safeguarding sensitive customer information. The most interesting, to me, requirement is Pretext Protection, which actually enshrines in law that companies need to have policies in place for how to prevent and mitigate social engineering attacks, both of the phishing variety as well as good old-fashioned impersonation.

COPPA

The Children's Online Privacy Protection Rule (COPPA, and yes, it’s infuriating that the acronym doesn’t match the name) is one of the few regulations with teeth, largely because it is hyperfocused on children, an area of lawmaking where overreaction is somewhat common.

COPPA provides for a number of (now) common-sense rules governing digital interactions that companies can have with children under 13 years old. Information can only be collected with:

  • Explicit parental consent.

  • Separate privacy policies must be drafted and posted for data about those under 13.

  • A reasonable means for parents to review their children's data.

  • Establish and maintain procedures for protecting that data, including around sharing that data.

  • Limits on retention of that data.

  • Prohibiting companies from asking for more data than is necessary to provide the service in question.

Sound weirdly familiar, like GDPR? Sure does. Wondering why only children in the US are afforded such protections? Us too!

FERPA

The Family Educational Rights Protection Act is sort of like HIPAA, but for education. Basically, it states that the parents of a child have a right to the information collected about their child by the school, and to have a say in the release of said information (within reason; they can't squash a subpoena or anything). When the child reaches 18, those rights transfer to the student. Most of FERPA comes down to the same policy generation around retention and access discussed in the section on HIPAA, though the disclosure bit is far more protective (again, because it's dealing with children).

FTC Act

The Federal Trade Commission Act of 1914 is actually the law that created the Federal Trade Commission, and the source of its power. You can think of the FTC as a quasi-consumer protection agency, because it can (and, depending on the political party in the presidency, will) go after companies for what aren't even really violations of law so much as they are deemed "unfair." The FTC Act empowers the commission to prevent unfair competition, as well as protect consumers from unfair/deceptive ads (though in practice, this has been watered down considerably by the courts).

Nevertheless, of late the FTC has been on a roll, specifically targeting digital practices. An excellent recent example was the settlement by Epic Games, makers of Fortnite. The FTC sued over a number of allegations, including violations of COPPA, but it also explicitly called out the company for using dark patterns to trick players into making purchases. The company’s practice of saving any credit cards used (and then making that card available to the kids playing), confusing purchasing prompts and misleading offers were specifically mentioned in the complaint.

CAN-SPAM

Quite possibly the most useless technology law on the books, CAN-SPAM (Controlling the Assault of Non-Solicited Pornography And Marketing Act) clearly put more time into the acronym than the legislation. The important takeaways are that emails need:

  • Accurate subjects

  • To disclose themselves as an ad

  • Unsubscribe links

  • A physical address for the company

And as your spam box will tell you, it solved the problem forever. This does not, however, mean you can ignore its strictures! As a consultant at a company that presumably wishes to stay on the right side of the law, you should still follow its instructions.

CCPA and Its Ilk

The California Consumer Privacy Act covers, as its name suggests, California residents in their dealings with technology companies. Loosely based on the GDPR, CCPA requires that businesses disclose what information they have about you and what they do with it. It covers items such as name, social security number, email address, records of products purchased, internet browsing history, geolocation data, fingerprints, and inferences from other personal information that could create a profile about your preferences and characteristics.

It is not as wide-reaching or thorough as GDPR, but it’s better than the (nonexistent) national privacy law.

The CCPA applies to companies with gross revenues totaling more than $25 million, businesses with information about more than 50K California residents, or businesses who derive at least 50% of their annual revenue from selling California residents’ data. There are similar measures that have already been made law in Connecticut, Virginia, Colorado, and Utah, as well as other states also considering relevant bills.

Other state regulations

The joy of the United States’ federalist system is that state laws can be different (and sometimes more stringent!) than federal law, as we see with CCPA. It would behoove you to do a little digging into the state regulations when you’re working with specific areas — e.g., background checks, where the laws differ from state to state, as even though you’re not based there, you may be subject to its jurisdiction.

There are two different approaches companies can take to dealing with state regulations: Either treat everyone under the strictest regulatory approach (e.g., treat every user like they’re from California) or make specific carve-outs based on the state of residence claimed by the user.

It is not uncommon, for example, to have three or four different disclosures or agreements for background checks ready to show a user based on what state they reside in. The specific approach you choose will vary greatly depending on the type of business, the information being collected, and the relevant state laws.

A single-image version with the regulations we spoke about grouped under their headers (e.g., Education has FERPA)

How to implement

Data compliance is critical, and the punitive aspects of GDPR’s enforcement means your team must have a solid strategy for compliance.

The most important aspect of dealing with any regulatory issue is first knowing what’s required for your business. Yes, you’re collecting emails, but to what end? If that data is necessary for your business to function, then you have your base-level requirements.

Matching those up against the relevant regulations will provide you with a starting point from which you can begin to develop the processes, procedures and applications that will allow your business to thrive. Don’t rely on “that’s how we’ve always done it” or “we’ve seen other people do x” as a business strategy.

The regulatory environment is constantly shifting, and it’s important to both keep abreast of changes as well as always knowing what data and services are integral to your business’s success. Keeping up with the prevalent standards will aid you not only in not getting sued, but also ensuring your companies that you’re a trustworthy and reliable partner.

How to keep up

It all seems a little daunting, no?

But you eat the proverbial regulatory elephant the same way you do any other large food item: one bite at a time. In the same way you didn’t become an overnight expert in securing your web applications against cross-site scripting attacks or properly manage your memory overhead, becoming a developer who’s well-versed in regulatory environments is a gradual process.

Now that you know about some of the rules that may apply to you, you know what to keep an eye out for. You know potential areas to research when new projects are pitched or started, and you know where to ask questions. You know to both talk to and listen to your company’s legal team when they start droning on about legalistic terms

People always seem confused by the title of this: "What does scrum have to do with measuring productivity?" they ask. And I smile contentedly, because that's the whole point.

Scrum is supposed to be a system for managing product work, iterating and delivering value to the customer. What usually winds up happening is scrum gets used for the management of software development work as a whole, from decisions about promotion to hiring and firing to everything else. That's not what scrum is designed to do, and it shows.

Now, I love to talk about process improvement, completely agnostic of whatever process framework you're using. I would much rather have a discussion about the work you're doing and what blockers you're hitting rather than discussing abstract concepts.

However, if you keep running into the same issues and blockers over and over again, it's usually worth examining your workflows to find out if you're actually applying the theory behind your framework to the actual work you're doing. The concept of Agile specifically is not about the processes involved, but you need to know and understand the rules before you should feel comfortable breaking them.

Processes

I want to start with a quick overview of a few key terms to make sure everyone's on the same page.

  • **Waterfall
**

In waterfall development, every item of work is scheduled out in advance. This is fantastic for management, because they can look at the schedule to see exactly what should be worked on, and have a concrete date by which everything will done.

This is horrible for everyone, including management, because the schedule is predicated upon developers being unerring prophets who are able to forecast not only the exact work that needs to be done to develop a release, but also the exact amount of time said work will take.

The ultimate delimiter of the work to be done is the schedule - usually there’s a specific release date (hopefully but not always far out enough to even theoretically get all the work done); whatever can get done by that date tends to be what’s released.

Waterfall also suffers greatly because it’s completely inflexible. Requirements are gathered months ahead of time; any changes require completely reworking the schedule, so changes are frowned upon. Thus, when the product is released, it’s usually missing features that would have been extremely beneficial to have.

  • Agile

Agile can be viewed as a direct response to waterfall-style development; rather than a rigid schedule, the agile approach embraces iteration and quick releases. The three primary “laws” of agile are:

  • **Law of the customer** - The customer is the number one priority. Rather than focusing on hitting arbitrary milestones or internal benchmarks, agile teams should be focused on delivering products to customers that bring them additional value. A single line of code changed can be more worthwhile than an entirely new product if that line brings extra value to the customer.
    • Law of small teams - Developers are grouped into small teams that are given autonomy in how they implement the features they’re working on. When work is assigned to a team, it’s not done so prescriptively. In the best agile teams, the assignment is, “Here’s the problem we have, go solve it.”

    • Law of the network - There are differing interpretations on how to implement this, but essentially I view of the network as “the whole organization has to buy in to what the agile teams are doing.” The entire organization doesn’t need to have the same structure as the agile teams, but neither can it be structured in a manner antithetical to the processes or outcomes. The easiest counterexample is the entire dev department is using scrum, but the CTO still feels (by virtue of their title) the ability to step in and make changes or contribute code or modify stories on a whim. Just because the CTO is the manager doesn’t mean they have full control over every decision. Basically, law of the network means “respecting the agile method, even if you’re not directly involved.”

    It’s worth noting that agile is a philosophy, not a framework in and of itself. Both kanban and scrum are implementations of the agile philosophy.

  • **Kanban**

    This is usually the most confusing, because both scrum and kanban can use kanban boards (the table of stories, usually denoted by physical or virtual “post-its” that represent the team’s work). Kanban board splits up work into different “stages” (e.g., to-do, doing, done), and provides a visual way to track progression of stories.

    The primary difference between scrum and kanban as a product development methodology is that kanban does not have specific “sprints” of work - the delimiter of work is how many items are in a given status at a given time. For example, if team limits “doing” to four cards and there are already four cards in there, no more can be added until one is moved along to the next stage (usually this means developers will pair or mob on a story to get it through).

  • **Scrum**

    Scrum, by contrast, delimits its work by sprints. Sprints are the collection of work the team feels is necessary to complete to deliver value. They can be variable in their length (though in practice, they tend to be a specified time length, which causes its own issues).

    Scrum requires each team to have at least two people - a product owner and a scrum master. Usually there are also developers, QA and devops people on the team as well, but at a minimum you need the PO and SM.

    The product owner has the vision for what the product should be - they should be in constant contact with customers, potential customers and former customers to figure out how value can be added. The scrum master’s job is to be the sandpaper for the developers - not (as the name implies) their manager or boss, but the facilitator for ceremonies and provide coaching/guidance on stories and blockers.

## Other reasons processes fail

I will note that a lot of the reasons I will list below may also apply to other product management methodologies; however, I’m specifically limiting the scope to how they impact scrum teams.

Lack of product vision

I don’t want to lay the blame entirely on product owners for this issue - very often the problem is with how the role is designed and hired for. Product owners should be the final arbiters for product decisions. They should absolutely consult design, UX and customer service experts for their opinions, but the decisions ultimately lies with them.

Unfortunately, the breadth of skills required to be a good product owner are not in abundant supply, and product owners are, bafflingly, often considered afterthoughts at many organizations.

More than specific skills, though, product owners need to have a vision for what the product could be, as well as the flexibility to adapt that vision when new information comes in. Usually, this requires domain knowledge (that can be acquired, but needs to be done so systematically and quickly upon hiring), steadfastness of conviction and the ability to analyze data properly to understand what customers want.

Far too often product owners essentially turn into feature prioitizers, regurgitating nearly everything customers say they want and assigning a ranking to it. This often comes at the expense of both the product’s conceptual integrity as well as relationships with developers, who are supposed to be given problems to solve, not features to develop. This is the classic feature factory trap.

Mistake the rules for the reason

Far too often, people will adopt the ceremonies or trappings of scrum without actually accepting an agile mindset. This is where my favorite tagline, “that’s just waterfall with sprints” comes from.

If you’ve ever started a project by first projecting and planning how long it’s going to take you to deliver a given set of features, congratulations, you’re using waterfall.

To use scrum, you need to adopt the iterative mindset to how you view your product. If you’re developing Facebook, you don’t say, “we’re going to build a system that allows you to have an activity feed that shows posts from your friends, groups and advertisters, and have an instant messaging product, and ..”

Instead, you’d say, “we’re going to develop a platform that helps people connect to one another.” Then you’d figure out the greatest value you can add in one sprint (e.g., users can create profiles and upload their picture.). You know once you have profiles you’ll probably want the ability to post on others’ profiles, so that’s in the backlog.

That’s it. That’s the planning you do. Because once those releases get into customers’ hands, you’ll then have better ideas for how to deliver the next increment of value.

Simply because an organization has “sprints” and a “backlog” and do “retros” doesn’t mean its’ using scrum, it means it’s using the language of scrum.

Lack of discipline/iteration

Tacking on to the last point, not setting up your team for success in an agile environment can doom the product overall. Companies tend to like hiring more junior developers, because they’re cheaper, but not realizing that a junior developer is not just a senior developer working at 80% speed. Junior developers need to have mentoring and code reviews, and those things take time. If the schedule is not set up to allow for that necessary training and code quality checks to happen, the product will suffer overall.

Similarly, development teams are often kept at a starting remove from everyday users and their opinions/feedback. While I by no means advocate a direct open firehose of feedback, some organizations don’t ever let their devs see actual users using the product, which creates a horrible lack of feedback loop from a UX and product design perspective.

Properly investing in the team and the processes is essential to any organization, but especially one that uses scrum.

Lack of organizational shift

The last ancillary reason I want to talk about in terms of scrum failure is aligning the organization with the teams that are using scrum (we’re back to the law of network, here). Scrum does not just rely on the dev team buying in, it also requires the larger organization to at least respect the principles of scrum for the team.

The most common example of this I see is when the entire dev department is using scrum, but the CTO still feels (by virtue of their title) the ability to step in and make changes or contribute code or modify stories on a whim. Just because the CTO is the manager doesn’t mean they have full control over every decision. Removing the autonomy for the team messes with the fundamental principles of scrum, and usually indicates there will be other issues as well (and I guarantee that CTO will also be mad when the scrum is now unbalanced or work doesn’t get done, even though they’re the direct cause).

No. 1 reason scrum fails: It’s used for other purposes

By far, the biggest reason I see scrum failing to deliver is when the ceremonies or ideas or data generated by scrum gets used for something other than delivering value to the end users.

It’s completely understandable! Management broadly wants predictability, the ability to schedule a release months out so that marketing and sales can create content and be ready to go.

But that’s not how scrum works. Organizations are used to being able to dictate schedules for large releases of software all at once (via waterfall), and making dev deliver on those schedules. If you’re scheduling a featureset six months out, it’s almost guaranteed you’re not delivering in an agile manner.

Instead of marketing-driven development, why not flip the script and have development-driven marketing? There is absolutely no law of marketing that says you have to push a new feature the second it’s generally available. If the marketing team keeps up with what’s being planned a sprint in an advance, that means they’d typically have at least a full month of leadtime to prepare materials for release.

Rather than being schedulable, what dev teams should shoot for is reliability and dependability. If the dev team commits to solving an issue in a given sprint, it’d better be done within that sprint (within reason). If it’s not, it’s on the dev team to improve its process so the situation doesn’t happen again.

But why does scrum get pulled off track? Most often, it’s because data points in scrum get used to mean something else.

Estimates

The two hardest problems in computer science are estimates, naming things, and zero-based indexes. Estimates are notoriously difficult to get right, especially when developing new features. Estimates get inordinately more complex when we talk about story pointing.

Story points are a value assigned to a given story. They are supposed to be relative to other stories in the sprint - e.g., a 2 is bigger than a 1, or a medium is bigger than a small, whatever. Regardless of the scale you’re using, it is supposed to be a measure of complexity for the story for prioritization purposes only.

Unfortunately, what usually winds up happening is teams adopt some sort of translation scale (either direct or indirect), something like 1 = finish in an afternoon, 2 = finish in a day, 3 = multiple days, 5 = a week, etc. But then management wants to make sure everyone is pulling their fair share, so people are gently told that 10 is the expectation for the number of points they should complete in a two-week sprint, and now we are completely off the rails.

Story points are not time estimates. Full stop.

It’s not a contract, you’re not a traffic cop trying to make your quota. Story points are estimates of the complexity of a story for you to use in prioritization. That’s it.

I actually dislike measuring sprint velocity sprint-to-sprint, because I don’t think it’s helpful in most cases. It actually distorts the meaning of a sprint. Remember, sprints are supposed to be variable in length; if your increment of value is small, have a small sprint. But because sprint review and retro have to happen every second Friday, sprints have to be two weeks. Because the sprint is two weeks, now we have two separate focii, and the scrum methodology drifts further and further away.

Campbell’s law is one of my favorite axioms. Paraphrased, it states:

The more emphasis placed on a metric, the more those being measured will be incentivized to game it.

In the case above, if developers are told they should be getting 10 points per sprint, suddenly their focus is no longer on the customer. It’s now on the number of story points they have completed. They may be disincentivized to pick up larger stories, fearing they might get bogged down. They’re almost certainly going to overestimate the complexity of stories, because now underestimates mean they’re going to be penalized in terms of hitting their targets.

This is where what I call the Concilio Corollary (itself a play on the uncertainty principle) comes into play:

You change the outcome of development by measuring it.

It’s ultimately a question of incentives and focus. If you start needing to worry about metrics other than “delivering value to the user,” then your focus drifts from same. This especially comes into play when organizations worry about individual velocity.

I don’t believe in the practice of “putting stories down” or “pick up another story when slightly blocked.” If a developer is blocked, it’s on the scrum master and the rest of the team to help them get unblocked. But I absolutely understand the desire to do so if everybody’s expected to maintain a certain momentum, and other people letting their tasks lie to help you is detrimental to their productivity stats. How could we expect teamwork to flourish in such an environment?

So how do we measure productivity?

Short answer: don’t.

Long answer: Don’t measure “productivity” as if it’s a value that can be computed from a single number. Productivity on its own is useless.

I used to work at a college of medicine, and after a big website refresh they were all excited reporting how many pageviews the new site was getting. And it makes sense, because when we think of web analytics, we think page views and monthly visitors and time on site, all that good stuff.

Except … what’s the value of pageviews to a college? They’re not selling ads, where more views works out to more money. In fact, the entire point of the website was to get prospective students to apply. So rather than track “how many people looked at this site,” what they should have been doing was looking at “how many come to this site and then hit the ‘apply now’ button,” and comparing that to the previous incarnation.

First, you need to figure out what the metrics are being used for. There are any number of different reasons you might want to measure “productivity” on a development team. Some potential reasons include performance reviews, deciding who to lay off, justifying costs, figuring out where/whether to invest more, or fixing issues on the development team.

But each of those reasons has a completely different dataset you should be using to make that decision. If you’re talking about performance reviews, knowing the individual velocity of a developer is useless. If it’s a junior, taking on a 5-point story might be a huge accomplishment. If you’re looking at a principal or a senior, you might actually expected a lower velocity, because they’re spending more time pairing with other developers to mentor them or help them get unblocked.

Second, find the data that answers the question. When I worked at a newspaper, we used to have screens all over the place that showed how many pageviews specific articles were getting. Except, we didn’t sell ads based on total pageviews. We got paid a LOT of money to sell ads to people in our geographical area, and a pittance for everything else. A million pageviews usually meant we had gone viral, but most of those hits were essentially worthless to us. To properly track and incentivize for best return, we should have been tracking local pageviews as our primary metric.

Similarly, if you’re trying to justify costs for your development team, just throwing the sprint velocity out there as the number to look at might work at the beginning, but that now becomes the standard you’re measured against. And once you start having to maintain features or fix bugs, those numbers are going to go down (it’s almost always easier to complete a high-point new-feature story than a high-point maintenance story, simply because you don’t have to understand or worry about as much context).

There are a number of newer metrics that have been proposed as standards that dev teams should be using. I don’t have an inherent problem with most of these metrics, but I do want to caution not to just adopt them wholesale as a replacement for sprint velocity. Instead, carefully consider what you’re trying to use the data for, then select those metrics that provide that data. Those metrics are SPACE and DORA. Please note that these are not all individual metrics; some of them (such as “number of handoffs”) are team-based.

SPACE

• Satisfaction and well-being

◦ This involves developer satisfaction surveys, analyzing retention numbers, things of that nature. Try to quantify how your developers feel about their processes.

• Performance

◦ This might include some form of story points shipped, but would also include things like number and quality of code reviews.

• Activity

◦ Story points completed, frequency of deployments, code reviews completed, or amount of time spent coding vs. architecting, etc.

• Communication/collaboration

◦ Time spent pairing, writing documentation, slack responses, on-call/office hours

• Efficiency/flow

◦ Time to get code reviewed, number of handoffs, time between acceptance and deployment

DORA

DORA, or DevOps Research and Assessment, are mostly team-based metrics. They include:

• Frequency of deployments

• Time between acceptance and deployment

• How frequently deployments fail

• How long it takes to recover/restore from failed

Focus on impact

But all of these metrics should be secondary, as the primary purpose of a scrum team is to deliver value. Thus, the primary metrics should measure direct impact of work: How much value did we deliver to customers?

This can be difficult to ascertain! It requires a lot of setup and analysis around observability, but these are things that a properly focused scrum team should already be doing. When the dev team is handed a story for a new feature, one factor of that story should be success criterion: e.g., at least 10% of active users use this feature in the first 10 days. That measurement should be what matters most. And failing to meet that mark doesn’t mean the individual developer failed, it means some underlying assumption (whether it’s discoverability or user need) is flawed, and should be corrected for the next set of iterations.

It comes down to outcome-driven-development vs. feature-driven-development. In scrum, you should have autonomous teams working to build solutions that provide value to the customer. That also includes accountability for the decisions that were made, and a quick feedback loop coupled with iteration to ensure that quality is being delivered continuously.

TL;DR

In summation, these are the important bits:

• Buy in up and down the corporate stack - structure needs to at least enable the scrum team, not work against it

• Don’t estimate more than you need to, and relatively at that

• Know what you’re measuring and why

Now, I know individual developers are probably not in a position to take action at the level “stop using metrics for the wrong reasons.” That’s why I have a set of individual takeaways you can use.

• Great mindset for performance review

◦ I am a terrible self-promoter, but keeping in mind the value I was creating made it easy for me come promotion time to say, “this is definitively what I did and how I added value to the team.” It made it much easier for me than trying to remember what specific stories I had worked on or which specific ideas were mine.

• Push toward alignment

◦ Try to push your leaders into finding metrics that answer the questions they’re actually asking. You may not be able to get them to abandon sprint velocity right off the bat, but the more people see useful, actionable metrics the less they focus on useless ones.

• Try to champion customer value

◦ It’s what scrum is for, so using customer value as your North Star usually helps cut through confusion and disagreement.

• Get better at knowing what you know / don't know

◦ This is literally the point of sprint retros, but sharing understanding of how the system works will help your whole team to improve the process and produce better software.

Since this post is long enough on its own, I also have a separate post from when I gave this talk in Michigan of questions people asked and my answers.

That's not REAL waterfall, it's just a babbling brook on a hill.

The Game is a mind game in which the objective is to avoid thinking about The Game itself. Thinking about The Game constitutes a loss, which must be announced each time it occurs.

The programming version of The Game has the same rules, but you lose if you think about David Heinemeier Hansson (aka DHH).

And no, I'm not linking to why I lost today.

Broke a four-month winning streak, dangit.

How it feels

Link How it feels

I can't explain how this feels.

Athletics bans don't affect me, personally, in terms of preventing me from playing sports - I'm well beyond the age or ability for it to matter.

But that fact doesn't make it feel any less like another punch to the head, another hit to the gut, another in a long line of kicks when I already feel so beaten down.

I can't explain this feeling.

It's yet another way of being told that we're different, separate from, less than. Trans women are women except. Trans men are men but.

It's especially disheartening when so many struggle to have even the basic aspects of their dignity respected (names, pronouns, getting an education, not getting fired for existing while trans). Time and again, the only concrete actions taken are to strip more from us.

I can't feel.

It's a systematic desecration of our humanity, a systemic approach to telling us not only do we not belong, but that we shouldn't exist.

A cistem built on our destruction.

I can't.

I desperately want to avoid talking about the (junk) science of it all. I'm putting the finishing touches on a conference talk about properly being data-driven - so many people take whatever (bad) available data they have and try to map it to outcomes that are only loosely correlated. This is a prime example.

If the concern is the effects of testosterone on performance, then organize your damn divisions among testosterone blood counts. Period.

Turning Back cover

Turning Back

by Katia Rose

Highly Recommended

It took me a long time to read this book. Not because of the quality (it was softly mesmerizing, to no surprise), but because it's the second in what I assume is to be a trilogy. I kept seeing it in my TBR pile and would go to read it, before remembering that, once I finished it, there would only be one more chance to enter this world for the first time. So I put it off.

It was worth the wait.

Katia Rose's remote Vancouver (BC) campground – where these stories take place – even makes me, an avowed inside-only kitty, want to drive out and pitch a tent in the wilderness. Though perhaps there was a touch too much romanticism in the wild's seduction of the main character city girl, it's described with such loving detail that it's impossible not to get swept away.

The characters, as is always the case with Rose, are painstakingly crafted with realistic backstories, baggage, fears and doubts. But even grounded in realism, the sparks between the two main characters (Kennedy and Trish) are more than enough to convince of the romance catching hold, sweeping them away.

I thoroughly enjoyed this book, and wait with some trepidation for the last entry. It can't come soon enough and yet, I know, I'll have to wait to read it.

Synopsis

Trish Rivers lives a good life.   A happy life.   A safe and predictable life spent running the cafe at her family’s campground, perfecting her award-winning recipes, and terrorizing the local small town bartender with her endless supply of bad jokes.   Trish has never wanted more—or at least, she’s never admitted she wants more, but that was before Kennedy March showed up on Vancouver Island.   That was before Trish realized falling for your sister’s girlfriend’s best friend doesn’t fit into a safe and predictable life, especially when you’ve never fallen for a girl before.   Kennedy’s not sure why life as a real estate star in Toronto doesn’t feel quite as shiny as it used to, but a spontaneous vacation to visit her newly coupled-up best friend seems like the perfect opportunity to ignore the problem.   Three weeks without client calls, benefit galas, and, most of all, dating apps is worth braving the woods for, but her plans for relaxation come crashing to a halt at the sight of Trish—the absolutely off-limits and definitely straight little sister of her best friend’s new girlfriend.   There’s no path to each other that doesn’t end in disaster, but the farther they go, the more Trish and Kennedy realize it might be too late to turn back.

Almost enough to make me want to visit Canada. Almost. (j/k I love British Columbia, and no other provinces.)

I grew up on Clean Code, both the book and the concept. I strove for my code to be “clean,” and it was the standard against which I measured myself.

And I don’t think I was alone! Many of the programmers I’ve gotten to know over the years took a similar trajectory, venerating CC along with Code Complete and Pragmatic Programmer as the books everyone should read.

But along the way, “clean” started to take on a new meaning. It’s not just from the context of code, either; whether in interior design or architecture or print design, “clean” started to arise as a synonym for “minimalism.”

This was brought home to me when I was working with a junior developer a couple years ago. I refactored a component related to one we working on together to enable necessary functionality, and I was showing him the changes. This was a 200-line component, and he skimmed it about 45 seconds before saying “Nice, much cleaner.”

And it bugged me, but I wasn’t sure why. He was correct - it was cleaner, but it felt like that shouldn’t have been something he was accurately able to identify simply by glancing at it. Or at least, if that was the metric he was using, “clean” wasn’t cutting it.

Because the fact of the matter is you can’t judge the quality of code without reading it and understanding what it’s trying to do, especially without considering it in the context of its larger codebase. You can find signifiers (e.g., fewer lines of code, fewer methods in a class), but “terse” is not a direct synonym of “clean.” Sometimes less code is harder to understand or maintain than more code.

I wanted to find an approach, a rubric, that allowed for more specificity. When I get feedback, I much prefer hearing the specific aspects that are being praised or need work on - someone telling me “that code’s clean” or not isn’t particularly actionable.

So now I say code should be Comprehensible, Predictable and Maintainable. I liked those three elements because they’re important on their own, but also each builds on the others. You cannot have predictable and maintainable code unless it’s also comprehensible, for example.

  • Comprehensible - People other than the author, at the time the code is written, can understand both what the code is doing and why.

  • Predictable - If we look at one part of the code (a method, a class, a module), we should be able to infer a number of properties about the rest.

  • Maintainable - Easy to modify and keep up, as code runs forever

Comprehensibility is important because we don’t all share the context - even if you’re the only person who’s ever going to read the code, the you of three weeks from now will have an entirely different set of issues you’re focusing on, and will not bring the same thoughts to bear when reasoning about the code. And, especially in a professional context, rare is the code that’s only ever read by one other person.

Predictability speaks to cohesion and replicability across your codebase. If I have a method load on a model responsible for pulling that object’s information from the database, all the other models should use load when pulling object info from the DB. Even though you could use get or loadFromDb or any number of terms that are still technically comprehensible, the predictability of using the same word to mean the same thing reduces overall cognitive load when reasoning about the application. If I have to keep track of which word means the action I’m trying to take based on which specific model I’m using, that’s a layer of mental overhead that’s doing nothing toward actually increasing the value or functionality of the software.

Maintainability is the sort of an extension of comprehensibility - how easy is it the code to change or fix down the road? Maintainability includes things like the “open to extension, closed to modification” principle from SOLID, but also things like comments (which we’ll get to, specifically, later on). Comprehensibility is focused on the “what” the code is doing, which often requires in-code context and clear naming. Maintainability on the other hand, focuses on the “why” - so that, if I need to modify it later on, I know what the intent of the method/class/variable was, and can adjust accordingly.

The single most important aspect of CPM code is naming things. Naming stuff right is hard. How we name things influences how we reason about them, how we classify them, and how others will perceive them. Because those names eventually evolve to carry meaning on their own, which can be influenced by outside contexts, and that whole messy ball of definition is what the next person is going to be using when they think about the thing.

I do believe most programmers intellectually know the importance of naming things, but it’s never given the proper level of respect and care its importance would suggest. Very rarely do I see code reviews that suggest renaming variables or methods to enhance clarity - basically, the rule is if it’s good enough that the reviewer understands it at that moment, that’s fine. I don’t think it is.

A class called User should contain all the methods related to the User model. This seems like an uncontroversial stance. But you have to consider that model in the context of its overall codebase. If there is (and there should be) also a class called Authorization in that codebase,  there are already inferences we should be able to draw simply from the names of those two things.

We should assume User and Authorization are closely related; I would assume that some method in Authorization is going to be responsible for verifying that the user of the application is a User allowed to access parts of the application. I would assume these classes are fairly tightly coupled in some respects, and it would be difficult to use one without the other, in some respect.

Names provide signposts and architecture hints of the broader application, and the more attuned to them you are (as both a writer and reader of code), the more information will be able to be conveyed simply by paying attention to them.

If naming is the single most important aspect of CPM, the single most important aspect of naming things is consistency. I personally don’t care about most styling arguments (camelCase vs. snake_case, tabs vs. spaces, whatever). If there’s a style guide for your language or framework, my opinion is you should follow it as closely as possible, deviating only if there’s an actual significant benefit to doing so.

Following style conventions has the two advantages: allowing for easier interoperability of code from different sources, and enabling the use of linters and formatters.

Code is easier to share (both out to others and in from others) if they use same naming conventions and styles, because you’re not adding an extra layer of reasoning atop the code. If you have to remember that Library A uses camelCase for methods but Framework B uses snake_case, that’s however large a section of your brain that is focusing on something other than the logic of what the code is doing.

And enabling linters and formatters means there’s a whole section of code maintenance you no longer have to worry about - you can offload that work to the machine. Remember, computers exist to help us solve problems and offload processing. A deterministic set of rules that can be applied consistently is literally the class of problems computers are designed to handle.

Very broadly, my approach to subjective questions is: Be consistent. Anything that doesn’t directly impact comprehensibility is a subjective decision. Make a decision, set your linter or formatter, and never give another thought to it. Again, consistency is the most important aspect of naming.

But a critically under-appreciated aspect of naming is the context of the author. Everyone sort of assumes we all share the same context, in lots of ways. “Because we work on the same team/at the same company, the next developer will know the meaning of the class PayGrimples.” That may be very broadly true, in that they’ve probably heard of PayGrimples, but it doesn’t mean they share the same context.

A pop-culture example of this is pretty easy - think of the greatest spaceship pilot in the universe, one James Tiberius Kirk. Think about all his exploits, all the strange new worlds he’s discovered. Get a good picture of him in your head.

Which one did you pick? Was it The Original Series’ William Shatner? The new movies’ Chris Pine? Or was it Strange New Worlds’ Paul Wesley?

You weren’t wrong in whatever you picked. Any of those is a valid and correct answer. But if we were talking about Kirk in conversation, you likely would have asked to clarify which one I meant. If we hadn’t, we could talk about two entirely different versions of the same concept indefinitely until we hit upon a divergence point when one of us realized.

Code has that same issue, except whoever’s reading it can’t ask for that clarification. And they can only find out they’re thinking about a different version of the concept if they a) read and digest the code in its entirety before working on it, or b) introduce or uncover a bug in the course of changing it. So when we name things, we should strive for the utmost clarity.

⛔ Unclear without context

type User = { id: number; username: string; firstName: string; lastName: string; isActive: boolean; }

The above is a very basic user model, most of whose properties are clear enough. Id, username, firstName and lastName are all pretty self-explanatory. But then we get to the boolean isActive.

This could mean any number of things in context. They include, but are not limited to:

  • The user is moving their mouse on the screen right now

  • The user has a logged-in session

  • The user has an active subscription

  • The user has logged in within the last 24 hours

  • The user has performed an authenticated activity in the last 24 hours

  • The user has logged in within the last 60 days

All of those are things we may want to know about the user of any application, depending on what we’re trying to do. Even similar-sounding events with the same time horizon (logged in within the last 24 hours vs. authenticated activity in the last 24 hours) give us different information - I can infer the maximum age of the authentication token in the logged-in case, but without knowing the token exchange process, I cannot make the same inference for authenticated activity.

So why not just provide the meaning with the name?

✅ Clarity without context

type User = { id: number; username: string; firstName: string; lastName: string; loggedInPrevious24Hours: boolean; }

Clarity comes through naming things explicitly. Ambiguity is the enemy of clarity, even when you assume the person reading the code should know something.

It’s reasonable to assume that the people reading your code are developers - that is, people familiar with coding concepts. Every other context (industry/domain, organization) is not a safe assumption. Therefore, if you have names or terms that are also used in coding, you should clarify the other meaning. (You should do this generally, as well, but specifically with programming-related terms.)

⛔ Ambiguity kills comprehension

class Class {} class Post {}

The word “class” is generally understanding in programming as an object-oriented prototype. Outside of programming, it could refer to a classroom of children; a classification system; a group of children in the same grade (e.g., junior class); or a social hierarchy (e.g., upper-class, lower-class).

Post is even worse, because it can be a verb or a noun even in a programming context. Blogs usually have posts, but you can also post content (or the HTTP verb, POST). Non-tech-wise, we have places to which you can be sent (“I’m being sent to our post in London”), referring to the mail system, or even structural support for fences.

✅ Specificity aids everyone

class Classroom {} class BlogPost {}

All of this is important because being clear matters more than being concise or clever. After consistency, the most important aspect of naming is being descriptive. The name should describe what the code is doing (vs. why or how) - what a method is doing, or what purpose a variable serves.

For the most part, Classes should be nouns, because they’re describing their domain of influence. Methods should include verbs, because they’re performing actions. Variables should be nouns, reflective of whatever purpose they’re serving.

If you find yourself struggling with the length of your names of methods, variables or classes, that’s not a bad thing. It’s usually a sign you need to consider refactoring (more on this a bit later).

To the point of clarity, be sure to use properly spelled real words and names.

⛔ Abbreviations and shortcuts

class DateUtil { static function dateStrFrmo(date: Date): string { ... } }

Humans have surprisingly good short- and medium-term recall around words and names. Using real words and names makes the concept easier for us to reason about, and easier to keep track of in our heads.

I took the example above from a GitHub code search. I think the original example may have been written by a native German speaker, because if we assume “Frmo” is supposed to be “From,” it’s using the German sentence structure that puts the verb at the end of the sentence. That makes sense! But if someone isn’t familiar with that sentence construction, the name of the method becomes functionally useless.

The misspelling part is important in two respects: one, it can introduce confusion (is it supposed to be “from” or ”form”?). The other is relying on the computer - searches, within the IDE or if you’re GREPing, are looking for specific terms. If it’s spelled wrong, it’s not going to get caught in the search.

✅ Use properly spelled real words and names

class DateUtil { static function getStringFromDate(date: Date): string { ... } }

Here we’ve modified it so we essentially have an English sentence - get the string from the date. I know what’s being passed in (the date), and I know what’s coming out (the string), and I know overall what’s happening (I’m getting the string from the date).

Beyond naming, there is one other “big” rule that gets us to comprehensible, predictable and maintainable code, an old adage: “Keep it simple, sweetheart.” I’m not speaking to system complexity here - your overall architecture should be as complex as needed to do the job. It’s closer to SOLID’s single-responsibility principle, writ large: Every module, every class, every method, every variable should have one job.

To our earlier example of Users and Authorization, users will take care of the users while authorization handles auth. Neither of them should care about the internal workings of the other; Authorization just needs to know it can call User::load to return the user object.

At the method level, this is how we keep our names to a manageable length. You should be able to describe what the method in a very short sentence. If you need more length (or you leave out things it’s doing), it’s probably a sign that the method is trying to do too much.

Smaller methods enable reusability - if the method is only doing a specific thing, we are more likely to be able to use it somewhere else. If the method is doing multiple things, we’d likely need to add a parameter in the other cases where we want to use it, because we don’t want all of those things to happen all the time.

Keeping each method to a single task means we can decompose complex methods into multiple individual methods. This also makes it easier to read the code.

Literally just reading the names of methods allows us to infer what’s going on, divorced of context. For the example below, we would know from the file name this is Typescript, and I’ll give one hint that it’s frontend.

✅ Keep it simple, even for complex actions

function constructor() { this.assignElements(); this.setInterval(); this.getNewArt(); this.listenForInstructions(); }

Initializing this class assigns elements and sets an interval (meaning there are actions that happen on a set schedule); then we get new art, and listen for instructions. Without even knowing the name of the class, we can pretty confidently assume this has to do with art, and that art gets changed frequently (hence the interval). But there also appears to be a manual interruption possible, with listen for instructions.

If we were debugging an issue related to keyboard commands, I would first look to listenForInstructions. If there’s an issue with art not showing up, I would check getNewArt.

Each method is narrowly scoped, even if a lot happens. Keeping things simple aids comprehension and predictability, but it’s also vital for maintainability. It makes it much easier to write tests.

We cannot confidently change code without tests. If we’re making modifications to code without tests, we can read, guess and hope that it won’t create any downstream issues, but unless we know exactly what should happen with a given method in all the ways it can be used, we cannot be certain of the impact of any change. A downstream issue is the definition of a regression; determining the output of a method in changing circumstances is the definition of a test. Thus why we test to avoid regressions.

A good unit test is like a science experiment - a hypothesis is proffered, and borne out or disproven through data, accounting for variables. In programming, variables are literally variables.

If we know exactly what our code will do, we have the flexibility to use it in different circumstances. That may sound tautological, but the confidence we know “exactly” what it will do comes through tests, not an internal sense of “I know what that function does." I would argue most bugs arise through either typos or incorrect assumptions. Most of the typo bugs are caught before release. Most of the insidious bugs that take forever to debug are because someone made an assumption along the way that you have to find and correct.

If all functions perform as we expect, integration issues are drastically reduced. Good unit testing reduces the amount of integration and regression testing you have to do. Maintenance overall becomes easier because we have solid bulwarks of functionality, rather than needing to reason through all possible eventualities fresh every time (or worse, assuming).

I’m not a huge believer in code coverage as a benchmark for quality. I think it can be helpful to have a minimal coverage requirement as you’re starting to remind yourself to write tests, but 100% coverage means absolutely nothing on its own. Quality is much more important than quantity when it comes to testing, especially that you’re testing the right things.

Keeping it simple also relates to abstractions. Code is a series of abstractions (unless you’re writing assembly, in which case, vaya con Dios), but I’m referring specifically to abstractions in the codebase that you write. The cardinal sin of object-oriented programming is a simple rule: “Don’t Repeat Yourself.” It’s not … bad advice, but neither is it a simple panacea we could automate away with, say, a linter or a formatter (or, god forbid, AI).

DRY is overemphasized, possibly because it’s such an easy heuristic to apply. “Hey this looks like other code” is easy to see at a glance, and if you just have an automatic reaction of “I shouldn’t repeat myself ever,” you’ll automatically push that logic up to single method that can be used in multiple places.

But deduplication requires an abstraction. In most cases, you’re not performing exactly the same logic in two places, but two minor variations (or the same logic on two different types of objects). Those variations then require you to include a parameter, to account for a slight branch.

Having that abstracted method hinders comprehensibility. Even if it’s easier/faster to read a one-line reference to the abstracted method, the actual logic being performed now happens out-of-sight.

I am much less concerned with duplication of code than I am making sure we find the right abstraction. Thus, I want to propose a different model for thinking about repetition, two rules  (because again, simpler != terse) to replace the one DRY rule: we’ll call it the Concilio Corollary to the DRY rule, or the damp dyad.

  1. Don’t repeat yourself repeating yourself

  2. The wrong abstraction will cost you more than repetition

DRYRY is a little tongue-in-cheek, but essentially don’t worry about trying to find an abstraction until you’ve implemented similar logic at least three times. Twice is a coincidence, three times is a pattern. Once you’ve seen the code being used in three different places, you now have the context to know whether it’s a) actually doing the same work, and b) how to abstract it to work in different scenarios.

If you find yourself adding a parameter that changes the flow of logic in each scenario, it’s probably more correct to abstract only those small parts that are the same, and implement the particular logic in the context it’s being used. That’s how we find the right abstraction.

All of this is important because existing code has inertia. This is relevant whether you’re a more senior developer or just starting out in your career.

Those with less experience tend to be terrified to change existing code, and understandably so. That code already exists, it’s doing a job. Even if you’re going in to fix a bug, presumably that code was working well enough when it was written that no one noticed it. And no one wants to be the one to create an error, so the existing code is treated as something close to sacrosanct.

For more experienced developers, know that when you’re writing code you’re creating the building blocks of the application. You’re setting the patterns that other developers later will try to implement, because it’s “correct” and becomes that codebase’s style. Heck, that’s literally the predictability maxim - we want to it look similar when it does similar things. But that means if you’re writing the wrong abstraction in one place, its impact may not be limited to that single area.

And when a new case arises, the next developer has to decide (without the context of the person who originally wrote it) whether to modify the existing abstraction, or create a new one. But the old one is “correct” (again, in that exists), so it’s safer to just use that one. Or, worst case, use it as a template to create a new abstraction. In either case, a new paradigm is being created that needs to be tested and raises the overhead on maintenance, because now we have a separate logic branch.

Those are the big topics I wanted to hit. The rest of these recommendations are important, but lack an overall theme. The biggest of these I want to discuss is commenting.

Naming should be used so we know the “what” of code, comments should be used so we know the “why.” I am not referring to automated comments here (e.g., explanations for input parameters in the like in JSDoc), but rather qualitative comments. I would argue that, currently, most existing comments I see would be superfluous if proper naming conventions were used.

What I want to see in a comment is why a particular variable is a particular value, when it’s not clear from the existing context.

⛔ Don't explain the what

const SOCIAL_MEDIA_CHARACTER_COUNT = 116; // shortens title for social media sharing export const getSocialShareText = (post: BlogPost) => { if (post.title.length =< SOCIAL_MEDIA_CHARACTER_COUNT) { return post.title; } else { return post.title.substr(0,SOCIAL_MEDIA_CHARACTER_COUNT); } }

This a pretty typical example of what I see comments used for. We’ve used naming properly (the method gets the social share text, the constant is the character count we use for social media posts)j, so the comment “shortens title for social media sharing” is superfluous.

This method provides the social media content. The piece of information I don’t have about this code that I would like, both for comprehensibility and maintainability, is why the character count is 116.

The answer is that Twitter used to be the social media service with the shortest content length, 140 characters. Except that since we’re developing an app, we’re always including a URL, for which Twitter automatically generates a shortlink that takes up 23 characters (+ 1 for the space between content and link). 140-23-1 = 116.

That context does not exist within the application, and it’s not under our control. So we should include it in a comment, so that if that number changes (or something else becomes popular but has a shorter length limit, or we stop worrying about Twitter entirely), we know both from reading the code what this does, and it puts a signpost with the word “Twitter” in the comment so it can be found if we just do a search.

✅ Explain the "why"

// Twitter has shortest character limit (140); URL shortener is always 23 + space const SOCIAL_MEDIA_CHARACTER_COUNT = 116; export const getSocialShareText = (post: BlogPost) => { if (post.title.length =< SOCIAL_MEDIA_CHARACTER_COUNT) { return post.title + ' ' + post.url; } else { return post.title.substr(0,SOCIAL_MEDIA_CHARACTER_COUNT) + ' ' + post.url; } }

The other thing to keep in mind about comments is that they’re a dependency just as much as code. If we do update that character count, we also need to update the comment explaining it, otherwise we’ve actively corrupted the context for the next person who has to make a change.

I used to say “never use ternaries,” but I’ve come around a bit. I now believe ternaries should be used only declaratively, with proper formatting.

✅ Use declarative ternaries, with formatting

`const title = (postRequest['title']) ? postRequest['title'] : '';

const title = postRequest['title'] || '';`

Ternaries are short, concise, and difficult to reason about if they’re too complicated. When I say “declarative” ternaries, I mean “the value of a variable is one of two options, dependent upon a single condition.”

If you need to test multiple conditions, or if you have more than one variable changing as a result of a condition or set of conditions, don’t use ternaries. Use regular if-else statements. It’s easier to read and comprehend, and it’s easier to make changes down the road (more likely if already have multiple conditions or states).

And never nest ternaries.

The last bit is around testing, specifically standard library functions. A standard library function is one that comes packaged in with the programming language you’re using - think Math.round() for Javascript, or the above substring method on strings str.substr(0,3).

As a rule, you should not test the functionality of code you have no control over - if Chrome is shipping a bad Math.round(), there isn’t anything you can do about it (plus, if you go down that rabbit hole long enough you’ll eventually have to test that the heat death of the universe hasn’t yet happened). Standard library functions fit that description.

But sometimes you do you want to test a method that only uses standard library functionality - the reason is not that you’re testing that functionality, but rather that you’re arriving at the desired result.

We’ll use the social media text as the example. I will always assume substring is working properly until I get user reports, and even then the most I would do is forward them along. What I want to test for is the length of the string that is returned - does it meet my requirements (under 116)? I’m not testing the functionality, I’m including a flag to myself and future developers that this is the maximum length and, if someone modifies the functionality of the method, it should be flagged.

describe('getSocialMediaText restricts to Twitter length', ()=> { it('when title is less than length', () => { expect(getSocialMediaText(MockPostShortTitle).length =< 116) }), it('when the title is more than length', () => { expect(getSocialMediaText(MockPostLongTitle).length =< 116) }) });

If we were testing functionality, I would call the same constant in my test, because that’s what’s being used internally. But because I’m testing outcomes, I use an independent value. If someone changes the length without changing the test, they’ll get notified. They can at that point change the value used in the test, too, but the test has served its purpose - it notified someone when they violated my “why.”

TL;DR

  • Focus on specific aspects of code quality
  • Comprehensible, Predictable, Maintainable
  • Name stuff properly
    • Clarity over concision and wit
  • Keep things simple
    • One module, one class, one method, one variable: One job
  • Write tests
    • The only way to confidently modify or reuse code is be assured of what it does
  • Remember the damp dyad
    • Don’t repeat yourself repeating yourself

    • The wrong abstraction costs more than repetition

  • Comments should explain "why"
    • Provide context for the next person (let naming focus on “what”)

It is definitely TL, but if I had to W it, you have to R it. Or just come to one of my talks!

When I gave my talk, "That's not real scrum: Measuring and managing productivity for development teams" at MiTechCon 2024 in Pontiac, MI, there were a number of great questions, both in-person and from the app. I collected them here, as a supplement to the accessible version of the talk.

Q: What are best practices on implementing agile concepts for enterprise technology teams that are not app dev (e.g., DevOps, Cloud, DBA, etc.)?

A brief summary: 1) Define your client (often not the software's end-user; could be another internal group), and 2) find the way to release iteratively to provide them value. This often requires overcoming entrenched models of request/delivery — similar to how development tends to be viewed as a "service provider" who gets handed a list of features to develop, I would imagine a lot of teams trying to make that transition are viewed as providers and expected to just do what they're told. Working back the request cycle with the appropriate "client" to figure out how to deliver incremental/iterative value is how you can deliver successfully with agile!

Q: How do I convince a client who wants stuff at a certain time to trust the agile process?

There's no inherent conflict between a fixed-cost SOW and scrum process. The tension that tends to exist in these situations is not the cost structure, but rather what is promised to be delivered and when. Problems ensue when you're delivering a fixed set of requirements by a certain date - you can certainly do that work in a somewhat agile fashion and gain some of the benefits, but you're ultimately setting yourself up to experience tension as you get feedback through iterations that might ultimately diverge from the original requirements.

This is the "change order hell" that often comes with client work — agile is by definition flexible in its results, so if we try to prescribe them ahead of time, we're setting ourselves up for headaches. That's not to say it's not worth doing (the process may be beneficial to the people doing the work if the waterfall outcome is prescribed), but note (to yourself and the client) that a waterfall outcome (fixed set of features at a fixed date) brings with it waterfall risk, even if you do the work in an agile fashion.

It is unfortunately very often difficult, but this is part of the "organizational shift" I spoke about. If the sales team does not sell based on agile output, it's very difficult to perform proper agile development in order the reap all its benefits.

Q: We're using Agile well; How do we dissuade skip-level leadership from demanding waterfall delivery dates using agile processes?

This is very similar to the previous answer, with the caveat that it's not on you to convince a level of leadership beyond your own manager of anything. You can and should be providing your manager with the information and advice mentioned in the above answer, but ultimately that convincing has to come from the people they manage, not levels removed. Scrum (and agile, generally) requires buy-in up and down the corporate stack.

Q: What are best practices for ownership of the product backlog?

Best practices are contextual! Ownership of the product backlog is such a tricky question.

In general, I think product backlogs tend to have too many items. I am very much a fan of expiring backlog items — if they haven't been worked on in 30 days (two-ish sprints), they go away (system-enforced!) until the problem they address comes up again.

The product owner is accountable for the priority and what's included or removed from the product backlog.

I kind of think teams should have two separate stores of stories: One is the backlog, specific ideas or stories that are going to be worked on (as above) in the next sprint or two), which is the product owner's responsibility. The second is a brainstorming pool — preferably not even in the same system (because it is NOT the case that you should be just be plucking from the pool and plopping on the backlog). Rather, these are just broad ideas or needs we want to capture so we don't lose sight of them, but from them, specific problems are identified and stories written. This should be curated by the product owner, but allow for easier/broader access to add to it.

Q: Is it ever recommended to have the Scrum Master also be Product Manager?

(I am assuming for the sake of this question that Product Manager = Product Owner. If I am mistaken, apologies!)

I would generally not**** recommend the product owner and the scrum master be the same person, though I am aware by necessity it sometimes happens. It takes a lot of varied skills to do both of those jobs, and in most cases if it happens successfully it's because there's a separate system in place to compensate in one or both areas. (e.g., there's a separate engineering manager who's picking up a lot of what would generally be SM work, or the product owner is in name only because someone else/external is doing the requirements- gathering/customer interaction). Both positions require a TON of work to perform properly - direct customer interaction, focus groups, metrics analysis and stakeholder interaction are just some of a PM's duties, while the SM should be devoted to the dev team to make sure any blocks get cleared and work continues apace.

But even more than time, there's a philosophical divide that would be difficult to resolve in one person. The SM should be looking at things from a perspective of what's possible now, whereas the PM should have a longer-term view of what should be happening soon. Rare is the individual who can hold both of those things in their head with equal weight; usually one is going to be prioritized over the other, to the detriment of the process overall.

Q: What is the best (highest paying) Scrum certification?

If your pay is directly correlated with the specific certification you have, you are very likely working for the company that provides it. Specific certifications may be more favored in certain industries or verticals, but that's no more than generally indicative of pay than the difference between any two different companies.

More broadly, I view certifications as proof of knowledge that should be useful and transferable regardless of specific situation. Much like Agile, delivering value (and a track record of doing same) is the best route to long-term career success (and hence more money).

Q: Can you use an agile scrum approach without a central staffing resource database?

Yes, with a but! You do not need a formal method of tracking your resourcing, but the scrum master (at the team level) needs to know their resourcing (in terms of how many developers are going to be available to work that sprint) in order to properly plan the sprint. If someone is taking a vacation, you need to either a) pull in fewer stories, b) increase your sprint length, or c) pull in additional resources (if availble to you).

Even at the story level, this matters. If you have a backend ticket and your one BE developer is out, you're not gonna want to put that in the sprint. But it doesn't need to be a formal, centralized database. It could be as simple as everyone noting their PTO during sprint planning.

What's always both heartening and a little bit sad to me is how much the scrum teams want to produce good products, provide value, and it's over-management that holds them back from doing so.