Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Tuesday, March 12, 2013

Tied to the Web Layer

Struts 2 claims that "actions can be POJOs". Developers find out pretty quickly that not extending ActionSupport means you lose some Struts 2 functionality (primarily I18N and validation).

One source of confusion is what "POJO" means. POJOs don't mean you don't extend a base class. POJOs are classes not directly tied to unrelated libraries, specifications, etc. For example, Struts 1 actions were directly coupled to the Servlet specification and Struts 1: S1 action methods had signatures including things like HttpServletRequest and ActionForm.

I think of S2 actions as the interface between the client (browser, REST consumer, etc.) and the stuff that actually gets stuff done. S2 handles validation, type conversion, flow (or at least conversion of business-level flow into web-app flow), etc.

Heavy lifting happens outside of anything related to my web layer: persistence, logic, and calculations happen in services, utilities, models, and glue. How is it relevant that my web layer actions are tied to their web layer? What would be the cost of changing web layers?

Web layers all have their own ideas about how to interface to clients. Some use annotations. Some use XML. Some use conventions. They do validations differently. They handle flow differently. They handle form parameters differently. No matter what, the layer between the client and my business logic is going to change, radically or not, if I port to a new web framework.

That my actions extend ActionSupport isn't going to be the pain point: the request handlers are going to change no matter what. How I expose validation errors to the view will change. How I retrieve form parameters will change. How I define validation will change. How I do I18N will change. How I code the view layer itself will change.

That's not to say there aren't (or shouldn't be) unified ways to do all those things, but at the moment, there isn't a single standard approach (and maybe there shouldn't be, although a "web AST" would be cool). The trick is to minimize the coupling between the client and the application's guts.

- Work in progress -

Saturday, November 12, 2011

Testing singletons while avoiding their constructors

Singletons are evil, and here's why.

Fair enough. Yet they exist, and they're not intrinsically evil--just misused. Can we mock enough to make testing them feasible? Yep, and here's a Contrived Example™ that shows how (and why we might want to).

"Embedded" singletons or utility classes can make testing is problematic. Injected singletons are different; then it's an issue of whether or not it should be a singleton at all--different discussion.

"Embedded" singletons look like this. (Utility classes are essentially the same, minus an instance.)


Let's say (a) we need to test this code, (b) we cannot modify this code, and (c) the singleton's constructor is long-running, but required for fetch() execution. For testing, then, we need to (a) avoid the constructor for speed reasons, and (b) mock the fetch() method to return known data for the test. We can't just mock fetch(), because the constructor would still run.

Here's our (contrived) singleton class; we sleep() in the constructor to pretend it's doing something interesting like caching data from a web service, to be returned by fetch().


The undecorated test does what you'd expect, and takes as much time as you'd expect.


Now, with a combination of PowerMock and EasyMock, we'll put the kibosh on that, eliminate the constructor, and return the data we want. (PowerMock sits on top of EasyMock or Mockito. (Both are great, although I tend towards Mockito.)


Most of the test class is self-explanatory. The nutshell version is that we annotate the test class itself and tell it to run with the PowerMock runner (@RunWith), and that we're going to be messing with LongRunningCtor's innards (@PrepareForTest).

Inside the test itself, we tell it to suppress LongRunningCtor's constructor (before mocking, otherwise the constructor will fire during the createPartialMock() call). We also prepare for mayhem by calling mockStatic(). (This mocks all the class's static methods; we could also choose specific static methods to mock using mockStaticPartial().)

Our test now takes a fraction of the time because we're skipping the slow constructor, and our mock returns known data so we can exercise only the calling code.

Ideally, code is structured so this kind of byte-code treachery is unnecessary--it's a great reason for dependency injection/inversion of control. In the real world, technical and timing constraints don't always allow the kind of restructuring we'd like.

With the aid of some tools that do the low-level dirty work for us, we have a relatively clean way to work around some types of system limitations, and still write tests that can execute quickly.

The gist used in this post also includes the relevant Maven dependencies.

Sunday, January 30, 2011

Java/Struts Interview Back Online!

Aww yeah; it's back, YouTubier than ever. (The audio conversion is a bit spikey--I'll have to try it again I think.)

Watch it on YouTube!


Myeeeeah update! Update! myeeeeeeeeeaaaaaaaaa Update! Implementing googling!

For those keeping score at home... still haven't found anyone I actually *want* to hire, although there have been a few people that would have been solid workers, I really need someone thinking a bit more abstractly.

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.

Sunday, November 23, 2008

