Thursday, April 30, 2009

Good Programmers ARE Lazy...

...but not in the way this article seems to think the phrase means. Did anybody really think that by saying "Good programmers are lazy" we meant "showing a lack of effort or care", or "characterized by lack of effort or activity"? Come on: it's a humorous expression with enough truth in it to take seriously.

When people say that "good programmers are lazy" it means that good programmers try to find ways to cut down the amount of time spent on boring and/or repetitive things. Boring and repetitive things include build and deploy processes, boilerplate code and documentation, repeating oneself, and so on. We *could* do all those things manually. We *could* write the same code over and over and change only a few details. We *could* execute our tests by hand.

But we'd rather not. We'd rather our tools did our builds. We'd rather abstract our code so we can re-use it across projects. We'd rather spend the time and effort to create something we can use over and over again--thus saving *more* time in the future (and maybe even saving *other* people's time).

Does that mean we're lazy in the strictest, non-humorous sense of the word? Of course not. It's usually much more time-consuming, the first time around, to produce something that will save time in the future. It requires more thought, more testing, more development, more of just about everything.

But we do it anyway, because we're lazy: we don't want to have to do the same work *again*. Cort Dougan took a humorous aphorism and turned it into a diatribe against... well, something the aphorism never was. His article continues an assault against several unrelated topics.

Testing is no longer part of the development process?! If anything the burgeoning TDD movement has brought it closer to the forefront than ever before. Apprenticeship is gone? Hardly--mentoring is stronger now than ever before, in both professional and amateur programming.

XP couples distinct modules because it encourages making sure changes don't break existing code? Continuous integration doesn't promote tight coupling--only code can be tightly coupled. How often code is checked in, built, and tested has nothing to do with our architecture.
"Languages with garbage collection and sophisticated data types hide complexities from programmers. These languages are useful for teaching programming but are dangerous for production use."
I don't even know where to begin on that one. How is a language with GC dangerous for production? Java is dangerous for production? What kind of production are we talking about here? If we're talking a resource-constrained, deterministic real-time system maybe it is (and even that is just a maybe). What constitutes a "sophisticated data type"? Don't we *want* to shield ourselves from complexity when practical?

The article then moves into a "solutions" section, including things like "have a list of tasks that must be completed". Even us "lazy" programmers have a TODO list. "Design then write?" Even the *most* extreme of extreme programmers will usually sketch out a data model or high-level system overview. "Write an example." Oh, you mean XP and/or TDD. Check.

Then it moves into bizzarro world: "fire software testers." Right, because I'm guaranteed to catch every error present in a system. "Know what you're doing at all times." Okay, thanks for that.
"A useful exercise I used for someone I worked with once was to stop him every 10 minutes and ask him what he was trying to do."
I'm trying to get you to STOP INTERRUPTING ME EVERY 10 MINUTES, so I don't have to spend an additional 15 minutes getting back into flow. I'm trying not to punch you in the face. I'm trying to find another job.

"Good programmers are lazy" doesn't mean we sit around in a pile of our own filth and make the pizza delivery guy step over empty boxes to hand us our next meal. It means that good programmers attempt to find reusable solutions to problems so that the next time we face them we *can* be lazy, push a button, and have our work done for us.

Being lazy often means a large up-front investment: that's not lazy, that's just prudent.

Thursday, April 23, 2009

Java is NOT Design by Contract.

In a recent DZone comment thread somebody stated:
[...] Java did great in pushing design-by-contract [...]
This caught me off-guard; I've never heard anybody refer to Java as a DbC language before. The rationale provided was that Java was the first general-purpose language to push interfaces--but interfaces are probably the weakest form of DbC I can think of. (We'll ignore that Eiffel predates Java by something approaching a decade.)

Here's a simple example highlighting the weakness in thinking Java is DbC. A simple bank system might expose the following interface:

interface Account {
void deposit(Money amount);
void withdraw(Money amount);
Money getBalance();
}

We know the operations we can perform on an account, but know absolutely nothing about the behavior of an account or the expectations of the interface methods. Can the amount be null? Negative? We don't know. Does making a deposit actually increase the amount of money in the account? We don't know. Sure, we can check the Javadocs, but they're not tied directly to the code.

There is nothing contained in an interface definition other than the operations we can perform.

In Eiffel, a strong DbC language, the deposit() method would look something similar to the following. It turns out the Eiffel tutorial has this exact example, which I didn't know when I started. I've removed some of the example for clarity.

deposit (sum: INTEGER) is
require
non_negative: sum >= 0
do
balance := balance + sum
ensure
updated: balance = old balance + sum
end

