is now [learn more]
PODCAST

What’s wrong with SOLID and Test Driven Development with Daniel Terhorst-North

Transcript

Kevin Montalbo

Welcome to episode 67 of the Coding Over Cocktails podcast. My name is Kevin Montalbo. Joining us from Sydney Australia is Toro Cloud CEO and founder David Brown. Good day, David.

David Brown

Hi there, Kevin.

Kevin Montalbo

Hello. All right. Let me introduce our guest for today who helps business and technology leaders find simple pragmatic solutions to business and technical problems often using lean and agile techniques. He has 30 years of experience in it and is a frequent speaker at technology and business conferences worldwide. The originator of behavior driven development and deliberate discovery. He has published feature articles in numerous software and business applications and contributed to the R spec book, behavior driven development with our spec cucumber and friends and 97 things. Every programmer should know collective wisdom from the experts. Joining us today for a round of cocktails is Daniel Ter Hurst North. Hi, Dan, welcome to the show.

Daniel North

Hello. Thank you very much for having me by the joy of time zones. It is, it is morning here. So unfortunately, I won't be, 00, we're doing the coding over when I heard coding over cocktails. I was thinking is that like one of the, you know, the, the fifth agile value manifest.

David Brown

Well, Australian company, it's a Toros Manifest. We always kick off, we always end the week with beer o'clock. It's a tradition. So yeah, we don't want to promote alcoholism in alcohol. Alcohol isn't, I can't wrap my head around it. Um But yeah, that's, there is a bit of an ongoing theme there. And of course, all our product names are, are, are after cocktails as well. So, we have Italian cocktails as all our product names. But look, Dan, you, I wanna start off with solid. Now you have a problem with solid, which is interesting. So I think we should first all cover off what is solid. So the solid principles were introduced by Michael Feathers who build upon the work of Robert Martin in his paper, design principles and design pub patterns published back in 2000. Now those solid principles have served us well for over 20 years in terms of object oriented oriented programming. You are now challenging these principles. Before we get into your alternative, maybe you can run us through what is solid and what's your problem with it?

Daniel North

So, the phrase served us well is an interesting one. They've been around for a long time. Certainly. Um I've, as you say, I've been writing software for 30 years, um like as a full time hands-on programmer for the 1st 20 of those, for the last 10 or so, I've been a consultant, so I, I'm a cause of programming in other people. um I still code when I can. I love programming.

These days I tend to do a lot more looking at reviewing code, um looking at programming strategy, architectural strategy, that kind of thing. So helping teams write better software. Um So solid, solid's an interesting, I think of solid as a useful historical artifact.

OK. Um When the, when Robert Martin was producing, was describing all these principles, he was collecting things, you know, he wasn't just sitting there and pronoun making pronouncements. These are things that he'd seen in the wild and he thought they were useful things to bring together. So there was a, there was a, a good intent behind it. Um But some things stand the test of time and some things don't and a test driven development we're gonna talk about later is I came across that over 20 years ago. It was m decades old.

By the time I came across it, it's still completely relevant today. It's one of the most useful software design techniques I've ever encountered um Solid, not so much. So if you look at each of the five principles, you can see and this is what I did, I wrote an article, but before you know, before, before any of the cupid work or an article kind of um, deconstructing if you like just, just so and Solid is only five principles.

Now, there are over 100 of these things in his books. Um And as you say, my brothers happened to notice that on the first slide, if you change the order a bit, you could get this acronym Solid.

Um you could also get Lloyds and Doyle's as well. So, I mean, you know, idols, there you go. Idols. Um So you can look at them as idols and perhaps that makes me an icon of class. I don't know. But the um so the problem I have with them is let's look at them one by one single responsibility says code should code should have one reason to change. That's the technical definition. So in other words, you shouldn't, you shouldn't, you shouldn't conflate different aspects of code. You shouldn't have things like business logic in with view logic or data access logic, in with business logic. And you know, that kind of makes sense, right? You think?, that, that, yeah, that seems like a pretty good rule for life, right? And it kind of makes sense in an age when making changes to any code was a high transaction cost activity.

So I would change, I was working on big C++ systems, you know, multi million lines of plus C++ systems in the nineties. Um I, I wrote a a Europe wide um telecom um billing platform which was fun, lots of multi currency and, and, and, and fun, fun edge cases like you had to have one bill per customer, but one of the customers was first telecom, which itself was a reseller cos it might have tens of millions of call records in a month and the system, the original system wasn't designed for that. So I was, I was working on big systems and especially C++ is, it's become a much bigger, more complicated language. At that time, it was a pretty reasonable language for doing those kinds of systems.

