Dependency Injection

Summarized using AI

Live Coding with Ben

Ben Orenstein • June 24, 2013 • Earth

In the video titled "Live Coding with Ben," presented at Ancient City Ruby 2013 by Ben Orenstein, the session revolves around the concept of pair programming and the practical exploration of coding practices. The session emphasizes learning through observation and dialogue rather than traditional lectures. Ben introduces several key coding principles and practices through a live coding demonstration, where he investigates a code sample while inviting audience participation.

Key points discussed include:

- Refactoring Principles: The core of the session is about improving code through refactoring, focusing on collaboration and understanding the nuances of good coding practices.

- Law of Demeter: Ben highlights the importance of adhering to the Law of Demeter, which promotes loose coupling between classes to avoid structural duplication and improve maintainability. He explains violations of this principle in the provided code examples.

- Duplication and Coupling: The conversation extends into the significance of avoiding duplication in code, cross-referencing the DRY (Don’t Repeat Yourself) principle and discussing coupling and its implications for code quality.

- Dependency Injection: Ben explores the pros and cons of dependency injection, illustrating how it can enhance the flexibility and extendibility of code without necessitating modifications to existing classes.

- Testing Practices: Emphasis is placed on the relationship between code quality and testing, particularly the mantra of fast tests often equating to good tests.

- Code Smells: Throughout the talk, the concept of 'code smells' is introduced, which indicates potential issues in code that warrant attention.

- Audience Engagement: Ben encourages audience members to actively engage by asking questions and sharing insights during the coding process, creating an interactive learning environment.

The session concludes with the core takeaway that adhering closely to principles like the Law of Demeter and practicing good habits while coding can lead to superior software design. Ben emphasizes that while perfection may not always be achievable, striving for better code should be a continuous goal for developers.

Live Coding with Ben
Ben Orenstein • June 24, 2013 • Earth

