Thursday, February 21, 2008

albatross

In my home office I have four cardboard boxes packed tight with books. Ninety-percent of them are related to programming: languages, frameworks, best practices, and so on. Some of them are life-changing tomes (Design and Evolution of C++ and Effective C++, to name a few) while others are glorified API documentation, but all have one thing in common: they have not been opened in over four years. The Internet has made them irrelevant.

I still appreciate physical books - the remaining ten percent of my books are focused on consitutional law and American history, and it would not have been nearly as enjoyable to read them had they been e-books[1]. But the fact that I these extracurricular books are packed away just as tightly as their technology counterparts makes it clear that I have little use for books even when they provide content that isn't available on the Internet; the additional books that I've collected since my last move now sit on top of the boxes and will likely be packed away one weekend when I happen to have an extra cardboard box. Having contemplated this situation for a couple of days, I eventually found enlightenment in an old episode of Seinfeld:
Jerry: So that's it? You're out?

George: Except for one small problem. I left some books in her apartment.

Jerry: So, go get them.

George: Oh, no. No, I can't go back there. Jerry, it's so awkward and, you know, it could be dangerous... sexually. Something could happen, I'd be right back where I started.

Jerry: So forget about the books. Did you read them?

George: Well, yeah.

Jerry: What do you need them for?

George: I don't know. They're books.

Jerry: What is this obsession people have with books? They put them in their houses like they're trophies. What do you need it for after you've read it?
The books that I own were indispensable during my college years. They drenched my insatiable thirst for knowledge and helped me create the kind of software that was being churned out by real programmers, not just the toy projects that we got for homework. Each semester I would buy my textbooks early, read them, and then spend the rest of the semester learning about the things that weren't covered by RPI's curriculum but seemed really exciting, eventually putting those things to work in side projects that I never seemed to finish. This has led to a situation where all of my books are filled with knowledge that could be considered the foundation of my career or tragically antiquated[2]; either way, these books are just trophies that represent my ability to learn the basic skills required of a professional programmer. All of the new and advanced skills that I use in my day job have been gleaned from the countless tutorials and source code repositories scattered across the Internet.

And they're heavy trophies. When I look back on the last three or four moves I've made, the heaviest and most cumbersome thing to move was always my book collection. It's a chronic back problem waiting to happen, and now that I'm approaching my late twenties, I have to consider these things. The only reason I've looked through my books post-graduation was to find and ship two of them to a friend who was unfortunate enough to be working on a project full of old Win32 code.

Is that what my book collection has become? A used book depository for the handful of programmers that I know? It all seems so wasteful[3]. I think the time has come to get rid of my book collection; as anyone who has visited my past apartments will tell you, I've always been kind of a minimalist, and these books are doing more harm than good here in my office. I will try to give them away to college students and other aspiring programmers, but I have a feeling that many of them will go unclaimed, doomed to the recyling bin.

Of course, I don't think it will matter if I toss all of my books and then forget the ins and outs of the Win32 thread API, but it will matter if I can't articulate why I vote the way that I do or learn from past mistakes; for this reason, the lessons of American history will still have a physical presence in my life. So long as they fit in one box.

[1] I'm not saying that e-books are bad or that they will never be popular - they're just not my cup of tea.

[2] It's sad to look back on all of the books that I had to read just to realize that MFC was a disaster.

[3] And heavy - did I mention that?

Labels: , ,

Thursday, February 14, 2008

binding

I've been working on the Zero team for almost a year now, and in that time, Groovy has become my language of choice, both for Zero applications and non-Zero utilities. Groovy is, as Jerry Cuomo put it, "the nicotine patch for Java programmers"; it provides many of the cool features found in Python while freeing me from the tedious boilerplate of Java, all with a gentle learning curve. Like most Java-turned-Groovy users, I started out writing Java-centric code, picking up Groovy's shortcuts and elegance as I grew more experienced and shared code bases with other Groovy users. There are still many features that are not part of my toolbelt, but every day I seem to pick up a new one.