Um This is before Java. And um so you would, you, you'd, you'd make your change in your code and compiling was pretty quick, you know, I could, I could write some C++ code and then run, make and then the compiling stage was, you know, a few minutes. There's then a stage called linking and linking is where a linker resolves all of the various bits of your code and makes sure they all connect to each other that could take literally hours. So in other words, a one line change could take, you could have a multi hour build, not, not building and running tests, cos we won't do automated testing much then just getting a binary that you can run was a multi hour endeavor and when the transaction cost is high, what you tend to do is do more work.

So I, so you, you make bigger changes because if the cost of a change is high, then you, you, you know, you shove in a load of stuff, you don't want to keep doing that every, you know, right, every few lines of code. And so that means that you then have an exponentially higher likelihood of introducing bugs. So this is the context you're working in. And so what they're saying is look, if you're making changes to business logic for crying out loud, don't make changes to the, to the view at the same time. Don't put them in the same coat because that's just gonna be a nightmare. Um If you play that forward to now, we have like the equivalent language to something like C++ which is your business systems language is Java or C# or maybe go sometimes these days, Rust is coming up. But like for a language like Java or C or C#I'm typing in my ID, the program is compiling behind my fingertips in real time. I've got a hot reloading of apps, right?

So my transaction cost for making a change is nil. So that's the first change. The second change is that code itself is a lot more malleable. And I think Java was the language that made this mainstream small talk is where it started, but it's the idea of refactoring. So if I'm writing C or C++, it's, it's kind of like brick laying, right?

So you write a file something dot C and then you, you're done with that file and you get the next file, something dot C or something dot, CCPP or whatever it is. Um And, and you write the files and you park them, ok? And so that you wouldn't generally go back and make a change to a file or if you did, you were making a change within that file. And so the prevalent version control system, for instance CV S at the time, if you renamed the file, you lost all the history, because history was file-based. So if you renamed a file in CV S, you just lost all the, all, all of its change history. Um That wasn't a bug in CV S, that's just like a, a um a consequence of how uncommon that action was. And now Java comes along and Java couples the name of a class to the name of a file and the name of a package to an entire directory structure, right?

So now suddenly when you have refactoring tools in Java, changing file names and changing entire directory hierarchies is common, it becomes a single keystroke. Yeah. And so suddenly, tools like CV S are breaking and that's where subversion came from. It was the next generation of CV S that was refactoring aware. That was the big thing it did is a change, you know, the change of a bunch of files was atomic instead of per file and we play that forward and we get tools like it.

So, the mindset that cha that code would only change in one place just became nonsense, co code changes all over the place. And also the tools for navigating code became much, much richer, right? So instead of using V I or emacs or whatever you're using for your, for editing your C++ code, which had pretty good code. Navigation. There's a brilliant thing, it is called C tags that they would both use, that would allow you to navigate code. But like in, in um intelli A, I can just find usages across a file with across a code basically with hundreds of thousands or millions of files in it. And it goes, yeah, here they are right. Here they are. And I can guarantee there's no false, false positives because I can build AAA deterministic A ST from my code, right?

So wait, so there's the whole context. So now let's take a look at single responsibility when I first start writing a new piece of code in, in some language, in Python, in Rust, in, go in whatever it is. Why do I want an arbitrary separation of all the bits that are changing together because they're in my head right now, you know, the, the U I doesn't change on its own apart from for trivial U I changes, if you're gonna make that button blue, that's a U I change, right? Usually a U I change is because I've added some more information or I've changed the information and I changed the information in the business layer. So that means that changed in correspondence with that and that probably changed because there was some data change or some event change. And so actually all these things do change together. And so now what I've got is a bookkeeping exercise, right? Where I have to go, you know, I've got the guest to set, to, get, to set, to get to set, to get to set if you ever did any enterprise Java back in the day, most of your life was copying and pasting code between getters and setters like this is madness except then you get rails, right? And rails has the same thing. You have models and views and controllers and in separate directories because that's what single responsibility says is that they have to, they don't say they have to live in separate places, but that's what software craftsmen do is they, they, they, they take these things to the nth degree. um and, and now, and now we're stuck with this model where in order to make a change to code, I have to go ferreting around in all different files. Right. I've never done that. I've managed to get my 30 years without using the single responsibility principle. So, it's, you know, again, I describe it as neither necessary nor sufficient if you do it, I mean, might, maybe the, the other thing I'll, and I'll shut up cos I know we've got a lot more. We're only on the, the other thing to bear in mind is you can think of it as a premature optimization of code structure.