Now we know, as does the compiler and runtime, that sum must be zero or above, as stated in the require section. We also know that when we're done that the new balance will equal the old balance plus what we just deposited, as defined in the ensure section.

Now that is DbC. But that isn't even all of it: Eiffel also allows class-level contractual information. The following is part of the tutorial's account class:

invariant
consistent_balance:
(all_deposits /= Void) implies (balance = all_deposits . total)
zero_if_no_deposits:
(all_deposits = Void) implies (balance = 0)

Still want to claim that Java is a DbC language? Yes, we can do all of this in Java code--but we can do that in any language, no matter how DbC (or not).

Interfaces may be *a* form of DbC, but they're the weakest form possible. Interfaces define only *what* we may do, and provide zero information about expectations.

In a previous post I discussed DbC for Java via SpringContracts; it's a step in making Java much more DbC-like. With a fuller expression language it would be a pretty good solution.

Monday, April 20, 2009

People Still Do JSP Wrong--But Why?

The JavaRanch is a site for "Java greenhorns" (although it caters to quite advanced users as well). As such sometimes things are posted there that make even relatively new Java programmers cringe.

A recent post in the Struts forum asked a question about frames, which ends up being the least of the problems. The code snippet posted looked like this, spacing preserved:

<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr class="topbanner">
<td height="81">

<%
String contextPath = (String)request.getContextPath();
IDfCollection cabinetList = (IDfCollection)session.getAttribute("allCabinets");
try{
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse (new File("tree.xml"));
doc.getDocumentElement().normalize();
NodeList listOfCabinets = doc.getElementsByTagName("branch");
int noOfCabinets = listOfCabinets.getLength();
for(int i=0; i<noOfCabinets; i++){
Node cabinet = listOfCabinets.item(i);
NamedNodeMap attributeMap = cabinet.getAttributes();
for(int j=0; j<attributeMap.getLength(); j++){
Node attribute = attributeMap.item(j);

if(attribute.getNodeName().equalsIgnoreCase("id")){
String value = attribute.getNodeValue();
%>
<tr bgcolor="#CCD3D9">
<td height="1" colspan="2" class="helptextbold2">

<div class="trigger" onclick="javascript:showBranch(<%=value%>);swapFolder(<%=value%>)" id="<%=value%>">
<img src="images/closed.gif" border="0">
<table align="left" width="20%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td bgcolor="white">

<html:frame>
<a
target="<%=contextPath%>/DocumentManagement.do?cabinetName=<%=value%>&methodName=getCabinetContents"
onclick="javascript:showBranch(<%=value%>);swapFolder(<%=value%>)">
<%=value%>
</a>
</html:frame>
<%
}
}
}
%>

</div>
<br>
</td></tr></table>

I wonder about the environment and mindset that allows code like this to exist. I'm not (merely) singling out the person that asked the original question; I see code like this all the time. I do, however, have problems understanding how, in 2009, there exist places where code like this can be written. Where are the mentors? Where are the examples that beat code like this into a bloody pulp and make even the thought of writing it unimaginable?

Code written by people that care (almost!) never looks like this. Attention to detail pervades well-written code: take indentation, for example. I don't know of any editors that make indentation impossible. Indentation matters: it's a drop-dead simple way of indicating structure and hierarchy. Indentation can reveal flaws in structure and hierarchy, the snippet above having several. Incorrect indentation is misleading, impedes understanding, and creates unnecessary cognitive overhead. Indentation doesn't matter to the compiler: a valid point--but it matters to *people*.

The indentation isn't the most disturbing part of the code above--once I corrected the indentation (as best as I could, considering the snippet's incompleteness) the real killer is the chunk of XML processing code sitting in the JSP. Ignore that it's parsing an XML file on every page load, ignore that it's iterating over a *map* to retrieve a single mapped value (the id).

Come on: even apps that used servlets and JSP can be written to remove the need for this kind of programming. And this is *Struts* (Struts 1, but even still)... why bother using Struts at all if this is the code you're going to write?

Do the XML processing in a *real* Java file, where it belongs. Put it in a service object so when caching is implemented all you need to do is change the service implementation used by the action.

