Shadowing Practice: DRY Often Makes Your Code Worse - Learn English Speaking with Video

Creating lesson...
1
Here's some example code for normalizing email addresses and usernames.
2
There's two functions here that do that job.
3
And I have a main function that has a bunch of email addresses and users and then normalizes them.
4
Winner on this, then this is what we get.
5
Now, obviously, this code has quite a bit of duplication, right?
6
If you take a look at these function bodies.
7
So, naturally, we should apply dry.
8
Don't repeat yourself and remove it.
9
Let's do that.
10
So first I'm going to create a new function called normalize strings.
11
And this is going to get a list of items.
12
And it will return a list of strings.
13
Now we just need to pass in the various options that control how these strings are being normalized.
14
So should there be an add symbol?
15
Is there a minimum length of the string?
16
And a couple of other things as well that we can all see from these two functions.
17
So let me paste that in here like so.
18
So these are all the options that we have.
19
Then inside the function we can create the result which will be a list of strings.
20
Initially that will be empty and in the end this is what we're going to return.
21
And then we can go over the items in the list of items.
22
And then for For example,
23
if strip white space, we're going to strip the item.
24
And if lowercase, we're going to turn it into lowercase.
25
And similarly, we can go through all of these different options
26
and do whatever we need to do in order to take care of those.
27
we're going to append the item to the result and then we can return it.
28
And now that we removed all of this nasty duplication, we can now replace these calls with our new function.
29
So instead of calling normalize email addresses, we can call normalize strings.
30
And then we just need to pass the email addresses.
31
So for an email address, the require at symbol needs to be there.
32
We also want to split the add symbol and we want to strip the mail prefix.
33
And that gives us our normalized emails.
34
Then I can do the same thing for usernames.
35
So also here, normalized strings.
36
And then I pass the usernames.
37
The minimum length should be 3.
38
There we go and we also want to remove the at prefix like so.
39
And now when I run this code again, we get exactly the same results.
40
So what happened here?
41
There's less duplication for sure.
42
I removed most of it, but the code has become way worse.
43
The behavior currently is impossible to understand.
44
There is all sorts of flags that interact in non-obvious ways.
45
Every new requirement now means that we need to add another parameter to this very generic function that doesn't repeat itself.
46
So I may have removed duplication, but I also turned the code into a hot mess.
47
So what actually happened here?
48
Now, before I show you what is actually the right way to refactor this,
49
what I've learned over the years is that it's not just important that you know how software design principles and patterns work.
50
It's also important that you understand the trade-offs that are behind them.
51
And that's exactly what I go deep into in software design mastery.
52
This is not just another course with patterns and principles.
53
It's a comprehensive system for thinking about architecture, boundaries, trade-offs, long-term maintainability.
54
If you want to become truly confident in your design decisions, join the waiting list at rnodecodes.mastery.
55
The link is also in the video description.
56
So what does this teach us about dry?
57
Well, don't repeat yourself doesn't mean that you should merge anything that looks similar into a one function.
58
It's actually more about not duplicating knowledge and knowledge in code is in things like data,
59
rules, business logic, those kinds of things.
60
Now in the battery factor that I just did I purely focused on how the code was shaped.
61
I looked at if statements for loops and things like that and then tried to remove all of that duplication.
62
If you want to improve code don't just blindly apply a principle like dry.
63
You actually need to understand the code.
64
So let's try this again but now let's focus on behavior and responsibilities.
65
So I just threw out the bad refactor that I did and I went back to the original code.
66
So this is again what it looks like.
67
Let's analyze what is happening here.
68
So first thing is that these normalized functions actually do two things.
69
One which is filtering.
70
For example here if there is not an ad in address it's simply not going to consider it.
71
But we see the same thing happening in the username.
72
So there is filtering and there is normalization.
73
Now if we don't focus too much on trying to remove all the duplication, we can actually start splitting out this logic more, which is what makes way more sense when you want to improve the code.
74
For example, for the filtering bit, we can use another function to check whether an email address is actually valid.
75
So let's say we have function isValidEmail.
76
Let's get some address.
77
And this is going to give us a boolean value that determines whether this address is actually valid.
78
And that is actually where we can use this check.
79
So here we're going to return that there is actually an add sign in the address.
80
And then now we can write it like this.
81
So now we moved some of the logic, and this is still pretty simple, but we moved some of logic outside of the function
82
which is nice and we can do the same thing for the usernames.
83
So here the length of the username should be more or equal than three like so.
84
But now that we've split out this logic, we can take a look at, for example, this function and see if we can focus the responsibility a bit more.
85
Because currently, this is responsible for checking that an email address is valid by calling this function.
86
It's responsible for looping through a list of addresses and then actually doing the normalization process.
87
So those are actually way too many responsibilities.
88
So let's split up the responsibilities.
89
And again, I'm not thinking about duplication at this moment.
90
I'm truly just thinking about how to organize this code better.
91
And if I have to write a few extra lines of code for that, I don't really care about it.
92
So instead of having this function that normalizes all the email address in the list and also checks whether emails are valid,
93
let's create another function called normalizeEmailAddress.
94
That does basically the normalization job for a single email address.
95
This normalizes the address and will return that as a string value.
96
So then we can basically take this part like so and I'll put it in here and then we can refactor that.
97
So this actually should not be part of email address normalization.
98
So the first step is removing whitespace and turning it into a lowercase.
99
Then we get the local part and the domain.
100
We remove the prefix from the domain and then we're simply going to return this as a result.
101
So this is our normalize email address function.
102
And now actually normalize email addresses can be very simple.
103
Because we don't need all of this complication here.
104
We can even make this a lot shorter and just use a list comprehension.
105
And there we check if the email address is valid.
106
So now we turn this complicated function into something that's way simpler.
107
And for usernames we can do the same thing.
108
So here I'm also simply copying this, putting it in here.
109
We don't need the valid check here.
110
And I can simply return this as a result.
111
don't need to store it here.
112
And then also here in normalized usernames I can simply use a list comprehension.
113
Like so.
114
Let's run this to check whether this still works as expected.
115
Now when you take a look at this version of the code actually I didn't remove all the duplication
116
because that wasn't the focus I didn't focus on trying to remove duplication
117
and actually there is still duplication in here like normalizing email
118
addresses well this code looks a lot like normalizing the usernames
119
except it calls slightly different functions now you could decide to abstract
120
that away and make like a filter and process function
121
or something like that if you really wanted to but honestly to me this isn't that bad that there is some duplication.
122
However I did remove the right duplication in the sense
123
that validation rules like these kind of checks are now in a single place
124
and normalization rules are also in a single place
125
because they're grouped in these functions now they're not all mixed up
126
and by doing this it means that our control flow stays simple
127
and still readable even though there is still some duplication
128
and actually in many cases having some duplication in code is good these loops
129
or list comprehensions I don't really mind
130
that they're duplicated it's they're pretty cheap it's not many lines of code it's easy to read
131
but more importantly duplication can sometimes help you enforce boundaries for
132
example you may also encounter duplication sometimes in your api right
133
you might have a database schema you might have an api output schema these are going to be very similar
134
so you might be tempted to use the same object for
135
that maybe if you're using sql model or something but that couples your API directly to your database, your persistent layer.
136
By keeping them separate you avoid leaking database concerns into your API
137
and it gives you flexibility to evolve each of these independently.
138
So there is some duplication in that case there but repeating yourself is actually protecting your design in that case.
139
So overall when you're working on code like this I'd say prefer duplication over the wrong way of abstracting things.
140
Look for duplicated rules not duplicated loops and try to fix those.
141
If you notice
142
that you need to add a bunch of flags in order
143
to remove the duplication from the code that's probably a red flag, pun intended.
144
So instead focus on truly understanding the code.
145
You'll be way better at organizing the code more effectively.
146
And what I typically do when I write code whether that's me
147
or some AI coding agent is
148
that I start writing I don't really think about how it looks I copy things around
149
when I need them but when I notice
150
that there is actually duplicated rules then I might abstract things away
151
so abstraction is a consequence of writing the code
152
and copying things around I don't start there
153
when using a tool like cloud code you can just let it write all the code
154
but then you do need to take that step of understanding the code
155
that it grows and seeing if you can abstract away a couple of things
156
and by the way
157
if you enjoy these types of design videos give a video
158
a like subscribe to the channel it helps me reach more people here on youtube
159
so finally dry don't repeat yourself is not a wrong principle
160
but it's really easy to misuse it's easy to think
161
that you should somehow not have any duplication in the logic That's not what it means.
162
The key thing is that you understand the code and
163
that you abstract away the right things so that they're properly separated and that knowledge, data, business logic is not duplicated in your code.
164
If you do it blindly, just start refactoring and moving things around, you'll often end up in a worse place.
165
You need to understand it and that leads to better abstractions.
166
But I'd like to hear what you think.
167
Do you apply the dry principle yourself to code?
168
Do you tend to over abstract things or do you tend to keep duplication around much longer?
169
Have you ever tried to refactor something removing duplication and it completely backfires?
170
Let me know in the comments.
171
Now, if you want to explore more software design videos, check out my design patterns playlist right here.
172
Thanks for watching and see you next time.