Because I use Groovy both for RESTful resource implementations and utility scripts, I often use Zero's /app/scripts directory to store code that is in any way reusable; this shortens my resource scripts and keeps time spent refactoring to a minimum. The only problem with invoking code in /app/scripts is that you have to do so with generic, reflection-based APIs, like so:
def script = "FooUtils.groovy";
def method = "getFoo";
def params = ["param1", "param2", ...];
def foo = invokeMethod(script, method, params);
To make it so the code in /app/scripts is in scope for your other Groovy code, you need to create a binding. Making a Groovy binding for a script isn't hard, it's just kind of tedious: you write a Java class that maps all standalone function names to reflection-based invocations on the Java class, and then use Groovy's script engine API to call the target function. You must also update your configuration file to register your Java class as a Groovy binding. The whole process is outlined in Zero's documentation as well as every developerWorks article I've written in the last six months. If you follow the instructions prescribed by the Zero team, the block of code shown above will become much more readable:
def foo = getFoo("param1", "param2", ...);
It's not often that I put code in /app/scripts that isn't meant to be shared with the rest of my application, so after I while I started poking around zero.core to see if there was a way to enable bindings automatically, with no Java code or config stanzas. The short answer is that, yes, it would be possible, but we would take a performance hit because of some additional reflection; I have not bothered to implement this solution, so I cannot say how severe this performance hit would be. I didn't want to go through a lot of trouble only to find out that my solution was slow as molasses, so instead I wrote a Groovy script to generate the binding classes and config stanzas for me.

The script is named binding.groovy, and you can download it here. You can look at a sample console session below:
$ ls
.
..
binding.groovy
my.zero.app
$ groovy binding my.zero.app
$ zero build
$ zero run
The script generates classes and configuration without touching any of your existing files. The zero build step compiles the Java classes so that they will be on the classpath at run time (zero run). You can find more details on usage, behavior, and licensing in the header comments.

Working on this tool gave me the opportunity to make a very useful comparison between Groovy and Java. Last summer I used Java to write RESTdoc, and that tool shares many requirements and behaviors with my latest one: both analyze the structure and code in a Zero application and use that information to generate one or more files using a template. RESTdoc is more complex because it must be usable from the command line, Ant scripts, and a GUI, but many of the algorithms are the same.

Based on my two experiences, I would have to say that using Groovy was far more enjoyable than using Java. But why?

First, I was able to get right to coding, without having to create all of the boilerplate that seems to appear in all of my non-web applications. You know: first write main(), then a non-static run(), then set up the exception handling, then define an exception hierarchy, and so on; then, just as you're starting to write real code, your mind starts to map out the larger pieces of the tool, and you start to think about which of these pieces should be pluggable, and then you start defining interfaces, and soon it's the end of the day and all you've done is create an Architecture.

Tomorrow, you think, I just have to write the code. And it seems like such a logical thought to have.

But it's not.

I wrote RESTdoc in just over two days. This latest tool required four hours. Granted, I was able to reuse many of the ideas I'd had while implementing RESTdoc, but those are just ideas - I couldn't reuse most of the code because it was all so... big. I knew that the code could be much simpler in Groovy, so I rewrote it. Quickly. The Groovy tool took less time because I was able to focus on actual logic and actual testing, not Java-oriented procedures that catered to my neuroses.

Second, the ability to use closures made my code smaller while also increasing its readability. Most of my closure usage is coupled with methods like each() and collect() (and their derivatives), methods that accept a closure as a parameter and apply it to a collection. I'm sure that some people abuse closures in a way that makes them feel like Java's anonymous classes, but for the most part they seem to function as a way to get things done with less bureaucracy.

The third thing that makes my Groovy development more enjoyable is the fact that lists (java.util.List) and maps (java.util.Map) are built into the language, and I can use them to create utility data structures without defining an inner class with getter and setter methods. You can do this in Java too, but it's frowned upon; it just doesn't feel right to put so much structure around your code and then use bags of goo to store your data. But while that's an appropriate feeling to have in many scenarios, it's a real downer when you're writing a script to generate config files. I love the fact that I can represent part of a parse tree with a set of key-value pairs and not feel guilty about it, and I really love the fact that I can create that set in one line of code:
return [
name: "getFoo",
params: ["param1", "param2"],
hasReturnValue: true
];
Finally, for all of the Java bashing I've done in this post, I have to remind myself that one of the best things about Groovy is the fact that it lets me devolve into traditional Java programming when I really need it. There are some tools for which Java integration is superior, and those tools aren't going to change any time soon. Java is also the original language of the JVM, and it is the best way to expose a language-agnostic API on that platform.