Even *Java* has mechanisms that allow (relatively, let's be realistic here) concise JSP. Hide the inner per-cabinet HTML in a JSP-based custom tag. Use JSTL. Use JSP EL. Drop the monstrosity above down to this:

<table class="cabinets">
<tr>
<td>
<c:forEach var="cabinetName" items="${cabinetNames}">
<app:cabinetInfo cabinetName="${cabinetName}"/>
</c:forEach>
</td>
</tr>
</table>

I rag on Java a *lot*, and I have reasons to--but this is 2009, and people writing the same kind of apps that people were writing circa 1998-2000 is inexcusable. In what company would the original example have survived even a *minimal* code review? It's not even acceptable for a rapid prototype, at least nowhere that I've been associated with. So where did the breakdown occur? Is it this particular developer? No, because code like this exists all over the place. That said, *good* developers strive to understand and work with the environment they're in, and use it to the best advantage possible.

Is it the company the developer works for? *Somebody* approved this code. Yes, the approver might have been the original developer--but that leads to a host of associated problems. Code reviews should be an integral part of a good development process. Mentoring can be part of, or parallel to, a code review process. This code should not have existed for more than a single checkin.

Is it the sample code found in books and the internet? Let's be honest--book code is highly edited for space and educational purposes. Internet code is largely the same, although some sample code is clearly better than others. "Graduated" code samples, where the code is drillable, with the basics covered first but that allow access to a complete code sample (you know, error handling, I18N, whatever) should be encouraged. We can't make people *use* good code, but we can get it in people's faces much, much more than we are now.

Some thing, or things, are broken when code like this is posted and the question is anything other than "How can I make this code tolerable, readable, extensible, and debuggable?" I don't know how to fix it, or to make people indent their code, or to convert all existing examples to be more instructive about something other than just the laser-focused point the example is trying to make--but I know that code like the original snippet makes me wonder about several steps in the coding process at at least one programming house, and it makes me want to make sure that my code, and the code of places I'm associated with, never looks like it.

Sunday, April 19, 2009

Does Anyone Love Java? Nah.

A post claims some people love Java. Fair enough: I'm sure some people love Java.

How many thought leaders love Java? How many people whose opinions we care about love Java? I'd wager it's a small number. Many of the most prominent in the Java world spend their time working around Java's limitations via frameworks, environments, and tools.

Do they "love Java", or do they react to its weaknesses because that's the environment they're working in and they want to make it suck as little as possible? They're spending their energy making the Java ecosystem a better place in which to live.

The article continues: "Why love Java? Let’s look at what Java offers: portability, automatic garbage collection, object orientation." But these features aren't unique to Java: why love Java in particular? What's compelling about Java the language?

Why love Java? Because there are great tools and libraries? That's a reason to love the Java ecosystem. What about Java the language? What does Java bring to the table that makes it worth loving? Okay, static typing makes tool development easy. It's also one of Java's greatest hinderances, and makes for redundant, boiler-plate programming. So it's a reason to like Java in one regard, but detest it in another. For me, reducing cognitive overhead is more important, so I lean to the "detest" side.

Using a google search for '"I hate Java" programming'? At the very least search for "Java sucks" (~14000), "Smalltalk sucks" (345), "Ruby sucks" (2390), or "Lisp sucks" (3120). '"I love Java" programming'? I got results for t-shirts. Doesn't count.

Show me why people say they "love Java". Here's one answer (I found surprisingly few, despite the "high" number of hits: 4910): "I love that Javadocs exist! I love that Java makes it easy for sane people to write decent software, relatively easily. I love that I have tons of pro tools that make development a breeze (IntelliJ IDEA and JFormDesigner amongst many others). I love Ant. And I love that compiler."

Javadocs? Allows sane people to write decent software relatively easily?! Ant? The compiler? These aren't reasons: there are documentation tools for essentially every language. The second point doesn't deserve a response. Ant may be a step up from make--but steps away from better tools. "Love that compiler" isn't even a reason... and they didn't even mention the JVM (also not Java, but the JVM is pretty bad-ass.

Here's another: "I love Java for how advanced it is, for the standards (see JCP and JSRs) that have been defined, for the other languages that you can run on top of it, for its rich frameworks and libraries, ..."

Advanced compared to what?! The standards... oy. The languages you run on top of it? That's the JVM, not Java. There are a lot of frameworks and libraries for Java--but they're all saddled by the same things that make Java broken, or exist to help alleviate Java's deficiencies.

Another: "I'm a big fan of programming in Java because it's so easy and fun." Compared to what? Obviously you're not familiar with the slew of easier languages, most of which are more fun, precisely because they're easier, more natural, and so on.

So sure. Some people may "love" Java. But until we see some concrete reasons why they love Java-the-language, and until they account for what they're comparing it to, I'll look at such claims somewhat skeptically. So far the only people I've run in to that "love Java" are people that (a) know very few other languages (and what they know are things like VB and C, not Lisp, Smalltalk, Ruby, Python, and so on) and/or (b) aren't very good programmers.

I know good Java programmers, but they don't "love Java": they tolerate it. The programmers that I happen to respect and listen to don't "love" Java--most dismiss it out of hand, and can provide reasons for doing so.