So if I am duty bound, honor bound to separate my code into areas that only have one reason to change, that means that I'm not allowing myself other things, right? So for instance, what I might have is a bunch of code that's to do with billing and a bunch of code that's to do with customer management and a bunch of code that's to do with um you know, with, with buying or something, whatever my product is, a bunch of things that are to do with search and, and those areas of functionality that might be a much more sensible way to arrange my code. But I don't get to do that because I'm already in models and views and controllers is my top level view of the world.

David Brown

Well, I might ask you, you're going, I mean, you came up with a, a new, an acronym called Cupid as your alternative to solid. So as you're going through these solid and you're talking about the single responsibility principle of solid at the moment, maybe you can run us through the Cupid alternative.,, and how res resolves these issues you have with solid.

Daniel North

So that's a great question. I'm going to counter with something a little different. So I thought so.

So. Ok, so originally here, here's the back story. Um I, I just poked the bear of solid in a fun talk about five years ago. It was literally a five minute talk in a pub with alcohol again, you know, drink, drink, drink, aware folks. Um And there were a whole series of these ignite fun, silly talks and it was a post conference event and I thought I'd poke it solid and, and I did, it was a five minute talk.

So for each of the five principles I gave 15 seconds describing it 15 seconds, describing why I don't like it. And 15 seconds saying what I would do instead and thinking I would have exactly the answer to your question. And as I wrote the talk, I realized that the thing I would do instead was the same thing every time which is write simple code now, clearly, right? Simple code is itself a bit vague.

So I needed to clarify what I meant by simple and by my working definition of simple is it's not about my head. It's code that fits in someone else's head. So someone else you um Kevin can come along see this code and go, yeah, I get what's going on here. And my qualifications for that person's head is that they understand the language, the idiomatic code in that style of language.

So they don't, you know, they're not gonna come, I'm not gonna take someone who's never seen go code before and say what does this do?

No. So, the idea is that someone who's familiar with the language, its ecosystem, its core libraries, it's run time, you know, it's built, it's build chain, yeah, tool chain. So given those things and also some familiarity with the domain that we're working in.

So if you have all those things and you can look at some code and it's obvious to you, then that's simple. If it's not obvious to you, it means that there's some tacit knowledge that's in Kevin's head, that's about how this module connects to that other module because you have to know about this other secret module over here, right? That's now not obvious. So how do we, how do we make that tacit knowledge explicit? And it turned out for each of these five, basically my go to was very simple code.

So some years later, this is where the keeper came from. Someone challenged me and said, well, if you know you clearly you're not a fan of solid, what would you replace it with and, and that led me to, you know, is, is there, are, are there a set of principles, is there a universally applicable set of principles to software or is it just such a vast field that, that doesn't make any sense?

And, I got to thinking about it and I ended up with properties. I said, I wouldn't describe any principles as universal. They're all contextual, but there are properties of code that I think make it joyful to work with that, make it, make coding fun. You know, I've been into code bases. I've been super lucky in my 30 years, I've been into code bases more than once, not often, but more than once and just smiled. You know, you look at the code and you're like, I get this and I'm about to have fun, right? I'm about to make a change here and I know I'm gonna do it confidently.

I know I'm gonna not mess things up because someone else who came before me put this together in such a way that it just couldn't be more self-explanatory, couldn't be more intention revealing. And it's mate, when you get that, you don't ever wanna you don't ever wanna not have that. And also it makes you super careful like when you're in there, I don't, I, I wanna leave it like this. What are these properties and then just trash it and then go, you know.

David Brown

they set benchmarks and what are the properties of those, of those five properties of keeping well. And so this is what? And so and so so then, so my counter is that I don't have a 1 to 1 correspondence with solid because I think individually each of them is silly. Each of them is, is again, neither necessary nor sufficient, um usefully useful at a time, right? In the mid nineties, which is, yeah, a generation ago, they were good, they were good sound advice, but they haven't aged well. So, what would I describe and say, I, so, so I described properties of code. So very briefly, Cupid is an acronym. So I started with a word and then added and then, and then then assigned properties um which is great fun because um and it was deliberate as well, you know, Cupid is like the, the, the, you know, it's um the God of love and, and it's about, you know, joy and romance and stuff and it's like the opposite of the kind of bro culture around in software, craftsmanship and solid and all of that. So I wanted something deliberately controversial. Um And, and it also means that you get to have candidates like there's loads of things that begin with. C um I'm gonna write, actually, I've got it in my head. I'm gonna write a series of articles of the runners up like I there were loads of I and I ended up with idiomatic, but there were, there were several for I that and then what I discovered delightfully as an accidental consequence is that all of the runners up you can derive from the five that made it so the five that made it kind of foundational. And then any, anything else you can say, well, because of these things, you're gonna necessarily get that. So briefly,

