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!