Next-gen Java Programming Style
codemonkeyism.com
codemonkeyism.com
I can not get behind this in Java if the filter, fold, or map operation is simply a one-off. (It's another matter entirely though if the power of the functional approach is useful in the situation, say if a filter should be switched dynamically.) To do this for something static though, such as eliminating empty strings or adding an array, is just worse than useless.
This is as clear an example as any of programming against the language, not into it. The code is longer, it is slower, and _for a Java programmer_ it is much less clear. Java was explicitly designed not to be a language for showing off cute constructs for their own sake.
The code is slower: It is slower but in my experience it is very rare that our performance bottle necks occur in these sections of code. We have actually profiled our code and changed from for loops in the legacy version to a redesigned version of the class using this more functional approach during refactoring and we can meet our performance needs just fine. More often than not the big performance improvements lie in disk i/o or more intelligent algorithms rather than just a general use of more functional idioms.
Much less clear _for a Java programmer_: Isn't that always the case until programmers start to learn other ways of doing things? If this was just one guy and not what appears to be a industry wide sea-change maybe I wouldn't argue. The functional paradigm however is being given a fair amount of attention and I don't think it's something you can classify as a niche concern.
"cute constructs for their own sake"- I believe the point of developers moving away from loops is that we are starting to realize that explicitly asking the compiler to loop through these items in this particular order is over-specification 99% of the time. Really we are just saying do this to each one of these. By shifting to a functional paradigm these types of tasks can be easily parallelized and abstracted to the point that you really care about.
Whether or not you think the performance implications are worth the benefits is a personal, contextual decision. But you just grossly misrepresented the entire point by saying that both styles are equivalent except that one is slower.
Why doesn't Java make it easier to refer to a method and call it dynamically?
For this example:
List<Person> beerDrinkers = new ArrayList<Person>();
for (Person p: persons) {
if (p.getAge() > 16) {
beerDrinkers.add(p);
}
}
If we had a legalAge method defined on Person returning true for any person over 16, then it would be nice to write the equivalent of List<Person> beerDrinkers = filter(persons, legalAge);
which would call the legalAge method on each person and keep the ones returning true. Like most things with Java, you can do this, kind of, but it means getting the instance class, looking up the method for the method name and signature, then invoking on the instance, all of which makes it just not worth it. Objective C has the idea of selectors, which is an easy way to specify the message you want to send to an object, which probably comes from some similar concept in SmallTalk.This is arguably a more object oriented solution to this general problem. For one, it better follows Demeter's Law, as you do not need to expose the getAge property.
list<Person> beerDrinkers = filter(persons, boost::mem_fn(&Person::legalAge));
Where filter looks something like: template <class Sequence, class Pred>
Sequence filter(const Sequence& in, Pred p)
{
Sequence out;
for (typename Sequence::const_iterator i = in.begin(); i != in.end(); ++i) {
if (p(*i)) {
out.insert(out.end(), *i);
}
}
return out;
}
We can even use this style if legalAge is something that takes a parameter, like ageCheck(age) using boost::bind (http://www.boost.org/doc/libs/1_39_0/libs/bind/bind.html): list<Person> beerDrinkers = filter(persons, boost::bind(&Person::ageCheck, 21, _1));http://docs.google.com/Doc.aspx?id=k73_1ggr36h
"Here is the same code rewritten using the proposed syntax:"
List<String> ls = ... ;
Collections.sort(ls,
Comparator<String>(String s1, String s2){ return s1.length() - s2.length(); });
By making anonymous inner class declaration more concise, you get many of the benefits of closures, without changing Java semantics.Pointing this out as unclear for a "Java programmer" is a bit of a red herring I think. Anyone can learn what map/filter/reduce/etc mean in no time at all -- it seems a simple task compared to learning the project-specific abstractions of any codebase.
I think it's really not. There's a talk out there, I think by Gosling, about the direction of Java including why lambdas were rejected for Java 7. One reason was actually to prevent the sort of functional code that polarizes people in terms of whether it is seen as beautiful or opaque. (E.g. currying, Y combinators.)
Java provides the flexibility to use functional programming through anonymous inner classes, but at considerable pain to the author. The point people miss is that that pain is actually a conscious part of the language design.
Anyone can learn about map/filter/reduce, and every programmer needs to for the situations when they are crucial. But on the other hand, the problems with explicit looping are much overstated and I'll admit to emotionally siding on the issue with the creators of Java and Python.
I don't think you can ever fully get the "how" out of programming, nor should you try, nor is "what" implicitly superior all the time in all situations.
That may be true, but it doesn't make it the right choice. And AFAIK Gosling himself has always been pro-closures, to remove this pain (see http://blogs.sun.com/jag/entry/closures).
>I'll admit to emotionally siding on the issue with the creators of Java and Python
The big difference in Python is that there are "pythonic" alternatives for the really common cases.
> nor is "what" implicitly superior all the time in all situations.
I agree there is such a thing as too much abstraction, but I really don't think map/filter/etc fall into this category. These operations are so frequent that if you don't abstract the how, you end up repeating it thousands of times in a significant codebase. At that point I think you end up on the wrong side of the fence.
public double foo(double x)
{
return x*x;
}
list=Utility.map(this,"foo",list);Might be worth the trade off in your case, but maybe not for the cases Google has in mind.
Google's approach, while more verbose, is a bit safer and more idiomatic.
I believe the more Java way would be to extend the List interface to add a map method and implement a corresponding class. To make this less of a pain, extend from one of the JDK provided classes if possible... but yes, it's still a pain.
That's enough for me to discard this article as chaff, but considering it even further, has anyone stopped to ask how the Java runtime and compiler handles these changes? Making new classes instead of mutating existing ones doesn't strike me as an efficient use of the system.
Finally, I am so sick of people lamenting being "trapped" in Java. This nonsense of being "trapped" is just a shield for people who don't want to go through the hassle of really using a different language. If I can squeak new languages in at Lockheed Martin on a huge spacerange project who's spec was literally conceived when I was still in diapers, then anyone can do it anywhere if they have the will.
Bloch's Effective Java is wonderful, but if it has a weakness, it might be that it assumes everyone is writing a library to be used by a lot of developers, many of who are outside your organization.
The example of public fields in data transfer objects is an example of this. Making the fields public is fine if this code is just for you and your team, because you can always refactor it to use accessors later if you need to. But if this code is in a library used by people outside your organization, introducing accessors later without breaking code will be almost impossible.
For what little it's worth:
1. Minor benefit as noted. Most devs don't do this. Note that in point 3 his sample loop doesn't declare the loop item final so I doubt he does it all that often either.
2. Ok so far as it goes.
3. What objective benefit am I supposed to get here? If we're pulling preferences out of our bums, I'll go for meaningful names in loop variables thanks.
4. Says who? AT&T braces for the win!
5. Not my preference. Fails the YAGNI principle certainly (which he's apparently in favour of in point 2).
6. Who says it's too hard to use? For simple threading problems the existing tools are more than adequate.
7. Again, what benefit does this convey? It's used in a few places in Java (StringBuffer/Builder) but hasn't proven popular more generally. I suspect there are good reasons for that.
8. Not wildly unreasonable, but Getter/Setter pairs often turn out to be necessary in fairly short order.
No, what getters and setters are is a huge verbose door cut through your encapsulation, turning a class into a mere vending machine.
On the one hand I understand where the author wants to go : by implementing many many interfaces you eventually sort of "emulate" duck-typing, while at the same time reinforcing type safety (specially when it comes to String).
On the other hand, it sounds like a good way to make something that was verbose to begin with even more verbose... but maybe I'm mistaking. I don't do much Java recently (some GWT/GXT sometimes), but I will probably give it a practical try...
But have you actually used this in practice ? Is it tractable ?
I'm actually thinking of trying this on (a rather old version of) C#, since I'm writing quite lots of code for (an old version of) mono. If only I could use F# sigh
Short version: yea, it works pretty well.
Long version is at this shameless blog plug (no ads): http://itgoon.blogspot.com/2009/08/javas-lots-of-little-file...
I don't see how using a const or final qualifier where appropriate increases bloat.
There are other problems with that idea, the first of which is that if someone else takes your code and extends it (say, for an open source project) they won't have the same "checking system" that you have, and so it won't catch their mistakes (while using "final" would). Also, I'm not a Java programmer (I mostly use C# or C), but marking classes/methods/variables in C# as 'sealed', 'final', 'static', etc. actually increases the running speed of that program on the CLR because it is able to skip some safety checks on the IL code when it is executed; I don't know that the JVM does that, but it might be worth looking into.
Don't forget that final things can still be changed, though.
somethingFinal.setName("teehee"); is still possible even if somethingFinal is final.
This would be know as really-really-late-binding.
(Yes, I know Java doesn't have named parameters, although it and many other languages that don't have it have a work-around with assignment. this is a general question.)
But this is Java, and it is the only way to cleanly allow inheritable initargs.
(Perl/Moose and CLOS get this very right. I only use setters in those languages in very, very rare occasions, and it is usually because I am hacking around something messy.)
synchronized is not hard to use. it's rather not a good practice to use it, since it will slow down code massively.
Down with Java, long live the JVM
He is advocating taking a verbose language and making it even more verbose and far less efficient. Think about what the final in "public final int x;" means in #8.
Many Java developers have fallen for the idea that everything is an interface to an interface. However, if you start by trying to get stuff done, you find a most scaffolding is pure waste.
The example in #8 is essentially recreating primitive tuple types present in the languages I just mentioned. Given that the overheads on such an object are small, and the garbage collector is good at dealing with short-lived objects, it makes sense to instantiate a new class when it is necessary to mutate it. Your optimiser will love you, and maintaining this style of code is considerably easier.
You might be all atwitter about the power of functional code. But, it's an old idea. Emulating the functional style a language that's not based on it provides minimal gain, at the cost of code bloat.
PS: Pun was intended to be funny not mean. This really is an old idea, which is occasionally useful, but mostly it's a waste of time, money, and CPU cycles.
And I really don't buy your "bloat" claim. Surely mutating member variables unnecessarily is "bloat". And having redundant getters and setters seems pretty bloated to me. In fact, forcing everything in the universe into a paradigm that largely consists of straight-line imperative code boxed up in classes seems like the ultimate example of bloat, given that one could simply code in an imperative style without using objects.
If anything, I would think that the measures suggested would result in marginally smaller code-size, which I assume is the metric you are employing to measure "bloat". In performance terms, I would imagine that these suggestions would result in no performance impact, or some small improvement as it is quite likely that the optimiser will be able to do a better job if you apply this style uniformly. As you say, it might be a minimal gain, but don't we as programmers have something of a responsibility to write the best programs we can and use our tools to the fullest of our abilities, especially when the cost is zero or almost-zero?
So what metric are you using here? I assume it's something a bit fuzzy like "readability" or "ease of maintenance"? In that case, you're basically saying "things that are different to what I already do are harder to do", which in addition to being mildly silly, is a total cop-out and is intellectual dishonesty. Too many good ideas in programming languages have been sunk by programmers who hate the idea of not being the expert all of the time, with such behaviour being hidden behind very weak justifications that sound technical, but are actually just about egos.
Naturally, this might not be the case with you at all! However, I'd be very interested to know on what objective basis you are making judgements about the awfulness and bloatedness of code (in any language) that employs a more "functional" style.
Anyway, the power of OOP is creating intelligent data. You can "automatically" do things with a Point that you need to explicitly do with integers. If you start dealing with a Fixed_Point objects, and Mobile_Point object, you now have bloat with little gain. It's far better to have a "Final" flag on your point, so it will toss an error when you try to change it vs. trying to maintain 2 separate classes. That way if you suddenly need to change your point you have to refractor less code.
Granted, if Java's foreach would automatically make helper threads to speed things up then there would be an advantage. But, changing the form without compiler support is pointless.
PS: Feel free to test your ideas, but allocating memory is still the enemy of speed. When you create a temporary object outside of the stack it really does slow things down.
Similarly, you don't think the tendency for most non-functional languages to adopt features and techniques from functional languages is because those ideas are inherently valuable? Sometimes a good idea is a good idea, and I think functional programming is an idea whose time has finally come. Maybe what you're labeling "fashion" is actually just a natural progression towards acceptance and adoption that started several decades ago.
Personally I think the trend towards selectively adopting functional features (if there is one!) could only be positive. If more programmers become comfortable with the concepts underpinning FP, then making the jump to using plain ol' FP (rather than <insert your language here> with anonymous first-class functions bolted on etc) will likely be much easier. Maybe it'll lead to wide-spread adoption!
To directly answer your question, I think that the merit of functional programming techniques is in their application as a whole. Sniping high-profile individual techniques does not bring a proportional benefit. It is simply cargo culting. It is "fashionable" to mention "functional" programming and to butcher the concept of referential transparency when writing code in Java, C++ and C# these days. All it does is create a new style of obfuscation for these languages.
I don't understand what this means.
> If you start dealing with a Fixed_Point objects, and Mobile_Point object, you now have bloat with little gain
Why would you not have a single point class implementing multiple interfaces? Surely if they do the same thing, you wouldn't bother. Good design would dictate that if they do similar things (but not the same), they should probably share an abstract parent class anyway.
> It's far better to have a "Final" flag on your point, so it will toss an error when you try to change it
And check this at runtime for every access!?! Why on earth would that be more efficient than static checking at compile time?
EX: Tail recursion (http://en.wikipedia.org/wiki/Tail_recursion) will be optimization if your code is a specific form AND your compiler also supports transforming to into loop. However, if you use the form without compiler support you are killing the stack and should manually convert your code to a loop by hand. Edit: Tail recursion really is just another loop; it's often used as a backhanded way to have mutable variables in a functional language, but in Java you might as well just have a loop.
And check this at runtime for every access!?! Why on earth would that be more efficient than static checking at compile time?
You only need to check it when you are updating a member variable not when you read it. Note: it does not save you from updating the variables inside the class if you bypass the getters and setters, but that’s a side issue. Anyway, if you check it ~50 times vs. creating one extra object you should come out ahead in speed. More importantly you will have far less and more maintainable code.
PS: Using multiple interfaces to the same class is a reasonable option, with some tradeoffs. You still need to maintain more code, but it is pure fluff so not that big a deal. However, that's not what he did.
Temporary fixed size objects can be created and destroyed with little overhead. But you need to profile things to get a good metric. http://java.sun.com/j2se/reference/whitepapers/memorymanagem... Has some of the details.
Creating an object that lives on the processor cache can take 150 cycles which is FAST. But, the more complex the object the longer the allocation, and you can quickly start to fragment your memory if you have several short lived objects that don't die at the same time. Assuming your checking a variable in L1 cache then it's still an order of magnitude faster, but once you start taking longer to load the object into cache etc so it's not really a stable time either...
PS: It's going to get really application specific so I can't think of realistic test outside of an actual application. Still I will try some simple cases tomorrow.
Just remember that final is a signal to the compiler that it can perform certain optimizations on your code. This includes inlining the value.
So if you use
public static final KEY="value1";
you can get inconsistent class files if you change the value, the copy classes that use KEY 'variable' across selectively.This is most ant webapp and J2EE compiling workflows.
When the compiler sees a final method call it can
(at its discretion) skip the normal approach of inserting code
http://www.codeguru.com/java/tij/tij0071.shtml