David Brown

you like you're a word.

Daniel North

I’m no, I, I've never played Wordle, I've seen it. I, I've just, I've never been inclined to play Wordle. I, I have of Wordle on my Twitter time straight. I mean on my Twitter timeline, but I don't actually play. Um So C is composable. So this is the idea, you know, the, the kind of the principle of comparing preferring composition over inheritance. But the, the idea with all of these, of these properties, is it not at a line of code just at a line of code level? So the idea is that all of them are fractal.

So I want composable code, I want composable functions or methods. I want composable classes or objects or and but then I want composable modules and I want composable subsystems. So when you're designing api it says composable there, when you are thinking about how how you're gonna build your code, there's composable. So for instance, one of the aspects of composable is dependencies, right? So if you've given me a lovely, lovely api and it drags in half the internet through maven, right. I'm much less likely to use it.

So, composability requires you to think small and requires you to be very, very discerning about what dependencies you absolutely need and what you can't roll your own. So, let's see. U is UNIX Philosophy which is do one thing and do it well. which kind of sounds a bit like single responsibility, right? Except except um very deliberately um the cupid properties of in the eye of the beholder, right? Beauty and joy is in the eye of the beholder. So this is it does one thing for you as a consumer, whereas the solid principles are from the perspective of the code. So it has one reason to change. Yeah.

So it may, it may do one thing and have one reason to change. But if I need to, if I, if from a consumer perspective, um that lump of business logic is no use without the view on it and without the data on it. So that that is do one thing. So I I, so, so so wi with the component piece with the B composable and do one thing, you've basically got UNIX to all of the UNIX shell commands, you know, the the the kind of core commands they're all about composable and they're all about doing one thing. Well, so cat gives me contents of files. W get or curl gives me contents of, of web pages, um et cetera. And then from, from that content, I can then filter that content using grap. I can then transform that content using said or, or I can then um so and, and so you can compare and then I can filter out what's left using um s unique for instance or sort.

So um so just having really simple primitives for text processing, I can build very sophisticated pipelines because everything is composable and each thing does one thing really comprehensively. So that's the up is about predictability. So predictable is the way I'm describing it is it's a generalization of testable, right? So Mike Feathers, um his, his lovely book, Working Effectively with Legacy Code, he describes legacy as anything without tests, right?

So I went broader than that cos I've seen, I've seen legacy code bases without tests that were joyful, that were brilliant to work in. And I've also seen entirely test driven code bases that were an absolute rat's nest and I wouldn't want to do work in them. Um So, so again, having full test coverage which we'll get on to later is neither necessary nor sufficient. Um Yeah, so so predictable is, is I know what it does, I can tell by looking at it what it does. So it's about intention revealing, it's about um it does what you think it will do So code that does what you think it will do. And also that it's easy to determine that it does what you think it will do. And that's not necessarily with automated tests.

You know, it may be through some kind of checker, it may be by running it, it may be by putting um, by looking at it. But if I can make code that is easy to instrument, right? That has its own telemetry that tells me when things are wrong that that fails in a well known way. So, predictable code isn't just about that. It follows the happy path every time. It's that when it fails, it's, it fails in, in well known ways and, and we often don't think about that. So does it fail silently?

Does it fail silently and corrupt data? Does it fail catastrophically? Right? You know, and I need to know this and this allows me then to use your API but as the P I is idiomatic and this is a really big deal, idiomatic means you write code like everyone else would like to write code. So it's a bo a lot about ego list programming, right? If I go into a code base and I can see that this is David's code and I can see that this is Kevin's code then, you know, props to you for having your own style. But it means that now I've got more cognitive load, I've got to not only think about the pricing algorithm problem I'm trying to solve. I've also gotta think about how David would have coded this and where he might have put this and his weird naming convention for stuff and his punch on for a different testing library from everyone else. Right? And all those lovely idiomatic, all those lovely personal quirks. So idiomatic code says write code like everyone else.

If the language itself has an idiomatic style, closure is a massively idiomatic language, you know, cloggers, they all write code that looks the same. They all write this lovely lispy style of code. And you can tell when someone's new to closure cos they're trying to write imperative kind of procedural code in a lovely functional listy language and it takes a while to get there. Likewise go has go format which takes all of your syntax, highlighter syntax discussions off the table. It also has a massive standard library where everything looks the same, right? And I hate their naming conventions. Something that does reading and writing is called a reader writer.

