Martin Probst's weblog

MacHeist software bundle

Tuesday, January 15, 2008, 08:57 — 0 comments Edit

MacHeist offers a software bundle consisting of a set of nice Mac OS X applications for 49$. While I certainly won’t need some of the applications, this includes Snapz Pro X, which itself costs 69$ standalone. Other apps include Pixelmator, CoverSutra and CSSEdit, so this is definitely worth looking at.

"Optimized for writes"

Monday, January 7, 2008, 09:08 — 0 comments Edit

Priceless @ dive into mark:

“What is that?” she exclaimed.

“It’s all the paperwork we’ve collected this year.”

“In one big pile?”

“It’s a perfectly good system. It’s just optimized for writes.”

Spring MVC / web framework. not so l33t

Thursday, December 20, 2007, 13:03 — 2 comments Edit

I’m currently digging into the Spring framework a bit and just finished walking through the step-by-step tutorial. It creates a simple application that displays a list of products, and then allows you to increase the price of all of them. The price increase is validated and persisted in an HSQL database.

Behold the line counts:

      23 ./.classpath
      23 ./.project
      33 ./bin/test-context.xml
      16 ./build.properties
     308 ./build.xml
       5 ./db/create_products.sql
       2 ./db/load_data.sql
       1 ./db/server.sh
       0 ./db/test.lck
     151 ./db/test.log
      17 ./db/test.properties
      10 ./db/test.script
      39 ./src/springapp/domain/Product.java
      23 ./src/springapp/repository/InMemoryProductDao.java
      48 ./src/springapp/repository/JdbcProductDao.java
      11 ./src/springapp/repository/ProductDao.java
      20 ./src/springapp/service/PriceIncrease.java
      53 ./src/springapp/service/PriceIncreaseValidator.java
      11 ./src/springapp/service/ProductManager.java
      29 ./src/springapp/service/SimpleProductManager.java
      36 ./src/springapp/web/InventoryController.java
      46 ./src/springapp/web/PriceIncreaseFormController.java
      37 ./test/springapp/domain/ProductTests.java
      45 ./test/springapp/repository/JdbcProductDaoTests.java
     100 ./test/springapp/service/SimpleProductManagerTests.java
      26 ./test/springapp/web/InventoryControllerTests.java
      33 ./test/test-context.xml
       2 ./war/index.jsp
      54 ./war/WEB-INF/applicationContext.xml
       3 ./war/WEB-INF/classes/jdbc.properties
      12 ./war/WEB-INF/classes/messages.properties
      18 ./war/WEB-INF/jsp/hello.jsp
       5 ./war/WEB-INF/jsp/include.jsp
      30 ./war/WEB-INF/jsp/priceincrease.jsp
      34 ./war/WEB-INF/springapp-servlet.xml
      33 ./war/WEB-INF/web.xml
    1337 total

So apart from telling me that either I or Spring are indeed totally 1337, how on earth do they justify this? To be fair, it’s about 200 lines less if you don’t calculate the DB log and the Eclipse specific files, but still, well over 1000 LOC for that?

What’s even worse is the number of concepts you have to understand. Apart from the probably ok Java and SQL stuff - why do we need a build file that says essentially “do as usual”, but on >300 lines? And in the particular funny ant style - lots of <property name=“src.dir” value=“src”/>. When did this change the last time? Why do we need a JSP taglib for even the most basic stuff? Separate setup for the application server for each tiny project? Three separate properties files? Lots of copying jars around?

And then all the XML configuration. >150 LOC not counting the build file. With gems like this:

      <property name=“driverClassName” value=“${jdbc.driverClassName}”/>
      <property name=“url” value=“${jdbc.url}”/>
      <property name=“username”  value=“${jdbc.username}”/>
      <property name=“password” value=“${jdbc.password}”/>
Isn’t that the kind of stupid, repetitive task we created computers for?

Repeated bloat

And it’s not just the one-time setup. Creating the form to increase prices with, i.e. a simple form to enter exactly one integer requires these five(!) components. The PriceIncreaseFormController (50 LOC), the PriceIncrease class to hold the integer(!) (20 LOC), the PriceIncreaseValidator (50 LOC), the priceincrease.jsp (30 LOC), and the XML configuration to glue it all together with 10 lines. That’s 160 lines of code for one simple form, without the code that actually performs the operation or any tests.

Loosely coupled XML

