Dirty Hacks Are OK
We've all done it; used a hidden field to switch a flag, done a dodgy cast to access a hidden field. Sometimes these are necessary, and you know what? It's OK.
Join the DZone community and get the full member experience.Join For Free
In practically every project, you’ve used a “dirty hack.”
sun.misc.Unsafe, changing a
final value with reflection, copy-pasting a class from a library to change just one line of wrong code. Even if you haven’t directly, a library that you are using most certainly contains some of these.
Whenever we do something like that, we are reminded (by StackOverflow answers and colleagues alike) that this is a hack and it’s not desirable. And that’s ok—the first thing we should think about when using such a hack is whether there isn’t a better way. A more object-oriented way, a more functional way. A way that the language allows for, but might require a bit more effort. But too often there is no such way, or at least not one that isn’t a compromise with other aspects (code readability, reuse, encapsulation, etc.). And especially in cases where 3rd-party libraries are being used and “hacked.”
Vendors are also trying to make us avoid them—changing the access to a field via reflection might not work in some environments (some Java EE cases included), due to a security manager. And one of the most “arcane” hacks—
sun.misc.Unsafe—is even going to be deprecated by Oracle.
But since these “hacks” are everywhere, including the Unsafe magic, deprecating or blocking any of them will just make the applications stop working. As you can see in the article linked above, practically every project depends on a
sun.misc.Unsafe. It wouldn’t be an understatement to say that such “dirty hacks” are the reason major frameworks and libraries in the Java ecosystem exist at all—Hibernate, Spring, and Guava are among the ones that use them heavily.
So deprecating them is not a good idea, but my point here is different. These hacks get things done. They work. With some caveats and risks, they do the task. If instead you’d need to fork a 3rd-party library and support the fork? Or suggest a patch and it doesn’t get accepted for a while, but your deadline is soon, these tricks are actually working solutions. They are not “beautiful,” but they’re OK.
Too often 3rd-party libraries don’t offer exactly what you need. Either there’s a bug, or some method doesn’t behave according to your expectations. If using setAccessible in order to change a field or invoke a private method works—it’s the better approach than forking (submit an improvement request, of course). But sometimes you have to change a body method—for these use cases I created my quickfix tool a few years ago. It’s dirty, but does the job, and together with the rest of these hacks, lets you move forward to delivering actual value, rather than wondering "should I use a visitor pattern here" or “should we fork this library and support it in our repository and maven repository manager until they accept our pull request and release a new version” or “should I write this with JNI”, or even “should we do this at all, it’s not possible without a hack.”
I know this is not the best advice I’ve given, and it’s certainly a slippery slope—too much of the “get it done quick and dirty, I don’t care” mentality is surely a disaster. But poison can be a cure in small doses, if applied with a full understanding of the issue.
Published at DZone with permission of Bozhidar Bozhanov, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.