Tales from the jar side: Trust the Java compiler, When trust on the job breaks down, and the Suez (Root) Canal
In which some restraint is shown by not including the WD-40 or giant cotton swab jokes. Beside, tugboat size doesn't matter; it's how you use them.
Welcome to Tales from the jar side, the Kousen IT newsletter, for the week of March 21 - 28, 2021. This week I taught my regular Introduction to Gradle course for Gradle, Inc, and a Functional Programming in Java course on the O’Reilly Learning Platform.
Most Experts Are Not Idiots
During my Functional Java course this week, one of the attendees asked me what I like to call the “performance question”. They wanted to know if the switch from the classical approaches (loops, if-statements, and mutable collections) to the functional idioms (streams, predicates, and immutables) has a significant performance cost.
As a trivial example, given a list of strings:
List<String> strings = List.of("this", "is", "a",
"list", "of", "strings");
and the goal of computing the total length of all the even-length strings, here’s the “before” picture:
And here is the “after” picture, using the functional approach:
Neither approach is particularly complicated, but the first one is the kind of code Java developers have been writing for over twenty years, while the second uses a more functional approach. In fact, once you get used to it, the second version is a lot easier to read than the first one.
The performance question is an entirely reasonable one, but it often bugs me. It causes me to go on a rant, which I’d like to explain here.
Much of the problem is the way the question is phrased. Rather than a simple, “how does this approach affect performance?”, it often gets a nasty tone of, “you idiot, you’re creating all these additional objects and then destroying them. Don’t you realize that this is much less efficient? How could they possibly want us to use this?”
I’m exaggerating, of course, and the person who asked the question in my class wasn’t anywhere near that confrontational. It just feels that way to me. Admittedly, I don’t care for performance questions in general. I’m a big believer that when it comes to code, understanding and maintenance is far more important than performance, and that being able to write code in an easy, intuitive way is much more vital than squeezing the last bit of speed and memory out of it. But the other reason I don’t like the question has to do with trust.
I know some of the members of the core team personally who work on the Java language and libraries, and they’re very smart people. They dig into the guts of the compiler and have active discussions about how to accomplish whatever they need to do. In short, I trust them to try to do the right thing.
Equally important, the functional features were added to Java as part of Java 8, which was released in March of 2014. That’s seven years ago, which is an eternity in this world. Believe me, if the switch to streams and lambdas caused even a 1% performance degradation, somebody would have noticed by now.
In other words, no, I don’t know the details of how this is implemented under the hood, because I don’t need to know. If the implementation caused a serious problem, it would either be fixed by now or abandoned.
There are good reasons to ask the performance question, of course:
You just want to know how the new way compares to the old one. I have a demo ready for that, which compares the performance of adding up 10 million long values using both approaches, as well as in parallel. The answer, btw, is that the stream approach is a bit faster than loops, though I would only say it’s comparable enough that you don’t need to worry about it.
You work for a high-speed trading firm on Wall Street, which means you actually care about locating your physical data center close enough to the trading floor to minimize speed of light delays. If that’s your situation, good luck with that. I’m not the right person to talk to about fine-grained optimizations of that magnitude.
You haven’t yet learned that “premature optimization” is a bad thing, and that it’s far more important to get code working before you try to make it as fast as possible. So many hours have been wasted optimizing too early. Get it working, get it right, make it fast, in that order.
Back in the early 90s, I had to learn the basics of C and C++. One of the “best practices” that was suggested back then was that if you wrote a for loop, be sure to increment the loop counter using ++count rather than count++, because the first approach avoided creating a temporary variable that the second approach didn’t. Since Java loops are similar, the practice continued, and you can partly tell from reading that kind of code that the developer came from the C world.
(I call that practice — learning about the world of the developer from their code — electronic anthropology, which I’ve mentioned in earlier newsletters.)
Do I follow that practice when I write Java code? Of course not, because we now have optimizing compilers that take care of that issue automatically, along with dozens of others. Let the compiler do what it does best, rather than relying on developers. Let the developers focus on solving problems in a maintainable, understandable way, rather than asking them to optimize features whose details are hidden under the hood anyway. In my view, the developer’s time is far more value than the compiler’s.
I understand the reason for the question, and if it’s asked with the assumption that there is a legitimate answer, I’m happy to address it. I even have a demo ready, as I said, and can talk about what practices do and do not affect performance. But when the question is asked with an attitude, I have a problem with it. That questioner is saying, “yes, I’ve only just been introduced to this technology, but I see a problem immediately that I’m sure all those so-called experts have missed for years.”
It’s possible you did. But it’s way more likely that anything you notice when seeing a technology for the first time has been thought of before. If it’s really a problem, I promise you that somebody somewhere saw it. Sure, even experts can be wrong, and the list of what’s best changes over time, but the way science and engineering works, lots of people evaluate expert claims on a regular basis. You may see something new, and good for you if you did, but try to at least assume experts aren’t complete idiots.
On a completely unrelated note, get whichever COVID vaccine is available as soon as you can.
Trust But Verify
There is another reason why people question experts these days, and it’s that they don’t trust their motives. For whatever reason, they believe the experts are lying to them. Sometimes they come up with conspiracy theories that reveal hidden reasons why the experts are making their recommendations, which benefit the experts but not you.
I don’t think you need to worry about that when you’re dealing with the core team at Oracle who work on the Java compiler, but there is an issue of trust I need to acknowledge. This is a bit of a running theme in my new book, Help Your Boss Help You, available now at the Pragmatic Bookshelf in beta form.
The book argues that one key to success at work is to build a productive relationship with your manager based on constructive loyalty. That means you trust your boss to do the things you don’t want to do, like fight organizational battles, protect you from external conflicts, and free you from distractions so you can get the job done. They trust us to do our jobs to the best of our ability, to support them when problems arise, and to make recommendations in our area but carry out whatever decisions they make.
The trust you need to have with your manager is different from the trust you have with your partner (if you have one), other members of your immediate family, or your friends both in real life and on social media. The problem at work is that sooner or later your manager will do something you don’t like, and you have to be able to object without fracturing the loyalty relationship. In this sense, trust is not an absolute. There are levels involved that allow you to work together, that let you protect yourself so you are neither surprised nor hurt when trust appears to be violated.
I’m struggling with this personally in two different business relationships I have at the moment. In each case, I no longer believe that the people I’m dealing with care that much about me or what I want. I would argue that I don’t trust them because they’re not trustworthy, but the situations are undoubtedly more nuanced.
I keep reminding myself that seeing bad motives on a routine basis is a trap. The problem with distrust is that every time one of those people contacts me, I’m immediately suspicious, and I see reasons for what they’re doing that might not actually be there. I’m hesitant to commit to anything, and I keep trying to verify that they’re doing what they said they would do. As the phrase at the height of the Cold War stated, “trust, but verify.” Unfortunately, that can be a huge waste of time and energy.
The way I’ve been trying to handle this is:
Recognize that I’m likely seeing hidden motives where none exist. Most people are doing the same thing I’m doing, which is just trying to get by as best can, and my needs and motives probably don’t enter into it. They’re probably not trying to take advantage of me, even if it feels like it sometimes. It’s possible my uncomfortable feelings about them are right, but don’t get carried away.
Acknowledge, at least to myself, that both relationships are on borrowed time. They’re both going to end, one way or another, so I only have to get the jobs done and I’ll be rid of them. In the meantime, sure, I’ll protect myself as best I can, but I can push back, too. Knowing you are definitely leaving is remarkably freeing. It lets you take risks, because if that risk ends the relationship, that was going to happen sooner or later anyway.
I’m not sure how to add this to the book. I did some research on levels of trust in relationships, but too much of it is handwaving done by consultants I don’t necessarily trust (oops, there it is again). I’m watching both situations, however, and trying to figure out the best way to handle them. Whatever I figure out will no doubt wind up in the book somehow.
If you have any suggestions, please let me know. After all, I have complete and implicit trust in all the brilliant, good-looking people who have the excellent taste to read my newsletter.
Meme Watch: Whatever Floats Your Boat
I didn’t have much a meme watch last week, mostly because no one event captured the whole world’s attention. Unlike this week, when we all focused on a big freakin’ boat.
Courtesy of istheshipstillstuck.com:
That’s a really good website. It not only shows the time and a map, it includes a list of the latest headlines from around the world. It even has a link at the bottom, which says, “To be peak 2021, bid on an NFT of this page (on Open Sea),” which is a riot.
Not only is the Ever Given (a weird name if I Ever Saw one, not to mention it’s own running gag) firmly wedged into the Suez Canal, it’s likely to be there until global warming raises the sea levels enough to float it away.
While this is costing the world economy literally billions of dollars, on the plus side it’s been a great source of memes. Here are a couple of them:
You shall not pass!
This Austin Powers variation was inevitable:
One approach for clearing the block that probably won’t work:
Reminder: Africa is big.
And yet, they’re doing it:
This one is a bit too real:
Variation on a theme:
Chess Grandmaster Nigel Short came up with a palindrome:
Sometimes the solution is easy:
This one is brilliant:
Is it the Love Boat, or Tinder only you swipe port and starboard? All I know is there are lots of good fish in the sea.
Hearkening back to an earlier meme:
Some perspective on why this situation is so captivating:
Finally, I’m sorry, but I simply can’t resist this one:
That’s enough. Presumably by the next newsletter, they’ll override the filibuster and the boat will move.
Last week:
Introduction to Gradle, for Gradle Inc.
Functional Programming in Java, on the O’Reilly Learning Platform
This week:
Reactive Spring, on the O’Reilly Learning Platform
Kotlin Fundamentals, an NFJS Virtual Workshop
Spring, private class