Showing posts with label Humor. Show all posts
Showing posts with label Humor. Show all posts

Monday, April 16, 2018

Java-Related April Fools Day Pranks

Although you'd never catch me stooping to this level, it has been interesting over the years to see some of the effort and thought put into Java-related April Fools' Day pranks. This post references and summarizes some of them.

Google Annotations Gallery (gag)

The Google Annotations Gallery (cleverly abbreviated as 'gag') is hosted on Google Code, so you may want to download that as soon as possible so that you do not miss out on it. Both gag-1.0.zip (original release) and gag-1.0.1.zip (supplements original release to "add many great user-suggested annotations"). These ZIP files include actual Java source code with the libraries that gag depends on.

Some of my favorite annotations provided by gag are @AhaMoment, @Blame, @BossMadeMeDoIt, @Facepalm, @Hack, @HandsOff, @IAmAwesome, @LegacySucks, @Magic, @Noop, and @OhNoYouDidnt.

I also enjoy the WHERE enumeration provided by 'gag' to allow one to specify "where" a particular annotation's meaning may have occurred. Values for WHERE cover the most likely locations to think up the best ideas (most "free time"): BATH, BED, BORING_MEETING, DMV, GYM_WORKOUT, SHOWER, TOILET, and TRAFFIC_JAM.

I was negligent in not mentioning the 'gag' library in my recent post on how to effectively divert blame.

New OpenJDK Project: Even Faster JDK Releases

This year (2018), the discuss OpenJDK mailing list includes a couple threads with April Fools' Day hoaxes. One of these, "New project proposal: even faster JDK releases," is particularly timely given the relatively recent change to a new Java release every six months. The new cadence has caused some concerns such as those described in "The Java release train is moving faster, but will developers be derailed?"

The April 1 proposal proposes "the creation of project Doomed, which aims to solve an extremely important issue caused by the currently specified fast release schedule, that of an equally fast adoption." Before making several other arguments for Project Doomed, the proposal states, "With project Doomed we aim at continuous release and deployment of the JDK, thus removing the need to have any version number and increase the adoption rate considerably and better position the JDK in the fast pacing world of cloud development."

New OpenJDK Project: The Block GC

Another April 1 thread on the discuss OpenJDK mailing list starts with the post "New Project Proposal: The Block GC." The proposal here is for "Block Chain GC", "an innovative new system for Garbage Collection." Among other advertised virtues of the Block Chain garbage collector is the ability for it to be "used to calculate hash values for popular cryptocurrencies, a.k.a. 'bitcoin mining'". The proposal also outlines where the default recipients of the revenues generated from the Block Chain garbage collector: "by default, the revenue extracted by the Block GC miner will be stored in the Block GC Project account. This revenue will be divided as follows: 90% will go to the initial committers of the Block GC Project, and 10% will go to the OpenJDK community."

Apache Software Foundation Sold to Oracle

The 2010 April Fools post "The Apache Software Foundation Receives Approval for Sale to Oracle Corporation" announced "Today, the Apache Software Foundation announced it has agreed to sell all IP and assets of the foundation to Oracle."

Frostbyte

ZeroTurnaround announced Frostbyte on April Fools Day in 2012 and advertised it as "a new stack-based language for the JVM" that was "born out of frustration of working with the standard Java software stack and tools." Among Frostbyte's advertised features were "use of inverse reverse Polish notation with parentheses" and "the built-in default language is Estonian." Perhaps the most promising feature of Frostbyte was "built-in AI that is able to make aesthetic judgments about your code and will outright disallow ugly code, over-abstractions and excessive copy-and-pasting."

Goto in Java

Another 2010 April Fools Day announcement was Joe Darcy's "Goto for the Java Programming Language." "Endorsed" by "Edsger Dijkstra" (author of "go to statement considered harmful"), this proposal advertises that it will "Provide the benefits of the time-testing goto control structure to Java programs." Fortunately, Java still doesn't have that form of a "goto," but it does have its own narrowly-scoped similar capability.

Neo 4 Java

On April Fools' Day 2016, the Neo4j blog announced Neo 4 Java, "a proprietary 100% pure Arabica available in the caffeine aisle soon, or possibly right at your desk if you happen to have a 3D printer or a really good intern."

Micecraft Java Edition Textures Finally Perfected

In "Java Edition Textures Finally Perfected," it was announced of April Fools Day this year that "a new default texture pack for the Java Edition of Minecraft" was being released. Not everyone thought this was funny because it apparently cost some Minecraft users quite a bit of time before they realized it was a one-day prank. A Minecraft bug, MC-127786, was reported with this moderator response, "April fools! This is an April Fools' joke by Mojang. Textures will return back to normal once April Fools' Day is over." Minecraft users should probably be especially wary of April Fools Day pranks because it's not the first time that Mojang has pulled one.

Conclusion

Several of the April Fools' Day posts described above required a surprising amount of ingenuity, effort, and time.

Sunday, April 1, 2018

Diverting Blame Effectively in Software Development

