Archive for the 'software' Category

Java Logging

Thursday, July 24th, 2008

Spent half the day fighting with Tomcat 5.5, trying to get log messages out of my application. I need to rant a bit here.

I’m deploying a vanilla webapp with its own log4j.xml in WEB-INF/classes. Why does this not just work out of the box? Because, hey, maybe you’d want to use some other logging library. Not that there are any out there that don’t suck, but y’know, maybe someday. So we need to leave this all open-ended and configurable.

You see, once upon a time, we had Log4J. It was good. In fact, it was perfectly sufficient. It solved the problem. It did just about everything you could want.

Unfortunately, Sun was also developing their java.util.logging (JUL) around that time. They went through the whole JSR community process, so they started earlier and finished later. It sucked, but Sun owns Java in a very literal sense, so we were pretty much stuck with it. Not in the sense of actually having to use it, thank god, but any poor bastard writing logging tools had to accommodate it.

So then we got Apache Commons Logging. It’s a diplomatic facade that stands in front of either of them so your code can be agnostic about whether you’re using Log4J or JUL under the hood. In practice, anyone who doesn’t have a paycheck from Sun and a gun to their head uses Log4J. Java Developer’s Journal did a comparison of the two. They tried to give a “fair and balanced” report, as in, “there are situations in which JUL might be the better choice.” If you read between the lines, those situations were essentially if you’re writing a toy application that would probably be fine with System.out.println().

There’s something of the paradox of choice here. Trying to leave all your options open is ultimately less effective. Your code has to be way more complex to support everything, and you almost always have some sort of mismatch that forces you into a limited-functionality common denominator. It’s not worth it. Pick something that works and go with it.

So today’s pain came about because rather than doing that, Tomcat 5.5 seems to have slapped yet another layer of indirection and indecision on things. It seems that one of the ways in which java.util.logging sucks is that you can’t have multiple configurations within an application. Why on earth would you want to do that? Well, if your application is a web application server, it needs to run a bunch of java libraries as if they were standalone applications. Kinda killer flaw there, huh? But who can pass up the challenge of hacking around something that thoroughly broken? And hey, it’ll make it standards-compliant.

So you end up with these gems from the Tomcat 5.5 logging page:

the default Tomcat configuration will use java.util.logging.

And a bit later on:

The default implementation of java.util.logging provided in the JDK is too limited to be useful.

How can you say that and still build in support for it? Grow a spine, people! How much simpler would this world be if you just followed that up with, “…so Tomcat uses Log4J exclusively. Don’t like it? Write your own app server.”

But no, what did they do? They hacked together their own implementation of the java.util.logging API. Apparently, it’s not “too limited to be useful,” but it “is not intended to be a fully-featured logging library.” Why bother? You’ve had a fully-featured logging library for the last 6 years. Why would you make the default logging configuration one which by your own admission is really not adequate? Why not make Log4J the default? If you really have to, then you can provide instructions on how to plug in your half-assed substitute.

Software Pin Factory

Friday, January 19th, 2007

I started reading Adam Smith’s The Wealth of Nations. For fun. Because I’m a big dork. Right at the beginning, he talks about division of labor and pin factories. Pins: little bits of wire with a point on on end and a knob on the other. The point is that a single craftsman, without particular skill or tools, could only make a handful of pins a day. In a pin factory, the process is divided into more than a dozen stages, each simple and specific, with its own tools. This process is literally hundreds of times more productive. Businesses have been trying to pull off this trick ever since.

It worked fantastically well in the industrial age. As we moved into more of a service economy, the principle still applied, though not as strongly. In your typical office, you have specialization of skills: Managers, admin assistants, sales, marketing, and so on. In a one person company, that one person can cover all those roles. Things will go smoother when they can divide the work up among several people, but not by a factor of hundreds.

