Abstraction Can Make Your Code Worse

Abstraction Can Make Your Code Worse


Abstraction Can Make Your Code Worse

Support me on https://www.patreon.com/codeaesthetic. Access to code examples, discord, song names and more at https://www.patreon.com/codeaesthetic

Adding abstraction to your code always feels like the right thing to do. But when you add abstraction, you add coupling which can often undermine the value of the abstraction.

#programming #code #design #softwaredesign


Content

0.299 -> you have a game where you have a main
2.52 -> character enemy characters and obstacles
5.759 -> for each of these objects we need to
7.859 -> have code that keeps track of its
9.9 -> position in the world and code for
11.94 -> rendering the image for each object
15.12 -> we could write the same code in all
17.1 -> three classes but you recognize that
19.859 -> this is all similar so instead you make
22.619 -> a third class called game object that
25.26 -> handles this for you
26.88 -> you now have a general implementation
29.099 -> that tracks and renders out the object
31.26 -> the code is mostly identical but you
34.26 -> allow the subclass to specify which
36.96 -> image is shown
39.18 -> you just created an abstraction
42.63 -> [Music]
46.62 -> Architects have gotten really good at
48.84 -> this game
49.92 -> of identifying repetition and extracting
52.32 -> it out we get into the mode of code
55.32 -> repetition bad more abstraction good
58.5 -> but there's a hidden trade-off that
60.12 -> doesn't get considered coupling
62.82 -> most Engineers conceptually understand
64.619 -> what coupling is and they definitely
66.84 -> feel its web when trying to modify an
69.42 -> over coupled system but when designing
72.06 -> software you don't feel the impacts of
74.76 -> coupling
77.04 -> I consider coupling to be an equal and
79.56 -> opposite reaction of abstraction for
81.84 -> every bit of abstraction you add you've
84.18 -> added more coupling
86.22 -> let's explore an example
88.86 -> we have a program that saves out data to
91.2 -> XML but that's the old format so we want
94.56 -> to move to Json
98.34 -> we could do this by adding a
99.96 -> configuration to the save logic to
102.18 -> support both modes
103.43 -> [Music]
108.6 -> but this will make the removal of XML
110.7 -> complicated and dangerous
112.979 -> because they're all intermingled
117 -> so instead we'll make the Json writer a
119.579 -> separate class then we can just chop off
121.979 -> the XML support by deleting the whole
123.96 -> file not needing to unweave the program
126.299 -> logic
128.58 -> alright so now we've written our fancy
130.44 -> new Json writing class
132.48 -> we might notice that both take in a file
134.819 -> name during construction
136.62 -> our little repetition detectors go off
138.8 -> and realize that maybe maybe we could
141.959 -> extract this out
144 -> so our instinct is to create a common
146.04 -> class called file saver that just takes
149.28 -> a file name and our subclasses can grab
151.8 -> it from this protected variable
158.16 -> but this is a bad idea
160.26 -> we've now coupled both of these classes
162.599 -> to the same input
164.7 -> they must take file input so if there
167.22 -> ever became a need to create something
169.14 -> that didn't use a file like a database
171.959 -> or Cloud connection this would break the
173.94 -> abstraction
175.26 -> and on the flip side this abstraction
177.06 -> brings us no value
179.16 -> what does this abstraction save us
181.86 -> well I guess we don't need to assign the
184.019 -> variable twice but this isn't any
186.3 -> complicated logic it's simply assigning
188.64 -> a variable
189.78 -> so for me this squarely fits into the
192.18 -> not worth it camp
194.519 -> okay
195.599 -> now what about the save functionality
198 -> we could consider creating an interface
199.68 -> that represents the save method but we
202.14 -> do know that this would increase
203.04 -> coupling because now both of these
205.14 -> classes are constrained to the same save
207.18 -> method
209.519 -> so what benefits does this abstraction
211.56 -> bring us
212.64 -> well let's look at the usage
215.099 -> we have an if statement that decides
216.9 -> which class to create and calls save on
219.36 -> one of them
220.799 -> so if we add a common interface we only
223.56 -> get to remove this one duplicate save
225.84 -> line that doesn't simplify the program
228.18 -> in any meaningful way
230.58 -> so I'd also put this into the it's not
232.5 -> worth it camp at this point it's better
234.599 -> to keep these as two distinct classes
237.84 -> with no connection at all
240.959 -> there are two cases where it would make
243.06 -> me decide it was worth it
245.28 -> one would be if we added more save
247.14 -> options
248.34 -> if we had three or more we might want to
250.739 -> extract the construction of these save
252.54 -> objects into a separate piece of code
257.28 -> especially if the different Savers had
259.32 -> different parameters like a database
261.359 -> configuration
263.94 -> the other case would be if we needed our
265.979 -> program to defer or repeat saving at a
268.5 -> different point in the program
270.18 -> for example if we wanted to save every
272.88 -> five minutes automatically we'd create a
275.34 -> class called interval saver and it would
278.639 -> make sense for this interval saver class
280.32 -> to be unaware which saver is calling in
283.86 -> both cases it becomes worth it when we
285.479 -> want to separate the decision of which
287.28 -> saver we want from the time we actually
289.62 -> want to save
292.38 -> overall it's good to only apply
294.419 -> abstraction when the value it brings
296.58 -> overweighs the coupling this does mean
299.04 -> that you might have a little bit of code
300.479 -> repetition but I think that a little
302.46 -> code repetition brings less pain when
304.68 -> changing code than over coupling
307.02 -> what do you think

Source: https://www.youtube.com/watch?v=rQlMtztiAoA