So what’s the different between Test-Driven Development (TDD) and Behavior-Driven Development (BDD)? I’ve written about that before, but I think that post lacks something more illustrative.
For one thing, I forgot to mention: I’m in the camp that thinks of the last D as design, instead of development. That matters.
I’ve heard developers say things like:
- “I don’t do TDD anymore, now I’m BDD all the way!”, or
- “I only do TDD, because I can’t use Cucumber, SpecFlow, or any one of those BDD tools.”
Here’s how I see it…
At some point, I learned to write unit/integration tests in this manner:
Through TDD, I learned to write such test before writing the actual code.
Then I learned about “BDD-style” tests, so I refactored tests such as the one above into the one below:
That was my transition from Arrange-Act-Assert (AAA) to Given-When-Then (GWT).
Then I learned that BDD and TDD go hand-in-hand:
No special tools, languages, test frameworks. In the example above, just plain C# and xUnit.net.
- BDD specifying the desired outcome
- TDD specifying the desired approach to achieve the desire outcome
Is Test Driven Development (TDD) practical when working with a lot of legacy code?
Yes, it is.
There’s an opportunity to practice Test Driven Development (TDD) whenever we write new code in a legacy system. As an example, when writing a new component, service, feature, etc., which is going to be called from the legacy system.
But what if the new code is to be written right in the middle of existing legacy code?
There’s still an opportunity for TDD.
Think what the new code is supposed to do.
Maybe it’s a new if-block that checks some variables in the existing code. That if-block asks the system a question; could that question be implemented as a method, a function, or similar approach, and then called from the existing code?
Or maybe the new lines will perform some sort of task, which is an opportunity to follow TDD to design and implement the new task, and then call it from the legacy code.
What about testing the existing legacy code?
There’s a possibility that the current state of the legacy code is so poor that even changing it to call any new code is so hard that a decision is made to only change the old code, and therefore, leaving no room for TDD.
If that’s the case, there’s still value in at least trying to write characterization tests for the existing code. That’s one scenario where using code coverage can yield benefits, as opposed to the bad way many people use it.
The existing system may be massive, so it’s important to know what we should write tests for.
What do we get from that?
The experience acquired with writing tests for legacy code makes us stronger TDD practitioners; as we experience the pain of writing tests for code that wasn’t implemented and designed with testability in mind, we also apply those lessons when designing new solutions.
But what if I’m working on a greenfield project and there’s no legacy code here?
Isn’t there? Are you sure? Many developers think of legacy code as code written a long, long time ago, often in defunct languages.
Michael Feathers defined legacy code as “code without tests”.
I’ve learned to think of legacy code as “code nobody wants to deal with, with or without tests”.
Sometimes a decision is made NOT to write tests (topic for another post). We can still write the code in ways that people won’t feel compelled to run away from it, even if there are no tests yet.
Sometimes we write tests within a sprint, but we do a poor job at writing those, so tests become “code nobody wants to deal with”.
In case you haven’t already, make sure to read and apply techniques from Michael Feathers’ Working Effectively with Legacy Code.
I give many talks on Testing (more specifically, TDD, BDD, unit testing, etc.) and often get asked for recommended reading on the topic.
I’ll list here some of the resources I remember I’ve read. Beware that some of them I’ve read a long time ago and do not know how well they’ve aged.
I’ll focus solely on books. I know I’ve read useful blog posts in the past, but I haven’t kept track of the most relevant for me, unfortunately.
Working Effectively with Legacy Code, by Michael Feathers
I’ve read this book twice. The first time was shortly after it came out in 2004. It had been only a couple of years since I learned about unit tests and had already felt the pain of writing tests for legacy code. I remember the book helped me a lot through period, and many of its lessons stuck with me.
I’ve read it a 2nd time earlier this year (2022) and believe the book has aged well, and think every developer should read it at some point in their career.
“oh, but I don’t work with legacy code”. If that’s you, just know that the code you wrote this morning may already be considered “legacy”.
Agile Principles Patterns and Practices in C, by Robert C. Martin
This book came out in 2006, and that’s when I think I’ve read it. I remember recommending it to many developers for several years afterward.
I loved the book because it covered OOP, Design Patterns, SOLID principles, and TDD, often writing tests before refactoring code that would eventually surface as a pattern or principle.
I have not revisited this book in many years, but I know that a lot of the things I’ve learned from it have stuck with me.
The Art of Unit Testing, by Roy Osherove
I recall learning things about fake objects (mocks, stubs, spies), and I remember recommending this book to other developers back then. If memory serves me right, it’s a short book to read and it provides good information for those getting started into the practice.
Fifty Quick Ideas to Improve Your Tests, by Gojko Adzic and David Evans
This one I’ve read earlier this year and enjoyed it very much, as it validated many of the lessons I’ve learned and applied over the years, and it also gave me some new ideas to try out.
The RSpec Book: Behaviour Drien Development with RSpec, Cucumber, and Friends, by David Chelimsky, Dan North, and others
I’ve read this book when I moved from .NET to Ruby on Rails in 2011. I found this book as I was digging more into Rails, Cucumber, RSpec, Testing, BDD, and all that stuff, and it helped me at the time.
Is that all?
Those are books that first come to mind when people ask. I’m sure I’ve read others in the last 20 years, but I didn’t use to keep track of it they way I have been in the last few years, and whichever other books I’ve read didn’t stick with me.
I’ve put out several blog posts on the topic of testing, documenting my questions, confusions, learnings, etc., and will continue to do so.
I also have a list of books on the topic on my “to read” list, and I’ll write up posts in case the books deserve it. 🙂
While the books mentioned here have helped me along the way, the single most important that shaped my practice has been actually doing it!
- To keep track of what books I own (it has happened that I purchased a book I already owned);
- To know the formats I own, such as printed, ebook, audiobook. Sometimes I’m listening to an audiobook and realize a printed copy would be better. Sometimes I finish reading a book and want to listen to it to revisit the content;
- To know what books I’m reading, have read, or that are in my to-read list;
- To know what books I’ve read in the current year, so I can put together my “Favorite Books I’ve Read in…” blog posts;
- To know what books I’ve read more than once. Sometimes people ask me for my favorite books, and I want to give them a better informed answer, instead of just relying on what comes to mind first;
- To know what books are the most recommended to me. It can be through a direct recommendation from friends or co-workers, or maybe through a recommendation found in a book or author I’m enjoying;
- To find my own notes on the book
This post outlines how I’m now handling all of that. I’m always refining things, but this should describe the core pieces and the direction I’m going. At the bottom of this post you’ll find some resources I’ve used to learn how to put this together.
When I get a book recommendation, I go to Obsidian and invoke the plugin to create a new book note:
The plugin has me type either the book’s name or ISBN. It shows me a list of what it found, I select the one I’m looking for, and complete the operation, which creates a note for me, like so:
I’ve split the window so we can see the markdown down created for the note on the left and the rendered version on the right.
That initial content comes from a template, which I got from the plugin and tweaked to my liking, including the following fields to the metadata you see at the top:
- status: unread/reading/read
- formats: ebook/paperback/audiobook
- recommendations: names and/or places I got the recommendations from
- finished: the dates when I finished reading the book
I then created a note that uses the Dataview plugin to query my notes and display the results:
The window is split to show the results on the left and the query on the right. Some non-public names are blurried.
The results let me answer the following question: what books have I not ready yet that has more than one recommendation?
Capturing my notes on a book
I take notes on books I’m reading. Whether it’s an ebook or printed book, I highlight passages and write on the book. If it’s an audiobook, I write notes using pen and paper (I actually use a reMarkable, but I’ll save that for another post).
Once I’m done with the book, I review my notes and highlights and consolidate them into that book note I created in Obsidian. My notes include quotes, images, links out to other notes or resources, my own thoughts, etc.
The image above shows my notes on a book on the left and the graph view on the right, which lets me see the connections I have associated with that book.
Tracking books I’ve read or am reading in a given year
As part of my annual review process, I’ve been looking over the books I’ve finished reading in that year and selecting my favorite ones. I put that list out as a blog post, such as this one for 2021. The following note helps me do such reflection:
Again, results on the left, query on the right.
The results include the years when I finished the book; it makes easy for me to see what books I’ve read more than once. Why? Two reasons:
- When people ask me for book recommendations or my favorite books, I have a better informed answer (instead of just relying on memory);
- When I see the years when I’ve read a given book, I can draw connections between that and other books or things I had going on around those times
At the bottom of that list (not shown in the capture above), I see a list of books I’m currently reading, which I use when I want to drop in and add a few notes even befor I’m done reading the book.
Listing all books
The simplest query I have is one that lists all books I’ve added:
On that list I can see:
- All books
- Their status, cover, and title
- Formats. This one is interesting: if I see a book that’s “unread” and has any kind of format (e.g., ebook), that means I’ve already purchased the book but haven’t read it yet. Also, if I see one like that and it has no recommendations, it just means I’ve heard or seen the book somewhere and want to read it.
About Dataview queries
These are the resources I’ve used to learn how to put together the system outlined in this post.
The first “personal information manager” I’ve used was Lotus Organizer in the mid 90s. Then there was Microsoft Schedule+, later replaced by Microsoft Outlook, which I stopped using as my personal tool in 2010 or so.
Then I got into Onfolio (which allowed downloading webpages, organizing them into collections, and building my own knowledge store). A nice little tool that vanished without further notice shortly after getting acquired.
Other than OneNote, all of those things disappeared in a matter of just a few years.
ALL of them. In just a FEW years.
How can we trust technology when it goes out like that? But I digress…
In 2009, I heard of Evernote, when they were still in Beta. I gave it a try and have been using it since then. Being able to use the same tool seamlessly on a PC, Mac, iPhone, iPad: that’s what got me hooked immediately. I’ve put out many blog posts on how I’ve been using it.
I always keep an eye out for different ways to improve my process and systems. Up until 2020, I haven’t found any reason to replace Evernote with anything else. Compared to the options above, this tool has had a very long and stable run for me. Kudos to them.
Their first version was implemented in WPF, which they’ve learned wasn’t the best choice for their product, and so they rewrote the entire software from scratch after a while. As a consumer of their tool, I remember switching between the two versions going painlessly. As far as I remember, they reached feature parity quickly (at least for the features I used extensively at the time).
But then in 2020 comes another full rewrite: as I understand, they had a different codebase for each operating system they supported (PC, OS, iOS, Android…), which was very hard to keep up with (adding features, fixing bugs…). So this time they went with ElectronJS.
I got into the beta program to try out the new version. I use the tool all day long, on a PC, on a Mac, and on my iPhone. Within a month I had to go back to the previous version, not because of the expected stability issues of a beta version, but because of the large number of missing features I’ve been relying on for several years.
To mention a few of those features:
- Lack of support for tabs. Here’s one of my use cases for it.
- Lack of multi-window support (I can open notes in separate windows, but I can’t have multiple Evernote windows)
As someone who works with 3 computer screens most of the day, being able to use those screens effectively is a must, and a tool that doesn’t let me run multiple windows severely impacts that need.
Evernote “Legacy”: multiple windows and tabs
I’ve reported to them all of the use cases and reasons why I was falling back to their “legacy” version, at least on my Mac, which is where I use the tool the most. I’ve kept using the latest version on my PC so I could stay updated on their progress. As I saw their comments about which features we could be expecting soon, and the lack of information on most of the features I was interested in, I figured I should start looking for alternatives.
With so many people swearing by Notion, I looked into it. Didn’t like it.
At a Virtual Brown Bag earlier this year, I heard of Obsidian. It looked interesting, so I noted I should look into it. A few months later, I start hearing good things about it from people whose opinion I trust. So I decided to spend more time on it. I’m liking it.
I’m gradually learning more about the tool. It doesn’t seem to fit all of my use cases yet. But it does work really well for some of them.
For some things, I’ve either completely moved over or started to move parts of it. For example, keeping track of my book reading or how to decide what book to read next, and building and maintaining my book library. Also, keeping track of quotes that inspire me.
I’m not in a hurry. I’m not desparate to use the flashy new toy. And I do see me using the different tools for different parts of my system.
Obsidian has one of the same issues that the Electron-based version of Evernote does: lack of multi-screen support. The latest version added an option to open/move a note into a separate window, but it currently doesn’t work well on the PC and Mac. It seems fine when the windows are showing on the same screen, but it gets really funky when I move the new windows to another screen.
Obsidian: Multiple windows and panes on a single screen
Looking at where Evernote has been putting their effort for the last 2 years and the direction they’re going, and where Obsidian is going with their community plugins and all, I’ll keep working at my gradual transition between the two tools.
I’ll put out separate posts talking about specific use cases.
This has become a personal mission: I want to help build environments where nobody starts a sentence with “may I ask a dumb question?“
The group welcomes questions.
The group encourages questions.
People feel safe asking questions.
Questions are asked to:
- clarify understanding
- identify coaching and mentoring opportunities
But how do we build such environments?
Here are some ideas:
- Avoid throwing “of course… everybody knows that… obviously…” into the conversation
- “Assume that the person you are listening to might know something you don’t”
- Ask questions and listen to answers to get a better understanding of those around you. Learn what they don’t know. Ask yourself “how can I help them take their next step?“
- Get to know the individuals. Learn to identify who are the ones who might have questions but won’t ask until they feel it’s safe to do so. Learn how to help them feel safe.
We may think we know something because “that’s how we’ve always done it”. Well, that’s not true. That might be how we’ve been doing it for a long time since we learned it.
But what if we learned it wrong?
Or what if we learned it right but eventually got sloppy and turned it into the way we’ve always done it?
That question from someone who doesn’t know something might be just what we need to challenge our assumptions, our biases, our beliefs that went into auto-pilot and never gotten updated.
Here’s something I’ve been pondering (by Marie-Christine Gasingirwa):
In life there isn’t a single person that knows everything and there is no person that knows nothing.
It’s not too late to learn because you just need to develop that interest, talk to people, share with them what you have and learn from them.
There is no breakthrough in this world if you are isolated, you can only make a breakthrough by talking to people.
There’s a lot of talk about “Work-Life Balance”…
I think if there’s no life…
There’s no work…
Some are doing only work and nothing else…
Others might say “Dude, get a life!”
It’s not either/or. There’s life… and work is a part of it.
But we too often fill up life with work…
But there’s more to life than just work…
We can turn some knobs to adjust how we live life, as in “this week/month/quarter/year I’m doing more of this, less of that”…
Turning those knobs can be something well-balanced and thought-out. But it can also be an abrupt change due to unforeseen events…
But everything changes, nothing stays the same, so we keep adjusting those dials again as time goes by…
Those areas of life don’t have to be isolated from each other; they can have some overlap!
It’s great to have some shared experiences, with the awareness to keep certain issues on the far edges…
These are some random thoughts and rough drawings I’ve been collecting and figured it might make sense to others out there.
The “knobs and dials” I mention in this post can be adjusted based on Core and Supporting Values.
A reading habit can be easily broken if we aren’t sure about what to read next. For many years, that hasn’t been an issue as I’ve been building my book library and there’s always something I can pick up. But how do I decide what to read next?
The easiest approach is to simply pick up a book I want to read and get started. Don’t overthink it. Just do it.
Next best approach is to pick something up that has been referred to me by people who have consistently been giving me good referrals.
Following that, if I’m enjoying a book that I’m reading and the author recommends other books, I add them to my “books wishlist” on Amazon.
When I hear one of my favorite authors have a new book out, I either get it or immediately add it to my wishlist.
Some books have been a referral from multiple sources; I indicate that on my wishlist. If a book has multiple referrals, I put it at the top of my list.
Back in my teenage years when I started reading fiction books in English, I had a practice of starting the next book immediately after finishing the previous one. Over the last several years I simply start reading books whenever I feel like. I don’t wait to finish one before starting another, which means that:
- I read many books at the same
- I’m always reading at least one book
- Some books I finish quickly, others I may go on reading for as long as a few years
How do you decide what book to read next?
Last week, I’ve asked if your values overlap with your employers’. As I mentioned, I looked at the list of values and found out my top 2, but I never said what they are. Here you go: legacy and making a difference. That’s what I call my core values. I’ve arrived at those by reflecting on my own life this far, revisiting the main highlights, interactions, and pivotal moments.
Several months after going through that process, I went back to the list to take another look at the other values I had also hightlighted: fairness, gratitude, humor, initiative, patience, personal fulfillment, responsibility, and spirituality. Those are what I call my supporting values.
What’s the distinction between core and supporting? When I look into my future, I hope my core values represent the life I’ve lived. As I look through my past, current moment, and the time between now and my future, I believe my supporting values will guide me to the future I want.
As time goes on, I turn the knobs on each one of those values, adjusting them to handle whatever situation I’m going through, and preparing me to move on to the next step in my journey. By being aware of my values I’m better able to set goals and processes to achieve them; whatever I come up with has to be directly related to one or more of those values.
So what does Improving have to do with any of that?
Improving’s guiding principles of Excellence, Involvement, and Dedication, our culture and Improvers provide me the inspiration, motivation, and environment to live into my values.
As I re-read James Clear’s Atomic Habits, I’ve run into these bits where he talks about how we “imitate the close”:
We soak up the qualities and practices of those around us.
Improvers’ qualities and practices have caught my attention when I first met a few of these folks back in 2007. After all these years living in this culture, Clear’s words resonate with me deeply:
One of the most effective things you can do to build better habits is to join a culture where your desired behavior is the normal behavior. New habits seem achievable when you see others doing them every day.
It doesn’t end there:
Your culture sets your expectation for what is “normal”. Surround yourself with people who have the habits you want to have yourself. You’ll rise together.
I’d like to add something to that: in my case, I already had habits that I considered good, and I’ve been able to not only keep those habits but also help others build those habits themselves. Oftentimes, it’s very hard to keep good habits when you’re surrounded by individuals whose habits are the polar opposite of ours.
To wrap up this pair of posts with actionable tips straight off of Clear’s book:
Join a culture where (1) your desired behavior is the normal behavior and (2) you already have something in common with the group.
Not happy with your job? Find an employer whose values align with your own.
Are you clear on what your values are? I had clues about my own, but it wasn’t until last year when I narrowed them down. How? By actively participating in a book club with my co-workers (something encouraged by Improving’s values).
We covered Brene Brown’s Dare to Lead. In a certain section of the book, there’s an activity for the readers to identify their values. It presents a long list of common values. We’re supposed to identify the top 2. Not easy, so we may start with our top 10, and then narrow it down. I found mine. I call the top 2 my core values, and the remaining 8 my supporting values. As I look at Improving’s values and philosophy, I see how the company makes it easy for me to live my own values.
Here are a few practical examples:
- I’m an avid book reader. Having great people to have conversations about the content enhances the experience a lot. We put the word out in our internal technical communities, and book clubs are formed.
- I identify a need for a space where I can gather motorcycle track riders who want to discuss their experiences, analyze their learnings, share their tips. I create the community and I get the space at Improving to have our meetings.
- My co-workers show interest in the practices I have to organize life, set and execute goals, pick up hobbies, learn languages. I put together my notes, create classes, and offer them as internal training. Many people join in, we deepen our relationships and have a great time.
- I’ve been practicing meditation, financial health, physical activities. Improving comes up with an internal, year-long initiative focusing the month of January on wellness. Tons of people join in, experiences are shared, good times are had, great results are achieved.
I could keep going on and on. In fact, the subject comes up in my mourning journalling very frequently. Sometimes, I make those words surface in this blog. Other times, I keep them to myself, as I introspect and look for ways to increase and/or leverage the overlap there is between my values and Improving’s.