Context & Background

In the video titled "DRY Often Makes Your Code Worse," the speaker discusses a common programming principle known as DRY, which stands for "Don't Repeat Yourself." While emphasizing efficiency in code, the speaker emphasizes the importance of balancing code clarity with the reduction of duplication. The discussion illustrates how applying this principle can sometimes lead to more complex and less understandable code, a lesson valuable not just for software developers but also for anyone learning how to effectively communicate, including English learners.

Top 5 Phrases for Daily Communication

  • Normalize email addresses - Understanding this phrase can enhance your vocabulary related to technology and communication.
  • Strip white space - A technical term that can also apply to the editing of text.
  • Append the item - This phrase is crucial in both coding and in speaking clearly when presenting ideas.
  • Needs to be - A versatile phrase used in various contexts to express necessity.
  • Return the result - This can help you articulate conclusions or final thoughts in discussions.

Step-by-step Shadowing Guide

Using a shadowing technique can significantly help you improve English pronunciation as you tackle the more complex phrases used in programming contexts. Here’s how you can apply shadow speak while watching this video:

  1. Choose a Shadowing App: Select an app that allows you to record your own voice or one that lets you repeat phrases at your own pace.
  2. Listen Actively: Play sections of the video and listen carefully to the speaker's pronunciation, intonation, and rhythm. Focus on the technical phrases mentioned above.
  3. Repeat Aloud: Use the shadowing technique by repeating the sentences just after you hear them. Ensure that your pronunciation matches that of the speaker.
  4. Record Yourself: After practicing, record your voice to assess your improvement and pinpoint areas needing more work.
  5. Review and Reflect: Listen to your recordings alongside the original video to understand your progress and adjust your pronunciation accordingly.

By incorporating these steps, you enhance your learning experience and effectively prepare for technical discussions, making your communication more precise and impactful.

What is the Shadowing Technique?

Shadowing is a science-backed language learning technique originally developed for professional interpreter training and popularized by polyglot Dr. Alexander Arguelles. The method is simple but powerful: you listen to native English audio and immediately repeat it out loud — like a shadow following the speaker with just a 1–2 second delay. Unlike passive listening or grammar drills, shadowing forces your brain and mouth muscles to simultaneously process and reproduce real speech patterns. Research shows it significantly improves pronunciation accuracy, intonation, rhythm, connected speech, listening comprehension, and speaking fluency — making it one of the most effective methods for IELTS Speaking preparation and real-world English communication.