And sometimes, I'm just not ready to do things The Groovy Way. Like all creatures of habit, there are times when I hang on desperately to the past, for no good reason at all. Groovy allows for all of that, and it doesn't mock me when I fail to use it to the best of its abilities. It just runs my script.

He'll come around, it says to itself. Some day.

Labels: , ,

Friday, February 8, 2008

astringency

On Wednesday I posted a little memo to all of my readers who may be hockey fans; it was only two sentences long, but it ended up causing much more grief than anything else I've written for this blog. I'm using this post as a budget therapy session.

First, I should clarify that this grief was completely internal and has nothing to do with the fact that the Hurricanes' best penalty killer is out for the season with a broken leg; in fact, I wrote the post in less than two minutes, and there is no evidence to suggest that any of my readers even read it, let alone cares about its topic. My pain is relate to Blogger's user interface, which I don't use for composing but do use for posting. After copying the text of my memo from a local file to Blogger's glorified <textarea/>, I accidentally hit some combination of keys that caused Blogger to initiate the publishing process and then go back two pages to the "dashboard"; it was all very fast, and not realizing what had happened, I started again by clicking the Create New Post button and re-copying my text.

Once I published, I realized that I had actually created two posts. The first had a permanent URL of /2008/02/rosey.htm and the second was at /2008/02/rosey-06.htm. This enraged me for reasons that I will get to shortly. My initial reaction was to delete both posts, republish my index page, and then create the post a third time. Upon doing this, my post resided at /2008/02/rosey_6595.htm. The exact role of these random numerical suffixes is unknown to people outside of the Blogger team, but I have a hunch: I think this is a case of REST pedantry.

Blogger is treating each new post as a completely new resource and it is ensuring that all new resources have a unique URI; because the tool uses the post title as the last token in the URI, it is tacking on a suffix so that the final URI does not conflict with any other resource. It does this even if the conflict is with a resource that no longer exists so that a client is never tricked into thinking it's dealing with the original resource (i.e., it does not realize the original resource was deleted).

This kind of behavior is similar to what you see in WS-* Land, where resources are identified using an endpoint reference (EPR). Once a WS-resource is destroyed (either implicitly or explicitly via WS-ResourceLifetime), its EPR is invalid forever. This is a pretty harsh requirement, but most implementations are able to satisfy it with the help of UUIDs. Blogger doesn't do anything so obtuse when constructing URIs for blog posts, but the suffixes make me think that there's some kind of logic in the Blogger engine that prevents two posts from ever having equal identifiers, even if their lifetimes do not overlap.

As someone who has had to implement universally unique identifiers with REST and WS-*, I can appreciate the motivation behind them; however, in the case of my blog, which is my own little sanctuary on the Internet, I would prefer to have more control over my URI space, even if it means I am not in 100% compliance with AtomPub or the majority opinion on rest-discuss. Let's face it, I'm doing this more for me than for you; if you want to read overly-zealous opinions about data formats and U.S. laws, there are eleventy scrillion other blogs that can fulfill your needs, but I only have one web site, and the fact that my URI space is completely organized except for one post is going to drive me absolutely insane.

/2008/02/rosey_6596.htm? What is that? It's just so... random. And un-RESTful. It might as well be an EPR.
<EndpointReference 
xmlns="http://www.w3.org/2005/08/addressing">
<Address>
http://codeunleashed.com/2008/02/rosey.htm
</Address>
<ReferenceProperties>
<ResourceId>6595</ResourceId>
</ReferenceProperties>
</EndpointReference>
At first I thought about changing the URI manually, but the index is stored in Blogger's database, so it will just revert back the next time I publish a post. I also considered deleting the post and keeping my feelings about the Hurricanes to myself, but I decided that writing seven paragraphs about five URI characters would be slightly less insane. It's part of my 2008 New Year's resolution to not waste time on small details that don't have an actual impact on future events. As you can see, it's going pretty well.

Labels:

Wednesday, February 6, 2008

rosey

FYI for all of you Carolina Hurricanes fans out there: the 2007-08 season is officially over.

That is all.

Labels: ,

Tuesday, February 5, 2008

