

Fear and Loathing in Programming La La Land (2012) - fogus
http://erlang.org/pipermail/erlang-questions/2012-March/065519.html

======
zwieback
I think the poster's point 1 is really the key here. In addition, I think
Intellisense-driven programming has a lot to do with it. I suspect a lot of
.NET programming goes like this (I know I've been guilty of this)

1) Hmm, let's see what classes are in this namespace... Ah, this one looks
like it might do the job so I'll type

    
    
      var foo = new ThingWithInterestingName();
    

2) Dang, don't want to scroll through tooltips for 23 different constructors
with poorly named params, think I'll just use the default constructor, they
probably implemented that for casual users like me.

3) Now I can type foo. and let IntelliSense give me options. When I call a
function I get an error for each call instead of some crazy exception for the
whole thing. Maybe I can even test stuff out in the Immediate window in the
debugger.

So, I think it's not only miseducation or layzness, it's that modern IDEs for
static languages encourage discovery based development in favor of reading
through API documents.

~~~
sparkie
There are legitimate reason to use create-set-call: for example, whenever you
need polymorphism on object construction - ie, you're constructing a yet
unknown type which implements an interface or extends a class.

C# doesn't allow you to specify in an interface or abstract class the
parameters that a constructor must take: which makes it very difficult to use
such classes as generic type arguments for instance. There's a new()
constraint which allows you to call a parameterless constructor, and if you
also constrain the generic type argument to some interface, you can set the
data you want through it.

If you expect parameters in the constructor though, you can't simply create a
new object of the type passed as a generic argument. You must use reflection
(Activator.CreateInstance(typeof(T) ...), assuming that there exists a
constructor for the yet unknown type (obviously not statically checkable). To
prove such a constructor exists at runtime, you can use
typeof(T).GetConstructors(), and search through the returned collection for a
ConstructorInfo with matching arguments. If you get this far, you'll probably
drop the idea and resort to the create-set-call mess instead.

I suppose a way of fixing this would be to introduce some kind of "constructor
pattern" into interfaces and non-sealed classes, requiring subclasses to
implement it and allowing the use of said constructor pattern as a generic
type argument constraint.

Another time you might need create-set-call is if constructing objects which
have a mutual reference to eachother. [ var a = new A(); var b = new B(a);
a.setB(b); ] cannot be expressed with parameters in both ctors. This might
seem like a "bad idea" due to the circular reference, but it's more common
than you'd think, and doesn't necessarily mean bad code.

~~~
strager
What's wrong with:

    
    
        void Foo<T>(Func<Int, String, T> makeT) where T : IIface {
            T myT = makeT(10, "hi");
            // ...
        }
    
        Foo((x, y) => new MyClass(x, y));
    

In patternese, this is injecting a factory dependency.

~~~
sparkie
I completely forgot about that pattern, not used C# in a while. Yes, this
works for cases where you know what class you might pass in ahead of time, and
can say new MyClass (although might break the principle of least
astonishment). There are cases when you can't use that pattern though: for
example, when you have some plugin framework, where plugins are loaded
dynamically at runtime, you search for classes implementing an IPlugin
interface, and create a new instance of said class.

Reflection must be used in that case. Using `new T()` for parameterless ctors
is just a call to Activator.CreateInstance<T>(), but there are no generic
CreateInstance overloads taking arguments.

------
jerf
It's convenient that the poster initialized the relevant flame war this will
degenerate into right in his post there. A discussion about the best way to
structure APIs is surely not complete without flaming people about being
elitist and that opportunistic programmers exist, and more flames about the
fact that since they are producing lots of real world programs you should just
shut up about them. I appreciate the guidance. I might have accidentally
started flaming about event-based programming or the utility of NULL pointers
instead, you know, and that would just be _gauche_.

~~~
coldtea
> _A discussion about the best way to structure APIs is surely not complete
> without flaming people about being elitist and that opportunistic
> programmers exist, and more flames about the fact that since they are
> producing lots of real world programs you should just shut up about them._

The initial posting was structured to very much ignite a flame war, already
from the title ("programming la-la land").

It was arrongant, condescending, and, as far as it's content is concerned,
shallow.

Basically merely a few quick remarks that were supposed to take down a proper
study (of which the "critic" misunderstood the scope, reasoning, and who it
concerns).

As for the existence of "opportunistic coders" (a concept which he also
misunderstood), he wasn't told to "just shut up about them", but to understand
that whatever the fuck his objections are, they are a real group, they are
valuable, and an organization operating in real life needs to also catter for
them.

~~~
tome
> The initial posting was structured to very much ignite a flame war

If that is indeed true, you will notice from the replies to his message that
he definitely did not succeed. However, I prefer to interpret it at face
value. He does say "Frankly, I've turned here for a bit of comfort. If anyone
likes completely initialising things rather than smacking one field at a time,
surely I will find such people here.". To me it is just venting amongst
friends.

------
oinksoft
Richard O'Keefe has deep knowledge of computer science and software
engineering, and his posts to erlang-questions, where you'll often encounter
Erlang, Prolog, LISP, Java, and C neatly woven into the same message, are
almost always enlightening.

~~~
stiff
He is the author of "The Craft Of Prolog", a quite famous book among people
caring about programming.

------
herge
Reading this, I though to myself that one of the biggest features I like in
python that is missing in java is named and optional parameters.

Also, any api/library that lets you create an object that is unusable because
specific methods to set up values haven't been called yet is very error prone.

~~~
sparkie
I think optional parameters are a mis-feature in C#. You can acheive the same
thing with a simple overload which calls a method without the optional
parameter, and this is more robust.

The problem with optional parameters is they work by call site rewriting. If I
have some library method where I give an optional parameter a default value,
and a program is built against it - if I later change the default value, this
will not be propagated to the program until it's recompiled - it'll continue
to use the old default.

They could probably fix this by implementing overloads behind the scenes,
rather than rewriting the call site though. If Java does ever implement this,
I hope they do it that way.

~~~
sitharus
Even worse, optional parameters are implemented backwards.

That is: public void DoSomething(string required, string optional = null) is
actually DoSomething(string, string), but at compile time a call to
DoSomething("foo") is compiled to DoSomething("foo", null).

Hence optional parameters are not recommended for an external API.

~~~
sukuriant
So you need to be mindful and have intelligent overloads for the DoSomething
method?

Personally, I don't really see that as much of a problem. Having run into that
issue before, I think the compiler catches it as as an error because its an
ambiguous method signature. Instead, you have to pass something like:
"DoSomething("foo", (string)null)" which, in that case, defeats the purpose of
the optional parameter altogether.

~~~
sitharus
Yeah, been through that before. We just standardised on using overloads for
external APIs, it's cleaner externally.

The real issue is if you have DoSomething(string what, autoRetry=true) and you
change to DoSomething(string what, autoRetry=false) - DLLs compiled against
the old version will call with true even if the authors wanted the default
behaviour.

~~~
sukuriant
That makes sense. As I said in my other thread, I locally deal with that
problem by passing null instead of a primitive (though admittedly, I would
probably use a primitive in cases of bool).

That said, in this circumstance my method sounds more like a hack and yours
the cleaner, correct route.

------
coldtea
Needlessly condescending and not so bright himself for it.

For example he didn't understand what the three categories of programmers were
meant to be (tendencies between good programmers working at MS -- hence, even
those deemed "opportunistic" are not some clueless idiots worthy for the Daily
WTF).

Second, there are a few cases to be made for the second style (even over named
parameters).

One is less clutter at the constructor level.

A second is easier reflection/dependency injection.

A third is it forces saner defaults.

Also, better readability for some (which is not all about cramming as many
lines in the same editor screen).

It also makes parameters independent of ordering -- which in the compiler they
are, but in a constructor they are not (except with named parameters, and even
those have to come AFTER non named ones).

The only real downsides are: a) the possibility of using a half-baked object.
But I don't see how that would be any different than omitting some of the
named params. b) third parties mutating the objects. But then you have the
same "issue" in most dynamic languages anyway.

