
Software reuse is more like an organ transplant than snapping Lego blocks (2011) - nilsandrey
https://www.johndcook.com/blog/2011/02/03/lego-blocks-and-organ-transplants/
======
_bxg1
This makes me realize: the one example I can think of where software has been
"Lego-like" is Unix piping. I'm not a Unix purist or anything, but they really
hit on something special when it came to "code talking to other code".

Speculating about what made it stand apart: it seems like the (enforced)
simplicity of the interfaces between pieces of code. Just text streams; one
in, one out, nothing more nothing less. No coming up with a host of parallel,
named streams that all have their own behaviors that need to be documented.
And good luck coming up with a complicated data protocol built atop your text
stream; it won't work with anything else and so nobody will use your program.

Interface complexity was harshly discouraged just by the facts-on-the-ground
of the ecosystem.

Compare that with the average library interface, or framework, or domain-
specific language, or REST API, etc. etc. and it becomes obvious why
integrating any of those things is more like performing surgery.

~~~
crimsonalucard5
Unix piping is basically functional programming.

If you ever wondered why some people are obsessed with functional programming
this is the reason why:

Functional programming forces every primitive in your program to be a Lego
Block.

A lot of functional programmers don't see the big picture. They see a sort of
elegance with the functional style, they like the immutability but they can't
explain the practical significance to the uninitiated.

Functional Programming is the answer to the question that has plagued me as a
programmer for years. How do I organize my program in such a way that it
becomes endlessly re-useable from a practical standpoint?

Functional programming transforms organ transplantation into lego building
blocks.

The "lego" is the "function" and "connecting two lego blocks" is "function
composition".

In short, another name for "Point free style" programming is "Lego building
block style" programming.

~~~
xvedejas
You can't just compose two functions because they're both written in a
functional programming language. The programmer has to have the foresight to
make their types compatible. I think the novelty of the Unix pipe for
interoperability is that they (typically) work on one agreed-upon kind of
data: human readable, white-space separated. So a lot of tools "just work"
with each other.

There's no reason you can't do this with functional programming, but obviously
you can do it with non-functional programming too, and you could certainly
fail to do this with functional programming.

~~~
hencq
Nicely put. That aligns very nicely with the philosophy behind Clojure and for
instance less so with Haskell. In Clojure you usually use only a few data
types, often (immutable) hashmaps. A program then simply becomes a series of
functions that transform data.

~~~
platz
Anytime someone mentions a nice thing about Haskell, you can be sure a Clojure
programmer will appear shortly, without being previously referenced, to try
and disparage them.

~~~
adamkl
Not sure where the hostility is coming from. I didn’t read anything
disparaging about Haskell in hencq’s comment. He/she just made a factual
statement about Clojure’s approach to data types being analogous to
Unix/strings when it comes to composition.

It comes with the same drawbacks (the lack of static typing is similar to
strings with Unix; you have to be aware of the details of the data coming in
and out because there is no type system to save you - unlike Haskell), but the
benefit is easier composition.

~~~
hencq
Yeah, I didn't mean anything disparaging about Haskell at all. I only
mentioned Haskell as an example of a functional programming language. I tried
to make a point (apparently poorly) about the easy composition that using a
limited number of (dynamic) types enables. Of course all the usual dynamic vs
static tradeoffs apply. Thanks for doing a better job explaining that :-)

~~~
crimsonalucard5
I don't think dynamic typing or static typing really applies.

In either case you have to compose functions With the correct types otherwise
you hit an error. The difference with dynamic types and static types is when
this error occurs. Run time for dynamic types and compilation time for static
types. Either way some type of error will always occur regardless.

Though I agree with you if you have a limited number of types things become
easier to deal with.

------
dmlorenzetti
One thing I appreciate about John D. Cook's blog is that he doesn't feel the
need to pad out what he wants to say.

Here, he had a thought, and he expressed it in two paragraphs. I'm sure he
could have riffed on the core idea for another 10 paragraphs, developed a few
tangential lines of thought, inserted pull quotes -- in short, turned it into
a full-blown essay.

Given that his blog serves, at least in part, as an advertisement for his
services, he even has some incentive to demonstrate how comprehensive and
"smart" he can be.

His unpadded style means I'm never afraid to check out a link to one of his
posts on HN. Whereas I will often forego clicking on links to Medium, or the
Atlantic, or wherever, until I have looked at a few comments to see whether it
will be worth my time.

~~~
partyboat1586
"I enjoy that John D. Cook doesn't pad his posts."

