RailsConf 2017

What Comes After SOLID? Seeking Holistic Software Quality

What Comes After SOLID? Seeking Holistic Software Quality

by Ariel Caplan

The talk "What Comes After SOLID? Seeking Holistic Software Quality" by Ariel Caplan at RailsConf 2017 addresses the gap between writing good code and delivering value through software development. Caplan emphasizes that the ultimate goal of software development is to create value, not merely to produce well-structured code. He raises critical questions about why developers commit to writing good code and how this impacts software quality.

Key Points:
- Value Creation Over Good Code: Developers should focus on creating value through problem-solving rather than just writing good code. Good code helps in delivering value, but it is not synonymous with quality software.
- Understanding User Needs: Developers must align their work with actual user needs and business objectives—working to generate revenue, lower costs, or reduce risks.
- Agile's Limitations: Caplan critiques the Agile methodology, arguing that it has not achieved its goal of bridging the gap between development and business needs. He highlights that trust and effective communication are crucial for a harmonious relationship between developers and business stakeholders.
- The USA Framework: Caplan introduces a framework consisting of three factors that define software quality: usefulness, sustainability, and accuracy. Each factor is associated with specific questions that developers should consider when assessing their work.
- Usefulness: Does it solve a problem effectively?
- Sustainability: Can we continue to develop without unnecessary obstacles?
- Accuracy: Does the software work as intended?
- Role of Practices: The talk discusses various software practices that enhance usefulness, sustainability, and accuracy. While traditional coding practices like SOLID principles are important, Caplan stresses the need for user-centered thinking and emphasizes empathy in design.
- Continuous Learning: Caplan emphasizes the importance of empathy, communication, and understanding business realities as essential skills for software developers.

In conclusion, Caplan urges developers to recognize the true purpose of their work as delivering real value to users through quality software. By fostering trust with stakeholders and applying the principles of usability, sustainability, and accuracy, developers can enhance the overall quality of their software products, leading to better outcomes for everyone involved.