(The off topic jab against "climate change" at the end was also pathetic --
apparently he's one of the climate change deniers, despite overwhelming
acceptance of the notion from the scientific community, putting them on par
with Creationists).

------
drawkbox
I like readable code, he didn't mention readability. The only thing I really
care about in code is that it is readable and doesn't stretch all in one line
and not broken up. Small chunks are better than a ninja one liner.

Constructor arguments/params are fine as long as the code is readable and line
breaks to keep it within a decent column size. I also think that constructor
arguments can sometimes get into overload messes just as method calls can. A
good api breaks up any overly parameterized constructor or methods.

I just want code to be readable, fit within a decent column area and make
sense. Whether it is in constructor params or method params there shouldn't be
too much done in one line for complexity sake.

If programmers don't get constructor params then they probably don't get
method params either. I think people just want stepped-readable code in most
cases. Named and optional params help to clear up long initialization or
method calls but in the end it is about balance and readability.

Smaller, iterative code bits are easier to put a breakpoint on as well say for
instance one param was null and it broke on constructor, it might take some
more inspection to find unless it was a specific set.

------
rdtsc
FYI this was posted in Erlang's mailing list. There was a following discussion
about it if anyone is interested.

[http://erlang.org/pipermail/erlang-
questions/2012-March/thre...](http://erlang.org/pipermail/erlang-
questions/2012-March/thread.html#65519)

------
aviraldg
From a purely technical point of view, doing this is a terrible idea as it
adds additional, unnecessary state to objects, and hence makes it possible for
them to break in more ways.

Using the Builder pattern, or keyword arguments, achieves the intended goal of
making API features discoverable without the added complexity.

------
tome
I don't know who Richard O'Keefe is but I do know he writes intelligent things
on the haskell-cafe mailing list.

