A Tale of map and parseInt in Three Acts Act 1: What?! import { describe, it, expect } from '@jest/globals'; describe("map parseInt over an array of strings", () => { it("should parse both numbers, but doesn't seem to", () => { expect(["0", "0"].map(parseInt)).toStrictEqual([0, 0]); }); }); The actual result is [0, NaN] . Huh. Act 2: Hmmm…. import { describe, it, expect } from '@jest/globals';…
Do you know the Rule of Three in refactoring? (If not, then read the References section.) More than a quarter century after this heuristic received its name, it continues to confuse and divide programmers. Most notably, some programmers swear by it while others (and I count myself as one) take a more relaxed attitude towards it. This lies at the center of the ongoing debate between whether to…
Today I read Jason Gorman’s “TDD Under the Microscope: One Outcome Per Test” . I like this and I propose one step more: the emergence of two interesting outcomes itself signals a potentially-helpful abstraction. First, let me restate the principle in Jason’s article, which I tend to follow: When one action leads to two interesting outcomes, consider writing two tests with the same action. … but it…
Before You Begin What is the Saff Squeeze? Read this tutorial . The Example I use jq to turn JSON into Plain Text Accounting journal entries. In particular, I administer a bowling league and use hledger to track the league finances. Each week, we collect cash from bowlers, pay some of that money to bowling center, and use the rest to fund prizes. When we collect cash, we record what we collect,…
This comment arose recently at The jbrains Experience in a discussion about whether all software design choices are “like, just my opinion, man”. I’ve kind of looked at this in the way. That a beginner needs rules because they don’t yet have the experience to judge each situation on its own. I suppose I am in a way asking for a rule to help hone my judgement when I should or might want to…
I’d like to share a few little points to help you or someone you care about through their day. You can write good code without TDD. Even the act of trying to write one test is already enough to clarify your thinking about what the system (or some part of it) ought to do. You don’t have to do TDD 100% all the time perfectly in order to benefit from doing it some of the time and pretty well. You…
I’ve been reading Kent Beck’s writing on Substack and on the occasion of the death of Niklaus Wirth , he shared part of a conversation he’d had with the professor when Kent had arranged to sit next to him on the flight home from a conference they’d both spoken at. Extreme Programming was just starting to crackle & pop, so I’m sure I was a bit over-enthusiastic. After I had given an impassioned…
Overture You’ve probably seen code like this: if (condition) ...more code... You’ve probably seen code that looks like this, and then after you understand it, you think of it more like this: if (protective_condition) ...now it's safe to run this code... You’ve almost certainly considered expressing this intention more directly using a Guard Clause: a structural pattern that emphasizes the…
I see so many programmers tying themselves up in knots, trying to find “the right” testing strategy. I’d like to offer them a simple idea intended to make at least one of these knots loosen itself and disappear. This issue shows up in a few forms: Which is better: TDD or BDD? Which should I write: functional tests or unit tests? The testing pyramid is wrong and I have invented a new shape for…
By now you’ve probably heard of Four Elements of Simple Design , among which you’ll find this suggestion: reveal intent . You’ve probably also read articles about how to do this, many of which feel entirely subjective and seem to beg their own question: if it’s enough to improve names, then I need good judgment to improve names; how do I develop that judgment? Deliberate practice . Repetition.…
I considered calling this article “Stubs Aren’t Parsers”, in the grand tradition of “Mocks Aren’t Stubs” and even “Stubs Aren’t Mocks” (which I never wrote, but wanted to). I don’t love the blaming tone of that title, even though it might feel catchy and sticky , so I’ve gone for a more-boring, less-blaming title. In his “The Hidden Cost of Mockito” 1 , Lars Eckart presents an example in Java of…
A member of The jbrains Experience posted about a name they had just encountered in their day-job code base: compareReportedProfileToTargetProfileAndReportResultToSupervisor() They reported that they’d already renamed the method, but I immediately saw it as an example of how naming fits together with refactoring. I wanted to combine a version of playing “What’s Not To Like About This Code?” with…
I have witnessed programmers express annoyance about how tests seem to interfere with changing production code. A discussion on this topic led here : In particular, it raised this commonly-heard expression of frustration in the vein of “Ask Why, But Never Answer” Aren’t tests supposed to make refactoring easier??? No. Isn’t that better? You can let go of this expectation now. May you be at peace.…
A member of my mentoring group started a discussion regarding this article: Victor Rentea’s “Overengineering in Onion/Hexagonal Architectures” . They commented that the article made them feel uncomfortable, because Victor’s advice seemed to be to drop all these architecture choices, because they represent overengineering. I wrote some words about this topic there and then I decided to refine my…
In the middle of a discussion about test doubles/mock objects and their role in design, someone posted this: Reminder: arguing against a toot does not imply critiquing the tooter. I’d like to focus on these parts 1 : “mocks expectations are repeated, if the contract changes you have to change all the expectations” “for me building software with ‘real’ parts feels better and more natural. it works,…
Code Reviews have a bad reputation. It seems easy to do them poorly, to create friction, to hurt people, and to waste both time and energy doing them. For this reason, I developed a simple serious game: “What’s Not To Like About This Code?” I’m going to practise criticizing code in public. I’ve decided to do this for two key reasons: It might help readers by making concrete some of the…
A mentoring client of mine said this recently: I took ownership of some strategically pivotal code and did precisely that, typically refactoring twice a week for about 18 months (my delivery was unaffected). The refactorings took at most half an hour. Last week I got reprimanded. I’ve read the room and stopped. Someone asked why someone reprimanded them, from which came this reply: I should be…
What is refactoring? You’d think that, in 2022, we’d have long settled this question already. Yes and no. A Problem I routinely encounter programmers who struggle with refactoring because they become stuck on this central question: I’m making these kinds of code changes (describes example)… am I refactoring? They might arrive at this central question because some well-meaning person has looked at…
Someone is circulating a talk—a concise one, which I appreciate—entitled “Refactoring is a code-smell” (sic). Before I continue, let me make a few things clear: I do not wish to shame nor criticize the speaker. Their talk triggered this article, but… I have not seen the talk; I’ve only been given one viewer’s impression it and… I am not trying to rebut/refute this talk, but rather I want to say a…
I think a lot of people fall off the TDD wagon because of this exact thing—they learn TDD by working on new code and then can’t seem to apply it to their existing work projects. And then they give up, naturally! When this happens, I help the person focus on the difference between “test-first” and “test-driven”. I hope that this offers them more-realistic expectations regarding the outcome. With…
Too many people are writing too many articles trying to direct others’ thinking on their own testing strategies. I am guilty of this and would like to contribute to reversing this trend. Instead: test until fear is transformed into boredom (Phlip Plumlee) if you don’t like something about the test, then try interpreting that as a sign of a design problem—usually an unhealthy dependency in the…
I like it when programming feels boring. I prefer to save the excitement for the actually difficult parts of the job of developing software: understanding what to try to build, navigating people, negotiating plans, all that stuff. When it comes time to write code, I’d like that to be exactly the right kind of boring: I want things to work, I want to make steady progress, and I want to know what’s…
I noticed that Ron Jeffries had written about a kata I hadn’t tried before , so I decided to try it. The exercise involves evaluating a polynomial of one variable at a single point. For example: 5x 3 + 4x 2 + 19x + 3 at the point x = 5 evaluates to 823. Check my arithmetic if you like. How does one write this incrementally and test-first? First things first: if you’ve never tried it, and…
When I teach evolutionary design with TDD, I often encounter programmers who don’t like all these little classes and all these extra interfaces. (Or all these little higher-order functions, if you prefer. It’s the same problem.) They worry that it creates a serious performance problem: deeper call stacks, passing parameters around, that kind of thing. They see memory being unnecessarily allocated…
This is not a step-by-step guide, but more of an overview that can help you stitch together the detailed step-by-step guides out there. Overview Install nodejs and npm packages from your distribution’s package manager. I’ll call this “System nodejs”. You’ll need sudo to interact with it. Install n , a node version manager, into System nodejs. Use n to install nodejs versions into your user space.…
I couldn’t figure this out myself, nor even find the appropriate Stack Overflow article on my own, so I’m writing this. I hope you find it and it alleviates your annoyed state. Is this you? I want to read input from stdin in my Java application. I want to run my application using gradle run . I’m learning the Kotlin build DSL for Gradle as a replacement for the Groovy build DSL, which I’m somewhat…
Change the code as usual 2. Write a test that only passes after the change 3. Revert to before 1 4. Type the test again (copy/paste is cheating & invalidates the warranty of the exercise) 5. Make it compile by changing the code 6. See it fail 7. Change the code to make it pass — Kent Beck ( @KentBeck ) July 30, 2021 I literally did this for one afternoon (back in 1999, I think) and began to feel…
I used to waste significant energy trying to edit shell commands at the shell command prompt. Yes, I could use vi mode on readline , but that never quite gave me the same, rich experience. I found it helpful for minor edits, but when someone introduced me to the edit-and-execute command, my entire relationship with command-line tools changed. Once I had the full power of my trusted text editor to…
Today I ran into an example of where I’d really have liked to have some way to write a unit test. Let me clarify: by unit test , I only mean any test with a smaller scope than the entire system . I don’t want a microtest. I would even have felt satisfied with clearer, more up-to-date documentation, although perhaps I might not have trusted it. So, There I Was… Today, I saw this task pop up in…
A Reader Question Recently I came across attempts to verify framework-based behavior. This is what I saw: We introduce a framework like JPA Query Builder, RestEasy, or Spark. Then we get two kinds of code: the code which uses a sequence of framework-specific calls (like run-time JPA query building) the code which uses annotations to configure system behavior (like JAX-RS annotations for ReST…
While writing something else entirely, I stumbled upon one of my earliest contributions to the evolutionary design/TDD community. I called them abstract test cases at the time, but today we know them as contract tests . Has much changed in the 20 years since I first wrote about this in public? No. I use contract tests to gain confidence that a module implements its declared protocol . If you…
Over at The 260 Bowler I’ve added a handful of diary entries (just blog posts ), so now I want a diary page (think recent posts ). I started simply, iterating over all the entries, summarizing them, then starting to add nice styles so that they look vaguely like a diary page. I’ll make it look really nice before I move on. I thought, “Hey! I should show these in reverse order, and then limit then…
In my evolutionary design practice, I consider removing duplication one of the three fundamental moves. 1 Accordingly, I practise this move daily and trust it as a primary tactic for understanding the needs of the design. I would like to share a little example with you. We encountered this example during a session of Evolutionary Design Without* Tests . We’re adding a feature to the Point of Sale…
I recently started a new project and used this as an opportunity to learn and practise a few things, among which we find 11ty, a static site generator . I fancy myself a static site generator hipster—I did it before people called it “JAMstack” and made it cool—first with Octopress, then with Jekyll . Indeed, I’ve built my other sites with Jekyll and even built the occasional plug-in, taking…
Complicated code only creates problems when humans try to change it. When we try to change code, we spend energy understanding it, and so we label code “complicated” when it feels like it requires “too much” energy to understand. That’s why we design software: we organize code in a way that reduces the cost of understanding it. “Too many” if conditions represents just one way to write complicated…
Limiting beliefs and unstated assumptions interfere with our performance. This is not a trifling matter. Here is yet another story of how that happens. TL;DR We often test a module by connecting it to a lightweight implementation of one of its collaborators, such as in-memory persistence. This works great for simulating happy paths, but it’s usually impossible to make an in-memory database fail…
A reader asked me this question: I’ve always wondered how does the basic flow of red, green, refactor reconcile with the concept of “make the change easy, then make the easy change”? Does that imply sometimes doing an extra refactoring before the next red [failing test] after deciding what the next change should be or is “make the change easy” referring to non-TDD things like an occasional…
Refactoring, the activity, involves the following things. improving the design of existing code … in a sequence of small transformations … that preserve the important behavior of the system … which you can complete relatively quickly … and which gives you inexpensive options to change direction. Effective refactoring combines the value of Real Options thinking with the care and attention of…
You don’t hate mocks; you hate side-effects. 1 When a mock annoys you, it realizes its purpose, showing you where a side-effect is getting in your way. If you refactor away from the side-effect, then you eliminate the mock. The mock is a consequence of your pain , not the cause of it. Please don’t blame the poor mock for doing its job. Clarifying Terms Here, when I say mock I specifically mean an…
When I teach evolutionary design, participants still often ask me which tools they ought to use to introduce test doubles into their projects. Yes, I nudge them gently in the direction of focusing on principles and techniques and away from fixating on tools, but they still need a place to start . This question often comes in the following form: Do you favor hand-rolling test doubles or using a…
If you add a port in Elm code , then you need to use that port in your Elm code, otherwise the generated Javascript might not even know that your Elm code uses ports at all. As I learn Elm and become accustomed to its compiler’s wonderfully-detailed error messages, encountering error messages like this suddenly feel jarring and I even have trouble understanding them for a moment. TypeError:…
How do object hierarchies evolve? Many programmers struggle with this question. Mostly, they want to know how object hierarchies can evolve safely and sensibly ! They have a picture in their mind that TDD is only safe in the hands of programmers with excellent design sense, but I believe that anyone can learn these skills with a combination of simple guidelines and guided practice. It would be…
A recent tweet caught my attention. The drawback of ‘contract’ as a metaphor is that it leads to discussion as to whether a party is right (conforms) or wrong (violates) instead of overall outcome (what’s the best way to make the system meet the needs of the stakeholders in our technical/economic context). — Nat Pryce ( @natpryce ) May 28, 2019 When I read this, one thought immediately came to my…
I recently had this problem: I was writing some tests with Spock, but IntelliJ IDEA wouldn’t run them. It would run my JUnit tests (written with JUnit 4), but it wouldn’t run my Spock tests (or “specs”, if you prefer). At least this is how it seemed to me. I had made this work before, so I couldn’t understand at all why it didn’t work now. And, of course, I wanted to get this working for a…
Doing (test && commit) || revert amounts to doing TDD very carefully , as an étude . If you already routinely take tiny steps, then you already almost do TCR, but something significant might change if you do it exactly . This remains to discover. Join me. References Kent Beck, “test && commit || revert” . Kent describes the technique and makes it clear: he doesn’t know exactly how it affects the…
I have a new Linux laptop and I wanted to run C# code. I had no idea where to start. I last wrote C# for money in 2004. It took me over an hour of hunting to figure out how to run a single test, so I decided to write a tutorial that could help someone else go from zero to NUnit with Visual Studio Code. Please add comments with suggestions for clearer explanations, additional useful details, or…
I made a silly mistake installing rvm on my new Linux laptop. I should mention that I don’t really know Linux yet, so that makes me susceptible to making this kind of silly mistake. I accidentally installed rvm as a multi-user/system-wide tool, rather than in single-user mode. Since I like the use the narrowest scope possible , I wanted to fix this. Of course I also had the problem that rvm…
I write contract tests in order to help with the drifting test doubles problem : how do I know that my stubs and expectations and spies and mocks behave “like the real thing”? I do this because contract tests run in less time than integrated tests, I feel more confident with passing contract tests than I do with integrated tests, and they help me document my understanding of the contracts of the…
In 2022 I learned about sd , a modern replacement for many of the simplest ways to use sed . Check it out! I decided to learn a little sed , because I can find it everywhere and it seems like the kind of tool that would make a bunch of everyday things easier and faster. I started with “Sed - An Introduction and Tutorial by Bruce Barnett” and immediately realized the enormity of the consequences of…
I taught evolutionary design in person to about 200 programmers this year. 1 In the 15 years that I’ve been doing this, I’ve spoken with confused programmers who felt unsure how to use dependency injection to improve their design. I tend to notice this confusion more often among the programmers who have “some experience” practising test-driven development—say, 6 months to 2 years. I’d like to…