RailsConf 2020 CE

Tidy First?

Tidy First?

by Kent Beck

In the talk 'Tidy First?' presented at RailsConf 2020, Kent Beck explores the intricate relationship between human dynamics and software design. Beck emphasizes that software design is fundamentally an exercise in human relationships, significantly influenced by the roles of those who use the software—termed 'waiters'—and those who can implement changes, known as 'changers.' The relationship between these two groups is marked by divergent incentives and needs, which can complicate the software development process. Key points from Beck's presentation include:

  • Human Relationships in Software Design: Beck asserts that the essence of software design challenges are often rooted in interpersonal dynamics rather than purely technical issues.
  • Waiters vs. Changers: He identifies two primary groups: 'waiters,' who desire changes but cannot make them, and 'changers,' who have the ability to make these changes. This distinction highlights the importance of maintaining open communication and understanding between both parties to facilitate smoother development processes.
  • Incentive Divergence: Beck discusses how the incentives of waiters and changers can differ significantly—a situation that may lead to frustration and inefficiencies if not managed well.
  • Second Set of Relationships Among Changers: He also addresses relationships among changers, emphasizing the need for collaboration when a change in behavior affects others' work, particularly when changes can break existing APIs.
  • Four Stages of Software Design Enlightenment: Beck outlines a progression in understanding software design, beginning with basic change implementation, moving to distinguishing between structural and behavioral changes, and culminating in strategic planning for changes that precede or follow subsequent tasks.
  • Experiment with Pull Requests: To improve relationships and workflows, he recommends breaking changes down into small, manageable pull requests that either address behavior or structure, rather than mixing the two. This practice not only enhances clarity but also helps maintain system integrity and team collaboration.

Beck concludes by reiterating that while technical skills are valuable, they must be complemented by strong interpersonal skills to navigate the complexities of software design effectively. By consciously managing these human relationships, developers can create more efficient and enjoyable software design processes, ultimately leading to better outcomes for all stakeholders involved.

