Object-Oriented Programming

Eastward Ho! A Clear Path Through Ruby With OO

Eastward Ho! A Clear Path Through Ruby With OO

by Jim Gay

In this presentation at RubyConf 2014, Jim Gay discusses the concept of Eastward-oriented Code, which is centered around the programming principle 'Tell, Don’t Ask.' This approach encourages better code organization, while minimizing messy structures that commonly arise from excessive queries within the code. Key themes include:

  • Understanding Eastward-oriented Code: The concept focuses on guiding information flow in a direction metaphorically described as 'eastward' for commands and 'westward' for queries, aiming to simplify code complexity.
  • Rules for Implementation: Gay introduces several rules to follow when writing code:
    • Always return 'self'.
    • Allow objects to query themselves, except in the case of factories.
    • Minimize the use of 'if' statements, as they can lead to excessive complexity.
  • Importance of Encapsulation: Gay emphasizes the need for objects to manage their data display without excessive external querying, thus ensuring that they control their representation.
  • A Practical Example: He uses a class structure for a 'Person' that handles addresses as an illustration, demonstrating how to avoid too many responsibilities within a class object which often leads to bugs and confusion.
  • Law of Demeter and Its Application: The Law of Demeter is mentioned, highlighting the need for objects to interact minimally with others, retaining knowledge only about themselves and their direct interactions.
  • Templates and Responsiveness: Gay suggests utilizing templates for formatting outputs, allowing objects to dictate how their information is represented while adhering to the principles discussed.
  • Conclusion and Mastery: The presentation concludes with an assertion that mastery lies in understanding what objects should control and implementing strategies that foster encapsulation and reduction of unnecessary queries.

Overall, Gay invites viewers to reflect on their coding practices and apply these rules to enhance the maintainability and clarity of their Ruby programs.