Do Java Web Application Frameworks *Really* Provide Too Much?

The other day we witnessed a DZone disaster. The article (Web Frameworks - We Need Less, But They Keep Adding More (Part 1)) was a five-paragraph claim that typical/most Java web frameworks were full of bloat and too complex, and that this is bad. I don't think anybody would argue that. The disaster's underpinnings? He was voted down, and called the downvoter a jerk.

I also voted the article down--I didn't like the article. IMO that's what the voting system is for. I was also called a jerk, and great hilarity ensued. Yes, I should have stopped feeding the troll, and I take full responsibility for my end of the discussion. I still, however, don't like the article, and believe his reaction was about as ridiculous as I've ever seen.

Are Java web frameworks actually "adding more"? Does "doing a simple task requires pages of code and configuration..." and do current frameworks want "... control of both sides of the web application coding (server and browser)"? Do "... many/most web frameworks is the fact that they try to do too much and require large amounts of configuration (usually with XML)"?

The popularity of Ruby on Rails prodded most Java-based web frameworks to move, often rapidly, *away* from static configuration. Some have moved towards annotations (still configuration), some towards convention-over-configuration, many allow multiple configuration (and configuration-less) styles. Even the annotation-based solutions are, at this point, pretty minimal in terms of cognitive overhead (which is the ultimate issue), although annotations are still configuration. Most frameworks, even *with* XML configuration, allow convention-style configuration via wildcards and the like, often allowing large web applications to be configured, even in XML, with only a few lines.

Do frameworks "force me to use your embedded code and/or tags in my HTML"? I know of very few that *force* us to use framework tags, although it's often unreasonable not to. The article is basically a commercial for jWebApp, and several jWebApp examples use jWebApp-specific tags. The explanation given in the DZone meltdown is "The tags are framework independent and optional, but are obviously needed to repopulate the form if validation fails." I'll largely discount the entire tag issue, then, if they're obviously needed for functionality normally associated with a web application. I'll admit a certain amount of confusion as to why it was brought up, however.

