
Show HN: Java Bullshifier - tkfx
https://takipi.github.io/java-bullshifier/
======
tkfx
Hi, Alex from OverOps here. We've created the "Bullshifier" internally to
stress test edge cases with our own monitoring tool
([http://www.overops.com](http://www.overops.com)).

Whenever an exception or a logged error / warning happens in production, it
shows you the complete source code leading to it, and the full variable state
across the entire call stack.

Using Java Bullshifier, we're able to generate random applications with call
stacks that can go thousands of frames deep and other quirky behaviors. This
helps us make sure the overhead is unnoticed, even in the most extreme cases.

Would be happy to answer any questions.

~~~
nogridbag
I've been wanting to build a generic version of this type of tool for quite
some time.

When I'm waiting several minutes for our app server to startup, I often ponder
what life would be like if we had chosen language X or another stack for our
application.

I've primarily worked on JRE-based stacks for some time and once a project
reaches a certain size developer happiness begins to decline due to large
compilation times, app startup times, etc. Even incremental compiling or hot-
reloading of classes seems unreliable at a certain app size (either due to
memory or some other reason).

It would be neat if there were a tool to generate large and complex apps with
various stacks to get a feeling what the developer experience would be like
1-2 years down the road once the app reaches a critical mass.

~~~
mahyarm
That is a good idea for testing out new stacks for that shiny new rewrite. One
thing I've realized is most projects are not designed for 100+ developers
working on it at +400kloc of code.

We adopted [https://buckbuild.com/](https://buckbuild.com/) at work for our
android builds, and it has sped it up a lot compared to our previous gradle
build process.

------
agentgt
At first I thought this another one of the several Java shaming projects that
have been posted in the past on HN (usually in regards to the ridiculous class
names of some projects ... aka Spring).

But this project actually has some serious utility particularly for byte code
manipulators are just alternative compilers like AspectJ. Particularly AspectJ
as I have seen it fail on things that neither the Eclipse compiler (JDT) or
Open JDK fail on.

------
antoineMoPa
I'm glad to learn that entire businesses exist thanks to the fact that Java
has overly verbose exception outputs which are designed to hide the
information you are seeking between 200 lines of call stack prints.

~~~
vbezhenar
As an experienced Java developer I love long Java stacktraces and I miss them
in most languages. In 90% cases stacktrace allows to find a bug without any
debugging, because it's just very obvious where it is.

Of course if someone doesn't care about exceptions, it's just a bad style.
Exception in the production log is like red light and alarm sound, BUG-BUG-
BUG. I saw projects, which throw stacktrace after stacktrace, gigabytes of
stacktraces (and then archived those teralogs and noone ever watched them).
But those projects have much more problems, verbose logs is the least of them.

Yes, with heavy framework usage, especially when those frameworks generate
proxy classes and wrappers and god knows what, it's often 2-3 lines of useful
information between 90 lines of not-so-useful library or even autogenerated
code. But only developer can judge it, environment should preserve anything.

~~~
hinkley
The problem has historically been that most J2EE frameworks overly rely on
delegation, because of GoF.

I don't like seeing the same 5 stack frames in the same class appear three
separate times in a single stack trace. Because what does that stack trace
say?

It says it took Foo five function calls -on itself- to figure out it's not
responsible for an operation. So Foo asks Bar to do it, and after half a dozen
more function calls someone asks Foo all over again. Who takes 5 function
calls to figure out it's STILL not responsible for this action. Lather, Rinse,
Repeat.

And how do you set a breakpoint in that call tree? Which time do you want to
debug it? How many more times was it called before the exception was thrown?

~~~
tajen
Your concern is right, but how could we have solved it? I think it's a
composition of the Reflection API, the Java style of not accepting optional
function parameters, and the pluggable systems.

We call the first framework function, which calls the second function with the
default values for the arguments that were optional. The second function looks
up the application's method using Reflection. Because Reflection code is
verbose and has a lot of tricky cases, we want to share code between all
places where we call it, so it delegates calling the API in 4 different
methods.

Then come up the ServletFilters in an HTTP application, which is an example of
pluggable system. If we declare 10 filters, they all do something like check
the authentication, gzip the response, check the XSRF token, transform a
WebApplicationException into a 404/500 reaponse. Unfortunately they all appear
as "ServletFilters" in the stacktrace, until they delegate to the final
HTTPServlet itself. Another example of pluggable system is OSGi: Each method
call is wrapped in 5 function calls if the method is in another classloader.

There's only one improvement I'm able to imagine: Java could define a
pluggable system at the language level, so we don't have to implement them
using function calls. This pluggable system stretches for all delegation
needs, from OSGi to ServletFilters to apps where the list of delegates were
defined by a REST api, etc. Sounds like a big JSR...

~~~
hinkley
Barbara Liskov and Bertrand Meyer both have talked about separating decision
making from execution. And though there work predates widespread adoption, I
find this happens to work remarkably well for unit testing as well.

The thing to remember is that when Java was young, the pool of people who
grasped OOAD was very small. Nearly all of us were making it up as we went
along. So Design Patterns came out and everyone glommed onto that book, and
then went out and wrote code so awful and convoluted that it's now a joke.

J2EE was built up in that space, on a foundation of bad assumptions and
unfounded theories. I was simply amazed that the same company that brought us
the Eight Fallacies of Distributed Computing brought us the J2EE 1.0 spec. I
was so appalled at its quality that I switched to UI development until well
after the 2.0 spec was out and implemented.

It says something profound that every vendor that had any succes with those
versions of the spec did it by defying the spec and supporting local dispatch.
A lot of people couldn't scale their app past two machines, but load balancer
eventually came around and fixed that.

Anyway, my point is you have a bunch of APIs written by newly minted experts,
many of the foundational ones by people with absolutely no awareness of the
physics of distributed computing, it's going to take a lot to spackle to cover
those sins. Some did, others doubled down, but overall every problem was
solved by another layer of indirection.

When refactoring came to the fore I hoped the industry would hastily reverse
course. Spring was supposed to fix a lot of this but from my view, Spring
became the thing is sought to replace. Full of cryptic levers and dials and
massive indirection.

I think it was Mike Feathers who attributed this to cowardice. People afraid
to make decisions put all the decisions behind a layer or two of indirection
so they can "cheaply" change their minds later. But again we are back to Meyer
and Liskov here.

If A then B (where A is the decision and B the action) allows you to change A
without adding much if anything to B, or add to B without changing A. If this
shows up in an inheritance hierarchy then you need about half as many
overridden methods for the same call tree. Which means a shallower call tree,
and code you can speak out loud.

------
btbuildem
We have folks on-site doing just this, but thanks for the thought!

~~~
imode
developers as a service is looking like a more realistic idea by the second!

------
iLoch
Do you have a De-bullshifier for existing Java codebases?

~~~
tkfx
Working on it as we speak ;)

------
qwertyuiop924
If you use the right random word combinations for the class name generation,
and the code actually does something, this may be near-indistinguishable from
a real Java codebase.

------
igt0
In fact, it is a kind of common practice to generate tons of code. For C
language, we have Csmith[1]. It is used to find bugs in llvm and GCC.

[1] [https://embed.cs.utah.edu/csmith/](https://embed.cs.utah.edu/csmith/)

------
MaxfordAndSons
Obligatory reference to
[https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...](https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition)

------
guard-of-terra
I wonder if you could use genetic algorithms on codebases like these to make
them do something useful.

~~~
bigiain
I wonder how much I'd have to spend on AWS if I just wrote the acceptance
tests for our next project, then ran this in a loop/cluster until it wrote
something that passed UAT... :)

------
tomcam
Wonder if people will use this to post bullshified apps to Github to impress
potential employers

~~~
guessmyname
That would actually work [1] to certain extend but once you have to prove your
real skills during a technical interview it will be clear that you are not a
real Java developer unless, of course, you are. If you are a Java developer
this tool will (probably?) have the effect that you suggest, to increase the
probability of an ATS [2] to hit your online developer persona.

I will actually try this because as people have mentioned before hiring is
broken and this is either a way to exploit and/or bypass some of the
inconveniences like coding challenges and the like used to filter non-
programmers.

[1]
[https://github.com/avinassh/rockstar#testimonials](https://github.com/avinassh/rockstar#testimonials)

[2]
[https://en.wikipedia.org/wiki/Applicant_tracking_system](https://en.wikipedia.org/wiki/Applicant_tracking_system)

------
userbinator
What does the generated code actually _do_ when run, besides heavily
exercising the JVM? Does it eventually print "Hello world" or something?

------
desireco42
It was about time somebody creates something like this. I do have a complain,
classes are named random. If you used a tool that generates human like names,
it would still be random but looked much better.

I will see to create a similar rails tool. I intend to test just stress of
people who will look at the code and try to understand what it does.

~~~
leeoniya
for some reason when I first saw the OP I wondered if it was
[http://projects.haykranen.nl/java/](http://projects.haykranen.nl/java/)

~~~
tkfx
Heh, this might actually be useful for v2.0 :)

~~~
leeoniya
D:

------
wstrange
Nice, but this should be refactored to generate microservices.

------
sedlich
Does this remind me legendary paper generator SCIgen... Good to know as a CS
teacher ;-)

------
Slartie
Neat idea! As a mostly-Java coder (by choice), I love both the approach to
testing your own tool as well as the slight side blow into the Java community
regarding long stack traces full of framework-contributed delegation classes
and virtual proxies.

But...not more than 20k classes? That doesn't really count as "massive Java
application" these days, more like an average-sized enterprise app when
including all its dependencies. You would at least triple that to reach
"massive" scale ;-)

------
ryanmccullagh
Kind of off topic, but this reminds me of my internship this summer. What
sucks about Spring is the horrible error messages. If there is something wrong
in the XML configuration, or dependency configuration, it doesn't actually
tell you that. Instead, it shows a deep stack trace with some strange
exception that doesn't relate to the problem at all.

~~~
sappapp
Then stop using spring. Don't get sucked into the vortex of using overhyped
tools that require consultant engagements to fix production bugs.

~~~
retbull
You could also not use xml. Because spring supports java configuration and the
stacktraces are easy to see.

------
self_awareness
Actually this could be a good platform for generating licensing algorithms
that would be included in commercial software. This level of obfuscation would
really be hard to crack by reverse engineers that produce cracks/keygens.

------
vortico
Features: Generates TONS OF CODE!!

I love it.