As software development has become a bigger and bigger business, the obvious thing has been to try to apply the same assembly line model: analyze, subdivide, specialize. And so we come to Enterprise Software development, which pretty much follows the old waterfall model: Requirements, architecture, design, implementation, test, support. The business analysts don’t write code, the architect doesn’t write test plans, and the programmers don’t field support calls. The business analyst writes a requirements document, the architect writes an architecture document, and so on. Each stage does their piece and throws it over the wall to the next team. The principle is sound: The more narrowly you divide up the skill set, the more specialized each group will be, and the better at their particular task. Push this far enough and eventually you can replace them with trained monkeys. Very clean, very elegant. Very efficient? Umm… no.

The problem is that there’s a significant difference between an Enterprise Software solution and a pin. A pin is a very simple thing. Everyone knows how it works and can tell at a glance if a given pin will do its job. Unless it’s bent, blunt or missing its head, it’s good to go. If an end user finds that one pin is poorly made, they just throw it away and get another.

An Enterprise Software system is not simple or obvious. Aside from the fact that even the customer often doesn’t entirely understand how they want it to work until they start using it, the amount of information that has to be communicated from stage to stage is huge. Requirements documents can be hundreds of page. None of the workers has any innate sense of whether the information handed to them from the previous stage is complete or accurate. Every misunderstanding is multiplied down the chain. It’s like playing “telephone” with War and Peace.

The key here is that when you divide up the labor in a process, you also incur a communications cost between each stage. It’s a trade-off: Each stage can be done more efficiently, but information about the work has to be passed between them. In the pin factory, the benefit of specialization is huge, and the communications transfer is tiny - as I said, the quality of a pin is obvious. In a software shop, the benefit of specialization may be significant, but the communications overhead is enormous. To come at it from a different angle, I’ve heard it said that a programmer is lucky if they get to spend 20% of their time actually writing code. The other 80% is communications overhead: reading documents, sitting in meetings, writing documents. Add in the time you spend on rework due to miscommunication, and that 20% starts to sound generous. Here, the assembly line is actually less efficient.

So what do you do? The popularity of “Agile” tools and techniques is clearly a response to this, along with component or service oriented architectures. Break the system up into independent, well-defined pieces, and put them in front of the users as quickly as possible. The catch here is that you can’t use trained monkeys. You need people who can talk to the end users and write code, who can carry the product all the way through the process. Maybe they need help from experts like domain specialists or QA engineers, maybe they can divvy up some of the work to tech writers or programmers, but the key is to capture an end-to-end understanding of the product in as few heads as possible.

Under the Hood

Friday, April 22nd, 2005

Imagine that you work in a large and somewhat old-fashioned office building. If you want to send a message to your buddy Joe over at XYZ Corp, this is how it goes. You write out your letter on a piece of paper and put a sticky note on it saying, “Please send to Joe Smith at XYZ Corp,” and hand it to your secretary. She (I said this was an old-fashioned place) puts the letter in an envelope and puts Joe Smith’s name on it. Then she looks up the address for XYZ Corp and writes that on the envelope, along with your return address. Then she hands it off to the guys in the mail room.

What they do is interesting. They look at the address for XYZ Corp and say, “Hmm… that’s out of town. It needs to go to Central.” So they put your envelope inside another envelope and write “Central Post Office” on it.

When it gets to the central post office, they open the outer envelope and read the address on your letter. They say, “Oh, this is going to Chicago,” or wherever. So they put your envelope inside another envelope and write “Central Post Office, Chicago” on it.

Then it gets to the Central Post Office in Chicago. They open up the envelope addressed to them and see the address for XYZ Corp. So they put it in another envelope that just has the 9-digit zip code for the XYZ Corp building on it.

It shows up at XYZ Corp, and the guys in their mail room open up that envelope and see that it’s addressed to Joe Smith. Somebody runs it upstairs to Joe’s secretary, and she opens the envelope and hands Joe your letter. When Joe sends a reply back, it works the same way.

This is how the Internet works.

It’s actually more complicated - there are more middlemen - but that’s fundamentally how it all works. It’s all these little letters (called “packets”) flying around a very, very fast postal system. This is a pretty clear match for email, but it’s also how everything from web pages to streaming video to Voice Over IP works.