You're like really, that's the best you could do, you know, and somebody that's reading and writing and printing, guess what that's called, right? But then the yeah. And then, but then what happens is that as you look through the core library, if you've done anything with the HTTP library, you've written to HTTP code and then you go to use the FTP library. It's like I've already been here because whoever designed the FTP library made it look just the same as the HTTP library and all the errors fail in the same way. And then you look at the SMTP library and guess what? Right. Any network protocol libraries have all been designed with a similar flavor. And so what they have, they bake that idiomaticness idiomatic.

Anyway, they bake that into the language and into all of the example code. And along with that, you get this effective go, which is a beautiful document that says here's how we write, go around here. I'm not advocating for go I think it's a really ugly language. It's very good for a very small subset of things.

Um but boy are they idiomatic, right? Because they know how many developer hours days millennia have been lost to pointless arguments about style, right? And how many really subtle bugs have come in because I thought I was in some of Kevin's code and actually I'm in some of David's code and he does error handling differently and my thing just suddenly failed, right? So, it's layered, right? So you have idiomatic, what the what the community does, then idiomatic, what we do around here like in this organization and then idiomatic how our team writes code and if you kind of layer those things on, it's pretty hard to write code that doesn't look like the other kits, right? But if you don't set those standards, yeah, if you don't set those lines in the sand when you start, you just end up with 10 different styles of code. And it makes change much harder and much less joyful. D the last one domain based, which is, and again, this goes right back to the, the, so the um the s conversation we were having earlier single responsibility conversation. So I'm a massive fan of Domain Drum and design. Domain Drum and design was one of the core ingredients to BDD back in the day in 2003 or something. Um And I'm a huge fan of Eric Evans. I think he's a AAA giant in our industry. Um His domain and design is the idea that writing software to solve business problems isn't the point, right? Understanding the domain and solving problems in that domain is the point and writing software is like a useful by product of that. So, you know, I'm trying to understand. So he is, his background is um shipping. So logistics and so what he does is he spends ages and ages working with people, understanding what they mean by a manifest, what they mean by moving cargo around, what they mean by um bonded warehouse and what all the and all the business rules flow from that and how we do work and just software just kind of seems to appear while he's having his conversation. But the names in the code represent things like, you know, if you've got a bonded warehouse, there will be a bonded warehouse thing in the code, but you can't not know that this code is about bonded warehouses or this code is about derivative pricing or this code is about patient healthcare management because it just says it you haven't got into I, you know, you've got in patient id or something and you can't not know. And so anyway, strong domain naming is just again, another way of reducing cognitive load. Um But then what I talk about is domain structure as well. And this goes right back to things like rails. Um and all these kinds of frameworks that have views here, controllers here, models here, helpers here, managers here, whatever it is. And like I don't care about all that. I mean, I know I'll need those things. But what I want at the top level is patient management, right? Um Order booking like I want my broad bounded context, my broad subdomains at the top of my code base and within those then the subdomains in there. And yeah, there'll be models and views and controllers in there, but I'm an adult and I can find them. So I don't want you, I want to see the framework, I want to see the solution.

David Brown

Now you, you briefly mentioned BDD, which is behavior driven development. When you were talking about Mandarin design, you developed behavior driven development as a response to the confusion and misunderstandings in your own words from various agile processes such as test driven development. So I'd like you to dive into if you may behavior driven development. What does that mean? And, and what, what, what was it develop in response to? So

Daniel North

it's interesting, I think with, with, with a lot of these techniques particularly with and TDD is a real a, a really good example. Um There, there are, there are, there are several others as well where you get a, I think a genuinely game changing technique that gets let down by a poor name.

OK. Kent Beck is a, is an amazing programmer. You know, he really is an amazing programmer. Um He isn't great at naming things or rather there are better names and, and so, so test drive and development suggests that there's tests, right? And he said, and he asked me when he describes it, he says, right? We're gonna start with a test, right? We're gonna start with a failing test. And I started doing this. I picked this up around late nineties again, so 20 something years ago. Um and I was fascinated by it.

So you write code for code that doesn't exist yet. So, yeah, so what we do, it's like a model client. You're like you're writing a model client for some code that doesn't exist. Let, let's, let's take an example. We're gonna go and get some, you and I, we're gonna go and get some code out of the database.

OK? So you ready sleeves up, we're gonna go, we're gonna go get some code out of the database. Let's you, let's write an API for that. So let's see. The API could be um connect a database run a query, close a connection, right? That's the three things we need to do. So we go, OK. And then we go, right? So let's write a client for that. And our client would be um connect a database, run a query, close a connection. And you look at me and you go, you know what's gonna happen here, Daniel, don't you? Like? What's that? They're gonna forget to close the connection.