~~~
Accujack
He's a concise blogger.

~~~
kyawzazaw
He blogs concisely.

~~~
Wingy
cncse blg

------
agentultra
Haskell is much closer to the lego blocks analogy than most languages I've
tried due to the focus on composition and polymorphism.

The teetering edge that grinds some people's gears are monads which don't
compose generally but _do_ compose in specific, concrete ways a-la _monad
transformers_. The next breakthrough here, I think, is going to be the work
coming out of effect systems based on free(r) monads and delimited
continuations. Once the dust settles here I think we'll have a good language
for composing side effects as well.

In the current state of things I think heart-surgery is an apt metaphor. The
lego brick analogy works for small, delimited domains with denotational
semantics. "Workflow" languages and such.

~~~
jkachmar
I like Haskell, I write Haskell at my day job (and did so at my previous day
job), and I help maintain some of the community build infrastructure so I’m
familiar with a large-ish graph of the Haskell ecosystem and how things fit
together.[0]

I don’t really think Haskell is _meaningfully_ superior than other languages
at the things that OP is talking about.

Refactoring Haskell _in the small_[1] is much nicer than many other languages,
I don’t disagree on that point. Despite this, Haskell applications are _just
as susceptible_ to the failures of software architecture that bind components
of software together as other languages are.

In some cases I would even suggest that combining two Haskell applications can
be _more_ fraught than in other languages, as the language community doesn’t
have much in the way of agreed-upon design patterns that provide common idioms
that can be used to enmesh them cleanly.

[0] I’m mostly belaboring these points to establish that I’m not talking out
of my ass, and that I’ve at least got some practical experience to back up my
points.

[1] This is to say when one refractors individual functions collections of
interlocking abstraction

~~~
fabianhjr
WAI is a great example on the sort of compat/interop interfaces that are more
common and easier to rollout in Haskell than in non-(typed functional)
languages.

[https://github.com/yesodweb/wai](https://github.com/yesodweb/wai)

~~~
zxcmx
Like WSGI or RACK?

What things make WAI easier than the equivalent abstraction in
$other_languages?

(Not going for a "gotcha" tone here, genuinely interested as a person who has
tried and failed a few times to write "useful" software in Haskell. Would like
to get there one day).

~~~
jkachmar
A WAI `Application` is defined as the following type alias:

    
    
      type Application =
        Request ->
        (Response -> IO ResponseReceived) ->
        IO ResponseReceived
    

...which is to say that WAI applications are “just” functions that accept an
incoming request and a callback that turns that request into a response object
(which may emit side effects), and which return a respond object (which may
emit side effects).

This leads to a very nice definition for middleware as the following type
alias:

    
    
      type Middleware =
        Application ->
        Application
    

...which says that any WAI middleware is just a function that turns one
application into another.

This means that WAI applications have a nice and easy to understand top-level
interface, and that complex chains of WAI middleware can be built up by
chaining smaller middlewares together.

The potential benefit here (over other language frameworks) is that the
“grammar” being used to describe applications and middleware is the same
“grammar” that’s used in most other Haskell applications (i.e. function
composition). Ideally, this should make it more easily understandable to a
Haskell practitioner who might not be intimately familiar with the framework
at first glance.

~~~
acidbaseextract
Not to be trite, but uh... like WSGI or Rack?

~~~
agentultra
I think the specifications are functionally equivalent and differ only in
their approach. I think WAI is influenced directly by WSGI/RACK.

------
nradov
And yet back in 1993, Visual Basic programmers were able to reuse software by
literally snapping together controls like Lego blocks. There was a rich
ecosystem of third-party controls. Competing tools such as Delphi had similar
features. Since then the industry has gone backwards, or at best sideways, in
many areas.

~~~
old-gregg
I wanted to make a similar point with piping UNIX commands. I can think of two
reasons why the degradation happened:

1\. Expansion of the software universe. Back in VB6 times, there were fewer
programmers but many languages. Reusing components made with different
languages was a big deal (VB used COM/ActiveX machinery to make this
possible), but today there are so many more developers, that each
language/ecosystem is big enough to exist on an island and happily not
interact with anything unless it's a grpc/rest endpoint.

2\. Transition to SaaS. We no longer use the same platform for building and
running. Your VB app used to run on more or less the same computer it was
built on. SaaS applications run in weird, custom-made, hard to reproduce and
fragile computers called "environments". They are composed from all kinds of
complex bits and this makes SaaS applications less portable. Frankly, they
feel more like "environment configuration" than "code" sometimes.

~~~
pjc50
The SaaS expansion _could_ make componentisation easier - it would just be
microservices, but from different companies. Somehow it doesn't. Possibly
because it's not in their interest to do so.

On the other hand .. look at how much software goes into e.g. car
entertainment systems. How many systems have "curl" in, for example. Have a
look at the vast list of BSD license acknowledgements in many systems.

Look at the npm ecosystem, where people complain that there's _too much_
componentisation.

~~~
old-gregg
Microservice has no new meaning (although a few content marketing teams may
disagree). It's just a process with an input and output. Building applications
consisting of multiple processes has been possible since forever. I would even
argue that piping multiple UNIX commands together is a valid example of
microservices :)