When you “go to” a web site, you’re really mailing out a request for a web page. It’s like writing off to a mail-order catalog company. There’s a standard form that defines how you ask for web pages. You fill it out and send it in. You’re sending this little form that says, “I want to see http://www.spuriouspundit.com/index.html”. That request goes out through this metaphorical postal system to the spuriouspundit.com server, and some little toiling minion there xeroxes off another copy of the index.html document and mails it back to you.

Like I said, it’s more complicated than that. How do you keep email and web pages and FTP sites all running on the same machine without tripping over each other? Imagine your office building has a bunch of different departments in it, but they all share the same mail room. Instead of a billing department and a sales department, you’ve got an email department and a web department and an FTP department. The way it works is that they each have different post office box numbers. Whenever a letter comes into your building, the mailroom guys just have to drop it in the right box. One of the rules of this postal system is that the addresses on letters have to have a box number. Furthermore, these box numbers are standardized, so that box 80 is the normal box number for the web department, box 25 is for email, etc. So when you send off your web page request, you know that it’s a web page request, and wherever it’s going, it should be going to box 80.

This is also how you keep your responses straight. Even if you’re the only guy at your company, you could be downloading a couple of mp3s in the background while you’re popping up new browser windows right and left. If all that stuff is landing in the same inbox, you’ll never sort it out. So each time you ask for a web page, you set up a new post office box just for its responses. Your downloads go to boxes 5001 and 5002, and your web pages end up in 5003, 5004, and so on.

Here’s the next wrinkle. Say you send off a request for some big, fat mp3 file that won’t all fit in one envelope. So it gets broken up into a whole bunch of separate letters. Now on top of that, like the real post office, stuff can get lost: Mail trucks get stolen; Some yutz in New Jersey cuts through a long-distance fiber-optic cable with a backhoe. Even if nothing gets lost, there’s no guarantee that everything is going to show up in the order you sent it.

So what do you do? First, you send a letter that effectively says, “Hey, I want to send a whole bunch of letters back and forth with you. Here’s the address you should send all the replies to.” This is where your web browser says, “Connecting to …” in the status bar. Once you’ve got an OK back, you say, “Send me that mp3 file.” You get a whole flood of letters back, numbered “1 of 23″, “2 of 23″ and so on. You count through them and realize that you’re missing number 17, so you send another message saying to re-send it. When you finally have all the letters, you can put them in the right order, open them up, and glom the mp3 file together.

This little procedure we’re going through here is called a Protocol. It’s not part of the postal system itself, but it’s a set of rules that people have agreed on for how to use the postal system. In this case, it’s a way of communicating reliably through a system that isn’t reliable. It’s a layer of communications on top of a layer of communications. It’s very meta.

The internet is built up of layers of these protocols. Like the envelopes inside envelopes, at each stage, you’re only concerned with the outermost layer. You slip on or peel off your envelope, and everything else is just the stuff inside it, be it one layer or many. IP, the Internet Protocol, is the postal system - simple, but not entirely reliable. TCP, the Transmission Control Protocol, provides the reliable, ordered delivery on top of IP. Email (SMTP), the web (HTTP), and others are actually another layer on top of TCP. Essentially, they all define standard forms for different mail-order requests.

Again, it’s even more complicated than that. But for now, lots and lots of little letters zipping back and forth across the world. That’s the way to think of it.

Programming Mindset

Sunday, April 17th, 2005

So, a friend of mine wants to learn Perl. I figure I can teach her that - Perl is simple. It couldn’t take more than a half-hour to get her up to speed on the basics.

Remember that Picture Hanging essay, about how you aren’t aware of how much you take for granted once you’ve learned something? Yeah. I had no idea how much stuff you have to learn before you can even start programming. You have to understand the environment - what’s going on in a computer - at a much deeper level than most users need. (As the tourist/business traveler/expatriate metaphor rears its head again.)

