Have you built your app on someone else's code? And beyond that,
does the "secret sauce" of your product depend on external
libraries or frameworks? While it's tempting to use the latest and
greatest tech as soon as it comes out, that's not always a great
idea. In this episode, Bill explains why, and what to do to protect
your code.

As developers, it’s good to be aware of these things, but
there’s often not much we can do about them. So, let’s ignore them
for now and talk only about the code.

In code, there are three kinds of dependencies:

1. Dependencies we control
This is code written and owned by us or our organization.

2. Dependencies we don’t control
This is code written by a third party vendor or open-source
software community.

3. Dependencies once removed
These are the code dependencies our third-party code dependencies
depend upon. (Say that three times fast!)

We’re going to talk mainly about dependencies we don’t
control.

Dependencies we control and dependencies once removed can still
cause headaches, but in the case of dependencies we control, we
should be able to directly intervene and mitigate any problems.

In the case of dependencies once removed, we can usually rely on
a third-party to take care of it for us, since they are dependent
on these, too.

Why third-party code dependencies are good

A large portion of your web application exists to solve common
problems: authentication, authorization, data access, error
handling, navigation, logging, encryption, displaying a list of
items, validating form inputs, and so on...

Regardless of which technology stack you use, there’s a good
chance that common solutions to these problems exist, and are
available as libraries that you can easily acquire and plug-in to
your codebase. Writing any of this stuff completely from scratch is
generally a waste of time.

You want to concentrate on code that either solves an uncommon
problem or solves a common problem in an uncommon way. That’s what
makes your application valuable: the code that implements the
business rules that are unique to your app alone — the “secret
sauce.”

Google’s search and page ranking algorithm, Facebook’s timeline
filtering, Netflix’s “recommended for you” section and data
compression algorithms— the code behind all of these features is
“secret sauce.”

Third-party code — in the form of libraries — allows you to
quickly implement those commoditized features of your app, so you
can stay focused on your “secret sauce.”

Why third-party code dependencies are bad

Take a look at any non-trivial web-app built in the last couple
of years and you’ll be absolutely astounded by the amount of code
that actually comes from a third-party library. What if one or more
of those third-party libraries changes drastically, or disappears,
or breaks?

If it’s open-source, perhaps you can fix it yourself. But how
well do you understand all the code in that library you don’t own?
A big reason why you use a library in the first place is to get the
benefits of the code without having to worry about all the details.
But now you’re stuck. You’ve completely tied your fortune to these
dependencies that you don’t own and don’t control.

Perhaps you think I’m exaggerating, or speaking from a purely
academic point of view. Let me assure you — I have dozens of
examples of clients who completely snookered themselves by
embedding third-party code too tightly into their app. Here‘s just
one recent example…

A former client of mine built their app using a
Backend-as-a-Service provider owned by Facebook, called Parse. They
used a JavaScript client library provided by Parse to consume the
Parse service. In the process, they tightly coupled all of their
code — including the “secret sauce” code — to this library.

Three months after my client’s initial product launch — just as
they started getting some good traction with real, paying
customers — Parse announced it was shutting down.

Now instead of focusing on iterating on their product and
growing their customer base, my client had to figure out how to
either migrate to a self-hosted, open-source version of Parse, or
replace Parse completely.

The disruption this caused for a young, fledgling application
was so huge that my client eventually scrapped the app
entirely.

Balancing the good and the bad

Several years ago, my go-to solution for overcoming the risks
while retaining the benefits of third-party-libraries was to wrap
them using the Adapter Pattern.

Essentially, you wrap the third party code in an adapter class
or module that you’ve written. This then works to expose the
functions of the third party libraries in a manner that you
control.

Using this pattern, if a third-party library or framework
changes, or goes away, you only have to fix a bit of adapter code.
The rest of your app stays intact.

This sounds good on paper. When you have self-contained
dependencies that only provide a few functions, this will do the
trick. But things can get ugly fast.

Can you imagine having to wrap the entire React library
(including JSX) before using any of it? How about wrapping jQuery,
or Angular, or the Spring framework in Java? This quickly becomes a
nightmare.

These days I recommend a more nuanced approach…

For each dependency you want to add to your codebase, evaluate
the level of risk it will introduce by multiplying two factors:

The likelihood that the dependency will change in a material
way.

The amount of damage a material change to the dependency would
do to your application.

A third-party library or framework is less likely to change when
some or all of the following things are true:

It has been around for several years and has had several major
releases.

It is widely used by many commercial applications.

It has the active support of a large organization — preferably a
household name company or institution.

A third-party library or framework will do less damage to your
application when some or all of the following things are true:

It’s only used by a small portion of your application, rather
than being used throughout.

The code that depends upon it is not part of that “secret sauce”
I talked about earlier.

Removing it requires minimal changes to your codebase.

Your entire application is very small and can be rewritten
quickly. (Be careful with this one — it’s rarely true for very
long.)
The riskier something is, the more likely you should be to wrap it
or avoid it altogether.

When it comes to the code that is really central to the value
proposition of your application —your “secret sauce” — you need to
be extremely protective of it. Make that code as independent as
possible. If you absolutely need to use a dependency, consider
injecting it rather than directly referencing it. Even then, be
careful.

Sometimes this means saying “no” to a third-party library you
think is really cool, or that you really want to use for one reason
or another. Be strong. Trust me, it will pay off. Just ask all
those people who invested heavily in the very first release of
Angular, or my former client who used Parse everywhere. It’s no
fun. Believe me.

Speaking of fun, take a look at this…

The image above is the dependency graph for an application
called TinyTag Explorer.

Generating a dependency graph for your existing apps is a great
way to understand the level of risk being introduced by your
dependencies. I’ve put together a list of free tools for generating
graphs similar to the above in a variety of languages including
JavaScript, C#, Java, PHP, and Python. You can get it here.

Help me help others

I want to help as many developers as I can by sharing my
knowledge and experience with them. Please help me by clicking the
❤ recommend button (green heart) below.