
The reusability fallacy – Part 3 - galaktor
https://www.ufried.com/blog/reusability_fallacy_3/
======
ivanbakel
>The latest paradigm “Microservices” became popular in the mid 2010s.

Microservices isn't for re-usability. It's main benefit is better
encapsulation, which should let you do independent resource
management/deployments/failures.

>If we look at reusability, we notice that this is the tightest form of
coupling possible: If the reused part is not available, the reusing part
cannot complete its work by definition.

What? This is a weird nothing-burger of a sentence. Why can't multiple
components re-use some resource without gracefully handling any failures? Why
does re-usability mean "cascading failures by design"?

>An important property of reuse is that the reusing part ... does not work
without the reused asset ... The reused functionality is an integral part of
the solution that (re-)uses it.

Oh, I see: because the author has defined it this way. Then the article goes
on to try to argue a semantic difference between "usability" and "re-
usability", in that usable components can be re-used independently, but in a
way that can gracefully fail! So the whole thing is just begging the question.

There's no argument here as to why I can't write a distributed component with
an eye to it being re-used in the future. There is no criticism of re-use in
distributed systems. The only criticism is of tight coupling, which is totally
valid, and then saying that re-use _demands_ tight coupling, which is not
substantiated.

~~~
derefr
I think the concept the author is talking around here can be stated more
simply:

When you _refactor_ software to reduce duplication, you _by default_ are
increasing coupling.

At the start, you some lines of code that were just sitting in the bodies of
two different functions. Now, both of those functions call one shared
function. But, in a proper minimal-change refactoring, you didn't change the
semantics of the code by doing this. So the shared function is still acting
the way that its parents did: as sets of lines sitting in the bodies of
functions. There's no circuit breaking or graceful failure there, because
there was no circuit breaking or graceful failure in the original, non-
refactored code.

Another way to put this is: compression makes data more fragile, in the sense
that small numbers of bits can be "depended on" by more bits in compressed
data than in uncompressed data. Direct duplication-elimination refactoring is,
essentially, just compression.

To actually get robustness, you can't just do this kind of refactoring and
then stop; you have to continue on and introduce a stable API to your
factored-out function/component/service, with a specified interface. Once you
do _that_ , then you cancel out the increase of coupling, because now
everything is just coupled to a description of the interface. _Then_ you get
the ability to re-use the function/component/service. Until you do that,
though, you just have something that is known to work exactly in the use-cases
it was extracted from; and which _shouldn 't_ be expected to work anywhere
else.

~~~
ivanbakel
I'd agree with you for this post, minus the weird re/usability semantics, but
that interpretation goes against the previous parts of this series.

If you read Part 1, the argument is largely against _even well-architectured_
versions of re-usability. The author takes issue with all components designed
for drop-in future use, believing that each problem requires a tailor-made
solution.

The re/usability debate seems weirdly entangled with the coupling debate for
no good reason. The author believes re-usability means tight coupling, and
"usability" means good APIs with loose coupling (which can be re-used...).

------
discreteevent
Szyperski also said this back in 1997. "Maximizing reuse minimizes use"