Something else that bugs me is the looseness of this thing. Not as in loose coupling, but as in “loose and falls apart”. Spring uses Java, a static, compiled, type checked language. This static-ness results in less expression, but usually better performance and earlier-caught errors. So far so good. But then we outsource half of our application logic into XML configuration files, with no checks at all. With an abundance of unchecked references to Java classes, field names, hard coded and duplicated URLs and so forth.

The benefits of a compiled language like Java are effectively eliminated by this. Typos in XML files will create NullPointerExceptions at runtime, refactoring doesn’t work anymore and the code cannot be understood as is anymore, but only through reading several XML files. This dispersion of single concerns into lots of files really scares me.

A better framework?

I wonder if this mess is simply due to Java or if there is a better way of doing this. I have seen references to Spring’s annotation based configuration, maybe that helps a bit. Even in static Java it should be possible to do better, with some reflection and by-convention magic.

Java closure syntax with a dash of Smalltalk

Tuesday, December 18, 2007, 12:24 — 0 comments Edit

I just came across a curious paragraph in the Closure Syntax Proposal for Java 7 by Gilad Bracha, Neal Gafter, James Gosling, and Peter von der Ahé, on page 8:

We are also experimenting with generalizing this to support an invocation syntax that interleaves parts of the method name and its arguments, which would allow more general user-defined control structures that look like if, if-else, do-while, and so on.

This doesn't play well with the return statement being given a new meaning within a closure; it returns from the closure instead of the enclosing method/function. Perhaps the return from a closure should be given a different syntax:

^ expression;

Note the Smalltalk-ish “^” return symbol, with the reference to interleaving method name parts and arguments before. I first thought this was an insider joke, but they seem to be serious about that ;-)

Other than that the proposal is really nice, I think. It fits very well into the existing Java syntax - the new blocks are simply blocks as they always have been, and the syntax for nested functions looks exactly like regular Java methods. They also seem to have made up their minds about the necessary type system changes.

J2EE not ready for the enterprise

Monday, December 17, 2007, 11:45 — 1 comment Edit

Well, not really. But it’s surprising how just about anything I’ve ever used gets i18n and especially Unicode support wrong, in some way or another.

After a lot of searching I just found out that you have to put “<%@ page contentType=“text/html; charset=UTF-8” %>” on every single JSP page to get the correct encoding, putting it in one include doesn’t work. How annoying. Thanks go to Cagan.

Puny Java Webstart Log Analyzer

Friday, December 14, 2007, 11:17 — 0 comments Edit

Just for kicks I wrote a trivial Java Web Start application. I wanted to analyze my web server access logs, and while grep + some Ruby code work it’s nicer to have something graphical.

I couldn’t find any existing JWS app, so I wrote one that parses a log in Apache’s combined format and produces some charts (using the nice JFreeChart library).

So here is JLogAnalyzer. It takes about one second per megabyte of logfile, which is quite awful, but it works. It displays the top 20 requested URIs, the top 20 User Agents and requests per day.

screenshot of jloganalyzer

Doing some Java after a long time work gave mixed feelings. Available libraries like JFreeChart are really nice, and Web Start is also great. Writing the code to parse and aggregate information from the log wasn’t - at least if you compare to equivalent Ruby code. Collections without closures simply suck. Running the parsing in a background task, including progress meter and all bells and whistles is ridiculously easy using SwingWorker and ProgressMonitorInputStream.

My only grief about JFreeChart is the use of a custom data set hierarchy that doesn’t use generics, instead of providing an easy interface to the Java Collections API. E.g., why require a PieDataSet if you could simply accept a List containing Map.Entry’s?

Use Spotlight instead of find/locate

Wednesday, December 5, 2007, 10:16 — 0 comments Edit

Might be really obvious, but you can use the command line Spotlight tool instead of find, locate, and grep -R. The cool thing is that it combines the speed of locate with the up-to-dateness of grep and find. It’s not a complete replacement, but useful anyways.

You can limit mdfind to a certain directory with the -onlyin switch, e.g. mdfind -onlyin foo subsitutes grep ‘…’ -R foo. It doesn’t have full regular expressions (as far as I know), but I don’t need those most of the time anyways.

Finding something by filename as in find is a bit ugly, you have to use some Spotlight specific attribute, e.g. mdfind ‘kMDItemDisplayName=“comment”’ will look for files starting with ‘comment’. Beware that this will also look through the Apple translated names, e.g. mdfind ‘kMDItemDisplayName=“Öffent”’ will find /Users/martin/Public, at least on a German mac. Looking for the correct key, kMDItemFSName, works, but is apparently not answered from a cache - it’s faster than a global find, but still quite slow on my system.

