
A bad citizen in Javaland (2006) - bencoder
http://darrenhobbs.com/2006/04/22/a-bad-citizen-in-javaland/
======
RyanZAG
I wonder how a functional version of this would go..

You need transportation, so you define an engine and a set of wheels and a
chair, and a whole universe. You define a way to have the engine, wheels and a
chair work together. You try to sit in the chair, but it's too small. You
can't change the chair because it's all immutable, so you create a new chair
along with a new universe and build a new car with the new chair.

You need to get to work, but you don't want to pollute your universe with
state, so you don't know where work is. So you put all of your state in your
relational stateful database and forget that this part exists in your
universe. Of course theoretically you could model your knowledge as a function
based off the state of the universe, but you don't have budget to do that. You
write comments about quick hacks to get around purity constraints. The hacks
are never removed and you end up passing stateful maps of database tables
around. You make a big todo note about how you should implement a new method
for handling this that you've read in a new academic paper, but never get the
500 hours you need to implement it.

EDIT: For those not getting it, the article is describing the difference
between the theory behind OO interaction between self contained actors and how
this really plays out in actual code. Instead of doing the theoretical part of
communication between actors, we have code which does
getCoworker().getWallet(). In the same way above, I've tried to show the
difference between theoretical functional programming where we can create pure
functions and how this actually plays out in real functional code.

~~~
danieldk
_You can 't change the chair because it's all immutable, so you create a new
chair along with a new universe and build a new car with the new chair._

No, if you read Okasaki, you knew you only have to reconstruct the part of the
universe (up to its origin) that refers (directly or indirectly) to the seat
;).

In fact, you can safely have two universes with different seats, where most of
the universes is shared.

~~~
RyanZAG
Oh that makes for a funny part of the ending too then.

While going about your work, you suddenly disappear along with your universe
and everything in it. Someone somewhere in the world drank a cup of coffee,
which means that he now has an empty cup instead of a full cup. A new universe
had to be created with the full cup replaced, and unfortunately your universe
had to be thrown away. You continue life as a clone in a new universe with an
empty coffee cup somewhere in Nebraska.

Why did this happen? Someone picked a copy-on-write map implementation because
it had a slightly faster O(logN) delete behavior and unfortunately the re-use
function of the map wasn't implemented yet because the author has gone on to
do a series on the use of monads in baking the ultimate croissant.

~~~
Someone
_" Someone somewhere in the world drank a cup of coffee, which means that he
now has an empty cup instead of a full cup"_

That cannot happen in an immutable world. To fill an empty cup, you cons a cup
and its contents. To get an empty cup again, you take the car of the cons. The
full cup will only get garbage collected if you do not reference it anymore.

~~~
catnaroek
> To fill an empty cup, you cons a cup and its contents.

That simply has the wrong type in mathematically civilized languages like
Standard ML or Haskell.

> The full cup will only get garbage collected if you do not reference it
> anymore.

This is orthogonal to functional programming. You can avoid the need for a
garbage collector with substructural types.

------
jt2190
I was about to dismiss this story as silly, but then it occurred to me that
the reason this is so funny is not because Java is a bad language per se, but
that it really didn't work well for programmers who don't understand Object
Orientation. I've read more than my fair share of code that reads exactly like
this story because of this lack of programmer understanding.

Consider:

 _You are born with no body parts._

    
    
        Person me = new Person();
    

_Should anyone attempt to interact with you before your organs have finished
arriving you will die._

    
    
        me.interact();
    

Throws a NullPointerException because the class designer improperly
initialized the instance. The designer should have provided a constructor.

    
    
        public static Person() {
            this.organs = new Organs();
        }
    

_One by one, your organs are pushed into you._

Instead, the class designer probably followed the JavaBean pattern and
provided a setter method for Organs:

    
    
        public void setOrgans(Organs organs) {
            this.organs = organs;
        }
    

etc.

(For those that don't remember: The JavaBean idea arose because early versions
of Java had no way of performing introspection, something that software tools
really, really need. JavaBeans broke object encapsulation by design. Many
programmers had to write beans to take advantage of their tools, and learned a
very bad habit.)

~~~
_asummers
In modern Java, one uses things like dependency injection (Guice, Spring,
whatever) for building up the services, and I find most programmers now abhor
setters for their POJOs. Want a new Person object with a different name? Make
a new one, it'll be okay, except in the most extreme of circumstances.
Ephemeral memory is cheap. When an object comes back from a constructor, it
should (in my mind at least) be immediately usable. People also enjoy the
builder pattern, I've found. When you call .build(), it will do the internal
checks to say if you screwed up, so you're guaranteed to never have a Person
with no Organs. This is, of course a run time check so less helpful than a
compiler error. Depending on the use case, it makes perfect sense, though.

Also side note, how do I do the code blocks in HN comments like you did?

~~~
bencoder
There's still a lot of getters everywhere though, which seemed to me to be the
bulk of the analogy.

    
    
        this.wallet = colleague.getWallet();
    

Code blocks are done with 4 space indentation at the start