Yeah. No, you're right. You're right. OK. Try open database. Run query. Finally. Close connection. OK. Yeah, that's, that's, yeah. OK. I'm happy with that. Fine. What about if the connect trails? yeah. Yeah, I just think about what kind of failure we're gonna have. OK. And so what we're doing is we're now designing the API and we're designing the API to like, and then you look at me and you go, who else who else in our world is ever gonna do? Tryin and we look at each other and we go like no one, right. So what if we put that behind the API and what if we just had a run query as the entire API and in our implementation of run query, we're gonna do that, try the final thing.

So it's a bit more work for us. Much easier to use. So we've just had a design discussion in writing a model client. We've taken a model client from three lines of code in a complicated construct to one line, right? Go us because hopefully many more people are gonna use our code than they're gonna write it in the first place. Yeah. So what we've just done is simplified the API that's test driven development.

Did you hear me use the word test in there at all? No, no cos I'm writing a model client. I'm not writing a test right now. It turns out that if I use this model client um to then exercise the thing I built and I can maybe put some assertions in there about how I think it should behave, then it becomes a test. So this is the and this is the linguistic shift is that your model clients, your code examples become a test after they were useful, right? I wrote the code to design the API. That was the value I then got from this handy by-product that I can run in the future and see that it still works. But the problem is all the spotlight went on the second bit and not on the first bit, including in Kent's head where he talks about it. It's a test, it's not a test, it's a model client. Even if you're Kent Beck, you're still writing a model client, right? And so as an experiment, this is 2003, I remember vividly, I remember the team I was on and I was trying to pitch TT DD to them. I was like, it's the best way to write software. It's brilliant. You end up with really good design.

I've been doing it for years and all of a sudden, they're like, no, we're programmers, we don't write tests. We have testers to write tests. And this is very much the culture of, you know, testers are cheap programmers or, you know, they're, they're the people who are good enough to be programmers that kind of mindset. And I was like, but it's not really a test, but you called it a test. It's called test of development. You said we're gonna write a test? I was like,, crap. How else can I need it?

Meanwhile, the testers got wind of this and they're like, are you getting the programmers to write tests? I was like, kinda, and they said that's our job and it was partly like a fear of losing their job. But it was also we know these programmers and they're rubbish at writing tests. Let me tell you. And so I thought, well, how can I describe this differently? And, and so I said, right, I'm not gonna use the word test. I'm gonna talk about behavior. I'm gonna say we are going to describe the behavior of the code before we write the code. It's like in a spec, you'd write a functional spec, right? In the functional spec, you'd say this is our expected inputs and outputs.

They say yes. So we're gonna call it specification. So we're gonna write an executable specification and executable certification will document the expected behavior of our code, right? So, and, and, and here this, this one became the cell. If you do this, David, you don't have to write a functional spec, right? Shut up and take my money. Either do TDD with Dan or you can write functional spec where, where's Dan? And so now people start and, and then suddenly all the adoption questions went away, you know. Yeah, let's do it because what we're doing, we're writing behavior ahead of time and then,, by the way, kids as a cool side effect, these things make pretty handy tests. Yeah. So that, and that was where BDD came from. It was an attempt to reframe TDD.

Cos I don't have a beef with TDD. I love TDD. I still think it's the most powerful model I've ever come across technique I've ever come across for design in the small, it doesn't give you design in the large, you still need to have AAA picture of the architecture that you're growing into, you need to make some decisions about. Are we event driven? Are we three tier? Are we a client server? Are we message based? What, what sort of, what sort of thing are we building? But in the small, when I'm building this piece of it, TDD is absolutely a brilliant way to come up with good design, especially with pair programming. They work so well together. So you and I sat down and we had that conversation in real time about that database API and we smashed it right.

We put all the other handling where it should be now that it's a single myth by the way. And we are earning the try. Finally, we can also do things like connection pooling. That's cool, right? We just got that for free, right? Cos we put that behind the A K I and all of that came out of, will anyone else ever do try finally? And he looked at me and he went, no doubt they won't, let's do that for them. So it's a brilliant design technique.

So, there we are then with BDD. And then I remember this vividly as well. In 2004, I was talking to a business analyst buddy at Thoughtworks, um called Chris Matt and is, and he said, what's this BDD thing then? Cos I've been hearing this, you know, going around thoughtworks about BDD and I said, basically you describe the behavior you want in terms of an automated way and then you implement the behavior and then you check that what you got is what you wanted. And he looks at me and he said, you know, you just described business analysis. What do you mean? I said, well, business analysis, you describe what you want, you write some software and then you check that it does what you're supposed to. And we both just went. right. Maybe this works at multiple levels, right? Maybe we could use B this BDD model to describe behavior. And we had there was a, there was a an index card kind of template going around. Thought works at the time. It was a lovely guy, Ivan Moore and what he would write on an index card, he'd write your stories on an index card, cos you old score. And if you, if it doesn't fit on a like a five by three inch index card, then it's too big. You need to write less words. Yeah, write a few words.