mdimport -X gives a list of known attributes that can be used in searches. With some bash scripting one could probably get quite close to locate or grep’s comment line interface.

Content sanitation, html5lib and Iñtërnâtiônàlizætiøn

Thursday, November 29, 2007, 16:13 — 0 comments Edit

As I wrote, I migrated to a handwritten blog engine mainly because I was unsatisfied with the way Wordpress handled my content*. So one of the goals was to properly handle any input HTML and Unicode characters.

Unicode

Unicode support turned out to be more tricky than expected. I decided that for anything written mostly in a western European language, there is only one encoding and it’s called UTF-8. Debugging Unicode issues can be quite ugly, as it can be quite difficult to find out how something is actually encoded. Useful utility: hex editor to find out what these bytes really are. Sadly, that doesn’t help much with MySQL.

First thing is to make sure that really every single part of the tool chain is unicode aware. There is a nice collection of tipps here. In my case, LC_ALL on my server had to be set to en_US.UTF-8, my MySQL tables had somehow been created as non-unicode. The original wordpress database had a totally bizarre mix of unicode and non-unicode columns in every table.

A very useful command in MySQL is

mysql> show create table <tablename>;
Watch out for the DEFAULT ENCODING and per-column encodings.

Also important is to run all mysql scripts with the proper charset set, it appears to default to some latin charset:

mysql -u … -p –default-character-set=utf8

HTML

I’m preprocessing all data from the outside using html5lib. html5lib will parse anything and produce a DOM tree that is similar to what a browser would create. I added some code to wrap plain text outside of block level elements in <p/> containers.

It works nice, although it’s quite slow. One caveat: to html5lib, UTF-8 is called ‘utf-8’, not ‘utf8’. You won’t notice your Babylonian problems until a German U-Umlaut Ü shows up as the character ‘端’ - probably some broken auto detection.

Anyways, now my database contents look good :-)

MacBook Pro defects summary

Thursday, November 29, 2007, 09:12 — 0 comments Edit

Since I bought my MacBook Pro (1st generation) in April 2006 I’m a very happy Mac OS user. The operating system and most applications on it are really nice.

On the other hand, the hardware dongle (i.e. the MacBook) I bought on that day has been horrible. The hardware itself is nice, it looks good, it’s reasonably fast, etc., but I’ve never experienced so many quality problems in any electronics equipment.

When it arrived, the keyboard (which is btw. much worse than the keyboard on my old Thinkpad X30) was broken, some keys didn’t work. You would think that Apple knows how to build keyboards by now…

Then in June 2006, on a business trip to Chicago, the whole system broke down, motherboard had to be exchanged. Luckily, that was on the last day.

Next thing was that the right fan died, somewhen in September.

Then I noticed that the notebook started to give me electric surges when it was connected to AC power. Apple refused to repair this, as the voltage was apparently below 50 V. I really find this development in the American torture debate alarming. The problem has stopped by now, though.

Early this year, the other fan - left side - died. I was just out of the 1 year guarantee and Apple first refused to repair that. After insisting they did, as it’s obviously a manufacturing failure if both fans break in such a short time frame.

And now yesterday I open Disk Utility and see that my internal harddrive reports a S.M.A.R.T. failure. Great.

For me this has been mostly annoying, as all repairs so far have been covered by guarantee. For Apple, selling me this sort of hardware must have been quite a financial loss. Assuming they make 1000 € out of a 3000 € MacBook Pro, the four repairs, including one that required expensive hardware, have probably eaten that up.

I’d be interested if the quality record of later models is similar. Several of my friends had quite a lot of hardware trouble with their models, too. I can’t imagine how Apple makes money from this, if their hardware fails so hard within guarantee time.

RubyGems upgrade 0.9.5

Wednesday, November 21, 2007, 19:56 — 0 comments Edit

RubyGems is available in version 0.9.5. And installing it with gem update –system broke about everything on my system :-(

Gems couldn’t find any already installed gem anymore. The fix was easy, though a bit time consuming: re-install all gems you have.

$ export installed_gems="`ls /Library/Ruby/Gems/gems/ | sed s/-[^-]*$//g | sort -u`"
$ gem install $installed_gems

(with /Library/Ruby/Gems/gems/ being the path to your gems)


New Post