------
ChrisMarshallNY
How about modding cars?

It's neither as bad as an organ transplant, nor as easy as LEGO.

It is also highly variable, dependent upon the SDKs and API choices.

I've written SDKs for decades. Some are super simple, where you just add the
dylib or source file, and call a function, and other ones require establishing
a context, instantiating one (or more) instances, and setting all kinds of
properties.

I think it's amusing, and accurate, in many cases; but, like most things in
life, it's not actually that simple.

~~~
seph-reed
In a word: "Engineering"

~~~
skwb
If only there was a specific job title for people whose primary job was to
"engineer" software.

~~~
ChrisMarshallNY
There seem to be many definitions of _" Engineer."_

I consider myself to be an "Engineer," but I forgot all my calculus, many
years ago (atrophied). There are those that assume any "Engineer" must know
calculus.

I consider myself to be an "Engineer," but I fail miserably at most of the
binary tree employment exams. There are those that assume that any "Engineer"
must know binary trees (I never came up through a CS curriculum, and, in 35
years of coding, I have never run into one single binary tree).

I consider myself to be an "Engineer," but have never sat for any kind of
board exam. There are those that assume that any "Engineer" should have at
least one board certificate on their wall.

I consider myself to be an "Engineer," but hold no college degree or
certificate even remotely connected to software development. There are those
that assume that any "Engineer" should have at least one "Engineering"
sheepskin on their wall.

What I _do_ have, however, is 35 years of consistently _delivering_ (as
opposed to just "writing") software products. Not all were ones that have made
me proud, but I have always been about "ship." I still keep that up, today,
even for free, open-source projects.

I have _Discipline_. _Lots_ of Discipline. I write reasonably efficient,
localized, accessible, error-checking, high-quality code, that can be
maintained after I move on.

I practice Configuration Management.

I have a consistent coding style.