Ben believes that the best way for programmers to learn is to watch each other work. We'll leave slides behind and focus instead on the greater information density achieved through live coding. We'll discuss the strengths and weaknesses of real code, and refactor it right onstage. As we do so, we'll bump into lots of meaty topics:
- Potential downfalls of the 'extract module' refactoring (aka ActiveSupport::Concern).
- The pros and cons of Dependency Injection.
- How two good OO design ideas (like SRP and Tell Don't Ask) can contradict each other, and what to do about it.
- How well--placed functional programming can improve a codebase.
- Whether the Law of Demeter should be followed religiously, and what it means if that's hard to do.
- Why fast tests are usually good tests, and vice versa.
- Audience participation is strongly encouraged, as is stealing the speaker's Vim tricks for your own use.

Ancient City Ruby 2013

00:00:00.440 Good afternoon, Ancient City Ruby! How's everybody doing? Jim can hear me in the back, and I verified that this is viewable from where you’re sitting, Jim. Can you see it okay?
00:00:07.040 I can actually see it! Awesome, Jim can see it. I can hear you, and I'm excited!
00:00:13.519 So, this talk: how many people have seen my 'Refactoring from Good to Great' talk? Very cool! So, this is not that. I've given that talk a few times, and I'm quite fond of it.
00:00:22.240 However, I was forced to let it leave the house to create a new talk that I will now inflict upon you. The good news is that this is a brand new talk, so what I would like from you, even more than usual, is feedback.
00:00:36.120 This talk is not a lecture; it isn't even really a talk. This is pair programming. We’re going to look at some code, talk about some code, make some changes to it, and discuss those changes.
00:00:43.280 The point is not for me to just drop knowledge bombs on you, although I may drop a couple. The point is for us to have a dialogue, to have a conversation.
00:00:50.120 Because we’re pairing, you must follow a very important rule of pairing: if you don’t understand something, you must be aggressive about admitting it. Do not hesitate to say, "I don’t understand what you’re saying." Heckling is encouraged!
00:01:01.160 One of my metrics for a talk's success is how long it takes me to show code, so let’s get this up there.
00:01:07.720 By the way, I work at Thoughtbot in Boston. Has anyone listened to our podcast? Cool, we have a podcast you might like.
00:01:13.440 Alright, so take a look at this code. What's good about this code? The methods are short. Yes, what's that? It’s written in Vim!
00:01:21.120 Absolutely! That’s a damn good point. The best code is always written in Vim!
00:01:29.480 As you can see, the methods are short, and the class is short. It's only six lines. I’m using something called relative numbers, so as I move this around, the numbers change. My cursor is always on line zero.
00:01:50.040 Now, for a while, I would tell people that relative numbers aren’t good because they have one downside: if you’re pairing, you might say, "Change line five," and then we’d find ourselves counting down from five, four, three, two.
00:02:00.159 But actually, relative numbers are awesome, and I’ve now been convinced of their awesomeness. You’re going to see me forget this, so I’d like you to remind me; this is a new habit I'm trying to instill.
00:02:08.000 So, every time you see me go to visual mode, that's a signal: there’s a better way to do this!
00:02:14.080 Rather than going to visual mode to delete a method, I would rather say, "d2j" so I can see that two lines below is that end, because I have relative numbers.
00:02:22.000 Or "d3j" also works. The point is you can see how many lines away things are.
00:02:28.000 If I want to drop down to user.parent or to line nine, I could just say "9j" and go down there.
00:02:33.040 It’s a little faster. I paired with Joe Ferris, our CTO, the other day for the first time in a while, and he had switched to relative numbers.
00:02:42.000 He was doing stuff, and I realized I had been wrong all these years. Relative numbers is correct. I reverse my previous incorrect position, and I think everyone should try out relative numbers.
00:02:49.599 Just set relative numbers to one. If you don’t know how it works, do a little RTFM.
00:02:58.360 So, we talked about what's good about this code. What's not so good about this code?
00:03:04.839 The Law of Demeter. Raise your hand if you think it’s DeMeter. Raise your hand if you think it’s Deiter.
00:03:10.919 It’s good, right? People who are really into the etymology of words have told me it’s DeMeter.
00:03:19.760 So, I say I will say DeMeter if you tell me that a method takes two parameters, which no one is taking me up on.
00:03:27.360 Therefore, I’m probably going to say DeMeter, but sometimes I’ll say Deeter just so I can make sure to troll you.
00:03:37.120 A police officer is a Deeter; if we were in Europe, we'd say colomer.
00:03:44.320 That’d be a better local joke. So, yes, there’s a Law of Demeter violation on line zero.
00:03:51.840 It’s also on line negative four. I’m going to hit 8j to move up.
00:03:58.800 So, right here, is that a Law of Demeter violation? Let’s clarify. The Law of Demeter says you can call methods in your own class; that's fine.
00:04:04.920 You can call methods on your parameters. You can’t call methods on the return values of your parameters unless it's of the same type.
00:04:14.640 It's okay to call methods on your parameters. If we build things in our own class—if we build something ourselves, we can call methods on that as well.
00:04:22.360 So, line zero is not a Law of Demeter violation. This is, and it’s because user returns a company, which is then called.
00:04:30.480 Also, on line four, three, two, and one, there’s an even worse Law of Demeter violation.
00:04:37.360 Now, really quick, let me get my tests ready. I'll be running tests.
00:04:43.240 They look like this; they're fast because they’re not in Rails.
00:04:49.159 So how important is the Law of Demeter? The Law of Demeter is actually kind of important.
00:04:55.080 The reason it’s kind of important is because it’s about duplication. Almost every programmer knows about DRY, right?
00:05:04.120 They know you shouldn’t take something like the number of retries a user is allowed.
00:05:12.920 There should be a single authoritative source for the number of password retries you’re allowed or other similar pieces of data.
00:05:20.560 This is data duplication you want to avoid. There’s also other kinds of duplication.
00:05:27.920 Now, Demeter is concerned with structural duplication. The problem is that user presenter knows that user, when you call, returns something.
00:05:35.760 What I’d rather have is for user presenter to be more context-independent. I want it to take a parameter that I can call certain methods on.
00:05:43.440 That's a contract I’m okay with, but I don’t want to know about the next level down.
00:05:51.480 The problem is the structure of my app is now encoded in this class. This class is coupled to other pieces of my application.
00:06:01.600 Coupling is a real pain. Let’s define this real quick. Coupling is the degree to which components in a system rely on each other.
00:06:09.080 If component A has no coupling whatsoever to component B, no matter how much you change A, you will never break B.
00:06:16.960 If they are coupled at all, some changes you can make to A will break B.
00:06:23.600 This is sort of the source of almost all the heartache in programming. If everything were decoupled, you could always make local changes.
00:06:30.960 One of the hardest things is modifying a coupled system and understanding how those changes will ripple throughout the system.
00:06:38.160 Much of programming is about managing that concern. The Law of Demeter helps ensure that structural duplications do not leak into the system.
00:06:48.480 Some coupling is necessary. If everything in the system were totally decoupled, nothing could talk to each other.
00:06:54.520 That wouldn't make much sense. You could never build a system from small pieces and build it up.
00:07:01.440 Some coupling is necessary, but there are different kinds of coupling, and we want to aim for the lowest form.
00:07:07.519 I wrote a blog post about types of coupling; you can check it out. It’s on the Thoughtbot blog.
00:07:21.000 When I talk about the Law of Demeter, how many people follow the Law of Demeter all the time?
00:07:26.960 How many people follow it most of the time? How many people just heard about it today?
00:07:32.000 Awesome! That’s a great thing to know about. Most programmers say this about duplication.
00:07:39.760 They say, "Yeah, I usually don’t allow duplication," and then they have some sort of heuristic that’s often pulled from a blog post.
00:07:50.560 How many people have a similar heuristic? Something along those lines? Okay, here’s the problem with that.
00:07:57.680 I used to have the same thing, and then someone explained how it actually works to me, and I was suddenly like, "Oh, this makes a lot of sense."
00:08:06.840 How many people do code review? How many people do code review by a pull request on GitHub or by diffs in general?
00:08:12.560 The problem is, you can’t see duplication on a diff. If I copy and paste an entire class and change one line, then submit a pull request, you will see a bunch of green which looks nice.
00:08:22.480 "Hey, that looks great! Who wrote that?" You will say, "Yep, looks good to merge." The only way you'll find that duplication is if you go searching through the source tree.
00:08:29.120 In reality, just like the idea of saying, "Oh, I’ll go back and fix that later," that almost never happens.
00:08:38.520 Has anybody played Go, the game? It’s a really cool game with incredibly simple rules, and yet the complexity and beauty are incredible.
00:08:45.440 You should absolutely at least achieve beginner competence with Go. It’s such an amazing and fascinating game.
00:08:55.760 There’s a saying in Go that goes, "Beware of going back to fix up things." It implies that when you’re playing, you should just leave things in good shape.
00:09:07.559 You shouldn’t think, "Well, there’s trouble there, but I’ll come back to fix it later." You should follow that maxim in your code as well.
00:09:12.880 Don’t even duplicate once. It's so easy to miss the next duplication when you come back to it later.
00:09:17.080 The Law of Demeter is about duplication. If you follow it, you will avoid structural duplication. I suggest you follow it almost all the time.
00:09:26.880 If you can’t follow it, you should ask yourself why.
00:09:34.480 I noticed something interesting: when programmers are new, they care a lot about duplication because they’ve read about DRY.
00:09:41.440 As they gain experience, they develop a more nuanced view about duplication, which I think is a good thing.
00:09:47.119 Nuance is important; there are very few rules in programming that are absolute or things you should always do.
00:09:54.000 I think that when it comes to duplication, there isn’t anything like that, but I see that intermediate programmers often ignore it after they've gotten away with it a few times.
00:10:00.920 On the other hand, better programmers tend to start caring about it a lot more. I think this is very important.
00:10:09.920 Kent Beck has said he thinks he’s a decent programmer with excellent habits. Good code comes out of really good habits.
00:10:18.480 You don’t need to be a genius; you just need to be disciplined, and caring about duplication is part of that discipline.
00:10:23.520 So, I know some of you learned about Demeter today; some of you knew it before but maybe weren’t clear about it.
00:10:31.920 Don’t worry so much about the definition of Demeter; worry about the duplication.
00:10:38.600 Here are my tests for the same file.
00:10:45.040 So this first test is for a method that does not violate Demeter. Notice how it’s very flat.
00:10:56.960 We’ve got a user stub and a method stub on it—using ancient mock, by the way.
00:11:03.520 This test looks good to me. This test tests a method that violates Demeter.
00:11:08.840 Here’s your clue: we build a company and then we put that company in a different stub and pass it in.
00:11:15.680 That’s your clue! Even if you don’t know what Demeter is, when you find yourself reaching for nested stubs, that should send alarm bells ringing.
00:11:22.000 It should be a smell that you pay attention to. By the way, 'code smells' is a term worth knowing. A code smell is something that indicates there may be a problem.
00:11:29.520 However, that does not indicate that there is a problem. I sometimes note code smells and ignore them because sometimes the cure is worse than the disease.
00:11:37.680 Here’s a parent company name which is even worse. Predictably, the setup is even worse. Do you see how ugly this is getting?
00:11:45.080 This is your test talking to you. This is my test talking to me and saying, "Hey, you’re making an example of Law of Demeter violations."
00:11:52.000 By the way, this is not how you fix it. Stubbing does not fix the problem.
00:12:01.320 People like to say, 'Oh, stubs suck because they’re brittle.' When I change my code, I often have to change my stubs.
00:12:09.680 Part of that is people encoding the structure of their application into their stubs, which is exactly what’s happening here.
00:12:17.440 When I change the way that users and companies are associated, I might flip them around or make one optional.
00:12:25.440 Then, I have to come back and update these stubs because they’re ugly, and they’re encoding the content of the application.
00:12:33.040 Someone tweeted that we should add a 'law of Demeter' violator to this, which is pretty awesome.
00:12:40.800 Let’s look at another example of how not to fix this. A lot of people will say, 'This code looks much cleaner!'
00:12:52.000 If I’m looking at this screen, I’d say, 'Yeah, those tests are pretty awesome. Nice and flat!'
00:12:58.800 At Thoughtbot, we have a style guide that says do not prefer to use 'let' or 'subject'.
00:13:05.440 And there are a couple reasons for this. This test seems better at a superficial level within the body of the it blocks.
00:13:11.680 However, it still has the same duplication on top as those lines still encode the structure of the application.
00:13:19.440 They just make the rest of the test look a little better, but there are a couple problems here.
00:13:27.760 Here’s the first reason we don’t use 'let': they create something called a 'mystery guest'. Without looking, what is 'user'?
00:13:35.360 You don’t know! That’s a mystery guest! It’s an object that has shown up in our verification or exercise steps.
00:13:41.200 It was not created during the setup phase, so 'let' obscures that setup phase.
00:13:47.920 It makes it happen implicitly as part of this exercise step. So when I refer to 'user' here, it calls the 'let's' and does my setup implicitly.
00:13:54.640 I prefer my tests to look flat and have an explicit setup step.
00:14:02.160 The second problem is that these tests are going to be kind of fragile because of creating a complicated fixture for every step.
00:14:10.160 I imagine many of you have had the situation where you need to add one more test.
00:14:16.040 You say, "We just need a user that doesn’t have a company!" So, you start writing that, right?
00:14:23.760 You want it to return a default when it doesn’t have a company. You get here and think, 'Okay, what am I going to do?'
00:14:31.120 Well, user already has a company, so let me destroy the company. Right, that seems awesome, right? Who here likes slow tests?
00:14:37.760 Exactly! Because we defined the standard fixture, we’ve made it harder to add tests.
00:14:44.000 That fixture tends to be fragile; it's going to be slow. We’re going to have performance concerns; we’re building more data than we need.
00:14:53.680 These are very lightweight stubs, but a lot of times they are not.
00:15:02.120 There's another concept I’ve stumbled upon recently which I really like: the Open/Close Principle.
00:15:08.800 How many people have heard of the Open/Close Principle? Good!
00:15:15.200 So, have you heard of Bob Martin and his SOLID principles?
00:15:22.400 O is open to extension but closed for modification. What does that mean?
00:15:28.960 It means it should be possible to add new behaviors to a system without changing existing classes.
00:15:36.160 The primary way you can do that is by injecting dependencies.
00:15:43.680 If your class takes an outside dependency, you can write a new class that performs differently and feed that into the existing class.
00:15:50.960 That way, you get new behavior without changing the code in the existing class.
00:15:59.000 That’s a nice benefit, because every time you change a class, you might break it. We try our best, but sometimes we muck it up.
00:16:07.040 The Open/Close Principle says it’s better if you don’t have to change the class. It’s open to extension but closed for modification.
00:16:14.720 We don’t want to change the code; we’d rather add methods or inject dependencies.
00:16:20.880 I’d like if, once I’ve written a test, I never had to edit it again.
00:16:28.080 Part of my motivation for that is because it’s hard to ensure I still have good test coverage if I break 10 tests.
00:16:36.160 I can go through and fix them, and I will do it carefully, but it’s hard for me to verify if everything that used to be tested is still being tested.
00:16:42.640 To avoid these tricky situations, I want to have good habits.
00:16:49.440 This standard fixture approach violates the Open/Close Principle for tests.
00:16:56.720 It makes it really likely that I’m going to break existing tests when I need to edit these stubs.
00:17:03.520 As someone pointed out, we have a style guide at Thoughtbot talking about the general principles for how we implement things.
00:17:09.920 It says, "Don’t use 'let'." Then, can you show us an example of not using it? Absolutely! I would love to show you an example of not using that.
00:17:18.720 So, let’s go back to the tests that I prefer.
00:17:26.880 Here we go! This is an example of not using 'let'. Notice that each test builds up exactly what it needs inside itself.
00:17:35.520 These tests need fixing though—let’s address that issue.
00:17:43.000 The problem is that we're still encoding the values. Let’s fix the Law of Demeter violation and see what happens to the tests.
00:17:50.000 Okay, so we will come in here. For 'company name', rather than this, we’ll say, 'we’ve delegated that from user.'
Explore all talks recorded at Ancient City Ruby 2013
+3