I previously blogged on how to effectively sweep problems under the rug in Java, but even with the tactics discussed in that post, it's not always possible to hide every problem encountered when developing software. In this post, I look at tactics software developers can use to avoid direct blame for problems and issues that cannot be hidden or easily fixed.

Dealing with Version Control Tools

Version control (AKA source control) offers several advantages, but can also be one of the easiest ways for others to know when you've introduced a particular bug or issue. One option that seems to not be used much anymore is to avoid version control systems altogether. Without version control, it isn't as easy for someone else to find out who delivered a particular line or lines of code.

Even with some sort of version control in place, there are tactics to reduce the ability of others to see when you've introduced a bad piece of code or made a change with negative repercussions. One tactic is to convince a fellow developer to merge your changeset for you. Depending on the version control system you're using, this is accomplished in different ways, but at a high-level typically involves you supplying a patch of your changes and asking the fellow develop to merge that patch's changes into the main development branch.

Because it's often not easy to get someone else to merge for you or to otherwise prevent the version control system from showing you as the responsible individual for code changes, an easier tactic is to put things in the version control commit or merge comments that deflect blame. These comments might ascribe the change to someone else. The comment could say something about merging someone else's changes for them or that the changes were someone else's idea and imply that you merely made the requested changes for them.

The problem with referencing other developers in version control delivery comments is that, in many version control systems, these developers will see the delivery comments as the deliveries are being made. In such cases, it's often better, if possible with your version control system's configuration, to change the comment AFTER the delivery has been made and AFTER any automatic notices of the delivery have been issued.

In-code Comments

In-code comments can be a great way to divert blame. A well-written comment can be convincing and might even preclude a fellow developer from bothering to use the version control system history to see who made a change if that developer sees an in-code comment explaining the change or addition. These in-code comments might state things like, "This was Frank's idea" or "Change made at Anna's request." If mentioning specific names is too risky, the comments can be more vague as to whose ideas are implemented ("I was directed to do this because ...").

A specialized form of an in-code command that can be particularly useful in deflecting blame is the infamous "TODO" comment. This "TODO" comment can be used to make your problem someone else's future problem. This approach is particularly effective if the current problem is described in this comment in such a way that it seems impossible to address it now and so it must be addressed at some point in the future. One might even go further and pretend it's someone else's "TODO" by placing the other person's initials in the comment or referencing the other individual. There might even be an implication that the other individual will be or should be the one to resolve the issue.

Apply Logical Fallacies

There are numerous logical fallacies that can be applied in response to others' critical code reviews or other mentions of problems with your code. One that can be effective is an "appeal to ridicule" in which you make it obvious that you won't waste time on such an absurd argument; this works best when you are the more experienced developer or are in a higher or more powerful position. Sometimes, to pull this off, you might need to imply that the other person will some day understand.

The "false authority" logical fallacy is also effective; with this one, you just need to find one person who makes an argument for doing something the way you did it and then cite that is THE authority. You want the person writing this to seem as credible as possible for this to work well. Alternatively, one could use "false attribution" to quote someone well-credentialed authority in favor of one's position without actually citing the source (because there isn't any).

One particularly effective approach can be to respond to critiques with comments quoted by authorities out of context. One of the most obvious here is to defend one's poor code choices with the argument that one was simply avoiding premature optimization.

Muddy the Waters

There are several tactics one can use to "muddy the waters" to make it difficult to ascertain who did what when. Some examples include mixing substantial changes with refactorings and cosmetic changes in single change sets, breaking an otherwise cohesive set of changes into multiple merges over time to make it difficult to see when the issue was introduced, making changes in files with lots of changes so that others' merges show up over your own merges, etc.

Write Unit Tests that "Prove" Your Code Works

Unit tests can be very useful for a variety of reasons, but they can also be the first to expose your issues. Fortunately, you can make unit tests work for you when covering up your issues by writing tests that assert your incorrect code is fine. Then, when someone finds an issue with your code, you can blame the unit test for being at fault.

Blame External Forces

When it's not possible or ill advised to blame another developer, blaming inanimate items that won't attempt to defend themselves can be effective. This approach is most effective when the blame is directed at items that are already viewed with disdain by those around you and include things such as tools (IDE, version control, static analysis tools, unit test frameworks, etc.), schedules (including deadlines), libraries and APIs, existing code, the environment ("it worked on my machine"), etc.

Management and/or customers can often be blamed to at least partially deflect attention. Being outraged at the ridiculous requests or unrealistic requests of clients and/or management can lead to empathy and agreement from fellow developers.

Divert Blame to Code Reviewers and/or Test Organization

When all else fails, blame can be diverted to code reviewers. When problems are found during a code review, you can state that you placed them there intentionally to test the quality of the reviews and see if anyone was actually reviewing. When issues are found after the code reviews, you can blame the reviewers for not finding the issues during their review. If you have a separate test organization, the same tactics can be applied; you can say your problem was intentionally added to verify the testers were doing their job if found by Test or can blame Test for not finding the issues if they arise after testing.