I have consistent processes, even though it may seem as if I am "shooting from
the hip." I write about that here:
[https://medium.com/chrismarshallny](https://medium.com/chrismarshallny)
(several articles cover my process).

I try to keep up with current, _practical_ technology without getting sucked
into the "buzzword maelstrom."

I practice and support Usability, Localization, and Accessibility in my work.

I take all that extra time to make sure that my code is "ship" code; not just
"code." That means lots of really boring stuff that always takes a lot longer
than I'd like.

I test my code six ways to Sunday (My testing code usually dwarfs the product
code. I write about that here: [https://medium.com/chrismarshallny/testing-
harness-vs-unit-4...](https://medium.com/chrismarshallny/testing-harness-vs-
unit-498766c499aa)).

I document the living bejeezus out of my code (I write about that here:
[https://medium.com/chrismarshallny/leaving-a-
legacy-1c2ddb0c...](https://medium.com/chrismarshallny/leaving-a-
legacy-1c2ddb0c8014)).

I have always stood behind my code; taking Responsibility and Accountability.
Never lying, and admitting (and fixing) failings, learning from those that
went before me; while treating my superiors, peers, and subordinates with the
utmost respect.

I have always been keenly aware of the way that my customers used my code, and
have always welcomed negative feedback (I write about that here:
[https://medium.com/chrismarshallny/the-road-most-traveled-
by...](https://medium.com/chrismarshallny/the-road-most-traveled-
by-9a66249bbfd6) -scroll down to "Negative Feedback Is Incredibly Valuable").

I am not afraid to admit ignorance, or ask questions. Almost every project I
start, I don't know how to do. I write about that here:
[https://medium.com/chrismarshallny/thats-not-what-ships-
are-...](https://medium.com/chrismarshallny/thats-not-what-ships-are-built-
for-595f4ae2c284)

Apparently, my employers also considered me to be an "Engineer," despite these
awful failings. I had them fooled, eh?

~~~
the-dude
Lots of I

~~~
ChrisMarshallNY
Yup. I learned not to use "you" very much on teh internets tubes. People
like...well... _you_...don't like being dictated to.

I've learned the value of speaking from personal experience, as opposed to
vague, hand-wavy, often passive-aggressive, "keyboard warrior" stuff.

I find that personal _experience_ , and personal _ethos_ tends to be a lot
more relevant to most folks, over personal _opinion_ , especially when it is
applied as a projection.

In fact, one of my editing disciplines is to do a search-and-replace for "you"
and replace it with "I" or "me."

You'll see a lot of "we," "us," and "our" in my writing, as well.

 _FUN FACT: Did you know that I nuked a number of passive-aggressive slaps
from this posting? I 'm a really experienced troll. I have made it a point to
change my stripes. One way that I am doing this, is putting my brand and
personal information behind everything I post._

------
DivisionSol
When I’m working with Unix utilities like grep or doing stuff with xargs... it
genuinely feels like I’m playing with legos.

I feel like this is trying to argue for more “consulting surgeons” when we
need more “tooling machinists” who know how to make a good LEGO block.

~~~
catalogia
xargs/etc are like arcane legos, where there's more than one brick vendor in
the mix with different vendor's versions of the brick supporting different
features, or the same feature but implemented in different ways. And even if
you're only dealing with one brick vendor, there's still little uniformity in
the interfaces of different bricks. GNU vs BSD xargs, -0 vs -print0, etc.

True lego have the property that if two parts snap together, it's a valid
configuration. That's definitely not the case for unix utilities. You have to
read a manual for each sort of brick.

~~~
buzzkillington
I love unix for what it was. But it made a lot of concessions for 70s hardware
that we're stuck with.

It is rather unfortunate for us that everything that's come afterwards has
been in some way even worse.

------
mynegation
This is an astute metaphor. In my experience software reuse simplicity
strongly depends on the following factors:

* interface surface area (i.e. how much of an interface is exposed)

* data types of data coming in and out (static or dynamic). Static languages have an advantage here as many integration constraints can be expressed with types.

* whether it is a very focused functionality (e.g. extracting EXIF from file) vs cross-cutting concerns (e.g. logging)

The more limited surface area, the simpler the data types and invariants, the
more localized it is - the more it is like LEGO as opposed to an organ
transplant

------
jackhalford
For reusing software source I agree. The only current way around this is with
the unix pipe system where you reuse software _executables_ instead of
software _source code_

The reason it works is because unix softwares agree to a simple contract of
reading from stdin and writing to stdout, which is very limiting in terms of
concurrency but unlocks a huge world of compatibility.

I wonder if we will ever get software legos without the runtime bloat from
forking.

ps: to anyone countering with examples of languages that are reusable through
modules, that doesn't count because you are locked in to a given language.

~~~
meatmanek
> I wonder if we will ever get software legos without the runtime bloat from
> forking.

In a sense, shared object files / dynamically linked libraries meet this
criteria -- they can be loaded into program memory and used by a single
process.

There's also flowgraph-based signal processing systems, like gnuradio, which
heavily use the concept of pipes (usually a stream of numbers or a stream of
vectors of numbers) but, as I understand it, don't require OS forking. (Though
they do implement their own schedulers for concurrency, and for gnuradio at
least, blocks are typically shipped as source so I'm not sure whether that
counts as reusing executables vs. reusing source code.)

------
davedx
IMHO conflating “systems” and “components” here. Module and package management
has never been better and building “a system” from components, open source or
otherwise, is extremely effective. Integrating software systems (with e.g.
API’s, webhooks and event busses) is non-trivial, complex and difficult. They
are not the same endeavor.

~~~
lostcolony
Really depends.

Building a system from components can be quite tricky, as the components tend
to only play nicely together if they've been built for one another, or to some
agreed upon spec. Otherwise you have to be very fluent in all of them, and
write glue code. And there be dragons.

APIs tend to be all over the place, yes, but you can have a well defined API
spec that really can allow specific implementations to be swapped out fairly
trivially, such that it really is more like 'components'. Think SQL, for
instance.

I think you may just be noticing that when things adhere to a spec, they tend
to be able to combined pretty easily; if not, they don't.

