I liked the story at 16:05 - this is why i love TDD. Especially given my relatively low skill level where I make a lot of mistakes and frequently rewrite things. Having the confidence in every little function I built is so powerful.
I'm so sad. Voices in our industry like Feathers, Cunningham, all the original XP proponents, are not listened enough. While all the "kids" re-invent the wheel the wrong way and get so much media coverage. And what they say (which is often wrong) counts as bread and butter. This video should get instead millions of views.
Jesus! You really spoke to the right people! Michael Feathers is a legend and a personal hero of mine. I wish he had more things on youtube and more books!
Even if you're not using TDD as a methodology, practicing with it will level up the way you think about your code. I agree with folks that say tdd adds too much time to dev cycle but doing it for high value items helps write clean code.
I used to work as an electrical engineer, and having to work around physical constraints did allow me to work better in some areas. But I also enjoy the freedom in software to do things the way I want. Pros and cons for each 🤷🏽♂️
I had written some small cli utility in python for parsing and had to make a choice of what cli library to take. And i've chosen from those which would have a) out of the box unittest support, b) were based on simple to understand principles for others to pick up. When i presented the utility to my colleagues, they could follow along without problems, and even commented that the cli library choice (Cleo) was fantastic, because normally cli requires messing around with standard argparse module, which is at the end much more error prone and takes more time to understand. All in all, i would say because i started to write unittests for the functions from the day one, i could safely refactor midway, and had always the feeling to be on track, even if i wanted to explore another ways. Because all the valuable algorithmic intellectual work was safe under the guard of unittests. At the end i had about 500 LoC and 50 Unittests (which just covered the most basic stuff) May be i'll take it as a rule of thumb at least 1 UT for 10 LoC :) And to be honest, i'm a software tester, and i dont't trust computer systems, libraries, programming languages, peoples intellectual abilities. I feel great if i have a test even for basic things. Its a contract, it's something you can rely on. Anyone can write code which no one knows what it does.
16:55 Pre-covid, I used to hack away on a project on the commute to and from work on the train, and would frequently leave myself with a failing test as a bookmark to remind myself where I was and what I was doing. It's such a good tool.
Are there people here, which are practising FP on a larger scale in larger groups? In my experience, the best thing of OOP is the self-afvertisement of functions you write. You make a new Functionality on a class, and it is directly advertised to other programmers (even of different teams) by code completion making your code more likely to not be reused. How Do you guys organise this communication of functionality across teams?
Extremely interesting interview! Right now, I'm working on adding unit tests to our team's Vue 2 codebase. I'm bothering to do that, based on "Working Effectively with Legacy Code".
Keep in mind: 21:50 “you don't have to be upset that you only have like 52 coverage in your system” The point of microtests isn't to test feature correctness but to act as the “instant feedback machine” that warns you when unwanted changes occur during refactoring. Ian Cooper's talk “TDD, Where Did It All Go Wrong” is also helpful in this regard as he emphasizes that many microtests are only temporarily useful; they need to be deleted before they become a maintenance burden. I would also recommend J. B. Rainsberger's 2017 talk “The Well-Balanced Programmer” which has an interesting treatment of the hexagonal architecture (sorry, Vue counts as part of the HOW, not the Happy Zone). Finally, Martin Fowler's 2021 article "On the Diverse And Fantastical Shapes of Testing" is also worth a read emphasizing that often “sociable microtest” are more useful than the “solitary tests” that where popularized by the London/Mockist school of unit testing (made all too easy with current generation of mocking frameworks).
Is TDD strictly writing test first before writing code or is it writing code with testing in mind (testable code) regardless of whether test is written first, along side writing code or after writing code? For me, I lean towards the latter. I need to decide and know the structure of what I want to test to an extent before writing test. Can't get my head around writing test for something that doesn't yet exist.
I don't really follow TDD. Quite frankly, the problems I work on aren't that complex. It's mostly web endpoints that have a relatively limited set of rules on what to do and when. I aim my tests to cover those rules at the highest level possible that makes it so the tests are still easy to setup and fast to run. 90% of the time it's the class that the web layer uses directly. It's basically calling a single method on a single class with 3-4 parameters. If I do run across a chunk of more complex logic that will have lots of irrelevant setup, I pull that out and write tests just for that. For example, I worked on an ecommerce project with very particular metric tracking requirements. Testing that by refunding and making orders would require a lot of irrelevant details and setup. Some of this is foresight and some of this is just noticing the path I'm going down and diverting course before the tests turn into a complete disaster.
How do you properly do tdd and domain driven design, while trying to remain functional and immutable, when you're writing a plugin for a program that only exposes api via COM interfaces, and the objects are a bunch of globally mutable OOP monstrosities? I'm trying to write a plugin for autodesk inventor, but the same sort of thing would apply to like.. Excel
Yeah i sometimes mess about with modding games or writing automation scripts like auto hotkey. I find i basically need to write very small chunks of code and do lots of manual testing, since there just isn't always a test framework available in these tools. (Just did some googling and ahk does have a test framework, wow!)
Full on TDD could be difficult, at least in the beginning. I'd start with a Façade with the idea - to define an API that aligns with the needs your domain (think in terms of a “Consumer-Driven Contract”) - to act as an anti-corruption layer, i.e. it should be much easier to support domain-specific behaviour via the Façade than the COM API directly. It sounds like the COM API might be stateful but you could level the field by forcefully resetting residual state between each interaction while using builders to create command sequences (that rely on intermediate state in the COM API) that execute atomically. Other than that the Façade should be largely transformational operating largely as an adapter exposing an idealized API. For testing a custom test double of the original COM API that simulates only the behaviour (responses) relevant to the Façade could be useful.
The biggest drawback I've seen in test driven development is that mocks are essentially duplicate code to simulate other systems. Ideally, each real code component should generate it's own mock for testing purposes or at least be written only once and imported for each dependency tested against it.
That certainly is a common problem in the use of mocks, but it is really a signal that the design is poor. It usually means that the code isn't really sending messages to collaborators, it is collecting data from them, it is violating the guideline of "Tell don't ask!".
The "Glue System, or Computational System?" section. YES! A well designed front end is a Glue system, not computational. Unit tests simply aren't as effective there.
Far from it. 20:58 “where you're gonna find the computational bits and try to go and isolate those and get test coverage around this” 6:12 “if you have a private method you want to test then you know chances are that's part of an abstraction that's begging to be pulled out” In 2002 Michael Feathers also authored the article “The Humble Dialog Box”. So essentially the logic that one would find inside of the hooks of a typical React application would be pulled out and relocated in a sub system on the other side of context leaving all the "React components" extremely thin, only responsible for (1) rendering visual state as published by the corresponding sub system(s) and (2) directing user events to the relevant sub system. Isolated in such a way these sub systems would be testable (due to improved design) where microtests, testing only important invariants (not implementations) then provide near instant feedback during refactoring to “reduce volatility in the marginal cost of the next feature”. Testing the actual rendering and event propagation is left for E2E testing.
@@PeerReynders Yes, absolutely. However, in a thin client, those "hooks" you talk about are a very small percentage of the code and many of them are very simple. Making sure a particular hook pulls the first name out of a GET response to display in a label can be tested, but the logic itself is pretty simple (as little as `response.first_name`...) so there really isn't much to test there. Sure, isolate the computational bits and get test coverage around those, but that's not going to get you high code coverage. I'm glad they also remarked that code coverage should not be a goal...
@@danielt63 The issue with the React ecosystem is that the supporting packages directly integrate with React. It's “the application's” responsibility to manage the why and how of the data and to initiate processing based on user interaction. Lean React components should only render information as presented by “the application” and forward user interactions to “the application”. These “React integrations” deprive you of seeing “the application” (i.e. interfere with design) and the boundary around it . Ryan Florence's 2022 Reactathon talk “When To Fetch: Remixing React Router” pretty much comes to the conclusion that "fetch" has no business being inside a React Component and even if you are using ReactQuery, you are using “one of those integrations” that interfere with design. Also forget about "code coverage". Leave "use case coverage" to E2E tests. Microtests aren't about correctness; they form your refactoring feedback system that warns you when undesirable change happens.
Great info here, but UI done right, in terms of UX, probably shouldn't include rounded frames around each persons video stream, complete with animated borders... drove me absolutely crazy watching this. Massively distracting. Very 90's - cringe. Just split the screen down the middle, with zero rounded borders, no animated background etc. Basic stuff. Content is king, content speaks for itself. UI/UX should compliment that, not distract from it - it should be invisible to the end user, in terms of cognitive load. The moment you introduce multiple animations in a long form video, is the moment your audience gets distracted. The importance here is the conversation. Arguably, you could just have audio here :shrug: - podcast.
Haha agreed! I usually just listen to these while washing dishes or doing other chores anyway. The way the sizes of the video panels constantly grow and shrink is really distracting.
Dave has that 100k Plaque in the background. Well deserved! Been here for 2 years now and still coming back. I appreciate all you do Dave.
I liked the story at 16:05 - this is why i love TDD. Especially given my relatively low skill level where I make a lot of mistakes and frequently rewrite things. Having the confidence in every little function I built is so powerful.
It's always a pleasure to listen to Michael Feathers. Thanks for this.
I'm so sad. Voices in our industry like Feathers, Cunningham, all the original XP proponents, are not listened enough.
While all the "kids" re-invent the wheel the wrong way and get so much media coverage. And what they say (which is often wrong) counts as bread and butter.
This video should get instead millions of views.
Jesus! You really spoke to the right people! Michael Feathers is a legend and a personal hero of mine. I wish he had more things on youtube and more books!
I cant agree more. More Michael on the stage.
Well that was an absolute treat, thank you both!
Even if you're not using TDD as a methodology, practicing with it will level up the way you think about your code. I agree with folks that say tdd adds too much time to dev cycle but doing it for high value items helps write clean code.
In Smalltalk you have the Workspace or Playground. It's the equivalent of a REPL, but for objects.
I used to work as an electrical engineer, and having to work around physical constraints did allow me to work better in some areas. But I also enjoy the freedom in software to do things the way I want. Pros and cons for each 🤷🏽♂️
Dave: The correct title of Michael's book is “Working Effectively with Legacy Code”. Please update the description!
Love these chats! They’re worth a whole university course!🎉❤😅
I had written some small cli utility in python for parsing and had to make a choice of what cli library to take. And i've chosen from those which would have a) out of the box unittest support, b) were based on simple to understand principles for others to pick up. When i presented the utility to my colleagues, they could follow along without problems, and even commented that the cli library choice (Cleo) was fantastic, because normally cli requires messing around with standard argparse module, which is at the end much more error prone and takes more time to understand.
All in all, i would say because i started to write unittests for the functions from the day one, i could safely refactor midway, and had always the feeling to be on track, even if i wanted to explore another ways. Because all the valuable algorithmic intellectual work was safe under the guard of unittests.
At the end i had about 500 LoC and 50 Unittests (which just covered the most basic stuff) May be i'll take it as a rule of thumb at least 1 UT for 10 LoC :)
And to be honest, i'm a software tester, and i dont't trust computer systems, libraries, programming languages, peoples intellectual abilities. I feel great if i have a test even for basic things. Its a contract, it's something you can rely on. Anyone can write code which no one knows what it does.
16:55 Pre-covid, I used to hack away on a project on the commute to and from work on the train, and would frequently leave myself with a failing test as a bookmark to remind myself where I was and what I was doing. It's such a good tool.
Great interview! Always good insights and instructions
Are there people here, which are practising FP on a larger scale in larger groups?
In my experience, the best thing of OOP is the self-afvertisement of functions you write.
You make a new Functionality on a class, and it is directly advertised to other programmers (even of different teams) by code completion
making your code more likely to not be reused.
How Do you guys organise this communication of functionality across teams?
Extremely interesting interview! Right now, I'm working on adding unit tests to our team's Vue 2 codebase. I'm bothering to do that, based on "Working Effectively with Legacy Code".
Keep in mind:
21:50 “you don't have to be upset that you only have like 52 coverage in your system”
The point of microtests isn't to test feature correctness but to act as the “instant feedback machine” that warns you when unwanted changes occur during refactoring. Ian Cooper's talk “TDD, Where Did It All Go Wrong” is also helpful in this regard as he emphasizes that many microtests are only temporarily useful; they need to be deleted before they become a maintenance burden. I would also recommend J. B. Rainsberger's 2017 talk “The Well-Balanced Programmer” which has an interesting treatment of the hexagonal architecture (sorry, Vue counts as part of the HOW, not the Happy Zone).
Finally, Martin Fowler's 2021 article "On the Diverse And Fantastical Shapes of Testing" is also worth a read emphasizing that often “sociable microtest” are more useful than the “solitary tests” that where popularized by the London/Mockist school of unit testing (made all too easy with current generation of mocking frameworks).
Is TDD strictly writing test first before writing code or is it writing code with testing in mind (testable code) regardless of whether test is written first, along side writing code or after writing code?
For me, I lean towards the latter. I need to decide and know the structure of what I want to test to an extent before writing test. Can't get my head around writing test for something that doesn't yet exist.
No, TDD is definitely test-first. Otherwise, you aren't driving the design from tests.
Is that Jinx on the shirt? Didn't know you were a league of legends fan
😉
Test driven development is great because it requires people thoroughly think about what they're trying to build before they build it.
This was so helpful!! Thank you
were you running before starting the video? lol.
No but it was over 40 degrees C that day. 🥵
In Ireland a keener is a person who was paid to wail at a funeral
oh
I don't really follow TDD.
Quite frankly, the problems I work on aren't that complex. It's mostly web endpoints that have a relatively limited set of rules on what to do and when.
I aim my tests to cover those rules at the highest level possible that makes it so the tests are still easy to setup and fast to run. 90% of the time it's the class that the web layer uses directly. It's basically calling a single method on a single class with 3-4 parameters.
If I do run across a chunk of more complex logic that will have lots of irrelevant setup, I pull that out and write tests just for that. For example, I worked on an ecommerce project with very particular metric tracking requirements. Testing that by refunding and making orders would require a lot of irrelevant details and setup.
Some of this is foresight and some of this is just noticing the path I'm going down and diverting course before the tests turn into a complete disaster.
How do you properly do tdd and domain driven design, while trying to remain functional and immutable, when you're writing a plugin for a program that only exposes api via COM interfaces, and the objects are a bunch of globally mutable OOP monstrosities? I'm trying to write a plugin for autodesk inventor, but the same sort of thing would apply to like.. Excel
Yeah i sometimes mess about with modding games or writing automation scripts like auto hotkey. I find i basically need to write very small chunks of code and do lots of manual testing, since there just isn't always a test framework available in these tools.
(Just did some googling and ahk does have a test framework, wow!)
Full on TDD could be difficult, at least in the beginning.
I'd start with a Façade with the idea
- to define an API that aligns with the needs your domain (think in terms of a “Consumer-Driven Contract”)
- to act as an anti-corruption layer, i.e. it should be much easier to support domain-specific behaviour via the Façade than the COM API directly.
It sounds like the COM API might be stateful but you could level the field by forcefully resetting residual state between each interaction while using builders to create command sequences (that rely on intermediate state in the COM API) that execute atomically. Other than that the Façade should be largely transformational operating largely as an adapter exposing an idealized API.
For testing a custom test double of the original COM API that simulates only the behaviour (responses) relevant to the Façade could be useful.
@@PeerReynders Your comments on this channel are always helpful :)
The biggest drawback I've seen in test driven development is that mocks are essentially duplicate code to simulate other systems. Ideally, each real code component should generate it's own mock for testing purposes or at least be written only once and imported for each dependency tested against it.
That certainly is a common problem in the use of mocks, but it is really a signal that the design is poor. It usually means that the code isn't really sending messages to collaborators, it is collecting data from them, it is violating the guideline of "Tell don't ask!".
Yet that's not the definition of a Unit as put forward by the TDD proponents.
By coincidence I have asked the same question today "Why everyone want to do everything in k8s right now???"
39:40
If you're very keen on something, in Aus / NZ you would be a "keen bean"
Me reading this, thinking "oh god, I'm in trouble"
I thought Legacy Code been COBOL with some DL/I involved.
Hi Michael
The "Glue System, or Computational System?" section. YES! A well designed front end is a Glue system, not computational. Unit tests simply aren't as effective there.
Far from it.
20:58 “where you're gonna find the computational bits and try to go and isolate those and get test coverage around this”
6:12 “if you have a private method you want to test then you know chances are that's part of an abstraction that's begging to be pulled out”
In 2002 Michael Feathers also authored the article “The Humble Dialog Box”.
So essentially the logic that one would find inside of the hooks of a typical React application would be pulled out and relocated in a sub system on the other side of context leaving all the "React components" extremely thin, only responsible for (1) rendering visual state as published by the corresponding sub system(s) and (2) directing user events to the relevant sub system.
Isolated in such a way these sub systems would be testable (due to improved design) where microtests, testing only important invariants (not implementations) then provide near instant feedback during refactoring to “reduce volatility in the marginal cost of the next feature”.
Testing the actual rendering and event propagation is left for E2E testing.
@@PeerReynders Yes, absolutely. However, in a thin client, those "hooks" you talk about are a very small percentage of the code and many of them are very simple. Making sure a particular hook pulls the first name out of a GET response to display in a label can be tested, but the logic itself is pretty simple (as little as `response.first_name`...) so there really isn't much to test there. Sure, isolate the computational bits and get test coverage around those, but that's not going to get you high code coverage. I'm glad they also remarked that code coverage should not be a goal...
@@danielt63 The issue with the React ecosystem is that the supporting packages directly integrate with React.
It's “the application's” responsibility to manage the why and how of the data and to initiate processing based on user interaction. Lean React components should only render information as presented by “the application” and forward user interactions to “the application”.
These “React integrations” deprive you of seeing “the application” (i.e. interfere with design) and the boundary around it .
Ryan Florence's 2022 Reactathon talk “When To Fetch: Remixing React Router” pretty much comes to the conclusion that "fetch" has no business being inside a React Component and even if you are using ReactQuery, you are using “one of those integrations” that interfere with design.
Also forget about "code coverage". Leave "use case coverage" to E2E tests. Microtests aren't about correctness; they form your refactoring feedback system that warns you when undesirable change happens.
💯💯💯
Engineering? Science? Sure. But also philosophy.
TDD when done right looks a lot like BDD.
Great info here, but UI done right, in terms of UX, probably shouldn't include rounded frames around each persons video stream, complete with animated borders... drove me absolutely crazy watching this. Massively distracting. Very 90's - cringe. Just split the screen down the middle, with zero rounded borders, no animated background etc.
Basic stuff. Content is king, content speaks for itself. UI/UX should compliment that, not distract from it - it should be invisible to the end user, in terms of cognitive load.
The moment you introduce multiple animations in a long form video, is the moment your audience gets distracted.
The importance here is the conversation.
Arguably, you could just have audio here :shrug: - podcast.
Haha agreed! I usually just listen to these while washing dishes or doing other chores anyway. The way the sizes of the video panels constantly grow and shrink is really distracting.
@Ned Gerblansky lol right. And it’s a chat just watch as a podcast if it’s that triggering lol.
It does remind me of what people were using Flash for circa 1997