00:00:11.540 All right, sorry for the delays. I want to start out today by doing a little exercise. The exercise is listed from a book called Nonviolent Communication, and it's called "Translating 'Have to' to 'Choose to.'"
00:00:18.900 The idea is that we all have things in our lives that we do not because we inherently enjoy them, but just out of some kind of sense of obligation. We feel that we have to do them.
00:00:25.099 The purpose of the exercise is to acknowledge that there's a choice there. Once we realize that it's a choice, we can figure out what we're going to do about it and think about how we make that decision. So you take all these things in your life that you don't really enjoy doing, make a big list of them, and then fill in this sentence with each item.
00:00:37.200 You say, "I choose to do X because I want Y." You figure out what the reason is for making the choice to do that thing. What you'll basically find is that one of a few things will happen: maybe you’ll realize that the thing you want is actually really important and you’ll find new meaning in what you were doing, making it feel more like an active choice. Or you may find that the thing you want wasn’t really that important, so you don’t really have to do it.
00:01:07.830 Or you might say that the thing you want is important, but maybe this isn't quite the right way to achieve that point. Maybe there are different, broader strategies that you need to pursue to get the thing that you want in a better way. So today, we're going to ask the question: why do we choose to write good code? That's a little bit of a scary question, right? What do you mean we have to write good code? It's ingrained in us.
00:01:58.200 We go to talks at conferences, we read books, we watch podcasts—I guess we watch ourselves online, we read blog posts—all about good code. We have to do it; that’s just what we do, right? But I’m here to tell you that you don’t have to write good code; you choose to write good code, hopefully.
00:02:33.340 Part of today will be figuring out why we choose to write good code—or rather, we fill in that second line: because I want...What do we put in that blank? Maybe we fill it in with this: if I don’t write good code, by some arbitrary standard, I’ll get fired. Sad reason, I know, but that might be it. Ideally, we find something meaningful and important in terms of why we’re choosing to write good code.
00:03:01.780 So why do we care about writing good code? This is a talk about software quality, and that's really the ultimate goal here. We have to ask: is good code actually the same as quality software? We’ll get back to that, but first, I want to talk about something somewhat, but not entirely different.
00:03:31.090 Dave Thomas, Bob Martin, and others—though I mention them because they were signatories on the original Agile Manifesto—have said that Agile is broken. It didn’t accomplish the revolution that it was supposed to accomplish. Here’s a quote from Bob Martin, quoting Kent Beck, who was also involved. He said that one of the goals of the Agile Manifesto was to heal the divide between development and business. There was a chasm created between those two sides, with a lot of tension.
00:04:05.769 The goal was to relieve some of that tension and find ways to work synergistically and harmoniously. Reality check: I don’t think it really worked, and they don’t either. At least, I have some people who were involved in Agile right from the top saying it's not a great situation.
00:04:24.550 What it became was a business person or project manager would take a course, get certified in something, and basically tell developers: "Okay, now you’re all going to do Agile, because that will lead to better software. It's something that developers do to keep business people happy."
00:04:30.840 If you could even do Agile, usually the form that this takes is Scrum. I forget the number, but around 60 to 80 percent of organizations that claim to be doing Agile are using Scrum as their implementation. In fact, as far as I can tell, I’ve read through the Scrum Guide and the Agile Manifesto and compared them, and Scrum only addresses maybe 50 percent of what Agile is; it kind of misses out on all the values.
00:04:42.460 So I'm not saying that Scrum is bad—I don’t want to give that impression. I think Scrum has a lot of really good ideas; it’s just not an implementation of Agile. It’s a framework in which you can choose to be Agile or not. It makes it easier in some ways, but it’s not actually agility. We don’t need more processes. Sometimes processes can be helpful, but they’re a tool towards something more important.
00:05:02.110 What I think that we need, and this is why I’m coming down somewhat hard on Scrum, is we need more trust. Scrum focuses a lot on transparency. As far as I understand, transparency is basically where we have two sides; each side asserts to the other: "I need to know what you’re doing at all times. I need you to be transparent about it so that when I think something is going wrong, I can jump in, complain, and micromanage you." Trust, on the other hand, is let’s have a conversation.
00:05:41.620 Let’s understand that there are two sides to the situation, and talk about the needs of each side. Each side can express their needs in a way that makes sense to the other side, and once we're confident that the other side has heard and understands them, we can rely on the other side to think about our needs and account for them in their decisions. That’s what trust is to me, at least, and that’s what allows us to build effective organizations.
00:06:11.620 I think we can solve this problem. It’s not even too complex; it's difficult, but not complex. It starts with communication. If we learn to communicate between developers and business people in a way that makes sense to both sides, then we can start building the trust that we need to have highly effective organizations.
00:06:34.930 So we have an ambitious goal today: we're going to create a common language for developers and business people to express their needs in a way that makes sense to both sides. The way we're going to achieve it is by identifying the tension points between the two sides and trying to understand them better. Again, figuring out why we write good code.
00:07:04.409 A lot of times, we push for good code in whatever way we define it, but writing good code takes time and investment. It’s hard to explain that to the other side, which causes a lot of tension.
00:07:10.469 So, first, let's figure out why do we write code? I really mean that: why do we write code? It seems like a strange question; we're developers; that’s what we do; that’s our job, right? Well, newsflash: controversial statement here, but I think it’s clear to me that your job is not to write code. Your job is to solve problems.
00:07:21.449 Let me give an anecdote from another field that will help us look at things a little more objectively. There was once a man who came to a plastic surgeon and said: "I need you to do some surgery for me; my ears are very large and I want you to make them smaller." So the surgeon decided to probe further: "Okay, why do you want this surgery? What problem are you trying to solve?"
00:07:46.319 The guy said: "Well, it’s not a problem for me at this stage of my life at all; I get along fine. We're all adults here. But when I was a kid, I got teased a lot. I got bullied over the size of my ears, and I don’t want to pass on that problem to my kids. I’m about to start a family and I don’t want them to inherit my ears, so how about you fix my ears?"
00:08:04.979 What the doctor did was say: "Hey, let’s talk about modern genetics. Let’s understand how these things work and why I can’t solve your problem as you suggested. If the doctor had said: "Okay, that's nice. Let's schedule a surgery," we would call that malpractice. But it's funny because that's very clear to all of us. However, what happens when someone approaches a developer and says: "Hey, I want you to build a mobile app for me," and the developer says: "Okay," without even understanding the problem that they're trying to solve?
00:08:58.259 They don’t understand whether that’s the right solution. Maybe they need a marketing director, maybe they need to not have an email campaign, maybe they need many things. There are thousands of apps in the App Store that reflect this problem; they don’t do anything for anybody. I have a hard time calling them high-quality apps because they don't solve a problem, and if you're not solving a problem, there's never a reason to write the code.
00:09:35.250 Now, this doesn’t sound very business-like, so let me offer a translation: Your job is to create value. That’s kind of a loaded term; it means a lot to different people, so I’ll give a working definition that we’ll use for the rest of the talk. Value creation in this context means one or more of three things: generating revenue, lowering costs, or reducing risk.
00:10:01.200 In the specific case of a nonprofit, instead of generating revenue, you can substitute doing whatever good that nonprofit is supposed to do. But, you know, on the whole, the same pattern still applies: those are the three things that we mainly care about. Where do you come in? Well, generally, the way that you do these three things is by meeting the needs of your users.
00:10:24.360 So we’re going to use meeting business needs and meeting user needs somewhat interchangeably in this talk; hopefully, they go together. When they don't, it’s a whole discussion that’s not getting into today. To recap: Why write code? To create value. That’s it. That’s the only reason we should ever be writing code.
00:10:42.120 If that's the case, why do we care about writing good code? I think the answer is simple: it usually helps to create value. Does that mean that good code is the same as quality software? According to this definition, I don’t think so.
00:11:12.220 Here’s the second of two controversial statements: I would define software quality as just the amount of value that it creates. If we’re writing code to create value, and it creates that value, it’s good for its purpose; hence, it is high quality. If it doesn’t meet the needs, then it can be really well-written under the hood, but it doesn’t help because it’s not actually solving a problem.
00:11:24.550 So rather than asking how you can write better code, what we would really be asking is how do we target our efforts in coding to maximize value creation, and how does good code fit within that whole broad picture? I’m going to commit a major programming sin now, which is solving a problem by writing an acronym—not JavaScript, just a human framework. It’s only three words, so hopefully, it’s not too bad.
00:11:57.360 I think there are three factors that, if we think about them, we can categorize almost anything about software quality. I call them usefulness, sustainability, and accuracy. We're going to talk about what each of these means. You’ll notice there’s an acronym here. I didn’t choose these words because of the acronym; it happens to be the acronym that came out.
00:12:22.290 So let's start with usefulness. Each of these is going to have a question. The target question in terms of usefulness is: does it solve a problem effectively? That’s pretty straightforward, but there are a lot of details involved. The target here is our users; again, using users and business needs interchangeably. The question we must ask is: is this a problem that affects users?
00:12:55.230 First of all, sometimes we spend a lot of money to code up a solution that doesn't actually address a need. We have to ensure, in whatever way we can, that we verify that the problem actually exists and that it affects the users we're going to be addressing. Then, even if we've correctly identified a problem, it's important to think about whether this is actually a solution to the problem or are we missing something?
00:13:15.890 And it can't just solve a problem; it has to solve the problem in a way that works for the users. Here’s a story from Tara Turner de la Fuente, who gave a keynote at RubyConf last year, which I think illustrates this point really nicely: she was working with a user of one of their applications to see what they were experiencing while uploading a spreadsheet with his whole bunch of rows.
00:14:02.709 Anything that the application could figure out was great, but then he had to fill it in, and one of the columns was a column for dates. Most people look for something like a date picker, right? In this case, the application decided to allow inputting dates through a drop-down menu without sorting them, so there were hundreds of dates in a completely unsorted list. They had to look through and somehow manage to find the right date.
00:14:35.840 If there was an error, by the way, you had to go back to the beginning, and it wouldn’t save what you had done so far! That technically meets the needs; they would eventually get it done, I guess, but it’s not in a way that works for the user. It’s really hard to call that a high-quality product. Next, we come to sustainability. What is sustainability about?
00:15:27.100 The question is: can we keep building without unnecessary obstacles? I thought about this a lot. I didn’t want to say without obstacles because there are always going to be obstacles. The question is whether we are identifying the most important obstacles and trying to account for them, trying to minimize what’s going to stand in the way as we continue developing.
00:15:56.530 The targets in this case are two-fold. The first is: is our software resistant to change? This breaks down into two sub-questions. One is an issue of understanding: is the software written in a way that leaves us unable to understand what it does, making it hard to make changes? The other piece is: even if it’s very clearly written and we understand what it does, do our architectural choices make it hard to change things later on? In effect, it just takes longer and is more effort.
00:16:41.509 The other target is the development team. We often forget that the development team is not just part of our software; it’s arguably more of a part of our software than the code itself. Think about how you care for your team. You don’t delete code and replace it with new stuff willy-nilly, do you? The rate of churn ideally is a lot lower.
00:17:03.250 If you crash the development team, you basically don’t have a product anymore. It’s crucial to be aware of whether the team is unstable in some way. If things tip a bit, is that going to prevent future progress? Will the team collapse or become less effective in some way? That’s sustainability.
00:17:31.719 Now let’s talk about accuracy. This is one that we probably think about the most. The question we’re asking is pretty simple: does the software work the way we think it does? The target here is ourselves. We have to ask four questions: Have we developed our understanding of the problem correctly? Sometimes we can do everything right in the coding step, but if we haven't taken the time to clarify whether this problem actually exists, we are failing.
00:18:01.210 Have we developed our understanding of the code? Is there something about the code that makes it hard for us to get to the next step? Are we just coding the wrong thing? Sometimes there can be cognitive overload; even if the code is clear, there may be too much going on. Too many integrated systems may overwhelm you to the point where you simply don't understand the full impact of your actions. Finally, our understanding of a problem changes over time.
00:19:07.980 If we don’t update the code to reflect that, it manifests as an accuracy problem. If any of these are failing, your software is broken. That's a bug report in any of those areas! To me, that means they’re all issues of accuracy. I can't speak for anyone else, but when I think about why I write good code, it’s because I want software that is useful, sustainable, and accurate, and good code is a significant tool that helps me achieve that.
00:19:40.270 Here’s a traditional model of the business-development chasm. Pictured in the right corner of the room, we have accuracy and sustainability. Those are seen as the domain of developers to write accurate code. On the left side, we have usefulness, which is the domain of designers, UX people, product folks, etc., and never the twain shall meet. We really subdivide those responsibilities, and it’s no surprise that each side wants to foster the factors they care about.
00:20:05.160 But today, the twain shall meet. What we need is to think about quality as all these factors together. We can’t leave out any element of that, and we have to be part of that usefulness circle as well. So, all of this has been pretty abstract, and I don’t want to leave you with vague ideas floating in the air. I want to take this down to a practical level. We’re going to ask the question: what is quality software?
00:20:51.080 We're actually going to fill in the things we do on a more granular level to address each of those three points: usefulness, sustainability, and accuracy. Now, this is a Venn diagram. There is going to be some overlap on occasion since practices might contribute to more than one of these circles.
00:21:26.020 In the middle, we have between accuracy and usefulness the question of: does it work in the way that users expect? We’re less thinking about ourselves storing things and more in the direction of our users. Between accuracy and sustainability, we're asking: can we keep building our system without breaking it? It’s about focusing on the future. And between sustainability and usefulness, we have the question of: are there obstacles to future usefulness?
00:21:55.150 Essentially, we want to understand that while they aren’t threatening usefulness right now, the choices we make now might have an impact on how useful our product is in the future. I titled this talk "Welcome Dr. SOLID." It’s a nice catchy title, but I don’t want to start by talking about SOLID because it’s a traditional metric of software quality.
00:22:27.400 We think a lot about it and talk about it, but I will not spend a lot of time on it. I am actually going to run through it quickly, so if you aren’t familiar with all the details of SOLID, that’s okay. I could spend the entire 40 minutes just talking about it, and you’d be bored for at least a minute, but we’ll cover this fine.
00:23:04.400 SOLID stands for five different principles related to creating what we might define as well-crafted software. The single responsibility principle means that every element in your system should do one thing and do it well. The open-closed principle means you should be able to add new features without modifying existing code. How you do that is a long story, so I won’t get into it.
00:23:35.900 The substitution principle is about using inheritance properly: don’t inherit from a superclass just because you like a method; inherit because it should implement all the functionalities of the superclass. Interface segregation is not that relevant in Ruby, but I think it is about limiting how objects depend on each other. You can do this with adequate interfaces.
00:24:02.430 Dependency inversion means you should depend on abstractions, not concretions. You’re basically pushing the dependency to the outside of your system, with the core elements depending on a theoretical idea of what the dependency does.
00:24:17.290 Let’s run through those principles really quickly. I think SRP is a big winner; if every item in your system does one thing and does it well, it’s easy to tell if it’s doing the thing it’s supposed to do. It’s much easier to change later because you know exactly what to modify. This is sort of a personal opinion, so I apologize; there will be a lot of personal opinions here.
00:24:40.400 The main thing here is not to learn the details but to see the way of thinking and ultimately how you will apply it yourself. Back to the topic at hand: I think single responsibility means that each part of a system has a very clear responsibility, which allows you to start thinking about whether this is the right responsibility.
00:25:04.880 Is it something that creates value for people? Or is it something that should or should not exist in our system? It opens up pathways to those conversations. I see open-closed as really being about the future, so I placed it in the sustainability category.
00:25:25.050 Substitution is about avoiding certain classes of errors, which I see as winning errors now and avoiding errors later. The remaining principles—interface segregation and dependency inversion—are also about the future, so those all fall into sustainability. Therefore, that’s where SOLID principles largely land.
00:25:59.710 Now, let’s talk about something a little different: Sandi Metz’s ‘Rules of 5,’ which you can read about in the first chapter of her book, "Practical Object-Oriented Design in Ruby." The first principle is transparent design—meaning that the consequences of changing code should be very obvious. The second principle is reasonable code; the cost of change should be proportional to the benefits.
00:26:33.300 The third principle is usable—basically, does your code hold up in other contexts? And the final principle, exemplary, means your code should set a good example for future coders. Ultimately, we all kind of look at the system and want to make improvements based on what we perceive as existing practices.
00:27:04.690 These principles are especially about the future, so I will also put them in the sustainability cluster. We are leaning heavily on sustainability here, but I want to diversify our strategy for quality just a little bit. Let’s talk about testing. One thing that often gets forgotten in our community is that testing at all is a choice.
00:27:46.600 There are a lot of places where teams do not test at all. So, choosing to test is a practice that we must prioritize. Code coverage means ensuring that every piece of your system is exercised in tests. There are different types of tests: unit tests are small pieces of your system, integration tests test how pieces interact with each other, and manual QA takes a broader perspective.
00:28:12.420 Now we have TDD and BDD. I won't offer my own definitions; I’ll reference how RSpec defines them—the difference is in the approach. With TDD, you start with very small units and build your way toward the edges, while in BDD, you start with a broader perspective and work your way down.
00:28:40.830 How do these practices work? They fall into the accuracy category, as they all help you write more accurate code. Coverage helps with future accuracy as well, so if anything changes in your code, you have a test alerting you. BDD, manual QA, and integration tests also connect to usefulness because they help you think about your system not merely in terms of whether the code is right, but in terms of the purpose behind that code.
00:29:19.640 I’ll place testing in the middle, as I think all these practices provide strong signals in many directions. Now, getting back to the hot new buzzwords everyone’s talking about—functional programming! Seems to be the new trend, though I can't say how true that might be. Type systems are trending, gradual typing, soft typing, TypeScript...
00:29:47.350 All of these are primarily about writing accurate code; they aim to avoid unexpected side effects. Scalability, however, is a bit different; it’s about future usefulness. I say this because when you really need scalability, your app is probably already down in production. Scalability is more about preparing for potential load in the future, which can be seen as being relevant to some apps.
00:30:22.590 Complexity metrics are fun, like cyclomatic complexity, which counts how many assignments, branches, and conditionals your code has. The more complex something is, the harder it is to write correctly the first time and the harder it is to write correctly later.
00:30:56.380 Now, let’s discuss team-oriented practices. Organizational conventions like having a consistent framework make it easier to move across teams. This includes having a style guide that is enforced programmatically with tools like RuboCop or ESLint to maintain consistency throughout your codebase.
00:31:31.610 The bus factor measures how many people on your team would need to be hit by a bus in order to destroy your application. Fun fact: most teams have a bus factor of one, which isn’t great! Team members can quit, be fired, take vacations, or get sick; we want to ideally avoid having our applications destroyed just because a single person is gone.
00:32:00.810 Mainly, we want knowledge sharing and to elevate everyone's skills on the team rather than hoarding knowledge. Code review is essential; it ensures code gets reviewed before it’s checked into version control.
00:32:32.370 Pair programming is like code review on steroids; it takes multiple developers and has them work on the code together, providing different perspectives. Internal documentation—keeping up with notes and other documentation—helps both onboard new developers and remind all current team members of important information they might have forgotten.
00:33:03.430 We also need debugging tools—essential for gaining insight into the system when things break. Lastly, mentorship is important. I choose to define mentorship as connecting two teammates who have different skill sets in formal, longer-term contexts.
00:33:33.270 Many of these fall into the sustainability category, as they improve how your team works together. I will put mentorship in a crossover between accuracy and sustainability because more skilled people end up writing better code.
00:34:13.390 Code review also sits in the crossover of accuracy and usefulness, as it serves as a good check to see if your code is what it’s supposed to do. It creates a chance for conversation about whether this is the right solution to the problem at hand.
00:34:39.650 Now, let’s wrap up a couple more essential practices: continuous integration makes sure your code is passing builds before deployment, while frequent releases allow you to find what's broken quickly. Refactoring should not just happen once; it should be done constantly to improve the health of your codebase.
00:35:15.470 Now, conventional APIs are also helpful, as they adhere to expected design patterns and conventions, allowing you to grow your application in a stable manner. Frequent releases deserve special mention; for a long time, I didn’t think frequent releases were vital.
00:35:42.020 Releasing frequently helps reveal what’s broken quickly, leading to more sustainable coding because you’re not building something on shaky foundations. You also aren't creating value until you ship!
00:36:05.610 We’ve covered a lot of ground and have a diverse strategy, but we’re still missing one key element: the user-oriented thinking focus. What goes into that usefulness section to balance this picture of software quality? The key practices center on delivering user value, which leads into all other factors.
00:36:43.300 Avoid getting caught up in what’s cool to build. Focus on delivering value, and you’ll prioritize what’s most important—user needs should inform your decision-making. Discoverability matters; you could build a fantastic feature but if no one can find it, it’s like you did nothing.
00:37:22.680 Empathetic UI—though this was just coined—means thinking about users' needs and in what situations they’ll be using the software. Anticipate their needs and deliver accordingly. One depends on your organization and their needs, but if you’re writing tax software, do try to avoid being late!
00:37:58.380 Performance often falls under the umbrella of computer science, yet it matters because users can’t wait forever for your app to work. It’s essential to focus on what they truly need, following more technical optimizations based on user needs.
00:38:33.270 Lastly, documentation is the voice of your software to users. If they detect discrepancies between your documentation and the actual software, they’ll think your documentation is broken, or that the software doesn’t work.
00:39:06.590 Think about writing client libraries to help your users effectively utilize the technical product you're providing. That's ultimately of greater value than working in a vacuum.
00:39:26.920 That covers the whole picture in my mind! There are numerous practices I care about, but time constraints limit our discussion today. Now, back to the question of quality software: I cannot dictate your answer; you must decide for yourselves.
00:39:48.170 So I leave you with a blank slate question to reflect on. Take these ideas back to your teams, think about the practices you engage in and care about as individuals and teams, and consider any areas that may be patchy.
00:40:01.440 Before I wrap up, let me offer a few parting thoughts. Different projects may require different balances of factors. Kent Beck has a 3x framework which highlights that even within a single project, what matters can evolve over time.
00:40:33.020 I don’t view focusing on good code first as negative for career development; however, it's more straightforward and takes less time to grasp. You can drastically improve your good coding skills over months to a few years. Eventually, this becomes automatic, so you'll find yourself struggling less to produce good code.
00:40:50.390 The understanding of broader business issues is more complex and requires continual refreshment, but it remains vital. Therefore, I recommend focusing upfront on good code, eventually expanding into business understanding as you progress.
00:41:12.540 Mapping out your career could look like this: starting out focused heavily on good code; over time, that focus shifts slightly as you build in more knowledge of business practices.
00:41:32.150 The crucial point is how much value you're creating. Building business understanding involves learning about your users and the broader industry, aiming to resolve organizational dysfunctions, and understanding various business practices and processes.
00:41:54.070 Finally, empathy is going to become increasingly important. Consider building your empathy skills; read books, learn, and engage with others who are different from you.
00:42:04.320 Try to listen to them, understand their needs and feelings, and see the humanity in everyone. This will not only make you a better person, but also a much more effective developer in your business.
00:42:12.170 I am starting a club that will be launching officially at the end of RailsConf. We’ll be reading empathy-themed books in both software contexts and broader applications while discussing how they relate to our professional lives. You can check out the Empathy Book Club site if interested!
00:42:36.850 I truly hope for more discussion of these topics in our community, so thank you for your time. Ultimately, make your software valuable, high-quality, and focused on creating value for your users.