------
someguy101010
It really depends on the complexity of the software doesn't it? Libraries and
packages often snap into my projects easily and without much modification at
all, especially if I'm planning on using them. I can see this analogy working
for more complex projects though, where you may be copy pasting code from on
project to another and trying to make it fit together.

~~~
julianlam
With significant enough abstraction and a sensible public API you can make
this claim, but more often than not you end up needing to dive into the
internals to hook things up properly.

------
milansuk
This is exactly what I'm working on right now. My approach is a little bit
different. It's about building a community, where people share LEGO pieces(I
call them Assets), but they also share where and how in the code they've made
the connections. After some time there will be enough connections so users
will just re-use them. Only time will show how well it will work.

I wrote about it few weeks ago:
[https://skyalt.com/blog/dsl.html](https://skyalt.com/blog/dsl.html)

>I have a plan on how to do that on paper, but because connecting assets
together can be complex, it's better If most of the users don't do that. The
key thing is that users don't share only assets, but also how and where they
are connected to each other. It's like when someone makes and publishes a
library, but also example code for how to work with a library. But in SkyAlt,
asset connections will be automated. This is also why it's very important to
build and grow the community - more assets, more connections, which means
easier to use.

~~~
hellodanylo
Do users have incentive to document and share the connections, other than
helping the community's long term goal?

Absence of such incentive appears to be the reason that open-source software
is not always perfectly connectable -- few people have a significant incentive
to ensure this design goal.

~~~
milansuk
I'll launch it in a few weeks, so right now I don't know.

I believe that in the future the most of software will be open-source and If
people don't have a problem sharing blocks/widgets/assets, they will not have
a problem to share information about connections.

Side note: Every program has 2 parts - instructions and data. When people
share assets and connections, both are instructions, so their data stay
private.

------
kstenerud
Software re-use is limited by the primitive structures and algorithms in the
language and runtime library. The more fundamental parts (queues, strings for
example) that are left to the user to implement, the less likely it is that it
will be possible to make compatible components.

------
rbosinger
I feel like if even on a purely technical level we eventually achieve Lego
like reuse that the business and social layer of things will ensure that
somebody always requires an off brand Lego block to be shoved in there. It's
almost human nature.

------
daenz
The reason for this is that LEGO has a tightly regulated interface that each
piece must adhere to. This interface regulation doesn't exist in software to
that degree, nor is it necessarily desirable.

------
petermcneeley
Well designed modular software is certainly like Lego. It just takes
investment. It is a choice to have organ transplant software be the default.
That choice is non investment.

------
shadowgovt
Depends on the software. Or to torture the analogy a bit: you can build
anything out of LEGO if you're willing to use a jigsaw, some Gorilla glue, a
blowtorch...

The point of frameworks is to provide the standardization of the "shape" of
various bits of software so it's a lot more like snapping together LEGO. But
even then, LEGO isn't universally snappable; some blocks just don't click to
other blocks in the product line. And then, of course, there's the "illegal"
block hacks ([https://crafty.diply.com/28429/14-illegal-lego-building-
hack...](https://crafty.diply.com/28429/14-illegal-lego-building-hacks-to-
pass-on-to-your-childrens-chil)) that work in practice but are not at all
using the tool the way it's specified. When software reuse _is_ like LEGO, we
should expect (a) some things we want to do, we can't really do without
jigsaws and glue and (b) sometimes, people _will_ do things that the software
technically allows but no sane person would call "desired" or "intended."

In fact, the LEGO-to-framework analogy works pretty great. And yeah, outside
the context of a consistent (and, I'd argue, opinionated) framework, you're
about as likely to have two pieces of software interoperate as you are likely
to pick two random chunks of matter in the universe, slap them against each
other, and have anything useful happen. I just tried it with a brick and this
glass of water on my table. Now I have "wet brick in a pile of shattered
glass," but I don't know anyone's going to give me a Series-A funding round
for that.

------
runningmike
Reuse of my own sloppy code is always easy. But reuse of complex code created
by others is often far more difficult since context is missing. Creating god
reusable software code block, are often the lower level apis The more context
specific software is, the harder reuse gets. It’s the pain of generic vs
context specific imho.

------
solidist
Fred Brooks had a similar take, in an opinionated way, with the concept of
"lead surgeon". Motivation to re-read the chapter in mythical man-month.

------
orenkt
So. Every editor has copy/paste functionality and search/replace. Using that
plus following the SOLID principle is my way to reuse code. And it is as if I
would build with LEGO bricks.

I tell you even a secret. Every piece of software has all the code you need to
work with it already - just copy/paste stuff. You only need to know where it
is. Every piece of software is it's own tutorial how to make that particular
piece of software.

I've done this for years. I call my method of working copy/paste method.

And by reading this, I think I know why I piss so many programmers when I say
what I do. And how fast I am with it.

------
bpyne
Someone well-known in the IT field wrote about software reuse in the large vs.
in the small about 10-15 years ago. The gist was that reuse in the small is a
success, i.e. it's fairly simple to write a function that developers reuse
within an application. When you try to generalize use beyond a certain context
it becomes significantly more complicated to be successful. I think the
motivation for the post was issues in object reuse in OO development. I'm
trying to find the original post.

John D. Cook's post shines the light once again on the difficulty of writing
reusable components.

~~~
hikarudo
I would love to have a link to that piece about software reuse in the large vs
in the small!

------
medymed
I would say software integration is more like a docking mechanism between
spacestation units that were designed in isolation by different countries than
like snapping LEGO blocks. At least software pieces are products of human
design and failure points can be identified without the many inscrutable
emergent phenomena and often-unmeasurable unknowns of biology.

------
jmiskovic
Lego is general graph structure. Our programs have roughly star topology -
bunch of libraries and some control logic that drives it. Good libraries _are_
like snapping Lego blocks. Those have good scope around domain, well designed
API and establish abstractions that don't leak. Think sqlite, zeromq, zlib.
The central controlling part is too "involved" in domain and chosen tech stack
to reuse easily.

The software that requires organ transplant just wasn't written to be reused.
It is a matter of effort and cost. You cannot just solve your problem and wrap
it in a library - you need to take care of all common use cases, define edge
case behavior, test, document... It costs a lot more and that price is hard to
justify. In the end it's the product that makes money and library is forgotten
as long as it does its job. We need to fix the open-source income ecosystem.

------
pragmatic
I disagree.

Never has it been easier to find existing code, download it and snap it into
your project. Npm, nuget, etc, etc.

Also, on the front end there are no shortage of plug and play widget
libraries.

Sometimes we need to take a step back and appreciate how things have improved
over the years.

~~~
JoeMayoBot
Exactly - with these packaging services, developers have learned how to make
their software more re-usable. The 3rd party component eco-system is a multi-
billion dollar industry that continues to grow.

------
aequitas
When reading the title I figured it would explain something different to what
the author does: when doing a organ transplant (except for the liver maybe)
the organ is no longer usable to the donor.

Translatable to software, your reusable piece of code might not be so reusable
as you think, missing lots of abstractions and having lots of specific code
for just one specific consumer. Taking a piece of functionality from one part
of your software and using it for something else might harm the original use
due to broken API's, introduced complexity latency and failures, etc. Even
ending up with having 2 split versions of your reusable component for each use
case that you now have to maintain seperately.

------
majkinetor
This is not that accurate if we talk about libraries. Those mostly have well
defined scope, well defined interface, and are designed to be integrated so
most definitelly feel like LEGO.

However, this is totally accurate when reusing the code from your previous
project on your next one. I developed many large gov services, and each one
reused bunch of stuff from previous ones like user management, complete areas
of functionality etc. Here, the analogy is adequate, artefacts from previous
projects creeep in constantly. This feels more like single project evolving
(or devolving) over long period of time (years to decade).

------
Waterluvian
My favourite form of software reuse is when I just use my old code as
reference but import or duplicate almost none of it.

Feels so good to write similar software in 1/10th the time because the hard
fought ideas are already won.

~~~
imhoguy
That is knowledge reuse. Its hardly applicable with bigger project where the
knowledge is spread across teams or even lost, then we have things like NIH or
big-rewrites.

------
blobbers
[https://github.com/kohler/click](https://github.com/kohler/click) is a
library that I've found has a lot of reusability built into it, and operates a
lot like snapping Lego blocks together.

When you're talking about not being able to reuse code, I think it depends on
how you've designed your system. Design for reusability seems like it needs to
be key goal in development in order to achieve software re-use.

------
aazaa
The reason Lego works is a simple, well-defined interface. Two bricks stick
together by friction because the stud pattern on one matches the hole pattern
on the other precisely. Fortunately, that's a model that translates well to
software.

The way to make software reuse more like organ transplant than building Legos
is to ignore the advice to keep the interfaces simple and precise. Or worse,
don't even bother defining an interface, its data types, or error conditions.

------
bradleybuda
When I hear "snapping software like Lego bricks" my mind immediately goes to
the Spring Framework, which must be one of the largest, most-used, and most
complete (modern) attempts at this paradigm. I haven't used it for anything
large, but I would say it does not deliver on that promise.

I'm curious to hear from those who have worked on large, sophisticated, Spring
Framework apps - does it really feel like snapping pieces together?

~~~
TheAceOfHearts
No, but Rails definitely did feel like snapping pieces together. RailsCasts
was a blessing.

------
rsync
"People have been comparing software components to LEGO blocks for a couple
decades. We should be able to assemble applications by snapping together
modular components, just like LEGOs. There has been progress, but for the most
part we haven’t realized the promise LEGO-style software development."

    
    
      pg_dump -U postgres db | ssh user@rsync.net "dd of=db_dump"
    

... looks like Legos to me ...

------
ozim
OK but going all like it is not worth much because it is high chance of
failure is not helpful. Once I got burned on quite good interview when I went
a bit to far with notion that re usability in software is fake. In the end you
have to fix some things but it is not like someone is going to die. Unless you
really count on it and have really constrained budget, but in such case you
asked for it.

------
whiw
Having not used any of the following I may be wrong here, but don't dataflow
languages (eg Labview?) come close to this?
[https://en.wikipedia.org/wiki/Dataflow_programming](https://en.wikipedia.org/wiki/Dataflow_programming)

And isn't GNU Radio effectively a domain-specific language for plugging signal
processing elements together?

------
moonchild
See also: Joe Armstrong, 'Why do we need modules at all?'

[http://erlang.org/pipermail/erlang-
questions/2011-May/058768...](http://erlang.org/pipermail/erlang-
questions/2011-May/058768.html)

------
edejong
As long as each single project keeps reinventing their own Lego stubs, we
won't be going forward with reuse.

With Haskell and Scala's type-system we seem to come closer to universal Lego.
Still, like Lego, it can be hard to combine larger scale composites.

------
gcbw3
That comparison is silly. I've never seen anything built with LEGOs on
production.

~~~
ithkuil
not literally LEGOs, but many industries are based on repeated application of
basic building blocks. The simplest and most ancient example are ... bricks:
you build walls by composing objects of a few standardized sizes. This sounds
obvious but it's not how things were always made; if you build a wall with
stones, you have to invest more time into fitting them together neatly (and
often you have to use a hammer to break larger stones apart). Construction has
other examples of composition of prefabricated modules.

Another example, a lot of electronics was (and still is) implemented by
combining discrete components with well known behaviours (things like
[https://en.wikipedia.org/wiki/7400-series_integrated_circuit...](https://en.wikipedia.org/wiki/7400-series_integrated_circuits)).
At many levels in electronics you have abstractions upon abstractions
(transistors -> logical gates -> multiplexers -> ALUs -> CPUs; communication
busses, etc etc)

~~~
cgrealy
You can build a house with bricks. But you also need adhesive. And past a
certain (very low) complexity, you probably use wooden framing, cut to size.
And a different material for the roof, and glass for the windows and some kind
of insulation, plastics for piping, and so on and so on and so on. And that’s
not even getting started on more complex buildings.

As for electronics, yep, you start with discrete components, but as you said
yourself, you quickly end up with specifically designed components for
efficiency.

~~~
ithkuil
I don't think that software reuse the goal is to be zero-glue; perhaps that
part of the LEGO analogy (the lack of glue) distracts a bit.

What often happens with software development is that despite all the
abstractions that get built while building one piece of software, it often
turns out those abstractions can't be just pulled out and reused in another
context because often those abstractions are too leaky.

I think the "original sin" stems from how "cheap" it is to write a line of
code, and another one, and another one. It's not that good abstractions are
never being built during software development; but when they do they usually
take a long time to mature and have to be sought purposefully (and they cost
way much more to engineer).

What sets software development apart from other forms of engineering is that
it's often "ok" to build a house with mud and sticks that will collapse on the
first strong gust of wind because ... "because it's just a POC", "let's see if
we really have customers before doing it right", "making this too well has an
opportunity cost of not doing something else", etc etc

~~~
cgrealy
The point of Lego is not the zero glue, the point is that all components share
a common interface.

>>What often happens with software development is that despite all the
abstractions that get built while building one piece of software, it often
turns out those abstractions can't be just pulled out and reused in another
context because often those abstractions are too leaky.

My question is whether a non-leaky abstraction is even valuable.

Look at a real world example of non-trivial component reuse: a vehicle engine.

It has a single purpose: convert chemical energy to kinetic energy, and
they're really expensive to develop.

But you can't just drop a v6 into a Tesla.

~~~
ithkuil
yet it's clearly useful to have the concept of "the engine" even if you cannot
drop it in any vehicle.

E.g. it's a clear boundary between teams that collaborate on the "car" system,
it's something some engineers specialize in that is quite different from
"suspension system" (and such knowledge can be carried across engine design
instances).

But you're right, when we're talking about LEGO-style composability, as you
said, it's about having pieces that fit together and can be rearranged in many
ways, and the real world is far messier and rarely you have universal
composability; there are instances of "bounded" composability; e.g. the tyres
for my car likely fit many other similar vehicles, but not all.

~~~
cgrealy
>> yet it's clearly useful to have the concept of "the engine" even if you
cannot drop it in any vehicle.

Absolutely! I'm not arguing against modularity at all. I think the concept of
discrete subsystems interacting is pretty much universal (organs, components,
rooms, streets).

>> there are instances of "bounded" composability; e.g. the tyres for my car
likely fit many other similar vehicles, but not all.

Again, completely agree.

What I'm arguing against is uniformity of interface.

You wouldn't connect a tyre to a wheel the same way you would mount an engine
to a chassis.

~~~
ithkuil
> What I'm arguing against is uniformity of interface.

> You wouldn't connect a tyre to a wheel the same way you would mount an
> engine to a chassis.

Yes, you're right, LEGO is extremely uniform, and no real system is _that_
uniform.

And even a uniform interface doesn't mean any combination makes sense.

Attaching a LEGO brick with wheels on the roof of a LEGO car is not different
than soldering an axle on the roof of a car: technically possible but utterly
useless.

Actually, soldering an axle on the roof of a car is composing uniform
interfaces: atoms in chemical bonds form a finite set of building blocks too!

------
ronanyeah
I write full stack web in various functional programming languages, and I am
constantly copy-pasting 'lego blocks' between projects. If the compiler is
happy, I'm happy.

------
stackzero
Accurate IMO. You can get the components or organs but they don't snap
together, more careful integration required...like surgery

------
rhacker
Is software just too easy to write that everything becomes incompatible.
Everyone has the next best idea. It's XKCD 927 all the time.

Now if you instead look at Trucks and Campers, Rear Hitches, Fifth Wheels
Hitches, Goose Neck Hitches. Every truck you can buy on the market today (with
some strange exceptions Cybertruck cough) has very simple compatibility with
all of these various trailer types. Yes in some cases you have to buy a mod
kit, but when you look at the mod kit it literally bolts into pre-drilled
holes in your truck frame. It's all plug and play.

I feel like the reason it's like this is because no one person can go off and
design a truck in the dark. It's designed by many people and is beholden to
customers.

Software, on the other hand, just gets built by whoever wants to build
something. It doesn't have to fit some kind of standard. And it's not like
there are a lot of standards that already exist in whatever it is that the
software is doing.

In the real world however, you have Kubota tractors that need to fit a CAT
bucket.

I mean just read this page:

[https://www.spartanequipment.com/pages/buying-
tips/attachmen...](https://www.spartanequipment.com/pages/buying-
tips/attachments-buyers-guide.html)

Small quirks to it, but yeah, the rest of the world really is Legos, Software
is organ transplant.

------
leifg
Totally gonna use that for marketing purposes :D

------
pagutierrezn
If only organs could be connected with pipes

------
fbonetti
That's hilariously accurate.

------
app4soft
> _Software reuse is more like an organ transplant than snapping Lego blocks_

Funny, but Lego fans almost interpreted "organ transplant" exactly as
"snapping Lego blocks".[0]

[0] [http://xkcd.com/659/](http://xkcd.com/659/)

------
crimsonalucard5
Have you guys heard of functional programming?

Have you guys wondered why some people are so fanatic about functional
programming?

Functional programming forces your program to be lego blocks by Definition.

A function with no side effects IS A Lego Block.

If I never discovered functional programming I'd be like John D. Cook,
blogging about how programming is like organ transplantation.

Functional Programming is the answer to the question that has plagued me as a
programmer for years: How do I organize/design my program in such a way that
it becomes endlessly re-useable from a practical standpoint?

If this question plagues you as a programmer I urge you to take a closer look
at functional programming. Specifically look at functions and function
composition.

~~~
tiew9Vii
Strongly typed functional programing ;)

...follow the types