super

I will not be participating in today's voting because I live in North Carolina, and our primaries are scheduled for May 6th. Of course, I don't actually get a vote on May 6th, either - my vote has been negated by the people of Iowa, New Hampshire, and South Carolina, as well as the party officials that have punished any state that tried to hold a primary in January. Instead of selecting from the full slate of candidates available at the start of 2008, today's voters have to pick one of four "front-runners"; by the time the polling places open in North Carolina, there will only be one viable candidate in each party, making my vote irrelevant.

It amazes me that both parties have chosen to alienate voters in key swing states like Florida and Michigan in order to preserve a status quo that puts the entire nomination process in the hands of people who think The Old Man of the Mountain was an breathtaking monument. If you're trying to win control over an entire branch of the U.S. government, wouldn't you want to be sure that you're nominating someone who has the broadest appeal? This seems like an air-tight argument in favor of a national primary. Alternatively, we could conclude that the first votes should go to states like California and New York, states that offer a more complete representation of the American electorate. Either change would enhance the presidential election process by ensuring that more voices were heard before the field was winnowed.

Super Tuesday indeed.

Labels: , ,

Friday, February 1, 2008

fail

Apparently, the leaders in our executive and legislative branches have come to agreement with regards to saving the economy: they will courageously tackle our massive deficits, incalculable debt, and dismal growth by giving everyone $600. There are so many things wrong with this plan that I didn't even know where to begin; I had to go outside and throw rocks at the house for an hour until my anger subsided and I could write this post without breaking the keys off my keyboard. Let's look at the facts.

The main goal of the economic stimulus plan is to put cold, hard cash into the hands of normal Americans, who will take their unexpected bounty to the mall so they can buy presents and dine out; proponents say that this increase in consumer activity will boost payrolls, calm Wall Street, and save us from certain recession. The original version of the proposal (drafted by the House and endorsed by the president) would grant a $300 tax rebate to the dirt poor, $600 to taxpayers making less than $75,000 per year, and a few extra bones to people with kids; if you make between $75,000 and $87,000 per year, your rebate would decrease as your income increased, eventually bottoming out at $300. Six-figure breadwinners need not apply.

The Senate modified this proposal by doubling the maximum income levels so that wealthier individuals could get in on the super fantastic rebate action. It is not yet clear which version of the proposal will "win", but it looks fairly certain that all lower and middle class families will be getting a check for $600 just in time for those Memorial Day shopping extravaganzas.

Now, on the surface, this is encouraging: politicians managed to agree on a policy and enact a law in a matter of days, with an immediate result for the American public. Finally, a win for the middle class! Right?

Wrong.

Well, sort of. I'm sure that the extra $600 won't hurt middle class taxpayers, but the good feelings it creates will be short-lived; considering the deep financial hole that we are sitting in as a country, I think it would behoove us to consider the long-term impacts of this plan. This kind of inspection is not nearly as immediate or satisfying as the idea of giving everyone $600, but I am going to do it anyway.

The first thing that's wrong with this plan is that it confuses public sentiment with its original goals. Giving a few C-notes to middle class families on the brink of a recession may brighten their day, but it won't lead to concrete economic growth, which means that it won't really improve their lives. By most accounts, American families are in much the same situation as their government: they are in severe debt and find themselves robbing Peter to pay Paul, all to live the American Dream that is sold to them on TV. This means that the average person will use their $600 in one of three ways:

  1. Payment of credit card debt, overdue bills, or loan principals.

  2. Savings for emergencies, retirement, or education.

  3. Purchase of new clothes, music, or other things they don't need.

The first two options are obviously the more responsible ones for someone who has incurred a lot of debt or has not made a practice of planning for the future. That may sound good from the perspective of someone who wants to help average Americans, but remember: the goal of the plan is to revive economic growth. I will try to explain why I think these things are in conflict without sounding like a heartless bastard, but I can't guarantee anything. Just so you know.

In the first scenario, the person is paying off debt for things that he bought in the past. The debt is still very real to him, but in the eyes of financial analysts and corporate executives, it's ancient history; when John Q. Public bought that new iPod with his credit card last year, the bank that issued the credit card paid his debt to Apple Computer in full, and that payment was recorded and celebrated during the same fiscal quarter. The fact that John is beholden to his lender at an 18.9% APR does nothing to advance the state of the national economy; paying down his debt is a good thing when it comes to his blood pressure, but it's not going to register as new economic activity.