So and on the back of the index card, he did a, he wrote a line down it. I need two headings. I do this, this happens, right? I do this, this happens and that was his exceptions test, right? And so you go, I do this log in with the password. This happens, I see the landing page bad password. I this happens error message bad password, three times this happens, locked out, right? So really simple way to capture exceptions criteria. So Chris looks at this and he goes, yeah, that's not gonna work. So, what do you mean? He said, well, I do this. He said any number of things could happen.

Depends on the context, doesn't? It said like let's say you log in with the correct password. Yeah. And the system's down. Do you get in? No, you get a 501, don't you? Nothing to do with you like,, you're right. And so he added a third column at the beginning which is context and that's where given, when then came from. So given some context when I do this, then this happens. And so now we have this like really lightweight template if you like for capturing those um examples. So now at a code level, we could and I still to this day, 20 odd years later, I still to this day when I'm writing. So I do or, or if I write any BDD at all these days, I use things like pie test or J unit. I, you know, real simple what we would think of as unit testing frameworks.

There's a very few times I will reach for something like cucumber. It, it has its place, the plain text runners have their place, but it's much, much smaller space than you'd think. Anyway, that's a whole another conversation. Um So, yeah, so I still try to, you know, give when, then, so I go hash given hashtag hash hashtag or slash slash slash hash when slash then and then I start writing my, my model client and, and I throw from there. And so Chris and I kind of s budded up and we had this thing called behavioral and development. We started talking about it at conferences. So, so my beef with TDD has never been with TDD. I love TDD. I heart, I heart. Um The, I'm not obsessive about it and it has a place and the other big risk with TV D I wrote this big article about this last year. I don't write that many articles, but I had this thing out of my head for literally years that finally came out. Um Is that it's still 20 something, 30 something years on it. Still nothing to do with testing, right? And what I mean by that is this, let's say you and I pair on something and we do TDD and we end up with a bunch of code examples and we say, right, we've got tests now, but let's look at those tests. Those tests were the smallest number of model clients that triangulated our answer. So we probably just started with one to get the basic API and then we're gonna try one that's gonna test maybe some air conditions or something and maybe one that's gonna put in some bad input. Right. And we're going right. Are we confident that what we've built is probably robust? And we go, yeah, I'm down the pub or out for coffee.

Yeah. Um, if you're a tester looking at that you're just gonna break out in hives that's not tested. No, it's not, it's minimal viable assurance that you probably haven't messed it up too badly. But it's not testing. So I could take that test. I could say one of the tests that puts a value in and I could write a generative test based on that that puts in hundreds of millions of values and just keeps on running all the time and every now and then it beeps cos it finds a failure mode and it turns out that if you have a very, very small negative number close to zero, we're due to some floating point quirks in the Java library that it breaks our pricing. Like neither of us would ever have thought of that. Luckily, we're just slamming it with random numbers and one of them broke when it breaks, we can figure out why, but we're unlikely to break it. Right. That's testing. Assuming, assuming that it might break.

David Brown

that I'm gonna have to, cut you short, Dan, because we already, well, I, I think this is our longest podcast and you warned us beforehand that you, you had plenty of material on, on this subject matter and you were right because I haven't even asked you half the questions I had written to ask you. But I, I am, I think so. I am interested. One thing before we wrap up is, is what has been the community's response, to,, Cupid and BDD. What do you know that you get a lot of flak? Did you get accolades? You know what, what has been the response?,

Daniel North

That's a brilliant question. I think with BDD, it was, I was amazed, I was amazed at the adoption of BDD for me. It was, I, I never meant it to be a thing. Right? It was, genuinely, a coaching hack. It was, I was, I was convinced that this team would benefit from TDD and I was convinced that the push back I was getting about testing was totally irrelevant, but I couldn't convince him it was irrelevant.

So I just started over. I said, right, we're not gonna do that thing. We're not going to TDD. But what we're gonna do instead is write an executable spec and, and then, and then it, but then there was a thought that works. This is back in the early days of thought work where we had these things called away dates, you know, and the whole company would get together and do stuff and give talks and I gave a talk about it. And this wonderful lady Liz Keogh, um got very excited about it and said, right. How do I turn this into a thing? And, it kind of went sort of viral within thoughtworks.

