00:00:15.839
Thank you all for coming! I appreciate having such a crowd on such short notice.
00:00:21.600
We had a cancellation, so I jumped at the chance to get another opportunity to speak to you.
00:00:26.640
I'd like to say that I've only had a few hours to put this presentation together, but I've actually been working on this for a couple of years.
00:00:39.040
So if it's bad, it's because it’s bad!
00:00:48.079
This is one of those talks that suggests you're doing it wrong, and that can be problematic.
00:00:58.960
I realize that this is my mode of learning, so hopefully you won’t take anything personally. I’ll try not to be too preachy.
00:01:09.920
Unfortunately, I have a tendency to learn by convincing myself that what I'm doing is wrong just to see if I can find something wrong with it.
00:01:21.840
So when I do this, it's not meant to harm anyone except myself.
00:01:28.080
The thrust of this talk revolves around several points. One topic I discussed last year at the same time, in the same room, with some of the same people, is that TDD is still poorly understood and poorly done.
00:01:40.479
Automation, contrary to popular belief, can be ruinous to productivity. The productivity that you get from design is vastly superior to that which comes from automation.
00:01:55.119
TDD was supposed to be a path to greater mastery in design, but over the years since around 2000, it has become largely focused on tooling.
00:02:06.560
I want to talk about some fundamentals to get things going. These are the fundamentals about us, and by 'us', I mean me, as I project myself onto you.
00:02:24.560
This is my prejudice on how I think that you work, based on who I am. I want to talk about things that are subtle, and things that are crude.
00:02:40.959
Things that are subtle are things you might not yet be attuned to, things that you might dismiss as negligible because they are often mistaken for misunderstanding.
00:02:55.679
I'll state quite audaciously that the things that are subtle are what you want to pay attention to and leverage, but they're very easy to miss.
00:03:10.239
On the opposite end of the spectrum, there are crude things. Crude things are tangible and material. For the purposes of this talk, crude things are necessities and starting points.
00:03:22.959
They involve muscle memory, drills, and dogmas. Unfortunately, crude things are what we are hardwired to connect with.
00:03:38.560
This stems from the fact that we have spent more years as humans evading saber-toothed cats than we have evading software defects or design defects.
00:03:46.159
Crude things can be traps, as they may get in the way of realizing the subtler things. Crude things are also easy to transfer—it's easier to teach you how to use a testing framework than to teach you about design.
00:04:04.319
This is one reason why TDD ends up devolving into what one might call an 'intellectual materialism', where you know what you should be doing, but there's a cruder form of it that you might actually be doing.
00:04:18.160
Now, I don’t want anyone to be thrown off by the term 'mastery' here. In our Western industrial modern culture, we tend to view mastery with cynicism.
00:04:34.560
We often see everyday, tangible things as mystical, labeling them as 'zen' without truly understanding them.
00:04:49.280
The issue I want to raise about mastery is that it is more about the process than the destination, which reflects a more Eastern mindset.
00:05:02.240
Once you reframe it that way, you realize that mastery and the pursuit of perfection are not high concepts far removed from reality; they are everyday realities.
00:05:20.959
Recognizing mastery is about acknowledging the process of improvement and that pursuing mastery does not automatically give you the right to claim it.
00:05:42.720
The connection to subtlety here is that as you advance in a skill, the early steps you take yield noticeable changes. For example, if you’ve never written a line of code before, the moment you write one line is a significant change.
00:06:03.199
However, as you progress, the changes and refinements you make become less noticeable. A person with extensive experience in coding may overlook these subtle refinements, viewing them as negligible.
00:06:20.360
Yet, these finer adjustments accumulate and can cause an exponential increase in your capabilities and productivity.
00:06:37.680
This is crucial because design resides in the realm of the subtle. Test-driven development is also subtle, whereas test-first programming can be seen as crude.
00:06:52.760
You can find yourself doing test-first programming while thinking you're doing TDD, and it’s important to recognize that this isn’t necessarily the same.
00:07:05.760
Through my practice of TDD, it's possible to write code that meets the criteria of test-first programming but still ends up with design qualities that are less than desirable.
00:07:20.119
Test-first programming doesn't inherently lead to the desirable goals of test-driven development. We are hardwired to notice crude things, which often takes our focus away from subtler details.
00:07:44.320
You can have TDD in your mind, yet be doing test-first programming in practice without realizing the distinction—unless you stop occasionally to reflect on your code and consider if you are truly succeeding.
00:08:11.600
This reflection might involve adopting a pessimistic viewpoint as a thought experiment to examine the potential shortcomings of your work.
00:08:39.360
Let's now quickly discuss automation, which focuses on tooling—the material side of the spectrum.
00:08:51.200
Automation can distract your thinking from design principles and can often lead to further complications rather than reducing them.
00:09:08.000
I would like to reference a paper from an industrial psychologist discussing how automation can expand rather than eliminate human operator problems.
00:09:25.119
This has been evident with the rise of unit testing over the past decade and a half, where the assumption was that writing a lot of unit tests would document the code.
00:09:42.959
What tends to occur is that programmers stop engaging with the code directly and instead rely on automation, creating a growing separation from the systems they are building.
00:10:05.759
As human operators, we must maintain our intimacy with the codebase, while also acknowledging that automation can detract from our understanding of the systems we are working on.
00:10:20.399
This topic further reflects that we still exist in a craft state rather than a fully industrialized one; craftsmanship combined with industry is the optimal approach.
00:10:39.279
We must address the realization that not every process should be automated, and the predicament lies in the fact that we create automation as part of our product.
00:10:56.800
As pro-automation product developers, we are resistant to the idea that the core thrust of our work may not be as beneficial as we self-affirm.
00:11:12.960
It's often said that TDD is about design. If you observe people practicing test-first programming, you can see two similar actions that yield very different outcomes.
00:11:28.800
The key difference lies in the understanding of the software design characteristics and what qualifies as good design.
00:11:44.000
If you don’t begin with a clear notion of desirable design, it becomes difficult to achieve it. Conversely, you may also become hypersensitive to any friction.
00:12:00.960
Rather than viewing small frictions as negligible, consider them as signs of looming issues that may be subtle and masked by your current skill level.
00:12:15.200
Much like how cancer starts small but can grow pervasive, small benefits can have a significant impact on your productivity in the long run.
00:12:33.760
Good design encompasses principles such as encapsulation, coupling, and abstraction. These are higher-order principles that contrast with more tangible design principles.
00:12:53.000
Encapsulation refers to the idea of telling objects or systems what to do rather than asking them. Coupling refers to the entanglement between modules, which in Ruby could be a class.
00:13:08.320
With weaker encapsulation, there tends to be more coupling, which detracts from the clarity and function of your code.
00:13:22.799
The goal of design is not about getting a computer to execute instructions—rather, it's about how human beings can achieve clarity over the code they write.
00:13:39.100
Design is ultimately about enhancing human cognition. It predicts productivity, which is fundamentally more valuable than automation.
00:13:58.080
We tend to underestimate the impact of subtle design mistakes. Every sense of frustration or friction should be recognized as an indication that there is a deeper issue to address.
00:14:17.480
Design mistakes that appear minor can accumulate over time, leading to pervasive problems that significantly inhibit productivity.
00:14:42.720
Therefore, it is crucial to act on these signs rather than dismiss them as negligible, recognizing they can have a mass impact.
00:15:00.320
Good design principles are not just esoteric academics; they are practical guidelines that can enhance your productivity and efficiency.
00:15:16.800
This shift in perspective can significantly reduce your downtime spent resolving issues, allowing for smoother workflow.
00:15:30.120
It’s a tough realization that every test introduces additional coupling; however, the question is how to maintain productivity while assessing designs.
00:16:03.760
The truth is, poor design leads to excessive reliance on testing, which inadvertently creates a cycle of increasing coupling and complexity.
00:16:22.960
This vicious cycle drives your productivity down. Each testing framework available naturally encourages you to break productive design principles.
00:16:40.959
The syntaxes and grammars of testing frameworks often become obstructions in your creative flow of test-driven development.
00:16:54.720
The focus should thus be on designing workable software rather than just functional software. Working software is a necessity, but it's the bare minimum.
00:17:07.840
You can achieve better design without sacrificing usability; workable software is software that a human can engage with easily.
00:17:17.919
We often encounter the idea that it’s normal to be stumped when dealing with code, yet that signifies a lack of maturity in our industrial understanding.
00:17:35.600
It’s crucial to improve knowledge transfer and momentum in our development processes, avoiding the sawtooth patterns of momentum loss.
00:17:52.240
This requires reexamining what we consider 'services' in software design. Services should ideally only accept commands rather than return data.
00:18:06.560
For instance, a construct labeled 'service' in service-oriented architecture should not provide direct data on request. Instead, it should confirm commands.
00:18:24.960
It’s essential to distinguish between services and database structures. Many definitions blur the lines, hindering our understanding of design.
00:18:39.840
Many mechanisms mislabel data retrieval by services as valid, which indeed confuses the conceptual architecture.
00:18:59.920
With objects, proper design can become difficult when using certain frameworks like Active Record, which can violate sound design principles.
00:19:13.600
We often employ shortcuts in such frameworks that may yield immediate results, but they can obstruct better long-term practices of clarity and insight.
00:19:36.320
If you have never seen a better architecture or design, it might be time for exploration to see what's possible beyond what we typically encounter.
00:19:56.480
To illustrate my point, I want to share a quick sample application as a demonstration.
00:20:03.040
This is a simple example of string reversal, a trivial concept; however, it's a great way to explore TDD.
00:20:14.560
I'll be using a library called 'Proof', which is not a full-blown library but rather a proof of concept to discuss the design focus in TDD.
00:20:28.800
This approach emphasizes minimal automation to maintain a direct connection with the code.
00:20:46.080
Fielding questions about structure or semantics often disrupts the flow, so I prefer to simplify those considerations.
00:21:04.560
As I develop this example live, let’s analyze and collaborate on how to seamlessly integrate TDD into our code.
00:21:16.800
The idea is to write down thought processes as they occur, nurturing a coherent design even pre-implementation.
00:21:27.520
So far, I’m demonstrating the string reversal process as a fundamental example of TDD.
00:21:34.880
As I sketch out my code, it's crucial to emphasize the importance of clarity over complexity when structuring test cases.
00:21:55.680
Shaping my code is about exploring design principles without letting external frameworks constrain my creative results.
00:22:05.840
This approach leads to producing cleaner and more effective results in my coding process.
00:22:29.920
Ultimately, we want our environments to reflect best practices in a way that induces productivity rather than obstructs it.
00:22:47.920
By espousing these principles and sharing this framework, I hope to cultivate a positive conversation around effective TDD practices.
00:23:15.440
Thank you for your attention, and I'm looking forward to your thoughts and insights on this topic.