The second article begins the actual technical discussion, using the "perfect web framework" (which turns out to be jWebApp). It includes code and configuration (which we didn't want, if I recall) samples as well as a laundry list of features.

The example request handler skeleton given is this (slightly reformatted and redacted):

public class Customer extends RequestHandler {
public String validateSaveCustomer(ServerInterface serverInterface) { ... }
public String processSaveCustomer(ServerInterface serverInterface) { ... }
public String processGetCustomer(ServerInterface serverInterface) { ... }
}

ServerInterface is a wrapper around an HttpServletRequest, HttpServletResponse, and ServletContext, directly tying request handlers to the servlet framework. The wrapper class also defines a slew of convenience methods that access things like request objects and so on.

Directly tying to the servlet spec creates an awkward dependency that unnecessarily complicates testing. These days it's relatively unusual to find a framework with such an explicit dependency on the servlet specification. If time has taught us anything it's that dependencies like this are (largely) unnecessary and impede development.

The Hello World example on the jWebApp site shows an example with a similar skeleton:

public class HelloWorld extends RequestHandler {
public String processHello(ServerInterface serverInterface) { ... }
public String processHelloAgain(ServerInterface serverInterface) { ... }
}

This example is intended to service the /helloWorld/hello and /helloWorld/helloAgain URLs. The "configuration-less" configuration, however, looks like this:


jwaRequestServlet
jwebapp.RequestServlet



jwaRequestServlet
/helloWorld/hello



jwaRequestServlet
/helloWorld/helloAgain


The first mapping is reasonable, the jwaRequestServlet is acting as a controller. What's less clear to me is why the next two servlet mappings are necessary: they seem redundant and unnecessary. Again, in modern Java frameworks this would be handled automatically via convention, wildcarding (XML or annotation configuration), or classpath-scanning convention (configuration-free or annotations).

Note that as with most other modern Java frameworks it's possible to use convention-based URLs in jWebApp, but we're then back to comparing apples to apples.

The article then goes on to say that he would like to "optionally define simple configuration":









This brings us back into the realm of a typical XML-configured framework, which seems to go against the grain of part one, which makes me wonder what the point was in the first place. At the end of part two is a laundry list of features desired in "the perfect framework", but none of them seem to be features that are particularly lacking in other modern frameworks.

Some features present in jWebApp *are* nice to have, and it's cool they're integrated into jWebApp--but those features aren't necessarily features that *should* be integrated into a web application framework. If they meet the needs of the developer and/or project then that's a Good Thing, and a definite win. Some of the features, however, like emailing, payment processing (I only found support for PayPal, but I suspect there's more), and so on may be so project- or environment-specific that having them included in the framework itself is at best useless, at worst an unnecessary distraction. It may not be *fundamentally* bad they're included, but directly integrating cross-cutting concerns like that always raises my eyebrow.

Moving away from the articles and towards the framework itself there are several claims made regarding the features of jWebApp. The lack of need for custom tags is mentioned (no *need*, but again--they're used by the framework to provide the same functionality provided by most other frameworks' tags). Easy AJAX support is touted, but appears to be handled by creating a JSP page that returns JSON-formatted data which is then evaled in JavaScript, rather than the automatic JSON de/serialization offered by other frameworks (often including automatic help in avoiding scripting attacks).

Something not mentioned in the jWebApp documentation is Spring integration, which for the types of applications I write is a very important requirement: yes, Spring *can* be complicated and it's definitely overkill for many types of applications--but those aren't the applications I write. If all we need is dependency injection (something I didn't find support for in jWebApp--again, that doesn't mean it isn't there) then Spring is a pretty heavy solution--there are much lighter-weight DI containers. Once we throw in transaction management, AOP, and so on, I find out-of-the-box Spring support compelling, although there are other good solutions.

Simply put, I don't find anything compelling about jWebApp. That doesn't mean it's not an adequate for some problem domains or developers--it simply doesn't meet my needs. For quick, one-off, Java-based e-commerce apps it may be exactly what somebody is looking for, since it has typical functionality built-in.

The bottom line is that I still don't find the article I voted down interesting, particularly well-written (although it's not *badly* written), or of any great value. It was five paragraphs that didn't say very much. I feel badly that the author reacted so poorly--quit frankly if I'd known he'd fly off the handle like that I probably wouldn't have bothered voting it down, but part of the point of voting is to provide feedback to the community at large, and at the time I read it I didn't think it provided enough value to recommend it to others, and it seems to ignore the Java web app frameworks that alleviate the bulk of what's being complained about.

On the social aspects of the original DZone submissions, I'm somewhat at a loss. The author decries the childishness of "arbitrary" downvoting, then downvotes *multiple* submissions by his downvoters in retaliation... We may just be operating under different definitions of "childish", but IMO that's even *more* childish. It appears that the tantrums brought nothing more than *more* "arbitrary" downvoting. Is this a Good Thing? No, he's right that downvoting just because he played the fool isn't appropriate behavior: the only thing that should enter in to submission voting is the article itself. His playing tit-for-tat, however, completely demolishes any credibility he has to complain about arbitrary downvoting. I was called a jerk because I didn't like the article--this is also inappropriate behavior; not liking the article *is* an appropriate reason to vote it down.

Lesson(s) learned? For my part, I'm less likely to downvote an article I think has no redeeming value, depriving other readers of a reasoned opinion. On his part? I don't know--I'd like to think he'll come out the wiser, and I hope he does. I'm glad he's developed a framework that meets his needs, and if it meets the needs of others, I think that's terrific; more power to everybody involved. Despite his sarcastic parting comment: "Thank you all! You've shown me what the open-source community and netizenship is all about." (it was originally followed by a "Fuck off", but that part was deleted, which is good) I actually *do* believe this is what the open-source community and netizenship is all about: open discussion that sometimes happens to go horribly, horribly wrong.

Friday, February 01, 2008

Today's Java Irritant: No sense of closure.

There's still enough back-and-forth about the inclusion of closures in Java 7 that I'm nervous it might not make it in to the language.

James Gosling supports the addition of closures and states that the reason they weren't there in the first place was due to time pressures and seems to have some regret about their absence (understandable; he's a Pretty Smart Dude and probably feels the pain of Java wartage more keenly than most).

Ricky Clarkson blogs about why we need a new syntactic construct to make the use of closures cleaner and less verbose, even while admitting that Java does, in fact, have a form of support for closures already.

My languages of choice (Lisp, Smalltalk, Ruby, etc.) all have cleaner support for closures without the syntactic overhead that current Java has. For a trivial example we can compare the use of closures for processing a file.

file.each_line do |line|
# Process line of file.
end

With current Java syntax we might end up with something like this:

import static bar.baz.eachLine;
...
eachLine(file, new EachLine() {
void doLine(String line) {
// Process line of file.
}
});

We could also create a File-like object with an eachLine method.

This isn't the Worst Syntax in the World, but it still makes me think more when writing the code and when I'm reading it later.

A relatively minor point is that any variable used in the closure must be declared as final in the enclosing method. This may obfuscate the actual functionality of the enclosing method and, in some cases, require the introduction of a final variable just to satisfy the requirements of Java's current "closure" syntax/implementation.

It'll be interesting to see what finally happens; I hope that (a) support for closures is added and (b) it doesn't irritate me too much.

Monday, December 31, 2007

Today's Java Irritant: Design-by-Contract Disconnects.

Design-by-contract systems enforce API behavior. In Eiffel, contracts specify both internal and external behavior, at the language level.
connect_to_server (server: SOCKET)
require
server /= Void and then server.address /= Void
-- etc.
end

This does what it looks like, at runtime. (/= == != :)

The cost of doing the same in Java is higher; most frameworks use some form of aspect-oriented programming. This isn't a bad thing in itself, but gives some people (managerial types and unimaginative programmers) the heebie-jeebies. Dealing with issues created by lots of aspects can be daunting, but are relatively straight-forward in a well-educated Java house.

Lighter-weight solutions exist, may be preferable in many situations, and are easy to grok. Putting a chunk of precondition tests at the start of a method is trivial:
public String foo(final String bar_) {
Pre.notBlank(bar_);
// etc...
}
Here, the issue is that there's no automagic way to track or document preconditions other than either manually documenting them in Javadocs (preferably through a simple doclet tag, like @pre, or whatever) , or by programmatically scanning the source and pulling out "useful" information and doing something useful with it. Neither are particularly appealing: Javadocs go stale quickly, and writing a robust source parser is non-trivial.

Another answer is to use one of the annotation- and/or aspect-based solutions (or XDoclets, but... ew?) and swallow the bitter pill that is Java, and pay the cost of educating your developers. The packages I'm currently considering are Contract4J, which uses pre-built AspectJ aspects, and SpringContracts (which is nice since most my projects use Spring).

Monday, November 26, 2007

Today's Java Irritant: Java's Impoverished Mixology

Today's Java Irritant is the lack of mixins or similar functionality, although Warth et al.: Expanders have an implementation.

A current project has an interface consisting of about two dozen getters (and setters). This interface is implemented by a minimum of two classes due to design and lack of multiple inheritance.

Being forced to implement this functionality in even one place, not tucked away in some base class, module, mixin, etc. is irritating enough: having it in two places is more than twice as bad. Keeping the implementations in sync is irritating. Looking at the code so I know I can ignore it is irritating. Maintaining three sets of code (the interface and two classes) is irritating.

This functionality is available for Java--sort of. Warth et al. created Expanders via the Polyglot compiler front end. It allows classes to be non-invasively updated with new methods, fields, and superinterfaces.

Expanders look like what we want, and like the rest of Java, are statically-typed, preventing at least some types of errors.
package some.pkg;

public class SomeJavaClass {
// Normal class definition.
}

...

package interfaces;

public expander Foo of SomeJavaClass {

private String _someProp;

public void setSomeProp(final String someProp_) {
_someProp = someProp_;
}

public String getSomeProp() {
return _someProp;
}
}

...

import some.pkg;
use interfaces.Foo;

public class UseThatShiznit {

public static void main(final String[] args) {
SomeJavaClass anInstance = new SomeJavaClass();
anInstance.setSomeProperty("No brainer.");
}

}

This is a crude use of Expanders. Consider the creation of a Swing JTree-aware class via Expanders: rather than include Swing-specific information in the class itself we can create an Expander that implements TreeNode and ILabelProvider and since Expanders are typed, we can create different expanders for different classes. If there is shared behaviors, no worries; Expander behavior can be overridden just like class behavior.
use StringIconExp;
public expander PublicationExp of Publication implements TreeNode, ILabelProvider {
// Enumeration children()...
// String getText()...
public Icon getIcon() {
return "/icons/publication.gif".getIcon();
}
}

What's that getIcon() code doing?! Strings don't have a getIcon() method... but strings with an expander do.
public expander StringIconExp of String {
private Icon icon = null;
public Icon getIcon() {
if (icon == null)
icon = new ImageIcon(Object.class.getResource(this));
return icon;
}
}

Yes, this could be implemented with source generation tools, but that's a poor substitute for type-safe, naturally-composable functionality in the language itself, and it adds a layer of build-time complexity that must be documented and maintained.

If you think GroovyScala, and so on are tough sells, try selling Expanders. It's tantalizing, but experimental, and with the current crop of JVM languages, I doubt we'll be seeing it in mainline Java.