00:00:18.320 Today, I'm going to be talking about a concept called Eastward-oriented code, which is related to the principle of 'Tell, Don't Ask.'
00:00:26.080 My name is Jim Gay, and I'm Saturn Flyer on most platforms, including Twitter and GitHub, so feel free to tweet at me and share your thoughts.
00:00:32.880 Although I won't be checking during the presentation, I did travel west to enlighten you about heading east, and I've brought some friends along with me.
00:00:44.320 If you see them, please say hello! I practiced my presentation with them this morning.
00:00:50.320 They didn't quite grasp all of the concepts, so it helped me learn to slow down.
00:01:00.800 It's actually quite funny; when I posted a picture online, a friend asked about my daughter, and there she was.
00:01:07.439 She didn't refer to all of us as losers. At least, she hasn't said that!
00:01:14.880 Now, let's dive into Eastward-oriented code. This idea might seem confusing at first, and that's perfectly fine.
00:01:21.439 I just want you to stick with me, and together we'll explore some rules that you can apply to your own code.
00:01:26.560 You can then walk out of here and experiment with these ideas on your own.
00:01:31.840 This concept was coined by a developer named James Ladd from Australia.
00:01:37.360 We'll dive deeper into what he means by it shortly, but first, let's examine the flow of information in our code.
00:01:43.280 The idea is to visualize information traveling eastward, while information traveling westward can lead to complications.
00:01:49.520 If you think about navigating your code, you'd see queries moving westward, representing information going in a particular direction.
00:01:56.479 Meanwhile, commands should be directed eastward.
00:02:08.800 When I first encountered this concept, it was a bit perplexing.
00:02:14.560 However, I realized I could observe this phenomenon in my code.
00:02:22.800 Sometimes, when you look at your code, you'll notice how deeply nested it is.
00:02:29.280 You might find a series of nested 'if' statements that resemble a chaotic structure.
00:02:34.400 Identifying this is an indicator of poor design. You can also discern where information flows.
00:02:39.519 Is it traveling westward, or is it heading eastward?
00:02:45.120 Let's go over a couple of fundamental rules we'll apply to our code. Rule number one: always return 'self'.
00:02:52.720 Rule number two states that objects can query themselves, but factories are the exemption.
00:03:04.879 As programmers, we often use fancy terms such as 'polymorphism', 'encapsulation', and 'coupling', which are crucial concepts.
00:03:10.319 However, it sometimes becomes challenging to comprehend how these principles apply to our code.
00:03:22.159 On the flip side, there are simpler terms that we also use.
00:03:28.080 I'm curious to see how many people are familiar with the term 'this'. It’s probably the simplest and most powerful word at our disposal.
00:03:39.599 We can achieve remarkable things with it, but it can sometimes spiral out of control.
00:03:46.080 We need to be cautious of overusing it, as it can lead to messy code.
00:03:52.080 Some people have discussed avoiding 'if' statements altogether in programming. Initially, it may seem harmless to allow just one 'if'.
00:04:05.519 But the problem arises when our code accumulates numerous 'if' statements, leading to chaotic and complex structures.
00:04:34.080 Let's examine an example: we have a class 'Person' that contains an address that we want to display.
00:04:41.520 Many of us have done this with Active Record when we started learning Rails.
00:04:47.040 The code would display correctly in the view as long as you placed it in the right spot.
00:04:55.680 Now, let's consider how we display the address, depending on the available data.
00:05:03.680 We want to display it in a specific format, adding line breaks if we have both street and city data.
00:05:14.960 Conversely, if no city exists, we do not want to append a comma.
00:05:22.080 We have to make various decisions about the data and how to handle missing information.
00:05:34.720 I won't overwhelm you with an extensive code example, but let’s simplify it.
00:05:45.680 Now, let's analyze this implementation without examining the code in detail.
00:05:52.720 How many 'if' statements can you observe here?
00:05:56.560 I'd say there are about five or six, maybe even more if you dig deeper.
00:06:01.680 How many responsibilities is this class handling?
00:06:06.720 Too many! I believe the answer for both questions is simply too many.
00:06:14.880 Furthermore, I discovered a bug in my implementation.
00:06:20.400 We still end up with a comma showing up, even if the city is missing, which complicates things.
00:06:28.720 I wrote this code thinking it would clarify some information, but I found bugs instead.
00:06:32.240 So, let’s start embracing the rules. Rule number one: always return 'self'.
00:06:38.080 Here’s how that could look in our code, where we return 'self' from the method.
00:06:43.520 But what happens if we follow that rule? Well, it’s broken!
00:06:49.360 This indicates that perhaps we’re missing something — at least one more object.
00:06:54.479 Let’s discuss the principle of 'Tell, Don't Ask'. This was coined by Andy Hunt and Dave Thomas in an article advocating for a division of responsibilities without excessive coupling.
00:07:05.919 Initially, when I encountered this, it didn't seem clear. I thought I understood, but I moved on.
00:07:13.280 This topic frequently resurfaced in discussions among programmers.
00:07:18.400 An alternative way to conceptualize it is: 'Command, Don't Query'.
00:07:23.680 We shouldn't ask an object about its state and then perform operations based on that. It's far more efficient to just tell it to execute the desired action.
00:07:30.160 Think about it this way: when I’m getting my kids ready to go out, I simply tell them what to do!
00:07:36.560 For instance, I don’t want to ask them if they’ve put on their shoes. I’d rather just tell them to put their shoes on.
00:07:43.680 When I first studied 'Tell, Don't Ask', I felt reassured because Ruby allows me to append question marks to my methods.
00:07:50.880 Yet, understand that just because I appended a question mark doesn't mean it's solely a query.
00:07:57.040 Likewise, using commands doesn't imply absence of question marks.
00:08:03.440 Let's now clarify that we shouldn't hit the panic button just yet. Commands are straightforward!
00:08:13.440 But let's take a step back and revisit this mathematical connection.
00:08:21.440 When we query an object for its state, we're accessing information about itself.
00:08:28.800 In our address scenario, we’re probing for street details, checking the values and operating based on answers.
00:08:35.200 But are there any real commands found in this code?
00:08:42.240 It's difficult to pinpoint them.
00:08:50.240 As you assess this code, it's worth addressing the Law of Demeter. Has anyone here heard of it?
00:08:59.680 A few familiar faces nodding, good! This law states that objects should only interact with themselves, their parameters, and their created objects.
00:09:05.680 Yet in this code, we encounter a violation.
00:09:12.000 The object is inquiring about other objects. This leads us to needing knowledge of their entire interconnections even to proceed.
00:09:19.280 With a person trying to access the address, we can either go through complex interlocking structures.
00:09:25.920 So, how can we adjust our approach?
00:09:31.919 If Andy and Dave were to provide a practical example, they might illustrate programming a television.
00:09:40.000 In this situation, we need to identify a way to turn the television on.
00:09:46.560 Thus, one might imagine a scenario involving a power button.
00:09:53.120 Here's the kicker: if the power button changes, everything might break!
00:09:59.680 If that power button toggles, it can disrupt previous implementations.
00:10:06.880 It's crucial to have a consistent point of contact where we interact with the television.
00:10:13.120 We don't want the user class to break each and every time a minor change occurs.
00:10:20.320 This highlights the importance of isolating tasks.
00:10:26.560 So, how do we move towards a better-suited solution?
00:10:32.000 In the context of displaying an address, consider returning self while delegating formatting to the address or separate template.
00:10:41.760 This allows us to keep display logic contained within the address class.
00:10:48.480 We should strive to ensure no queries break our implementation.
00:10:54.000 If an address could manage its display, we also shouldn’t create an unnecessary burden.
00:11:01.440 The address, at least, should control how the formatting appears — aside from actual logic.
00:11:08.160 We can specify line breaks and handle all situations effectively; that's good!
00:11:14.880 Now, if there's a street, it's included. We proceed to format the address, considering components.
00:11:20.160 But keep in mind, the display ruling ought to stay with the address.
00:11:26.320 If we want to introduce different address formats, let’s utilize arguments.
00:11:32.080 This leads us towards improved flexibility, yet the responsibility remains clear.
00:11:38.640 We notice the person class still returns self, ensuring it only conforms to its basic functionality.
00:11:45.520 Yet it still needs an additional class to handle template formatting.
00:11:52.320 Templates can control display outputs while keeping the objects separate.
00:11:59.520 Now, the person should inform the address that it must be displayed using a template.
00:12:05.440 This sends the address to present itself on the template.
00:12:12.160 Within that, the person interacts, allowing the template to define how it establishes context.
00:12:19.520 The template, in essence, specifies how it will output the data but in conjunction with the address.
00:12:26.640 So we 'Tell the address to display itself' without accessing the address's information directly.
00:12:33.520 The template can handle its own output so that everything maintains a clean responsibility.
00:12:42.160 Should I decide to add an HTML template later, it knows how to convert the address into an HTML format.
00:12:50.720 At this point, we can see the templates dictate output formatting without impediment.
00:12:57.520 Returning to our application, when we tell the Person class to display addresses, we have to manage how the data comes into play.
00:13:06.400 We can implement value objects that can simplify our interactions. They allow us to collect attributes.
00:13:12.640 Assigning attributes through an open struct instance proves efficient.
00:13:19.680 This grants access without directly approaching the variables, thus maintaining encapsulation.
00:13:27.440 Now we switch the context; if an object wants to display various aspects, it knows how to do so.
00:13:33.440 Such that we keep personal identifiers, surroundings, or even sensitive data private.
00:13:40.000 We safeguard the ability to alter how and when this data gets presented, preserving privacy.
00:13:48.160 All decisions about what the address object reveals rests solely with the object owning that data.
00:13:55.840 By defining a method like 'to value', the address can determine if its data is publicly viewable.
00:14:00.960 It will leave room for any expansion desired or modify its output format.
00:14:07.680 The goal is to keep the address dictating what data is displayed without focusing on how it’s shown.
00:14:13.920 Now let's go back to the template example.
00:14:20.160 We notice querying happening everywhere, which contradicts our primary concept.
00:14:27.840 We encounter several instances where we’re asking the address about its attributes.
00:14:35.020 To ensure the code remains adhering to 'Tell, Don't Ask', we ought to format accordingly.
00:14:42.280 This leads us to the fourth rule: while querying is bad, it's acceptable in value objects since they serve a specific function.
00:14:52.320 The advantage here is that everything moves eastward, while your core principle of 'Tell, Don’t Ask' thrives without hindrances.
00:15:00.920 Each object clearly defines its responsibilities, enhancing code cohesion and clarity.
00:15:08.760 As James Ladd states, 'East orientation decreases coupling and increases code clarity, cohesion, and flexibility'.
00:15:13.880 On the other hand, we often find that well-structured code leads to fewer complications, even when blow-up occurs.
00:15:21.760 So it's crucial to recognize this moving forward.
00:15:28.640 We need to avoid leaking knowledge and responsibilities.
00:15:37.960 Wilfully letting queries seep fosters complications, such as polluting our systems.
00:15:41.840 Conversely, commands naturally enhance polymorphism and facilitate the delegation of tasks.
00:15:48.880 They shift responsibilities downwards, easing coding through traditional practices.
00:15:56.679 I've briefly touched upon how to achieve item potency as well.
00:16:04.960 By telling the address to display itself, we allow it to determine if work has already been done.
00:16:12.080 Plus, when we refer to previously queried facts, it helps limit challenge occurrences.
00:16:19.040 Let’s reiterate then, to structure effectively it requires following a few essential rules.
00:16:29.360 Always return 'self', allow objects to be querying themselves, and implement factories pragmatically.
00:16:37.760 Please indulge sparingly with breaking the rules, especially as they apply to value objects.
00:16:44.960 Follow James Ladd on Twitter; it’d be great if everyone reaches out to thank him for these principles!
00:16:52.800 To conclude, while East-oriented code aligns well with 'Tell, Don't Ask', true mastery lies within deciding what the object should control.
00:17:01.200 The beauty of it is the encapsulation and the removal of unnecessary queries.
00:17:08.960 Remember our tool and approach beyond just syntax or structural integrity!
00:17:18.480 Let’s strive to guide ourselves by implementation, and take those principles boldly into our own projects!
00:17:24.960 Thanks for your time today; I hope these insights help you cultivate your coding expertise!
00:17:32.000 So go on, return to your code and inspect your applied knowledge; identify and refine!
00:17:43.840 Thank you!