[https://books.google.ie/books?id=U896iwmtiagC&pg=PA45&lpg=PA...](https://books.google.ie/books?id=U896iwmtiagC&pg=PA45&lpg=PA45&dq=maximize+reuse+minimise+use+szyperski&source=bl&ots=FH0S7vrsaI&sig=ACfU3U1xIujcH8XOMiFlg7lXUWS4KHaR7g&hl=en&sa=X&ved=2ahUKEwiU7ufNyr3oAhVKSBUIHaXgBxEQ6AEwCnoECAUQAQ#v=onepage&q=maximize%20reuse%20minimise%20use%20szyperski&f=false)

------
galaktor
Part 1:
[https://www.ufried.com/blog/reusability_fallacy_1/](https://www.ufried.com/blog/reusability_fallacy_1/)

Part 2:
[https://www.ufried.com/blog/reusability_fallacy_2/](https://www.ufried.com/blog/reusability_fallacy_2/)

Part 1 was posted previously but without much discussion:
[https://news.ycombinator.com/item?id=22583605](https://news.ycombinator.com/item?id=22583605)

------
whack
The "fallacy" breaks down pretty quickly when we consider its implications. If
we were to follow the suggestions given, we shouldn't be using:

\- Email services such as SES or Sendgrid

\- Password auth services such as Firebase

\- Chat services such as Twilio

You might say those are extreme examples, and that's the whole point. Clearly
there are a ton of use-cases where it makes sense to build reusable services
once, and using it across many clients. Not just for "enhancements", but as an
integral part of your service's functionality. So how and where do we draw the
line between reusable services and avoiding service-dependencies? That's the
real question we should be asking, and one I don't see being answered in the
article.

~~~
meheleventyone
I look at it like this. It’s super useful to have a screwdriver that has an
adaptor that will take many different kinds of bits. It would be super painful
to have a really configurable bit that could with some work fit any screw.

My exemplar is a library for doing things with grids. It supported any kind of
2d grid. It was an amazing piece of design from a conceptual standpoint. Super
generic, clean and with some impressive demos doing very non-standard things.
It was also much easier for me to write my own grid implementation for my
usecase than learn how to use.

Being reusable because you do something well is great. Being “reusable”
because you can be made to do one thing out of a bunch once you learn how is
not. From a business point of view it’s about how valuable that flexibility is
and generally I think if it’s not part of the core business you are better
finding an inflexible fit rather than a flexible thing you have to sculpt to
work. Simply because the latter takes focus away from what you are actually
trying to do.

~~~
jodrellblank
> _It would be super painful to have a really configurable bit that could with
> some work fit any screw._

Why would it? Universal sockets exist: [https://images-na.ssl-images-
amazon.com/images/I/61UczrhrTuL...](https://images-na.ssl-images-
amazon.com/images/I/61UczrhrTuL._SY355_.jpg) \- I can imagine one built with
small enough pins to push into/around any kind of screw head, although I don't
know if one exists today.

~~~
meheleventyone
The super complex generic grid library is also probably useful for someone but
I’d say neither case is more universally useful due to the complexities
involved.

------
danielovichdk
I think about reuse in a couple of different ways.

I do not copy paste the same exact code multiple places. Then i use the same
code.

If the code is not exactly the same, it's not a copy, hence it's not up reuse.

I do not generalize code before 3rd strike and refactor can be applied, and
then I still use a lot of time thinking if it might a premature optimization.

I write microservices the same way as i write methods. If i copy and paste the
exact same microservice, it might be up for reuse (3 strikes). If it's reuse,
the same specifics applies as when programming a method or type.

I would never ever write any new code with reuse in mind. It's arrogant to
think one can forsee the future, and that's exactly what writing for rejse is
about. Start small, evolve.

------
nikanj
Java has the opposite problem. One of the often repeated taglines is "If
you're unhappy with X, you can easily replace it with Y, Z, or Q!"

I just want one well-working thing, not twenty alternatives - seven of which
turn out to be abandoned, three incomplete, one only works with Java 15 beta,
and two are actually forks of the same abandoned pre-Oracle blogpost from Sun.

~~~
lonelappde
Java has that "problem" because it is in wide use, and Java is good at
compatibility. Any popular tech is going to have many variations

------
6510
Like my own his English is good but not _that_ good. His seems the right way
to explain (there probably is a formal description for the style of writing
(and a word for it in German)) but when reception is not guaranteed (I keep
feeling like I almost got his point.) I would lower myself to explaining by
code example. Something like a "hello world" of usable vs re-usable. Someone
more skilled in the art should probably address note 6 (
[https://www.ufried.com/blog/reusability_fallacy_3/#fn:6](https://www.ufried.com/blog/reusability_fallacy_3/#fn:6)
)

I did recall a thought I had some years ago that I will describe crudely
because I'm lazy:

Parts of applications, by popularity, should be re-implemented in API's.

Parts of API's, by popularity, should be implemented in modules.

Parts of modules, by popularity, should be implemented in frameworks.

Parts of frameworks, by popularity, should be implemented in (higher)
languages (then lower)

Parts of languages, by popularity, should be baked into hardware.

(Unpopular parts should migrate the other way around but that is not important
right now)

------
galaxyLogic
What do we mean by "software reuse"? I propose this definition: Software reuse
happens whenever a given piece of code is called from more than one other
code-location.

That means whenever a function has more than one caller we have reuse. Or when
a web-service request is created from more than one code-location, we have
reuse.

Is there an official definition for what "software reuse" means?

------
m3kw9
From my experience actual good reusable code are very small and usually
relatively simple great specialized task. As the component get more features,
and when you use it, you are in a trade off situation where this works, but it
doesn’t fully do exactly what the requirement needs orbit does way more than
it needs