First, there’s the whole command-line thing. Fortunately, she had that down, ‘cuz I have no idea where I’d even start. Your whole frame of reference has to shift to deal with that. You have to explain about opening and reading from files - that a file is really a sequence of characters (don’t get started on bytes vs. characters). And by the way, the end of a line is actually marked by a character, but you can’t see it. Oh, and pipes: They’re like files, but they don’t really live anywhere. Ummm… yeah.

Then there’s the whole utility program thing: The idea that programs can be little tiny things, that they don’t have to have graphic interfaces - they “talk” to each other.

To most people, an application is something you see and interact with. Even when you do deal with things like the filesystem, it’s mediated by a graphic interface - a metaphor. It’s a good enough metaphor that people aren’t really aware that it is a metaphor, let alone what it’s a metaphor for. To someone whose idea of programs is Word and Excel, the idea of ‘piping’ the output from one program into another just doesn’t make any sense.

OK, so that’s all the environment. Those are the building blocks you have to work with, the walls you live within. Like I said, I got off fairly easy on most of that; I had someone who knew her way around the command line, and had even used grep a few times. The next step was explaining what a program is.

A program is a sequence of instructions, kinda like a recipe. But that doesn’t really capture the issue, because recipes are written for humans. Humans are smart. Computers are very, very stupid. Fast, but stupid.

A computer is like some sort of high-speed, idiot-savant imp. It works very quickly, and it can remember a huge amount of stuff, but it’s fundamentally dumb as a bucket of mud. It can’t think for itself at all. If you want it to do something, you have to explain in minute detail precisely how to do it. You also have to think of all the things that could go wrong and how to deal with them.

Let’s imagine you’ve got this sort of imp, and you want it to go get your groceries. It has to go to the store, find all the stuff on the list, pay for it, and come home. Simple, right? You’re underestimating how stupid your computer imp is. If it knows how to walk, open doors, follow directions, and cross streets without getting run over, it’s only because someone else programmed that much for you.

Let’s assume you’ve got an imp programming language that gives you that much. So you say, “Go to the grocery store, get everything on the list, pay for it, and come home.” First, it goes off and never comes back. You go to the grocery store to see what’s up, and your imp is standing in the freezer section. You told it to get pistachio ice cream. They’re out. The imp is waiting for them to restock.

So now you have to instruct it to try another store. You have to give the imp a list of stores, in addition to the list of groceries. If it gets to the last store without finding everything, it should just come home.

This seems too work, but it always takes your imp a really long time to get groceries. You spend a while following him around (debugging) and discover that he’s going to every store every time, even if he already has everything. Ooops, another fix to make.

You write a bunch more imp code, and send it off. It still never comes home. This time, it’s stuck at the cash register. Spaghetti sauce went up 5 cents from last time, and now your imp doesn’t have enough money, and is stuck in the act of paying. You can just give the imp some extra money, but you’ll always have to deal with the possibility that he won’t have enough. Even though it seems less than ideal, you tell him to just come home if he doesn’t have enough money for everything.

Everything works fine for a while, but eventually, you realize that you haven’t had vanilla ice cream for ages. It’s on the list. You check the stores, and sure enough, they’ve got tons of it. You double-check the list, and it’s on there as “Vannilla”. Okay, maybe you could come up with a system for correcting your typos - one that won’t result in your imp buying a gun when the store is out of gum - but that’s a lot of work. It’s easier for you to just type things right. But if you ever sell (or even give) your imp code to other people, you know there will be an unending stream of complaints about how your stupid imp won’t buy vanilla ice cream.

Programming is all about developing this mindset - learning to think through all of this stuff in advance, figuring out all the ways your imp could screw up anything you tell it to do.

Being Valuable

Saturday, January 1st, 2005

So, I said earlier that tech people shouldn’t have to negotiate for their salaries. Some of you took this the wrong way. It is not validation for you just sitting in your cube, doing your job, and not paying any attention to the company around you. That’s not good. You should not be completely ignorant of the business side of the house.

Let’s go through the basics here. You are working at a job. Your employers employ you. They pay you a salary. They pay you this salary because you do something that they consider useful. “Useful” generally means “makes money for them”. There may be a fairly indirect path to it, but what you do ultimately brings money in the door. Your usefulness to them is measured by how much money that is. Your perceived usefulness also depends on how visible the connection is between your work and money coming in.

