This is a class I wish I'd known about earlier: java.lang.Package. Euxx points out that is has the information you need to describe software's version: title, vendor and version for both software specification and the particular implementation. Yummy.
Monday, May 17, 2004
Clever use of Package
Wednesday, May 12, 2004
Propagating web exceptions to the test environment
Rather than use in-container testing such as Cactus, our project elected to run the tests separately and communicate with the web using httpunit and jwebunit. For the most part this has worked well but one lingering issue was that exceptions thrown in the container are hidden from the tests, and only show up as the exception handling page (our "red screen").
But, that is different now. We had passed the web session back and forth (a clever trick from Andrew McCormick using a helper servlet) using standard object serialization, but flattened it to a string on the trip back because of serial id mismatches. Then last night I realized that I could use XML serialization from the JDK (XMLEncoder) to serialize the session without worrying about mismatch issues. Once this worked, it was a small step to see to serialize web exceptions and rethrow them in unit tests. A rather neat solution, I think.
Saturday, May 01, 2004
Very excellent NKS lecture
Cluey (if that's his real name, Danil) pointed me to to Wolfram's excellent lecture, A New Kind of Science and the Future of Mathematics. Did you buy his book? I did. Wow, is it heavy. It's one of the few books I have to read in pieces — all in one go and I wind up skimming too much. And the pretty pictures... oh so many pretty pictures. Here's just one, but is it a doosie:
To be 20 again, and a new kind of programmer.
Tuesday, April 27, 2004
Personal best practises
Joe Walnes has a very interesting diagram of his personal best practises:
I wish I had the time to draw things like this. ;-)
UPDATE: I mistyped Joe's name for some reason. Sorry about that!
Thursday, April 22, 2004
Services and asynchronous message-passing style
An interesting short essay from Manageability: Loose Coupling and its connection to Robustness.
Wednesday, April 21, 2004
Brick Science
American Digest points out an amusing essay on the crapulence of some neer-do-well coders. Sadly, I encounter these people all the time.
I was fortunate to never have completed a course in Computer Science while at Rice. On the other hand, I was also very unfortunate as Rice has a truly fine department and I would have loved the chance to study programming languages or computer security from true experts. But I was fortunate as I learned how to write programs the old-fashioned way: by studying the code of masters and reading the right books. I had many friends who were excellent programmers, and they put me on the right course with things like the dragon book for compilers, Knuth for algorighms, or the ARM for C++. (No kidding — I learned C++ from the ARM and couldn't figure out why the compilers I tried out didn't seem to implement quite the same language as what I read. It was very eye-opening about what was right v. what was right now.) I learned Linux from the sources and studied good operating system programming from Lions. They both taught me how disgusting and unneccessary most software bloat is, and how a simple implementation is a thing of beauty.
Of late I've learned Java and its companions and become steeped in its culture, and discovered that JUnit is the best of the lot. I'll be happy to return to greener pastures, but for now I'll be satisfied simple with greenbacks for my troubles. I also learned that bird in hand isn't to be sneezed at; I can mix metaphors as well as languages.
Cool AspectJ trick
A nice trick for magically transforming new Fred() into something else from Brian McCallilster. In C++ I would provide a custom new operator, but AspectJ offers another interesting option. Too bad there are no destructors in Java.
Tuesday, April 20, 2004
The request, the session and the form
Struts sucks. Just kidding. Actually, struts really sucks. But it's better than nothing, and it's available everywhere, so like Microsoft Windows, it's the default bolt-on for J2EE webapps in spite of its short comings. And unlike Windows, it is open and free.
Complaints aside, I've been trying out three ways of passing data from an action to the corresponding controller:
- Use the request
- This is very sensible, but was not the initial approach in my current project. In the action stash the data as an attribute on the request, and fetch it back out in the controller. To ensure type safety, use wrapper methods and manifest constants (e.g.,
setFooId(Long)to set theFOO_IDattribute). - Use the session
- This is similar to using the request, and was the initial approach in my current project, but leaves garbage littered about and occassionally tricks code into using an old value from a previous request. Avoid. I'm working on moving session-based code to request-based code as I encounter it.
- Use the form
- This is the most interesting choice. On the surface, the controller has no form to use, only the action has one. But the form is stored as an attribute in the request, and you can fetch it back out if only you know the key for it. Struts uses the name field of the form bean from struts-config.xml as the attribute name. This is nice if you know the name, but fragile if you ever change it. Better would be to take your action mapping, and use that to get at the form bean name. If this works, this would be the best choice of all.
Ah, but just how does one get at the action mapping from inside a controller? That is the question I am presently working on. One way is to use the request processor to give you the action mapping, but I don't know how to get the request processor. More research awaits.
Friday, April 16, 2004
tearDown()
What's the right way to use tearDown() in JUnit tests? I spent an afternoon fixing all the places in our codebase where programmer's had forgotten to call super.setUp() and super.tearDown(), respectively, in their own setUp() and tearDown(). To prevent this in the future, I changed BaseTestCase, our in-house extension of JUnit's TestCase, to catch this in the future when running tests: setUp() and tearDown() in BaseTestCase set flags when run, and I overrode runBare() to check for these flags. Voila!
But Paul Holser, a fellow ThoughtWorker on the project, pointed out that tearDown() should also be recoded. Usually everyone writes:
protected void tearDown() throws Exception {
// do your tear down here
super.tearDown();
}
But Paul suggests instead:
protected void tearDown() throws Exception {
try {
// do your tear down here
} finally {
super.tearDown();
}
}
I think Paul is correct, but that means I need to go back and fix up some 50 spots and delay working on functionality. Is it worth the extra work?
Monday, April 12, 2004
AspectJ and IoC
Brian McCallister asks an intersting question:
Speaking of AOP -- a problem we have not found a good solution for is using an IoC container with AspectJ. You have no control over how aspects are instantiated at runtime, so you cannot exactly obtain them from a container.
The best we have come up with so far is to provide a static service lookup component that can provide the container to the aspect via a lookup. Yuck, completely breaks the point of the container. Static lookup to obtain a container and then use it to lookup components... far from ideal.
In cases where we've used proxy based AOP the container isn't a problem, but I find myself, and others at the company I work for, leaning more and more towards AspectJ from proxy based options.
Anyone have any ideas?
I wonder if any of my fellow ThoughtWorkers involved in these technologies have a solution?
Related to these, is a great new book I just got, Generative Programming by Czarnecki and Eisenecker. I especially appreciate the illustration of how flexible and forward-looking is C++ which this tome presents. And using Smalltalk to discuss metaobject protocols is very slick also. Too bad there isn't much Lisp. :-)
Monday, April 05, 2004
The Linux desktop
Merrick Schincariol has some excellent thoughts on the Linux desktop. And he should checkout KDE3. :-)
Tuesday, March 30, 2004
Bruce Eckel's tour de force on typing
What an essay! Bruce Eckel writes on typing in Java, Python, C++ and other languages.
Thursday, March 25, 2004
Automate everything
A lesson from J2EE development that is widely ignored, especially in corporate environments, is automate everything. In particular, Carlos Perez notes the phenomenal productivity of this approach in Mildly Complex Webapp in 2 Man Months!?.
Pallada: IntelliJ IDEA 4.1 (build 2002)
I just downloaded the latest EAP build from IntelliJ of IDEA 4.1 (build 2002)—4.0.2 is the current stable release—and am quite pleased with it. My subjective impression is that it is rather faster than 4.0 for my most common task: opening classes and files by name (C-n and S-C-n, respectively) and browsing classes from within source (C-Mouse-1). It seems to be about the same with memory usage for a largish project I work on most times. So far, I'm quite pleased and am looking forward to trying out the new JDK 1.5 support features on Wisk.
(See §B.5 of the GNU Emacs Manual for an explanation of notation for key bindings.)
UPDATE: I am having trouble with C-Space not working when there is a declaration of an as yet unimported class. Back to 4.0.2 for a while.
UPDATE: It turns out that C-Space does work, it just doesn't work the same as it used to. You need to now move the mouse over the type needing import, and 4.0.2 is the same. It used to work if the mouse was simply nearby.
Monday, March 22, 2004
Implements broken
Brian McCallister posted a clever idea: mark your borken objects with the Broken interface to support testing for known bugs. When the test fails, you know the bug was unexpectedly fixed:
Where it came up was in a discussion about my practice of writing test cases that are designed to pass if a known-bug which is not going to be fixed yet is allowed to stay in a source tree. The test passes if the bug still exists, fails if the bug has been fixed (so that we know -- this is typically done to document bugs in 3rd party libraries). The benefits of doing this compared to maintaining a seperate src/bugs set of tests which are known to fail wre under discussion (and being determined to be a hack). Instead the suggestion to use a tag to indicate the test is a known and acceptable bug is preferred -- hence implements Broken.
Thursday, March 18, 2004
The guantlet
An outstanding challenge from Leo Simons:
The open source community is giving you a choice: either we all work together, and you release a complete JVM under an open source and/or free software license, or we're going to do things on our own. In the latter case the java community will split and the linux desktop community will fragment further as well. There's a big chance microsoft will win as a result. And like before, you'll have only yourself to blame. In the former case, there's a big chance microsoft will lose, open source will win, and you'll reap the profits.
May the powers be listening.
Wednesday, March 17, 2004
Us thoughtworks assholes with shitty boring jobs
Wowie, zowie! I'm not even sure I like Groovy (I'm a Perl guy myself and Python has a lot of appeal to us Linux hackers), but this time, it's personal:
Whimsy has its place, it's known as perl and other such hacky toys. Leave java to the professionals. If you thoughtworks assholes have shitty boring jobs where you're forced to code in java, don't foist your crap onto the rest of us. Go be perl, ruby, or python monkeys or something suitably hacky that is more egofondlefriendly.
Actually, I find the entire thing rather amusing. The fellow has his point: why is Groovy part of a JSR? Let Groovy be Groovy, not an appendage of Java. That it is built on top of Java is nice and all, but it should be its own thing as much as Perl, Python or Ruby are. I really like that Groovy shares a byte-code interpreter and environment with Java, but that isn't enough to make Groovy a JSR. If that were enough, why not beautiful, elegant Jython? Now that has some groove in it.
Monday, March 15, 2004
Geek envy
I too am a very creative individual; I am a very competent programmer; I too need project management skills. Where's my software architect job? :-)
Thursday, March 11, 2004
The success of crap
Charles Miller writes about good projects failing and bad ones succeeding. I also learned what IKIFNI means. I think he left a word out.
Wither wisk?
Wisk is my current SoureForge project. Wisk is The Web Starter Kit, a straight-forward base project for staring Java web projects with a current toolset: Maven, Hibernate, XDoclet and their ilk. However, it also has toy examples of designing enterprise web applications based on my projects at ThoughtWorks. I work with a very bright group, and try to absorb from them as much as I can: it's like grad school for real-world programming. I've discovered that I should have read Martin Fowler's Patterns of Enterprise Application Architecture earlier—what a book! (And that's not just bootlicking.) So I'm looking to gear my toy examples in Wisk towards the terminology and practises in PoEAA. Hopefully that will make Wisk more useful.
Already Wisk helps shave Iteration 0 down quite a bit since one needn't setup the build environment from scratch but can start with a working, tested build and immediately begin developing. Qapla'!
Wednesday, March 03, 2004
A great discussion on hiring great open-source developers
TheServerSide.COM has a great ongoing discussion on how to hire great open-source developers. This is exactly the sort of internal discussion we frequently have at my company. We are filled with top-quality staff and take only the toughest assignments; without open-source our company would be dead, or at least missing most its staff.
Value objects
What is the correct design for value objects? I'm not talking EJB, but general user types for any kind of large application which takes external input. Some points I think on:
- In a language like Java, should value objects be the equivalent of
typedefs, that is, embody no knowledge? - If a value object has integrity checks in the constructor, what should it do on bad input?
- In Java, if the value object constructor throws on bad input, should it throw a checked or an unchecked exception?
- When mapping value objects to persistent storage, should the mapping match the underlying native type or should it also reflect input restrictions?
Colleagues and I have been discussing this since I joined my current project, and we settled on the most restrictive options: in Java, throw checked exceptions for bad input and in the persistence mapping use the most restricted storage type with integrity checks when possible. I understand the conservative thinking behind these decisions, but I also see that it leads to greater maintenance costs.
Was this the right thing to do?
Tuesday, March 02, 2004
All hail YAGNI
Wading into the YAGNI discussion, my current client would be much better served by YAGNI than "plan for the future". Why? Who knows the future at a Fortune 100 business? Buyouts. Changing requirements. New management, sometimes several times during the same year. Changed IT environments. Trying to plan for that is a guarantee that you will discard a large amount of expensive work. It is cheaper and better engineered to refactor and design iteratively than to spend large chunks of the front of your project on planning and heavy design. Worry not about change, but about ever making it to delivery. Did I mention cancelled projects among the risks?
If you are stuck in hostile territory and cannot refactor freely, you are forced to increase risk even further and plan up front as much as possible—you only get one swing at the ball when this happens to you, so you have to aim for the bleachers each time. Of course, this means you strike out far more often than need be, but a client opposed to refactoring gets what's coming to them.