People started finding that this technique was a great way for them to introduce TDD as well. And then suddenly the world picked it up and I had no plan, plan that was gonna happen. And then some time later, um in the Ruby community, especially, some folks that aren't me, some folks wrote a thing called A speck which was like a BDD style like a given when structuring for Ruby. And, and I was writing something in Ruby and I wanted something at a higher level than a spec ar aspects, a code level thing. And I wanted a given when then thing. So I wrote a give when then thing and I called it um our behaviour and then the ape folks which is David Chims, Alec Heide, some other folk folded that into R aspect and then a like went and basically rewrote it as cucumber and this thing just exploded, right?

So cucumber suddenly became, I think one of the most downloaded software products of all time or something. And, and so no one knew this was gonna happen. And then I think my head finally exploded when it had its own conference. IVDD got its own conference. I was like, wow, so, yeah, yeah, yeah. I, I've given keynotes of my own, my own things called and there was a lovely phrase. I learned many years ago that I try and live by, which is, if you, if you want an idea to travel a long way, don't try and travel with it. And I've never tried to be the BDD person.

Right. The BDD community is rich, exciting, vibrant, creative and way, way, way bigger than me. And that delights me. Um, but cupid is much more deliberate. Cupid is right. Well, look, you know what, I'm gonna do something here. I, I'm gonna talk about this thing. I've been, I've spoken about it at conferences. I've written this article um which appeared on hacker news. Um In fact, the back story appeared on hacker news and then the article appeared on hacker news and that, that was a nice bit of amplification. But then, and this came from totally left field I discovered I'm in the latest version of the thought works. Tech Radar, right?

Cupid is now a thing to explore or something. Not, it's not adopted. I can't remember what it's called, but like the thing where they're saying, we've come, we've become aware of this thing and you might, you know, want to have a look at it. Um And, and I'm like, wow, that's probably the shortest time from anything. Certainly I've done to anything that's appeared and that all tech radar and, and the, the feedback I've had from Cupid has been universally positive. There's a bunch of, of course, solid programmer, craftsman type who are just rattling pitchforks. But they're the same people who rattled pitchforks when I did the talk with the original, you know, poking the bear talk five years ago. So I'm kind of over them. Um, but, but other than that, um, no genuine there, there's been a lot of love, a lot of positivity and I'm super excited about cupid. So, yeah, I'm, I'm, I'm not sure where it goes. Um I, I unpacked the, well, I unpacked the article. It's a 5000 word article.

I unpacked it onto its own little website called Cupid dot dev. So if you go to Cupid dot dev, it lays out all of the properties and my um my aspiration at this stage is to start collecting case studies and putting them up on the website as well. So people can see other people using cupid and as a tool as a review construct as a, a set of maybe design principles, that kind of thing

David Brown

and of, and of your social channels. Dan is, is you more active on Twitter, linkedin on the Dan north.net website. Where, where, where do our listeners where should they follow you?

Daniel North

So I'm, on Twitter far more than I should be. That's my main channel. Like I'm not on Facebook or Instagram or anything I'm on, I'm on Twitter a lot. Um I, I occasionally go to linkedin but I find linkedin tends to be where messages go to die for me.

So I think I, use linkedin as like a big phone book. Um So Twitter, definitely. And del.net is where I, where I um publish things. But typically what I'll do is I'll publish something on Band North on that and then I'll tweet about it and that's how you find that

David Brown

look. So many interesting insights we could have gone on for way longer. Congratulations.

Daniel North

just ask me questions and I was just on a roll.

David Brown

Congratulations. You established our longest ever podcast by a good margin. I might say,

Daniel North

You know, you can't just, you can't just cut me out, right?

David Brown

Yeah, it's been a pleasure having you on the show. Thank you

Daniel North

very much. Thanks very much indeed. Ok.

Kevin Montalbo

Alright. Thank you very much, Dan.

David Brown

Sorry, I had to cut you short, Dan.

Daniel North

No worries. No, I was well, I was just chatting and, and like the thing is you ask these questions and I'm like, man, I could really spend some time unpacking that

David Brown

When, when we first wrote the questions of this, honestly, there was twice the number of questions I said, I said to Kevin just send four because these are, these are big areas, right? And I said if, if necessary, when, when we can just dive into more if necessary because sometimes, you know, they people answer questions in five minutes. And I, so I, I dive into the questions and, and drag but I just had a feeling that wasn't going to be the case here. So.

Daniel North

I, I apologize again. I don't know if you know, why don't you like solid?

David Brown

Be careful what you ask for

Daniel North

like, the touch tape,

David Brown

Dan. Enjoy the rest of your day. Thanks again.

Daniel North

Fantastic. Thanks James. Take care now. Bye

David Brown

bye bye.


Listen on your favourite platform


Other podcasts you might like