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 refactor. Indeed, so here are some rules that I’ve found helpful over the years: refactor only ...| The Code Whisperer
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 abstract-sounding advice that I provide. It might increase the amount of civility in code criticis...| The Code Whisperer
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 refactoring under an initiative, the colleague felt. I said I was refactoring to the Four Rules of...| The Code Whisperer
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 what they’re doing and exclaimed, “That’s not refactoring!” To someone trying har...| The Code Whisperer
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 few things about the claim as I understand it. Please take a moment before you co...| The Code Whisperer
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 test-first, we focus on correct behavior and fix defects. Usually, but not always, when...| The Code Whisperer
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 production code (The “driven” in test-driven development) faster-running tests tend to prov...| The Code Whisperer
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: 5x3 + 4x2 + 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 especially if you’re new to test-first programming, then try it yourself. Take small steps and never wr...| The Code Whisperer
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 and freed, memory becoming fragmented, and garbage collection happening at the worst possible...| The Code Whisperer
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. For these versions, you don’t need sudo. Steps I’m running Pop!_OS 21.04, which is e...| The Code Whisperer
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 used to. Great! That’s me, too. The Problem By default, gradle run uses an empty input ...| The Code Whisperer
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 the difference almost immediately. I also happened to like that feeling, even though there were mo...| The Code Whisperer
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 compose and edit commands, I stopped valuing GUI clients as highly and I started valuing the scrip...| The Code Whisperer
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 Todoist: Write a Netlify Function to schedule removing a participant from The jbrains Experience ...| The Code Whisperer
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 paths) Now I start seeing two kinds of unit tests. The first kind relates to verifying framework calls...| The Code Whisperer
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 prefer OOP terms, i use contract tests to gain confidence that a class implements its declared interface...| The Code Whisperer
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 to something like 5 or 10 entries.” When I thought about how to do that, I immediately jump...| The Code Whisperer
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 system: adding provincial sales tax to each item as the shopper purchases it. The system already ...| The Code Whisperer
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 advantage of my experience working in Ruby. In spite of my successes with Jekyll, I became espe...| The Code Whisperer
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 code. Most of us don’t immediately grasp long chains or deeply-branching trees of...| The Code Whisperer
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 the same ways that an SQL database would fail running on some remote server somewhere. This leads...| The Code Whisperer
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 larger-scale refactoring task? In short: yes to the first option. I often find myself doing th...| The Code Whisperer
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 engineering. It reduces volatility in the marginal cost of adding features. It reduces the over...| The Code Whisperer
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 expectation, often implemented by library functions with names like verify(), expect().toHaveBe...| The Code Whisperer
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 library (like NSubstitute, Mockito, or rspec-mock)? I choose the option that balances removing duplic...| The Code Whisperer
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: app.ports is undefined I saw this message in the browser’s Javascript console when I tried to add th...| The Code Whisperer
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 nice to have more examples. I have stumbled upon one that I’d like to share with you. I’m refacto...| The Code Whisperer
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 mind: are people really doing this?! And of course they are, because people relentlessly fi...| The Code Whisperer
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 training course, so I felt a certain pressure to get it to work. Nothing made sense to me. S...| The Code Whisperer
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 programmers just yet. James Shore, “Études for Excellence”. James and I both see the XP pr...| The Code Whisperer
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 better instructions. I’m especially interested in knowing how to package these setup instructions ...| The Code Whisperer
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 wouldn’t work without sudo and that seemed really weird to me. I figured that I should uninstall rvm...| The Code Whisperer
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 code that I use. Unfortunately, it remains possible to write a contract test that contradicts a...| The Code Whisperer
A reader asked me: Regarding contract tests, would you group both expectation and assertion checks together or would you keep them as separate checks along the lines of each separate line in your talk? The very short answer is “neither”. You can find the only slightly longer answer here.| The Code Whisperer
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 my choice. Anyhow, sed is a marvelous utility. Unfortunately, most people never learn its real ...| The Code Whisperer
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 share a few short pieces of advice, and if this advice leads you to ask some follow-up que...| The Code Whisperer
I just learned about zmv and I love it. If you already know about zmv or you already love rename, then don’t waste your time reading this. Sometimes I want to rename a bunch of files in a way that mv can’t handle. Most recently, I had a bunch of files with the same name in numbered directories (Page0/shot.jpg, Page1/shot.jpg, …), and I wanted numbered files instead (shot-0.jpg, shot-1.jpg, …). Plain globbing won’t do it. (If it will and I don’t know how, then please tell me) If yo...| The Code Whisperer
“I want to get a lot of wisdom on TDD techniques”. Many people ask me about this, especially when they sign up for my mailing list. They want the “advanced stuff”. I have good news and bad news for them: I don’t believe in “advanced TDD”. If you want advanced testing techniques, then you’re probably looking for techniques that will make your code worse, not better. (I don’t want you to do that.) If you want “advanced TDD”, then you’ve probably missed the single most im...| The Code Whisperer
A recent experience with a hotel coffee machine illustrated one primary difference of philosophy related to software design. It’s a Keurig machine and my wife Sarah was figuring out how to use it to make coffee. She noticed that when she inserted a K-Cup (the little containers of coffee), then the lid for the water reservoir popped open, so that she could fill it with water. At first, that seemed helpful, but immediately, I wondered about being able to open that reservoir even without inser...| The Code Whisperer
Today’s article answers a question that I received recently. Hey, I attended a talk of yours about continuous delivery. One of the main takeaways from that was the mention of Contract Testing. In my team we’re thinking about trying it out, starting first with one of our features and testing the contract Frontend<->Backend. We’ve seen some tools that might help like Pact, but are not sure if that’s the right way to go. If you could give us any help, it would be highly appreciated. In s...| The Code Whisperer
I don’t like to inherit implementation (create subclasses).1 When refactoring class hierarchies, I often pull behavior up into superclasses, then out into collaborators.2 Over time, I might find myself left with subclasses that only differ by overriding methods to return different constant values. Smalltalkers are used to this, but I never felt entirely comfortable with it. (No, I can’t explain that.) I often end up here because I’ve moved all the significant behavior variations out int...| The Code Whisperer
I’ve been teaching programmers about the value of isolated tests1 for a long time, and recently I’ve seen increasing resistance to the idea. I worry that this comes partly from having presented motivations and reasons that tends towards the overly-abstract, ironically enough. Perhaps I can improve matters by returning to the concrete issues and constraints that led me to being exploring this idea in the first place. Consider the following questions. When I want to fix a problem within the...| The Code Whisperer
I would like to use GitLab CI in order to be able to separate rebuilding a Jekyll site from deploying the static web pages to a production web server. I know that I can deploy a Jekyll project to Heroku using a buildpack to build the static site remotely; however, that seems wasteful to me compared to merely deploying the resulting static site into production. Since I don’t know how to use GitLab CI, I’d like to explore what it does. I most definitely do not want to use my Jekyll project ...| The Code Whisperer
The name template method is a perfect example of a structural name: it describes the implementation rather than the meaning or purpose. This is what happens when programmers name things. The Problem We have standard workflows in our systems that programmers copy and paste from module to module in order to achieve some kind of standard behavior. Programmers call this boilerplate. Programmers tend to copy and paste this code because — They don’t see the duplication, because usually not much...| The Code Whisperer
Many programmers believe that tests have special permission to repeat themselves, arguing that this repetition makes those tests “simpler” or “easier to read”. I challenge that claim in this free preview article at The jbrains Experience, where members get personalized consulting and answers to their questions.| The Code Whisperer
I recently encountered a code base in which someone had applied the Golden Master technique, but done so in a way I find risky, so I wanted to warn you against letting this happen in your code. This code exhibits a bad idea that probably started out as a good idea or seemed like a good idea at the time. This makes it plausible-but-risky, and this is where a lot of legacy code comes from. The golden master tests are designed as JUnit tests, which I like very much, because that should make it e...| The Code Whisperer
Today I’d like to share an example of a tiny cohesion risk. I leave it to you to evaluate the severity of the risk and the appropriateness of the refactoring. I like to deal with risks when they are small enough that their impact, while painful, probably won’t kill. What a cute design risk!Let’s start with the code here: patch_entries(simple_subdomain_redirect_rules, ->(k, v) { [k, SimpleSubdomainRedirect.new(k, v).to_nginx_server_block_configuration("/home/nginx/servers")] }) .map { |k...| The Code Whisperer
I often hear this: Why should we extract this code? We only use it in one place. It doesn’t make sense to extract it. And yet, that same person wants to write tests for private (or otherwise invisible) behavior. That person is only hurting themselves: they want to treat this code like a separate thing (because they want to test it), but they resist extracting it because “it doesn’t feel right”. I have safely extracted numerous mini-frameworks and mini-libraries and my only regret rema...| The Code Whisperer
In “What Is Functional Programming?” I spotted a nice example of how duplication in tests leads to a suggestion to improve the design. Let’s start with his example function getCurrentProgram(). public Program getCurrentProgram(TVGuide guide, int channel) { Schedule schedule = guide.getSchedule(channel); Program current = schedule.programAt(new Date()); return current; } As Kris Jenkins points out in his article, this function has a hardwired (difficult to change) implicit (unspoken) dep...| The Code Whisperer
When you use relative include paths in your code, you bind each source code file to its current location in the project’s file layout. You relegate yourself to having to run it from a very specific location on the file system. You generally make it unnecessarily difficult to automate running your application (or its tests) outside your development environment, such as in platform-as-a-service environments. You make things like Docker not just helpful, but necessary. So stop doing that. You ...| The Code Whisperer
No matter what one writes, no matter how carefully one tries to articulate it, a non-trivial segment of the readership will interpret it differently from what one intended. So it has gone with “Integrated Tests are a Scam”. I’d like to address some common differences of interpretation. “Integrated”, not “Integration” This point might seem small, but it matters. Word matters. Meaning matters. In 2009 I presented “Integration Tests are a Scam” to an audience at the Agile (Nort...| The Code Whisperer
The entry point. Sometimes it’s main(). Sometimes it’s an extension point in some complicated framework. Most importantly, it is the border where Their Stuff runs Your Stuff. When I see entry points in other applications, I don’t see a lot of evidence of having thought about the design much. It becomes a kind of junk drawer for code. This happens especially when programmers are working in environments they don’t feel particularly comfortable in. (I don’t know where to put things, so...| The Code Whisperer
You might have noticed dependency injection gaining popularity in recent years. You might also have noticed some notable figures (I’m thinking of Kevlin Henney) who appear to be bad-mouthing dependency injection, when really they are simply taking away what they feel is a veneer of mystery from the term.1 I must say that I appreciate their doing so without pretentious use of the annoying word “demystifying”. (Simply ignore my own “demystifying” article by most certainly not clicking...| The Code Whisperer
A Twitter follower asked me how to recover from feeling overwhelmed by too many integrated tests, calling it “a common struggle of mine”. If you haven’t seen this video (64 minutes), then you might not quite know what I mean by “integrated tests”. If a test passes or fails based on the behavior of many “interesting” bits of behavior, then I call it an integrated test. (Not an integration test—those check the integration between layers of a system.) Integrated tests tend to be ...| The Code Whisperer
This article describes an evolutionary design microtechnique. Specifically, it describes a weak signal that I use to guide myself towards more modular designs. I find it both simple and surprising: simple because it involves using a single value, but surprising because it involves a value that programmers largely recommend against using. I refer to the humble null. Yes: I have found a way to use null that doesn’t lead to heartache. I start with injecting collaborators through the constructo...| The Code Whisperer
We recently ran a legacy code retreat based on your format. People were questioning the value of subclass-to-test in a real world scenario. The best reason I could come up with for myself was that it’s a smaller step to separating out responsibilities from a class. How would you frame the value of subclass-to-test, and in which contexts would you use it? I view Subclass to Test as an intermediate step towards other refactorings like Replace Inheritance with Delegation, Introduce Named Const...| The Code Whisperer
I’ve written in the past that integrated tests are a scam, but that’s not what I mean here. Dear programmers, your tests are probably dragging you down. Here we have another delightful irony of agile software development, this time related to test-driven development. I give you The Fundamental Irony of Test-Driven Development. If you practise test-driven development, then depending on how you manage your short-term tasks, you run the risk of increasing your stress levels compared to not d...| The Code Whisperer
When clients ask me to help them with legacy code it generally takes less than 30 minutes for me to run into a debilitating constructor—a term I use to describe a constructor that does too much. You might think me melodramatic for calling it “debilitating”, but these constructors not only slow us down when we try to understand the code, but block our every effort to improve it. These constructors often hardwire a dependency either to some horrifying external resource (a database or a we...| The Code Whisperer
For years I’ve written about contract tests, and most notably have never had any clear examples of them to share with you. I’d like to change that today. I’m sharing this with you as a rough cut, meaning that I haven’t yet taken the time to seriously edit this, nor add much explanation. I feel tired just now, so I want to stop, but at the same time, my loyal readers deserve to see a real example. I’ve spent the last few days messing around with the Atom text editor, writing a packag...| The Code Whisperer
After one of the mob programming sessions I did with RubySteps last year, a viewer singled out this as a valuable piece of advice: One of the most important things that a programmer must learn how to do is to stop when they get to the end. I remember the first time I encountered this issue: in Steve McConnell’s excellent book Rapid Development, which I remember reading in 1997. (Wow! I should read it again.) He referred to “gold-plating” as one of his Classic Development Mistakes. You m...| The Code Whisperer
I had intended to write a nice article showing a concrete example of learning tests in action, then something wonderful happened: all the code disappeared. The Situation I love Typeform, especially because it integrates with Stripe for processing payments. Sadly, Typeform does not allow my customer to pay-what-they-think-it-was-worth unless I anchor them by presenting a handful of price options, similar to what you see here. Not the way I want to let my customers choose the amount they wish t...| The Code Whisperer
I upgraded to Mac OS 10.10 Yosemite and something strange happened with my installations of IntelliJ IDEA. They just disappeared. I still don’t know what happened to them. When I tried to reinstall IDEA 13 Community Edition, it crashed on launch. Fortunately, my Twitter community came to my rescue. I’m sharing my experience here, just to make it easier for those who upgrade after me. I found two solutions. A Risky Solution When I reinstalled Java SE 6 and made it my system Java virtual ma...| The Code Whisperer
How do I gain confidence in code that generates HTML, such as tag libraries or view templates? Well, it depends on what I’m trying to do. Am I learning how an existing tag library works? If so, then I create a bare project, install the tag library, use it to generate some HTML, then use something like HTMLUnit1 (any HTML parser will do) to check the results. This way, I can explore all the features that the tag library has without mixing those tests up with the tests for my project’s core...| The Code Whisperer
Almost everyone starts organizing their tests according to the module (or class or object) that they’re testing. If they have a class called Customer, then they have a test case class called CustomerTest and put all the tests for Customer into this one bundle (module, class, describe block, whatever you call it). Don’t stop here. If you continue to add all your Customer tests to CustomerTest, then you’ll certainly judge it as “too big” after a while. Even if you don’t, you’ll no...| The Code Whisperer
You have inherited some code. Congratulations. Now you need to change it. There, there. Michael Feathers once wrote that legacy code is “code without unit tests”. I use a slightly more general definition. By “legacy code”, I mean profitable code that we feel afraid to change. I think that both parts matter. You probably accepted the “afraid to change” part without any need for convincing. (If not, then this article probably won’t interest you.) Moreover, if the code doesn’t ge...| The Code Whisperer
Some time ago a client asked me some questions about spies and mocks. I wanted to share what we discussed with you. So here’s the issue my mind has been toiling over… The project I’m on is using Jasmine for BDD. Technically though, I think most people aren’t actually executing real TDD/BDD. As in, they’re not letting the tests guide their design, but instead are sticking on unit tests at the end, after writing most of the code… this is what their tests suggest, at least. I see, in...| The Code Whisperer
I think that programmers worry far too much about design. No, I don’t mean that they should care less about design. I think that programmers worry so much about design that they forget to just program. As they try to learn more about how to design software well, they become more reluctant to write code, fearing that “it won’t be right”. I think that we contribute to this reclutance by writing articles with a tone that implies don’t write code unless you write it my way. I don’t th...| The Code Whisperer
. @cyriux : Imho the best paper ever written in software engineering: https://t.co/C6kmmj0ntl Parnas, 1972 — Alistair Cockburn (@TotherAlistair) August 1, 2014 I don’t intend to argue Alistair’s contention one way or the other, but I invite you to set aside some time to read David Parnas’ paper “On the Criteria To Be Used in Decomposing Systems into Modules”, which I have embedded in this article. Do not let yourself be put off by the quaint-sounding title. If you prefer, think of...| The Code Whisperer
I wanted to change some of the styling at jbrains.ca, but I have a legacy Wordpress template, so I needed a way to start making incremental changes with something remotely approximating tests. I knew that I didn’t want to have to crawl every page to check that every pixel remained in the same place, in part because that would kill me, and in part because I don’t need every pixel to remain in the same place. I needed another way. How to Refactor CSS/SCSS I chose to replace the raw CSS with...| The Code Whisperer
I havewrittenelsewhere that people, not rules, do things. I have written this in exasperation over some people claiming that TDD has ruined their lives in all manner of ways. Enough! People, not rules, design software systems. People decide which rules to follow and when. The (human) system certainly influences them, but ultimately, the people decide. In particular, people, not TDD, decide how to design software systems. James Shore has recently written “How Does TDD Affect Design?” to of...| The Code Whisperer
In 2014 I read an article with the provocative title “Mockists are Dead. Long live Classicists.”. In it, the author frames mock objects (I assume that they mean all test doubles, as opposed to specifically method/function expectations) as “dangerous” and warns against a mistake he calls “tautological TDD”, which he describes as writing tests that merely repeat an idea in different words. This sounds risky to me, and something I’d probably want to warn against, but not something ...| The Code Whisperer
Recently Bob Marshall opined that refactoring code is waste. This reminds me of passionate discussions from a decade ago about testing: should we classify testing as a value-added activity or as an unavoidable waste? I’d like to change the question a little, but first, allow me to play the ball where it lies. If you haven’t read Bob’s article yet, then do so now. You’ll find it quite short; I read it in a few minutes. I composed this as a comment to Bob’s article, but it expanded to...| The Code Whisperer
If you like to teach test-first/test-driven techniques, then you have probably stumbled over configuration problems in your programming environment. This happens to every presenter at least once. We have a variety of ways to handle the problem, and today I’d like to share another one with you. Google Spreadsheet can run Javascript, which means that we now have a ready-to-go approximation of Fit. It took me only a few minutes to figure out how to write a Javascript function that operates on ...| The Code Whisperer
So maybe not an epic, age-old battle, but a battle nonetheless. The battle over the correct ordering of the Four Elements of Simple Design. A battle that I’ve always known I’d won, but until recently, could never justify to others. I can finally declare victory and bestow upon you the One True Sequence. Calm down; I’m joking. Seriously: it has always bothered me (a little) that I say it this way and Corey Haines says it that way, and somehow we both have it “right”. I never quite un...| The Code Whisperer
You might call this title “clickbait”. Yes and no. Of course, I want you to read this article, but at the same time, there is no bait and switch here. I use test doubles (“mock objects”, since that term refuses to die) freely and happily. I use them prominently as design tools. I like them. I feel grateful to them. And even so, my design sometimes improves when I remove them. To paraphrase Ron Jeffries, this is good news about the improved design and not bad news about test doubles. H...| The Code Whisperer
I just wanted an HTTP client. I asked my Twitter community which HTTP client to use. Certainly not HTTParty, because cool people don’t use HTTParty anymore. One takes these risks when one falls out of the loop with the latest and greatest tools. “Use Faraday”, they said. “It’s the best”, they said. Everything went fine until I needed to follow a redirect. What happened from that point forward could form the basis of a solid one-act play. I’ll spare you the horror and send you di...| The Code Whisperer
At Øredev 2013, I asked managers to tell me what makes their job difficult. I spoke to one manager who told me that they face immense pressure on two fronts: from the board of directors to deliver more features more often and from the programmers to give them more time to refactor. I’ve heard dozens of stories like these over the years and I’ve found a trick that helps. It doesn’t resolve the problem, but it helps take a significant step in the direction of a resolution. Warning. You a...| The Code Whisperer
Legacy code imposes an unbounded, inexact tax on the cost of all future features. This explains why I run events like Legacy Code Retreat, build training courses like Surviving Legacy Code, and write in general about improving the design of software systems. This further explains why I’m willing to accept the risk of people labeling me as an “over-engineerer”. What they label “over-engineering”, I consider managing risk. As part of managing risk, I like to test-drive changes to lega...| The Code Whisperer
I love having tricky conversations on Twitter. I know a lot of you don’t, because you can’t express yourself clearly in 140 characters or less, but I love it for precisely that reason. The constraint makes it easy to voice objections, which makes assumptions visible and encourages us to challenge them. You’d be amazed at the things that people object to – issues that you thought were settled a long time ago, which you take for granted, at least within certain of your social circles. T...| The Code Whisperer
A Twitter conversation about Primitive Obsession caught my eye today. That conversation began with this tweet: Re. “primitive obsession,” I say this poker-scoring program wouldn’t be bettered avoiding integers for rank and suit. jsoftware.com/jwiki/TracyHar… — Tracy Harms (@kaleidic) March 3, 2013 I can’t read J, so I can’t decide much about the quality of the code Tracy wrote, but I do notice one thing: There aren’t many functions that operate on the primitive data (card rank...| The Code Whisperer
The bottom line: Modularity. Details. Pick one. I often spend time with programmers who don’t like small methods and small classes, in spite of all the benefits of small methods and small classes: easier to test easier to read, quicker to skim costs less to understand, less to understand at once easier to build correctly, quicker to build easier to compose into working systems These programmers range from feeling vaguely uncomfortable to showing strong and open antipathy towards small metho...| The Code Whisperer
Another “demystifying” article. Great! I know… bear with me. Of the SOLID principles, the Dependency Inversion Principle remains somewhat misunderstood. I’d like to help with that. I hope you’ll ask questions and challenge these ideas, so that I can improve this little article. I learned the Dependency Inversion Principle from Bob Martin’s article, the salient part of which states: High level modules should not depend upon low level modules. Both should depend upon abstractions. o...| The Code Whisperer
I apologise for the pompous title; I wrote it just for fun. If this “demystifies” anything, I’ll consider that a coincidence. Of the SOLID principles, the most pompous-sounding is the one named for a person: Barbara Liskov. I don’t label her pompous – I never knew her – but of those five principles, only LSP has a common formulation that looks like the kind of mathematics so many programmers like to avoid, while others flock to. Let q(x) be a property provable about objects x of t...| The Code Whisperer
Just a fun link today. I read about Design by Contract first, didn’t understand it, then read about Test-Driven Development and began to think of TDD as a kind of DbC by example. Accordingly, I have respect for both practices and have even combined them on projects. Moreover, “Integrated Tests are a Scam” amounts to little more than Isolating Layers by Contract. When I saw the Vigil programming language today, I fell in love. To quote its README: When a Vigil program is executed, Vigil ...| The Code Whisperer
I really like Octopress, which is built on Jekyll. You can read a lot of articles about the advantages and disadvantages of pre-baked blogs, so I won’t bore you with those details. Instead, I’ll bore you on the subject of the one feature I miss with pre-baked blogs: scheduling posts for later publication. When I switched to a pre-baked blogging tool like Octopress, I gave up the ability to upload a post, but publish it later. Well, I didn’t really give it up entirely, but pre-baking my ...| The Code Whisperer
I’m pleased to announce that I have started writing a new book, entitled Responsible Design for Android. I really envision this as a series of short books, not wanting to repeat the 750-page behemoth that was JUnit Recipes. In Part 1, Dancing with the Android SDK, I explore a sensible architecture for the basic Android app, emphasising context independence to avoid letting the Android framework swallow my app whole. I use tactics that have worked to great effect in working with older framew...| The Code Whisperer
I’m coding like it’s 2000, meaning in Java. I thought I’d never see anything new regarding writing a test that expects to catch a specific exception. I saw something new, and I wonder who else has independently discovered it. @Test public void ioFailure() throws Exception { final IOException ioFailure = new IOException("Simulating a failure writing to the file."); try { new WriteTextToFileActionImpl() { @Override protected FileWriter fileWriterOn(File path) throws IOException { return n...| The Code Whisperer
I wish that I could take credit for this article, but I can’t. Instead, I have to credit two people: Lasse Koskela and Miško Hevery. I credit Lasse for writi...| blog.thecodewhisperer.com
The Saff Squeeze seems like an underused technique, possibly because people want to see more examples before they try it for themselves. Here is an example o...| blog.thecodewhisperer.com
No, tests aren't supposed to make refactoring _easier_; they make refactoring **safer**. Sometimes, by accident, they do both.| blog.thecodewhisperer.com
Debug with automated tests: it's systematic, it leaves a record of what we've learned, and it's boring in the best possible ways.| blog.thecodewhisperer.com
Many programmers struggle to adopt TDD because they put pressure on themselves or because some commentators try to shame them for their imperfections or beca...| blog.thecodewhisperer.com
TDD is for those who don't know how to design software, which doesn't have to mean that we're all dopes who are doomed to perpetual failure. Let's explore th...| blog.thecodewhisperer.com
A guard clause might be an embryonic parser, so what happens if you nudge it in that direction?| blog.thecodewhisperer.com
It's easy to give the instruction to **reveal intent**, but harder to provide helpful examples. I'd like to provide a tiny one that illustrates the point qui...| blog.thecodewhisperer.com
When you notice that you need| blog.thecodewhisperer.com
Let's look at a simple example of a name. Let's judge the name (kindly!), then imagine some likely next steps in refactoring. We can learn and do quite a lot...| blog.thecodewhisperer.com
The stronger your refactoring skill, the more easily you can use architecture advice as guidelines instead of as rules to enforce. This makes it significantl...| blog.thecodewhisperer.com
Just another little example of two people looking at a situation, one seeing a problem and the other seeing a solution.| blog.thecodewhisperer.com