The second scenario is even more optimistic and hopeful than the first, but it will also cause us to miss our target. I sincerely hope that the majority of Americans will save their rebate money, but I also realize that this will be discouraging because money in the (individual's) bank has no impact on our economic growth rate.

Given our history as consumers, and the fact that so many of our citizens came into debt by shopping and over-extending themselves, it is likely that many people will give in and go along with our third scenario. This is exactly what politicians are hoping for, but even this will not "save" us. The Experts concede that even if everyone spends their rebates on shiny new gadgets, the growth that we'll see next quarter will be 1-2%; now, 1-2% of the American economy is an incredibly large amount of money, but it will be overshadowed by the negative effects that we will see in subsequent quarters. If people don't do the responsible thing and pay down their bills, then they are only making their situation worse, and it will take them even longer to pay back this "free" rebate. Do we really want to encourage this kind of irresponsible spending? This is how we got in a hole to begin with!

Sending money to people who are in debt and don't have savings sounds nice, but it won't give us the results that our politicians want. If the recipients use it to pay bills or create savings, the economy will continue to stagnate; if they use it to buy more stuff, they are just digging themselves a deeper hole. Everyone will be excited for a couple of days in May, but we'll be back in a rut by June. Mission: not accomplished.

If we really wanted to increase economic growth by a few points this summer, we would give the $600 to those who make more than $75,000 per year because they are more likely to have disposable income. Now, let me be clear: I do not feel that the goal of temporarily increasing economic growth by 1-2% warrants giving a tax break to upper class taxpayers. Additionally, I do not need $600 from the government, nor will I feel any hostility if, when the final numbers are released, it turns out that I lost the tax rebate sweepstakes. I'm fine. Really. This is not sour grapes from someone who has a comfy job at the largest IT company in the world.

That said, people with disposable income tend to... dispose of it. They go out to eat and buy things they don't really need, all of which fuels the job market and salary numbers that have so concerned our dear leaders. The growth caused by such disposal of income would still be temporary, but it would happen. If this is the goal, the tax rebates should go to the upper middle class: those wealthy enough that they don't have unmanageable debt but not so wealthy that $600 is a drop in the bucket.

Of course, you cannot, in an election year, tell middle class voters who are financially strapped that the answer to their problems is a tax rebate for people who don't have any problems. I understand that. But I would hope that our leaders would understand the points I have raised and not make the proposal in the first place, thus avoiding the debate entirely.

The second thing that is wrong with this plan is that our government cannot afford to give us a tax rebate right now. We have not had a balanced budget in almost a decade. Our national debt makes me want to throw up under my desk. Our 401k money and future business plans are riding on the hope that large Asian countries will continue to buy our bonds. We are in a war that, whether you approve of it or not, costs billions of unbudgeted dollars per year. And despite all of this, the government wants to return part of its yearly income? If this idea were any more stupid, the amount of stupidity would cause some kind of cosmic integer overflow and make the whole thing brilliant.

Put another way: if the government were a person, he would have nothing to his name. He would have his credit cards taken away, his car repossessed, and his belongings sold at auction after settling in bankruptcy court. If such a person offered you $20 because he knew you were a little short on cash this month and couldn't afford to meet the gang for drinks, would you take it?

No?

Well, that's the situation we find ourselves in right now: we're handing out rebates like its 2001 despite a massive increase in debt. I'm a fairly libertarian guy, which means that I normally perk up when people mention tax cuts; the fact that I'm saying the government should keep our money should clarify just how bad I think our balance sheet is. It's never fun to pay taxes, but when your leaders overspend their budget multiple years in a row, you either have to increase their income (taxes) or boot them out of office. You can't Reagan-omics your way out of a $400 billion deficit. You certainly can't do it seven times.

In summary, this plan is a joke. In the best case, tax rebates for lower and middle class people will not generate economic growth, and in the worst case, it will generate a small bump in growth but increase the deficit and weaken the dollar. It's a lose-lose situation. Frankly, I have trouble believing that anyone involved with this plan would pass a second grade arithmetic test.

Fail.

Labels: , ,