~~~
reitanqild
Which is not a fault of the Java language: trainwrecks
(this->getThat()->getThose()-foreach(){ do stuff } is a general antipattern.

The correct way is IMO: colleague.getMoney() which can easily be implemented
in Java, PHP etc.

I'm getting a bit tired of this constant pecking at Java (nothing personal).
There are a number of questionable designs yes, there is a lot of ugly code
out there, yes, but almost every alternative might have been worse:

Teaching everyone C? Good luck.

Switch to C#? Until recently that would prevent you from using Linux on your
servers unless you were ready to put in technical effort and bet on MS not
suing you or the upstream effort.

Perl?

PHP?

Catch my drift folks? Java filled a niche. It was almost as easy as PHP once
you got started (although onboarding still is messy I think) and provided
superior tooling.

~~~
bencoder
Despite the name, I didn't see the article as taking a pop specifically at
Java. It seemed more about bad OOP in general. As you say, you'll see the same
patterns in every OO language.

------
darrenhobbs
Well, this made my day! I'd almost forgotten that blog was still running.
Achievement unlocked :)

~~~
anthonybsd
This is one of the best metaphors I've read in a long time!

------
gravypod
I feel that this is a representation of the fundamental misunderstanding of
how object orientation is really done. In my opinion, if designed this way,
this application was not well thought out.

If I was writing this, I would aim for this:

You wake up one day and you call to the heavens asking for transportation, you
yell out the location in front of you, and with no response from the skies a
self driving car appears.

You walk to the car and ask it to take you somewhere. Suddenly a pair of hands
reaches out from the car, pulls you in, and takes you to your location. While
you arrive, you are pushed out.

When you get to your job, you need money for lunch. You hand your wallet to
your friend and your friend puts money into it giving it back to you. You keep
your friends phone number on record if you would like to ask for money again.
If he is busy, you can leave a voice mail and eventually he will throw money
at your face hoping you catch it.

When you finally get home, you go into your bed and sleep until your bed wakes
you up the next day to start again.

It's silly, like the original post, but I prefer to give handles and let
abstracted code do it's magic. In all of these cases, I do not have the caller
assume anything. It does what it knows it can do.

Some things need a more fine tuned application of this, but the idea is you
just never assume something is true, only use what you know. That's where a
lot of people mess up in java.

~~~
GhotiFish
note: It's called "A _bad_ citizen...".

------
CrimsnBlade
Stuff like this is fascinating to me. I'm by no means an expert in writing
code, I'm very much a beginner, but the creative potential that is there has
always drawn me in.

If one was going to learn OOP correctly in Java (or Python) from the
beginning, where would be a good place to start? Are there any textbooks or
good websites for this?

~~~
jdmichal
The SOLID principles are all you need to know. [0] Then realize through them
that inheritance as generally taught is actually a bad idea and use interfaces
instead. Then realize that interfaces are just a weaker version of type
classes and reach enlightenment.

[0] [https://en.wikipedia.org/wiki/SOLID_%28object-
oriented_desig...](https://en.wikipedia.org/wiki/SOLID_%28object-
oriented_design%29)

~~~
rripken
Is this in reference to the type classes as seen in Haskell or something else?
I want to reach enlightenment but I'm stuck in Java for the time being.

~~~
jdmichal
Yes, as in Haskell type classes. Or Rust traits. Basically, anything that acts
like an interface (defines a contract) but allows external definition. So
you're not stuck wrapping your Integer in a ShowableInteger just to have an
Integer that implements the Show interface.

------
mrmondo
I'd love to see an annotated version of this.

------
TazeTSchnitzel
It's not quite the same sort of thing, but this reminds me of 'My Life as a
Forth Interpreter' (1986):
[https://news.ycombinator.com/item?id=7410883](https://news.ycombinator.com/item?id=7410883)

------
jlewallen
This is great! I can't help but feel there's also an opportunity in a sequel
to allude to the all too common "invent arbitrary abstract base classes to
keep my code DRY" anti-pattern.

~~~
jdmichal
For learning purposes for those reading this, what would you consider the
alternative?

I personally prefer just stuffing commonly used stuff into utility classes
containing only public static functions. Makes them really easy to test, too.

~~~
jlewallen
Thanks for asking! My answer, of course, depends on the particular scenario.
I've had success with simple static methods, especially early in a project.
I'd also consider some kind of composition (has-a vs is-a). The latter can be
especially nice as static methods gain complexity in the form of more
parameters/variations. This also shines if there's meaningful alternative
implementations that can be swapped or if you're writing business logic and
some legitimate business concepts start to congeal out of the code being re-
used.

------
jokoon
I can't understand java programmers telling me they don't like C.

~~~
lmm
A bad citizen in C counts to 32768 which corrupts the very fabric of the
universe, replacing New York with half of Los Angeles and leaving 25 people
repeating the same day indefinitely.

~~~
TeMPOraL
That sounds like a plot of a typical superhero comicbook. I guess we know what
language Marvel's universes are written in.

~~~
chris_wot
Every time a character swears they speak in Perl.

~~~
llogiq
But the universe is certainly written in Brainfuck.

------
yuchi
This is true horror.

