Deprecation warnings in legacy JavaScript code using ES2015 proxies

Asís García
Trabe
Published in
4 min readApr 16, 2018
Photo by Pablo García Saldaña on Unsplash

Code evolves. As you add, change or remove features, you use new libraries, different coding styles or techniques, better tools. You can try to keep the old code up to date, but, as time passes, even the best maintained code base starts to develop some legacy areas (That old features you developed when you didn’t know about those useful array methods 😅).

The best way to deal with legacy code is refactoring early and refactoring often. Every time you change something (be it a technique, style, library, or tool), you should update the existing code to make sure that the change is consistent throughout the entire code base.

Of course, that’s easier said than done. Sometimes you just can’t afford to refactor the code, at least not immediately. So, the legacy stuff stays there. And then there is a chance that one of your coworkers (or even your future self!) will use that legacy stuff for a new feature. That way, the legacy “disease” spreads, making future refactoring efforts increasingly harder.

The best way to prevent that from happening (other than doing the refactoring on time), is to document the changes and warn anybody using legacy stuff about the alternatives.

Feature deprecation

According to the Wikipedia:

deprecation is the discouragement of use of some terminology, feature, design, or practice […] without completely removing it or prohibiting its use. It can also imply that a feature, design, or practice will be removed or discontinued entirely in the future.

In software development, deprecation is usually associated with changes in the APIs of libraries and frameworks. Deprecation warnings are messages that tell you to stop using some existing feature, as it is going to be removed or has been superseded by a better alternative.

But deprecation is not only relevant to library code. You can prevent legacy from spreading, warning your fellow coders when they use deprecated stuff.

Some languages have tools to mark code artifacts as deprecated. In .NET you can use the ObsoleteAttribute attribute. In Java, the @Deprecated annotation. Whenever you use a feature marked as deprecated, the compiler (and even the IDE) will warn you about it.

A Java example

Look at this (rather useless) Java example. In the first file I define a class with a deprecated method:

Then I use it in another class:

If I try to compile that, I will get a warning message:

$ javac Ex.java Greeter.java
Note: Ex.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

I can get even more information about the deprecated feature if I do as the message says and pass the -Xlint:deprecation flag:

$ javac Ex.java Greeter.java -Xlint:deprecation
Ex.java:5: warning: [deprecation] sayHi() in Greeter has been deprecated
new Greeter().sayHi();
^
1 warning

As you can see, using the @Deprecated annotation, you can mark your own Java code as deprecated, and warn everyone using it.

Deprecation in JavaScript

JavaScript has no “native” deprecation mechanism, so you’ll have to roll your own. It’s not ideal, but you can use the console to warn about deprecated stuff¹.

We start defining a utility function to prevent the deprecation messages from showing up in a production environment:

In the following example I add some deprecation warnings to a class, a method and a function:

The next time someone uses legacyFunction, LegacyClass or legacyMethod a warning will show up in the console.

Deprecation warnings using ES2015 proxies

Using a similar approach to the one described above, you can deprecate almost any code feature. But, what about deprecating properties? In JavaScript applications, accessing an object’s data directly through its properties is a very common practice. Using ES6 proxies, you can easily add deprecation warnings to object properties.

You can define a utility function to print a message (using deprecationWarning defined above) anytime the deprecated property is used:

Then you can use that function to deprecate any property access in any object:

Deprecate all the things!

The Proxy object lets you intercept access to properties, as we saw above, but also setting properties and constructing objects. You can write a more generic deprecateProperties function which you can use to deprecate both reading and writing for multiple properties:

You could even intercept a class constructor to deprecate a whole class:

Remember, when dealing with legacy code, you only have two options: either you make it disappear, or you warn everybody about it, to prevent it from spreading.

Notes

¹ It’s worth noting that this kind of deprecation warnings will happen at runtime… because there is no compile-time! I guess you could try with linter rules if you prefer to get deprecation warnings earlier.

--

--