This is why sales people make so much more than programmers. Their work is directly tied to money coming in. The sales guy can say, “I made X in sales this month.” You can argue that because you’re a really good programmer, it’s easy for the sales guys to sell your work. You can argue that the clever work you did six months ago has resulted in a better product, and increased sales now. But that’s very hand-wavey. It’s hard to put dollar figures on that.

There are two things you can do to increase your perceived usefulness. You can publicise your accomplishments, strengthening in the minds of your bosses the connection between your work and money coming in. You can also focus your work on things that make (or save) the company money. Both of these require understanding at least a bit about the business side of things.

Let’s say you’re a sysadmin (because if you aren’t, you probably know one), and you implemented an automated patch management system. Well, that sure made your life easier, and gave you more time for your other work (’cuz there’s no end of that). And it’s a much more scalable solution, to boot. But how do you sell that to your boss?

Your boss thinks in terms of money. It’s not that he’s inhumane or clueless, it’s just that money is how you measure things. People and equipment are manifestations of money. You are a person, and your time costs them money. Therefore things that save you time save him money. Now the hard part, the maddeningly imprecise part, is figuring out how much.

In this example, you’ll have to have some idea how much time you used to spend patching machines. Guess - you can preface your report with, “According to our estimates…” Say you used to spend 3 hours a week patching machines, it took you a week (40 hours) to set up the system, and now you only have to spend 5 minutes a day on it. So your system “cut patch management staffing requirements by 85%” and will “earn back its initial investment” after about 4 months. Yes, that’s management-speak, but “automated a bunch of stuff” is meaningless to anyone outside of the tech staff. You have to translate it - you have to explain the business impact of what you’re doing.

Note that this cuts both ways. If you only used to spend half an hour a week patching boxes, and it took you a month to set up the system, you’ll have a hell of a time explaining that. Ultimately, you need to learn to do the math up front.

So now what do you do with your new-found spare time? Make yourself useful. First, start learning the bigger picture. Learn more about why you do what you do, and then why your group does what it does. Then start thinking about how that might change, or how they should change. Research new tools and techniques you could use - not just “cool” stuff, but things that will help you do your job better. Learn to apply that business logic.

You can also learn more about the other parts of your company, how and why they do what they do. First off, this is just interesting, like exploring a new world or some weird parallel universe. But there may also be things you can do to help them out. I’m not talking about doing their work for them; I’m talking about situations where you say, “Hey, we could write a tool to do that,” or “Don’t you have a database to track all that?” - situations where a little work by you could save them a lot of time and trouble. You’d be amazed at how much tedious, repetitive crap other people put up with in their work - things that programmers would find some way to automate.

At one job, we had a graphic artist who got stuck doing a monthly update of a web page from a PDF file. It was table after table of financial data. She opened up the PDF file in one window, the HTML in another, and copied it field by field, by hand. Click, drag, CTRL-C, click, CTRL-V. For every single number in every table. The first time she did it, it took her two full days. She griped about it to me, and I said, “that’s insane.” I spent the next day hacking together a couple of utilities and a perl script, and came up with something that parsed the PDF file and generated the web pages. It took about 5 seconds to run, and after that, she just had about 15 minutes of reviewing the pages and making special format tweaks. I made a new best friend that day.

You can earn a lot of good karma that way. It can also help break up the monotony of your regular work. You pick little projects and do them incrementally, on your own terms. You’ve got your “customer” right there, so you can try out all the XP and agile methodology stuff you’ve been reading about. And it can give you an arena for learning new skills or technology. A quick and simple web-based form entry application may be perfect for teaching yourself Ruby On Rails. A report generation tool may be a good way to brush up on your Perl.

When you’re done, make sure everyone knows. Tell your boss, and get him to talk to your new-found friends over in graphic design or accounting or wherever. It’s one thing to toot your own horn, but it another when people outside your department are singing your praises.