Conclusion

This post has quickly looked at some of the tactics that a software developer may find useful when diverting blame.

By the way, Happy April Fools Day!

Saturday, April 1, 2017

How to Effectively Sweep Problems Under the Rug in Java

Because software bugs can make us appear bad as developers and lead to others thinking less of us, it is best to avoid writing bugs, to identify and fix bugs quickly, or to cover up our bugs. There are numerous blog posts and articles that discuss avoiding bugs and identifying and fixing bugs, so, in this blog post, I look at some of the most effective tactics for sweeping problems in Java code bases under the rug.

Swallow Checked Exceptions

Exceptions are one of the things that give us away when we've accidentally introduced bugs into the code. It's also a hassle to declare a throws clause on a method or catch a checked Exception. A solution to both problems is to simply catch the exception (even if it's a RuntimeException) at the point it might be thrown and do nothing. That keeps the API concise and there is little one could do about the checked exception anyway. By not logging it or doing anything about it, no one even needs to know it ever happened.

Comment Out or Remove Unhappy Unit Tests

Failed unit tests can be distracting and make it difficult to determine when new functionality has broken the tests. They can also reveal when we've broken something with code changes. Commenting out these failing unit tests will make the unit test report cleaner and make it easier to see if anyone else's new functionality breaks the unit tests.

Use @Ignore on JUnit-based Unit Tests

It may seem distasteful to comment out failing unit tests, so another and possibly more pleasing alternative is to annotate failing JUnit-based unit test methods with the @Ignore annotation.

Remove Individual Tests Altogether

If commenting out a broken test or annotating a broken test with @Ignore are unsatisfactory because someone might still detect we've broken a unit test, we can simply remove the offending unit test altogether.

Comment Out the Offending Assertion

We don't necessarily need to comment out or remove entire tests. It can be as simple as commenting out or removing the assert statements in a unit test method. The method can execute and run successfully every time because no assertions means no way to fail. This is especially effective when the unit test methods are very long and convoluted so that lack of assertions is not easily spotted.

Distract with the Noise of Useless and Redundant Tests

Commenting out unit tests, annotating JUnit-based unit tests with @Ignore, and even removing unit tests might be too obvious of ploys for sweeping issues under the rug in Java. To make these less obvious, another effective tactic is to write numerous unnecessary and redundant test methods in the same unit test class so that it appears that comprehensive testing is being done, but in reality only a small subset of functionality (the subset we know is working) is being tested.

Write Unit Tests That 'Prove' Your Code is Correct Even When It Is Not

We can take advantage of the fact that unit tests can only test what the author of the unit test thinks is the expected behavior of the software under test to write unit tests that demonstrate our code to be correct. If our code for adding two integers together accidentally returns a sum of 5 when 2 and 2 are provided, we can simply set the expected result in the unit test to also be 5. A pretty unit test report is presented and no has to be the wiser.

Avoid Logging Details

Logs can expose one's software problems and an effective approach to dealing with this risk is to not log at all, only log routine operations and results, and leave details (especially context) out of logged messages. Excessive logging of mundane details can also obscure any more meaningful messages that might reveal our code's weaknesses.

Avoid Descriptive toString() Implementations

A descriptive toString() method can reveal far too much about the state of any given instance and reveal our mistakes. Not overriding Object.toString() can make it more difficult to identify issues and associate issues with any given code or developer. The extra time required to track down issues gives you more time to move onto the next project before it is discovered that it's your code that's at fault. If you write a Java class that extends a class with a descriptive toString() you can override that method in your extended class to do nothing (effectively removing the potentially incriminating toString() output). If you want it to appear as if it was never implemented at all in the inheritance hierarchy, be sure to have your extended class's toString() method return System.identityHashCode(this).

Don't Let NullPointerExceptions Betray You

The NullPointerException is probably the most common exception a Java developer deals with. These are especially dangerous because they often reveal code's weak spots. One tactic to to simply wrap every line of code with a try-catch and simply swallow the exception (including the NPE). Another and less obvious tactic is to avoid NPEs by never returning or passing a null. Sometimes there are obvious defaults that make sense to use instead of null (such as empty Strings or collections), but sometimes we have to be more creative to avoid null. This is where it can be useful to use a "default" non-null value in place of null. There are two schools of thought on how to approach this arbitrary non-null default. One approach is to use the most commonly seen value in the set of data as the default because, if it's common anyway, it may not be noticed when a few more of that value show up and you are more likely to have code that appears to process that common value without incident. On the other hand, if you have a value that is almost never used, that can make a good default because there may be less code (especially well tested code) affected by it than by the commonly expected value.

Conclusion

As I reviewed these tactics to sweep issues in Java code under the rug, I noticed some recurring themes. Exceptions, logging, and unit tests are particularly troublesome in terms of exposing our software's weaknesses and therefore it's not surprising that most of the ways of effectively "covering our tracks" relate to handling of exceptions, logging, and unit tests.

 

 

 

Happy April Fools' Day!