00:00:08.830 I just got back from Gusto. Today, I want to talk about a study that I've begun into software design. After 40 years of programming, I figured it was time for me to understand a little bit more about what was going on.
00:00:12.910 As often happens at the beginning of a study, I realize there's a lot that I know in my gut that I can't articulate. So, I started writing things down. The first thing that came out of my pen was a shock to me: I wrote, 'Software design is an exercise in human relationships.'
00:00:22.960 And I thought, 'No, no, no, I'm going to write about coupling and cohesion, power law distributions, and things like that—not about human relationships.' But the more I thought about it, the more I realized that the essence of software design, the things that make it really hard, are human factors, not necessarily the technical things that I'm much more comfortable dealing with.
00:01:11.950 In today's presentation, I'll tell you about the two most important human relationships in software design. Then, I'll give you an experiment that you can run to help you improve the relationships within your teams regarding software design.
00:01:24.070 I'm going to divide the world into two kinds of people. The first kind of people use software; they might want to see its behavior change, but they can't actually enact those changes themselves. I'll refer to those people as 'waiters.' In contrast, there are people who can make the necessary changes to the software's behavior; I'll call them 'changers.'
00:01:39.580 It's the relationship between waiters and changers that makes software design such a challenge. In the long run, everyone wants to see the system change and evolve, and they would like it to happen as quickly as possible.
00:01:58.120 However, in the short run, the incentives of waiters and changers can diverge significantly, primarily because the perceptions they have of software development are so different. At one level, software development is a sequence of ideas that turn into behavior changes in the software, sparking more ideas and more behavior changes. This cycle goes on and on.
00:02:19.030 Both parties understand this cycle, recognizing the flow of behavior changes that reflect how the software evolves. However, beneath the surface, there's another set of changes occurring: changers know that the structure of the system dramatically affects the cost of making behavior changes.
00:02:33.530 Some of the investment in development goes into changes in structure, but these changes aren't visible to the waiters. This leads to conflict in the relationship. A common dysfunction occurs when behavior changes take all the precedence, causing the structure to worsen over time.
00:02:44.950 Eventually, it becomes impossible to make changes to the behavior, leading to frustration. There are issues where too much investment in structure, or making those investments at the wrong time, also damages the relationship. For example, if we focus solely on building the perfect structure, the behavior of the system may not change as waiters grow impatient.
00:03:00.140 This situation can lead to an endless cycle of investment in structure, where if you don't get it right now, you'll never get it right. Hence, we experience a divergence in incentives between waiters and changers. Maintaining this relationship is critical to software development.
00:03:13.450 Our goal should be to find a balance between the needs of both parties, ensuring that the investment in structure and behavior is sequenced so that everyone's needs are met as much as possible.
00:03:27.319 The second set of relationships exists between changers themselves. For instance, if I want to change an API that you call within our system, we are both changers, but the work I do affects your work. Thus, my relationship with you is crucial.
00:03:40.640 If I make breaking changes to the API and then insist, 'Oh, it's your responsibility to update to the new version,' you won’t be very happy with me. You already have behavior changes to implement, and you don't have time for my shenanigans.
00:03:50.210 So, it's also important to maintain relationships among changers, which can be challenging. These two fundamental relationships—between waiters and changers, and between changers and changers—can create difficulties in software design.
00:04:05.950 Now, what can we do about it? I've observed four stages of software design enlightenment. The first stage occurs early in your programming journey, where you can get programs to work by making various changes without understanding the underlying process.
00:04:14.060 At this level, you're just making changes in an if-statement, changing variable names as you go. Then, when there's a large collection of these changes, you clean them up.
00:04:28.390 Stage two happens when someone introduces you to Martin Fowler's refactoring book, leading you to realize that there are structural and behavioral changes that are fundamentally different. You start to recognize that you should wear one hat at a time: either changing the structure or changing the behavior.
00:04:44.840 Level three is where you start to think a few moves ahead, like in chess. You make structure changes to make behavior changes easier to implement, and vice versa. This approach aligns with the phrase I coined: 'Make easy, make the change easy.'
00:05:03.830 At this level, the changes you make are intentional and sequenced to make your work easier. If you haven't started doing this, I recommend you give it a try. Sometimes, software development can feel really hard.
00:05:17.640 With more experience, I've learned that if it feels hard, that's often a sign that I'm doing something wrong. While some challenges are genuine, I often need to focus on making my work easier and feeling good about the simple tasks that result.
00:05:30.440 The experiment I'm suggesting is to learn to sequence behavior and structure changes. Start dividing the changes you make into small pull requests. Make a little change to the behavior, test it, and then deploy it. Next, make a few changes to the structure, deploy those, and continue this cycle.
00:05:51.700 Each pull request should focus on either behavior or structure changes. This separation is crucial because structure changes are generally reversible. If you extract a helper method, you can easily revert that change if necessary.
00:06:11.680 In contrast, behavior changes are typically irreversible. For example, if my team at Gusto inadvertently files incorrect tax reports, it's not something that can simply be undone. There are lasting consequences involved.
00:06:26.920 As a reviewer, when examining behavior changes, you need to be aware of the test cases and potential backup plans. On the other hand, structure changes don’t generally require the same level of scrutiny if they're progressing in a reasonable direction.
00:06:40.670 Thus, the experiment involves dividing your PRs into smaller, manageable segments that either change the behavior or the structure of the system. Sometimes this means changing the behavior in a different order than you might typically do.
00:06:54.380 For example, like the keystone in an arch, the user interface changes might happen at the very end of a project, whereas in a traditional workflow, one large PR could see UI changes made at any point.
00:07:07.560 Using this approach, you can lead up to the final user interface change with multiple smaller PRs, ensuring that each increment is manageable, allowing for a more seamless integration.
00:07:20.220 Now, how does this relate to the relationships we've been discussing? A significant cost in these relationships comes from delays and variances. For example, you might have been able to complete a task in a day before, but now it takes a month.
00:07:35.060 Adopting a style that separates behavior and structure changes provides many more options for changing behavior early in the sequence if there’s urgency or delaying it for structure changes that benefit the long-term health of the software.
00:07:49.400 By splitting your PRs into either behavior or structure changes, you can ensure that waiters consistently receive a steady flow of what's needed. This approach allows you to be a better partner to them while simultaneously helping manage the relationships among changers.
00:08:10.390 If I'm changing an API and care about our relationship as changers, I might implement the new API in terms of the old one, and then help you update to the new API. After all migrations, I can remove the old version, thus ensuring a smoother transition.
00:08:24.060 This strategy of breaking down a significant change into manageable parts helps maintain cooperative relationships, as does breaking down behavior changes for waiters.
00:08:36.500 In conclusion, there are plenty of opportunities for refactoring and adjustments in coupling and cohesion that clarify how all of this works and why it works. Yet, I want to leave you with this central insight: Software design is fundamentally about human relationships.
00:08:48.670 We, as technologists, have many tools available to do a better job of maintaining our part in these relationships. Thank you very much, and I hope you’re all staying safe.