Software Architecture

The Design of Everyday Ruby

The Design of Everyday Ruby

by Ju Liu

In the talk titled "The Design of Everyday Ruby," Ju Liu explores the application of design principles from usability to software development. Hosted during RubyDay 2014, the presentation underscores the importance of reconsidering established programming principles such as DRY (Don't Repeat Yourself), SOLID, and others, advocating for flexibility in their application. Liu starts by referencing Donald Norman's influential book "The Design of Everyday Things" and discusses its impact on understanding usability in design.

Key Points:
- Application of Design Principles: Liu emphasizes how principles from usability can enhance the clarity and usability of software code. He suggests that these principles should not be treated as rigid rules but can be seen as flexible guidelines that improve our coding practices.
- Mental Models: Liu discusses the significance of aligning designer and user mental models, indicating that confusion arises when they do not match. Designers must communicate through the usability of an object, as actual user experience often diverges from the designer's intent.
- Visibility: Code should be structured to allow users to quickly understand its functionality without needing extensive explanations.
- Affordances: Objects (or code elements) must provide clear visual cues that indicate how they should be used. Liu illustrates this by using the example of doors, where proper design signals whether to push or pull.
- Constraints: Liu discusses how imposing constraints in design can prevent misuse—a principle applicable in coding that encourages intuitive use of functions and methods.
- Natural Mapping: He highlights the importance of a straightforward relationship between controls and their outcomes, akin to the intuitive handling of steering when driving.
- Challenging Principles: Liu warns against the over-application of principles like DRY, mentioning that while they promote efficiency, excessive abstraction can lead to confusion and complicated code.

Conclusion and Key Takeaways:

- Liu encourages developers to continuously evaluate the necessity and applicability of design principles, urging a mindful approach to simplicity and clarity in both coding and design. He concludes that the ultimate goal should be fostering an understandable, maintainable, and functional application, suggesting that principles should promote development rather than constrain it. Liu invites discussion and openness regarding feedback and shared experiences within the Ruby development community.

00:00:04.100 Okay, English. Um, so hey everybody, my name is Ju Liu. I really love working with Ruby, and I work at a company in London called Alpha Sites.
00:00:10.080 You can find me on Twitter at Arkham.
00:00:15.480 Has anyone here read this book? Raise your hand. I repeat: has anyone read this book? Raise your hand again. Okay, about 10 people. It's pretty good.
00:00:21.060 I read it for the first time about two years ago, and I really liked it. Then, a couple of months ago, I read it again.
00:00:27.660 I began to think about how the design principles explained in this book could be applied to software development. This sparked the idea to give this talk titled 'The Design of Everyday Ruby'. I took the title from the book written by Donald Norman, who founded a very famous usability consulting company called Nielsen Normans. He is well-known in the usability field.
00:01:01.559 I want to highlight something interesting: there is another book that is often quoted alongside 'The Design of Everyday Things', titled 'The Catalog of Unfindable Objects' by Carol Mann. I believe it is satirical in nature, focusing on objects that are incredibly difficult to find.
00:01:25.140 However, if you look at these unfindable objects through the lens of a software developer, you may find they aren’t as unfindable as they should be. I will start by discussing a few examples of these unfindable objects, although there aren’t many unfortunately. The first one is a coffee pot for messages.
00:01:51.180 I often find myself in a position where I build something and then, out of frustration, abandon it. For another example, consider a precise knife: you have a specific problem, and you construct a very precise solution for it. The most relevant object that fits well with software development is something like an all-in-one tool, akin to a Swiss knife.
00:02:29.459 Interestingly, the book 'The Design of Everyday Things' was not initially titled as such; it was originally 'The Psychology of Everyday Things'. The author realized that this title was not appealing to readers, so he changed it and it worked. The book sold millions of copies afterward. Its significance lies in teaching more about how the human mind works than merely how to design objects.
00:02:55.440 A crucial lesson from the book is that you will never view a door in the same way again. Usually, when you face a door, you don't think much about it. However, after reading this book, every time you stand in front of a door, you’ll find yourself reflecting on its design, whether you’re entering a bathroom or otherwise. I have two pictures to illustrate this.
00:03:30.180 On the left, we see a plate intended for pushing, while on the right, there’s a handle for pulling. This door communicates its purpose very clearly. However, there are doors with just a handle on one side, which could mean pull or twist, yet the label says push. This confusion leads our brains to ponder for a moment before deciding to push.
00:03:48.180 Unfortunately, confusion with doors can escalate even further. Take, for instance, doors on trains in Italy. Opening these doors can become a real challenge. You often find yourself unsure if you should push or pull, all while trying not to harm anyone coming from the other side. It’s embarrassing to struggle with something so simple, especially if you have a degree in computer science or a PhD.
00:04:30.660 What the book teaches us is that it's not your fault for feeling frustrated; blame instead the designer who failed to consider usability. Norman emphasizes understanding mental models, which involve the designer conceptualizing a problem and proposing a solution. The user, however, is typically just handed an object.
00:05:11.880 The designer's model and the user's model are often entirely different. While they may share similar names, there is rarely a direct correlation between them. The challenge arises because designers cannot directly communicate with users after the object is created. The only means of communication is through the object's design itself.
00:05:55.380 Norman states that design acts as a form of communication between the designer and the user; however, all communication must stem from the object itself. This leads to a unique form of communication that can confuse users. Despite this, users possess a natural understanding of how something should work by feeling it.
00:06:24.660 A device speaking clearly makes a significant difference. I am sure that everyone here can easily use a well-designed door. Conversely, a poorly designed door—confusing where one should push or pull with unclear signage—can lead to uncertainty.
00:06:47.340 The confusion doesn't only apply to doors. Every time I try to open certain doors, I feel a sense of embarrassment if I can't get it right. This feeling is compounded when your background and expertise in technology seem irrelevant in that moment. The point is that bad design creates confusion, and that confusion is the responsibility of the designer.
00:07:30.360 Norman discusses mental models again, noting that a designer considers the problem and creates a conceptual model while aiming to solve it. If successful, the solution transforms into an object. On the other hand, the user approaches the object and attempts to construct a mental model based on their interaction with it. This disparity demonstrates that designers and users are often at odds.
00:08:01.740 The key takeaway is that designers should strive for clarity. Poor design leads to confusion and frustration. Once a design is complete, users need to intuitively understand how to use it. That's why it’s crucial to design with the user's experience in mind.
00:08:33.840 In my discussions, I keep coming back to one important point: clarity. I aim for my code to maximize understandability—be coherent for the next developer or even for my future self. Norman reiterates the importance of communication in design. I think the essence revolves around creating a clarifying experience.
00:08:58.760 As I share this, I want to also touch on the design principles Norman lists and see how they apply to software development. I’ve focused on four principles: visibility, affordances, constraints, and natural mappings.
00:09:29.160 Let’s kick off with visibility. I believe visibility means users should be able to look at an object—let’s say a class in your code—and instantly grasp how it functions. For instance, think of a smartphone: while it has a multitude of complex functions, it remains user-friendly.
00:09:56.700 The trick is to hide infrequently used functions to reduce apparent complexity while ensuring that it remains evident what actions are available and how to perform them. So, when you're reading a class in your codebase, you should capture a clear understanding of its purpose in about fifteen seconds.
00:10:23.700 Next is the principle of affordances, which suggests visual clues that indicate how to use an object. For example, a suitcase has handles which implicitly suggest to the user how to lift it. Following this, consider doors: plates for pushing and handles for pulling act as cues.
00:10:49.740 Now, let's switch gears and dive into some code. Firstly, I want to bring up a relevant test. How many of you are familiar with the Screen Test method? Essentially, the trick involves squinting your eyes to see through them when looking at code. It’s a fun exercise, and let’s see how it goes.
00:11:20.299 Consider this class; I’m just going to change a single thing in this class. You shouldn’t even be able to see what I changed. If I alter one word in it, what does this tell you about the class? The first two methods represent the public interface while the last three methods are the implementation details. It’s vital that the public interface maintains a similar level of abstraction and mutual understanding.
00:11:59.640 A simple method name is a clue to the behavior of the class—it should be evident what it does without delving into implementation details. Clarity is key here. This highlights how we can make our code visible and easily understandable for future users—whether that’s ourselves or newcomers to the team.
00:12:25.500 Moving on, the concept of constraints refers to limiting possible actions. In design, applying constraints ensures users cannot misuse a device. For instance, a digital camera typically has a secure SD card slot that only fits a card one way, preventing errors in use.
00:13:01.800 For our software, the best way to ensure usability is to restrict choices rather than relying on users to remember function use. Take a situation where manipulating strings and arrays—the process can look similar but should be intuitively understood by the user.
00:13:30.960 The parallel might cause confusion. When two functions exist that perform similar actions, their parameter order can further complicate how users utilize them. In my code, I have also experienced this, creating parameters with inconsistent ordering. While it may seem trivial, users may struggle to remember this ordering, leading to their frustration.
00:14:03.480 The trick should emphasize keeping methods consistent in naming and ordering, ultimately ensuring users can intuitively access the features without unnecessary struggles. Let’s switch gears again and talk about natural mapping, a principle inherent in a clear relationship between control and outcome.
00:14:40.920 Think of driving a car; turning the steering wheel intuitively corresponds to going left or right. This kind of mapping simplifies interactions and ensures users understand their actions immediately, rather than relying on signage or labels which can lead to confusion.
00:15:12.540 Norman emphasizes that if you depend on labels or complex instructions, something needs reevaluation regarding the clarity of your design. The principle can also be seen in coding practices—instead of relying on comments, try making the code self-explanatory and clear.
00:15:53.220 In reviewing my past practices, clarity stands out. I often find designers not communicating their intentions clearly. Applying these principles when writing code can have a profound impact on improving readability and making the code more intuitive for any reader.
00:16:22.680 Conclusion: the goal of applying design principles is to foster clarity. Additionally, I want to emphasize you can challenge rules like DRY (Don't Repeat Yourself). While DRY encourages minimizing repetition, over-applying it can sometimes lead to convoluted code. Often, the push for DRY leads to premature abstractions that complicate development processes.
00:16:51.840 You may find yourself extracting code that seems beneficial but later leads to confusion. Similarly, while applying SOLID principles can assist, they shouldn't become rigid requirements—for instance, every control function shouldn't need to build a complex inheritance hierarchy unless it adds clear value.
00:17:24.480 Taking the essence from Uncle Bob, the SOLID principles exist to enhance code quality rather than serve as restrictive mantras. While hexagonal architecture provides a respected framework, you must realize when its complexity is unnecessary versus when it solves real problems. Always evaluate the benefits and trade-offs when applying any principle or pattern.
00:17:56.520 Wrapping up, it is better to maintain a balance in design and code clarity, ensuring that the application is functional, understandable, and maintainable. Just because a principle or design pattern exists doesn’t mean you should apply it without question. This is what we, as developers, need to consider to produce great software.
00:18:28.920 I'd also like to share a brief note about my employer: we have been a startup for eight years now and are profitable. Our team has grown from eight developers to sixteen. While operating in London and New York, we offer opportunities for remote work and have ten hours per month dedicated to pet projects or personal growth.
00:18:54.240 If anyone is interested in discussing or has further questions concerning design or our company, feel free to approach me. We genuinely care about sharing our passion for Ruby development and welcome feedback. Thank you for your time.
00:19:28.560 Now, if there are questions, I'd appreciate it if we could have an open discussion. I believe real conversations often provide the best learning experiences. Who wants to start?
00:19:56.760 You know, sometimes I find that companies push for advanced structures like hexagonal architecture but fail to see the potential confusion they may introduce. While certainly, architecture can enhance structure, we must also weigh it against possible usability issues.
00:20:35.760 Also, consider controlling the complexity of a project instead of letting the architecture dictate the approach. Reducing levels of indirection and maintaining simple solutions are just as important.
00:21:05.280 Overall, my perspective is that we should remain open-minded and adaptable. As developers, we need to constantly reevaluate the structures we use in our code to foster growth, collaboration, and efficiency.