Over the past few weeks, the developers at work have been taking turns bringing in their laptops... It wasn't something we planned but just started happening spontaneously. One guy brought his Centrino laptop running Linux, another guy brought a 17" screen Dell that he uses for CAD, one guy brought his shiny new Vista laptop and a couple days ago it was my turn to take in my MacBook.
In general my little black MacBook received a fairly warm welcome. People were surprised at how thin it was and the usability of a relatively small 13.3" screen. They liked the built in webcam and although the single button touchpad attracted a bit of grief they quieted down when I showed them that a two finger tap brought up contextual menus. I gave them the flashy demo with Exposé, the magnifying dock and Dashboard and gave them the super abbreviated tour of the iLife and iWork applications.
But in the end the one thing that seemed to get the most attention was the MagSafe Power Adapter. From the magnetic connector to the little brick with "wings" for winding the cord and a removable AC adapter, people definitely liked the design. But having just checked the Apple Store comments on this little item I'm hoping that my little white brick lasts a little longer than everyone else's. Yikes!
But other than the black finish which picks up fingerprints like nothing else I've ever owned, I'm very happy with my laptop. And now my co-workers don't think I'm so crazy for owning a Mac.
Thursday, March 22, 2007
Tuesday, January 30, 2007
Saturday, January 06, 2007
Java & Ruby HTTP Clients
In a mythical IT universe designed around a service oriented architecture (SOA) you could assemble several loosely coupled, autonomous services into a business solution. Each service would communicate in a platform and technology agnostic manner and XML would be the lingua franca. For example, if you needed to integrate data from several business partners you could call various SOAP or RESTful services, get structured XML, and then transform the results into something you could use.
But unfortunately that's not what happens in the real world. Instead of nice composable services you usually get web sites targeted at people not machines. That means you need to automate what would typically be browser conversations with various websites to get the data you need. And then you need to deal with the format of the resulting data. If you're lucky, the data may be structured in a comma separated value (CSV) text file. But undoubtedly you'll have to parse unstructured text representations of a report or get the data out of an excel spreadsheet or even a PDF. It's not pretty.
But lets forget that unpleasantness for the moment and deal with the first problem you'll encounter in trying to automate a browser conversation, getting by the various authentication mechanisms. Let's look at BASIC authentication first. It's pretty common and well supported in the Java-based Jakarta Commons HttpClient library and the Ruby Net::HTTP Standard Library.
BASIC Authentication
To start things off I created a simple Java-based "Dynamic Web Project" using the Eclipse Web Tools Project (WTP) plugins. To keep things simple I created a servlet that returns a string. Then I configured the application to protect the url for that servlet with basic authentication in web.xml. Then in Tomcat's server.xml I modified the context element for my web app to include a reference to the default Tomcat in-memory user database:
FORM based authentication
The next most common method is form-based authentication. When you make a request for a web resource, the response contains a cookie that identifies your session on the server. If that session indicates that you haven't been authenticated yet, then you're redirected to a form to enter your id and password. You fill in the values and then submit the form. Now assuming you entered the right credentials your session on the server will indicate that you're authenticated and every subsequent request (which includes the cookie to identify your now authenticated session) will execute normally. There are variations on this theme that may add more than one cookie so just be sure to capture the cookies and continue to submit them on every request in your conversation.
In order to test this I modified the web.xml file for my Java web app:
So there you go, you're past the website authentication and are ready to make whatever requests you need to get the data you require.

But unfortunately that's not what happens in the real world. Instead of nice composable services you usually get web sites targeted at people not machines. That means you need to automate what would typically be browser conversations with various websites to get the data you need. And then you need to deal with the format of the resulting data. If you're lucky, the data may be structured in a comma separated value (CSV) text file. But undoubtedly you'll have to parse unstructured text representations of a report or get the data out of an excel spreadsheet or even a PDF. It's not pretty.
But lets forget that unpleasantness for the moment and deal with the first problem you'll encounter in trying to automate a browser conversation, getting by the various authentication mechanisms. Let's look at BASIC authentication first. It's pretty common and well supported in the Java-based Jakarta Commons HttpClient library and the Ruby Net::HTTP Standard Library.
BASIC Authentication
To start things off I created a simple Java-based "Dynamic Web Project" using the Eclipse Web Tools Project (WTP) plugins. To keep things simple I created a servlet that returns a string. Then I configured the application to protect the url for that servlet with basic authentication in web.xml. Then in Tomcat's server.xml I modified the context element for my web app to include a reference to the default Tomcat in-memory user database:
<Context docBase="MyWebApp" path="/MyWebApp" [...]With that in place, and the server running we're able to write a couple of methods to access the servlet. In Java:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
debug="0" resourceName="UserDatabase"/>
</Context>
public static void basicAuthDemo()In this example I limited HttpClient's default authentication mechanism to BASIC. I know what my target system uses so why complicate matters with DIGEST or NTLM? Then it was a simple matter of defining the credentials and telling HttpClient to automatically use them and then executing the Http GET method. It looks surprisingly similar in Ruby:
throws HttpException, IOException{
HttpClient client = new HttpClient();
List<String> authPrefs = new ArrayList<String>();
authPrefs.add(AuthPolicy.BASIC);
client.getParams().setParameter(
AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
client.getState().setCredentials(
new AuthScope("localhost", 8080, "localhost:8080"),
new UsernamePasswordCredentials("tomcat", "tomcat")
);
GetMethod get = new GetMethod(
"http://localhost:8080/MyWebApp/myservlet");
get.setDoAuthentication(true);
client.executeMethod(get);
System.out.println(get.getResponseBodyAsString());
get.releaseConnection();
}
def basic_auth_demoThe difference between the two implementations is that the Java HttpClient is doing some housekeeping for you. You define a scope for your authentication and as long as you GetMethod is configured to do authentication it will automatically pick up any necessary credentials from the HttpClient instance. In Ruby you need to set the credentials on the GetMethod explicitly.
url = URI.parse('http://localhost:8080/MyWebApp/myservlet')
get = Net::HTTP::Get.new(url.path)
get.basic_auth('tomcat','tomcat')
response = Net::HTTP.new(url.host, url.port).start do |http|
http.request(get)
end
puts response.body
end
FORM based authentication
The next most common method is form-based authentication. When you make a request for a web resource, the response contains a cookie that identifies your session on the server. If that session indicates that you haven't been authenticated yet, then you're redirected to a form to enter your id and password. You fill in the values and then submit the form. Now assuming you entered the right credentials your session on the server will indicate that you're authenticated and every subsequent request (which includes the cookie to identify your now authenticated session) will execute normally. There are variations on this theme that may add more than one cookie so just be sure to capture the cookies and continue to submit them on every request in your conversation.
In order to test this I modified the web.xml file for my Java web app:
<login-config>and added the requisite JSP pages. The login.jsp contains a form that looks like this:
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>
<form method="POST" action="j_security_check">So the Java code to access the servlet using form based authentication looks like this:
Username:<input type="text" name="j_username"><br/>
Password:<input type="password" name="j_password"><br/>
<input type=submit value="Login">
</form>
public static void formAuthDemo()The Ruby code looks like this:
throws IOException, HttpException {
HttpClient client = new HttpClient();
// make the initial get to get the JSESSION cookie
GetMethod get = new GetMethod(
"http://localhost:8080/MyWebApp/myservlet");
client.executeMethod(get);
get.releaseConnection();
// authorize
PostMethod post = new PostMethod(
"http://localhost:8080/MyWebApp/j_security_check");
NameValuePair[] data = {
new NameValuePair("j_username", "tomcat"),
new NameValuePair("j_password", "tomcat")
};
post.setRequestBody(data);
client.executeMethod(post);
post.releaseConnection();
//resubmit the original request
client.executeMethod(get);
String response = get.getResponseBodyAsString();
get.releaseConnection();
System.out.println(response);
}
def form_auth_demoAgain, the two implementations are remarkably similar. The biggest difference is that the Java HttpClient library is again doing the housekeeping, by tracking and automatically resubmitting the cookies for you. In the Ruby code you have to fetch the cookie yourself from the response header and set the HTTP header for all future requests.
res = Net::HTTP.new('localhost', 8080).start do |http|
#make the initial get to get the JSESSION cookie
get = Net::HTTP::Get.new('/MyWebApp/myservlet')
response = http.request(get)
cookie = response.response['set-cookie'].split(';')[0]
#authorize
post = Net::HTTP::Post.new('/MyWebApp/j_security_check')
post.set_form_data({'j_username'=>'tomcat', 'j_password'=>'tomcat'})
post['Cookie'] = cookie
http.request(post)
#resubmit the original request
get['Cookie'] = cookie
response = http.request(get)
puts response.body
end
end
So there you go, you're past the website authentication and are ready to make whatever requests you need to get the data you require.
Tuesday, December 19, 2006
Mac OS X & Windows in Parallel
The first most natural reaction for a Mac guy like me is "Ick! Windows on my Mac?!". And yeah, it is a bit disgusting. After all we all know that Mac OS X is obviously the superior operating system, right?
Well even if you don't necessarily agree with that assertion, you have to agree that if you're any kind of web developer you can't ignore Internet Explorer. Despite all its warts and laughable standards adherence, it is the browser that most people use. So if you care about giving those users the best experience when visiting your site you need to view it in IE.
My solution was to use Windows 2000 (with SP4 and IE6 installed) within Parallels and I've been pretty happy. W2K runs very well and being able to seamlessly run my webapps in IE while continuing to work in Mac OS X gives me exactly what I need. So here's the recipe:
Well even if you don't necessarily agree with that assertion, you have to agree that if you're any kind of web developer you can't ignore Internet Explorer. Despite all its warts and laughable standards adherence, it is the browser that most people use. So if you care about giving those users the best experience when visiting your site you need to view it in IE.
My solution was to use Windows 2000 (with SP4 and IE6 installed) within Parallels and I've been pretty happy. W2K runs very well and being able to seamlessly run my webapps in IE while continuing to work in Mac OS X gives me exactly what I need. So here's the recipe:
- Install Parallels (get a demo from Parallels to try it out). You might also want to give the beta 3036 version a try (I did). It has some great features like the "coherence" view that lets you mix the W2K windows in with your Mac OS X windows.
- Create a Windows virtual machine and install Windows (take a deep breath its a little surreal)
- Once you have the VM open go to the Parallels Action menu and choose "Install Parallels Tools...". This improves performance, mouse support, the graphics capabilities and lets you drag files to the Windows desktop (and probably a bunch of other stuff too).
- Set Windows' screen resolution, colour depth, font antialiasing, and be sure to set "Show window contents while dragging". The last option is important if you use Parallels' coherence view.
- Start up your web server in Mac OS X, and be sure to open the necessary ports in your built-in Mac OS X firewall to let Windows see your server (e.g., Tomcat is 8080 by default and WEBrick is 3000 by default).
- Type in your Mac's IP address in IE and enjoy! (Well hopefully enjoy, IE has a tendency of frustrating a lot of developers).
Wednesday, December 06, 2006
Passionate Development
A lot of people seem to have a real passion for developing software. So why is it that we have so much bad code? Well I have my own theories. So without further ado I present my most-wanted list of culprits, in no-particular order:
New coders
New developers are great. They're happy to have a job and are excited and keen and want to change the world. But they don't really know what they're doing. Hey sorry, but I've been there, I know. You can always do better the second time. And when you're new you write a lot of code. You do the first thing that pops into your head. That's not usually a good recipe for creating good code. I've said it before and I'll say it again, mentor these people and give them training. They don't mind learning and usually take constructive feedback well.
Gung ho Project Managers
Project deadlines are very rarely made with developer input and even if they are, deadlines are never adjusted to account for unanticipated problems or changing requirements. The usual solution is to throw more coders at the problem. To write code under the obligation to create software to help someone do their job is one thing. To do it under duress is completely another. Project Managers love to be "under budget" and "on-time". A lot of them don't care what it takes to get there. Tie some of their compensation to creating maintable systems and they'll help do the right thing.
Heroes
You know who I'm talking about. Every place has at least one of them. An environment that routinely has ridiculous productivity expectations seems to attract the evil genius who works his ass off to produce a solution. Like the new coder, this guy writes a lot of code and lives for the pat-on-the-back and the "attaboy". But he isn't really interested in producing an elegant bit of code. Rather he lives for the hack that will make things work at the last minute and "save the company". The problem with this guy is that he perpetuates the bad productivity expectations and increases the brittleness of the environment. Keep some kryptonite handy to slow him down.
The Architect
You know that fat dude from the Matrix who talks in riddles that nobody understands (says shit like "vis a vis" and "ergo"). Picture that guy and make him an IT architect and you'll get my drift. Architecture is a good thing and somebody needs to think about it, but a lot of these enterprise architects have no accountability to anyone and dream up all kinds of crazy impractical things to do. Take for instance all this SOA, Web Service stuff... Good Lord what a mess! But talk to an "architect" and he'll have tears in his eyes when he explains the world he sees through his rose colored glasses. If you're gonna have people called "architects" (regardless of how bad that analogy is for software development) then assign them to projects and make them responsible for something. (btw: I was a technical architect once so save your hate mail. I know what I'm talking about, vis a vis)
The Academic
These guys are aspiring architects. They love to look for the next great solution and somehow work it into their latest projects. There is such a thing as the progression of technology and you should upgrade the technology in your project so that it doesn't become a backwater for discarded frameworks. But you need to be careful. If you blindly adopt the latest and greatest all the time then you'll spend more of your time working the bugs out of these frameworks than you will actually developing your own software. The elusive silver bullet will often shoot you in the foot.
Support Developers
A lot of places I've been devote some developers to supporting the applications in production. They're motivated by the desire to fix bugs and enhance the application to meet ongoing user demand. So while that's a good thing, they usually have to support 20 applications simultaneously, don't really understand how any of them are put together, and only have to touch the code every so often. So what happens is that the application code (no matter how lovingly crafted during development) slowly decays over time. The solution? Make sure the people who developed the application are resonsible for maintaining them. There's nothing like knowing your own code may come back to haunt you, to keep you focussed on writing good code.
DBAs
These characters live in an alternate universe of sets, joins and intersections and they rule this kingdom. They institute all kinds of rules that don't always make sense from all perspectives. Understandably, they want to enforce certain conventions so that things are consistent and easier to maintain. But every once in a while these guys need to stop defending the battlements and adopt the prevailing wisdom of the land. For example, DBA purists will usually get pretty hostile if you talk about using surrogate primary keys to ease the object relational mapping burden. They'll get all academic about composite natural keys. And while their argument may make absolute sense from their perspective, they need to undertand that their unreasonable rules can result in less elegant code. Don't even get me started on the "law" about only updating tables through stored procedures.
Summary
Nobody sets out to create nasty tangles of code. Most people are at least somewhat passionate about what they do. They want to have pride in their work. Now it's easy to fall into the trap of negativity and start believing in the futility of trying to make things better. (Lord knows I've fallen in there once or twice). But in the end that's what you have to work with. Greenfield development seems to be a rare commodity. So recognize the poor behaviors, try to understand the motivations behind them, state your opinion, make good decisions (or at least try to influence the decision makers) and do what you can to make your coding world better. And for god sakes, stop writing crap code! ;-)

New coders
New developers are great. They're happy to have a job and are excited and keen and want to change the world. But they don't really know what they're doing. Hey sorry, but I've been there, I know. You can always do better the second time. And when you're new you write a lot of code. You do the first thing that pops into your head. That's not usually a good recipe for creating good code. I've said it before and I'll say it again, mentor these people and give them training. They don't mind learning and usually take constructive feedback well.
Gung ho Project Managers
Project deadlines are very rarely made with developer input and even if they are, deadlines are never adjusted to account for unanticipated problems or changing requirements. The usual solution is to throw more coders at the problem. To write code under the obligation to create software to help someone do their job is one thing. To do it under duress is completely another. Project Managers love to be "under budget" and "on-time". A lot of them don't care what it takes to get there. Tie some of their compensation to creating maintable systems and they'll help do the right thing.
Heroes
You know who I'm talking about. Every place has at least one of them. An environment that routinely has ridiculous productivity expectations seems to attract the evil genius who works his ass off to produce a solution. Like the new coder, this guy writes a lot of code and lives for the pat-on-the-back and the "attaboy". But he isn't really interested in producing an elegant bit of code. Rather he lives for the hack that will make things work at the last minute and "save the company". The problem with this guy is that he perpetuates the bad productivity expectations and increases the brittleness of the environment. Keep some kryptonite handy to slow him down.
The Architect
You know that fat dude from the Matrix who talks in riddles that nobody understands (says shit like "vis a vis" and "ergo"). Picture that guy and make him an IT architect and you'll get my drift. Architecture is a good thing and somebody needs to think about it, but a lot of these enterprise architects have no accountability to anyone and dream up all kinds of crazy impractical things to do. Take for instance all this SOA, Web Service stuff... Good Lord what a mess! But talk to an "architect" and he'll have tears in his eyes when he explains the world he sees through his rose colored glasses. If you're gonna have people called "architects" (regardless of how bad that analogy is for software development) then assign them to projects and make them responsible for something. (btw: I was a technical architect once so save your hate mail. I know what I'm talking about, vis a vis)
The Academic
These guys are aspiring architects. They love to look for the next great solution and somehow work it into their latest projects. There is such a thing as the progression of technology and you should upgrade the technology in your project so that it doesn't become a backwater for discarded frameworks. But you need to be careful. If you blindly adopt the latest and greatest all the time then you'll spend more of your time working the bugs out of these frameworks than you will actually developing your own software. The elusive silver bullet will often shoot you in the foot.
Support Developers
A lot of places I've been devote some developers to supporting the applications in production. They're motivated by the desire to fix bugs and enhance the application to meet ongoing user demand. So while that's a good thing, they usually have to support 20 applications simultaneously, don't really understand how any of them are put together, and only have to touch the code every so often. So what happens is that the application code (no matter how lovingly crafted during development) slowly decays over time. The solution? Make sure the people who developed the application are resonsible for maintaining them. There's nothing like knowing your own code may come back to haunt you, to keep you focussed on writing good code.
DBAs
These characters live in an alternate universe of sets, joins and intersections and they rule this kingdom. They institute all kinds of rules that don't always make sense from all perspectives. Understandably, they want to enforce certain conventions so that things are consistent and easier to maintain. But every once in a while these guys need to stop defending the battlements and adopt the prevailing wisdom of the land. For example, DBA purists will usually get pretty hostile if you talk about using surrogate primary keys to ease the object relational mapping burden. They'll get all academic about composite natural keys. And while their argument may make absolute sense from their perspective, they need to undertand that their unreasonable rules can result in less elegant code. Don't even get me started on the "law" about only updating tables through stored procedures.
Summary
Nobody sets out to create nasty tangles of code. Most people are at least somewhat passionate about what they do. They want to have pride in their work. Now it's easy to fall into the trap of negativity and start believing in the futility of trying to make things better. (Lord knows I've fallen in there once or twice). But in the end that's what you have to work with. Greenfield development seems to be a rare commodity. So recognize the poor behaviors, try to understand the motivations behind them, state your opinion, make good decisions (or at least try to influence the decision makers) and do what you can to make your coding world better. And for god sakes, stop writing crap code! ;-)
Monday, December 04, 2006
Java Compiler Woes
To cut a long story short, I lost a couple days of effort to discover that you should always use the version of the Java compiler that matches your production environment. Take for example this little piece of Java code:
Compile it and run it in Java 1.4 and it prints out "100". Compile it and run it in Java 5 and it prints out "100". But now take that Java 5 compiled class (e.g., javac -target 1.4 -source 1.4 BigDecimalTest.java) and run it in Java 1.4 and you get:
The problem is that Java 5 introduced a new constructor for BigDecimal that takes an int. So once compiled in Java 5, the class expects to find a constructor to match that signature and when run in Java 1.4, it blows up spectacularly. Nasty little mess.
import java.math.BigDecimal;
public class BigDecimalTest {
public static void main(String[] args) {
BigDecimal big = new BigDecimal(100);
System.out.println(big);
}
}
Compile it and run it in Java 1.4 and it prints out "100". Compile it and run it in Java 5 and it prints out "100". But now take that Java 5 compiled class (e.g., javac -target 1.4 -source 1.4 BigDecimalTest.java) and run it in Java 1.4 and you get:
Exception in thread "main" java.lang.NoSuchMethodError:
java.math.BigDecimal.(I)V
at BigDecimalTest.main(BigDecimalTest.java:5)
The problem is that Java 5 introduced a new constructor for BigDecimal that takes an int. So once compiled in Java 5, the class expects to find a constructor to match that signature and when run in Java 1.4, it blows up spectacularly. Nasty little mess.
Sunday, December 03, 2006
Airmiles with that?
The latest edition to my family of computers is slowly making it's way around the world. It started its life in China, then Anchorage, then flew straight overhead to Memphis, and is now getting acquainted with Canadian customs in Mississauga. Unfortunately, more than half the shipping time has been spent there waiting for some customs official to give it the green light to move on. If only I could get air miles for the trip perhaps I'd have a little more patience for this delay. C'mon you guys, get a move on!
P.S., Ain't Google Maps cool?!
P.S., Ain't Google Maps cool?!
Wednesday, November 22, 2006
Enterprise Software? You gotta be kidding me!
If you create truly mediocre software for a vertical market in a mainstream technology like .NET, fill it with buzzwords like "web services", then the truly ignorant will shower you with bags of money. Apparently that's the recipe to becoming a success. Hard to believe isn't it? Well I wish it weren't true but it must be. Otherwise I have no explanation for the project that I'm working on.
Recommendation #1. Make it real ugly.
I commented earlier this year about the ugly UI, and since then things haven't gotten much better as I've started to dig around under the covers. The entire UI is driven via metadata. Nobody actually designs this interface to help the user solve his problem. Hell no! That's way too much work. Instead, tell it there's a new column and it just adds it the the grid. Wow. That's brilliant. Yeah it's ultimately flexible and configurable by every single client but then you end up with one ugly generic UI. Where's the dialogue between designer, developer, and user about what's critical?
Recommendation #2. Use .NET specific types in your Web Services
Because this is largely an integration project we tried to follow the vendor's recommendation to use their "platform-neutral, next-generation, SOA compliant", web services. Well that turned out to be a bust because their crappy implementation simply returns a serialized Microsoft .NET DataSet that no other toolset (including AXIS for Java) seems to be able to understand it. We ended up using a TCP/IP monitor to reverse engineer this abomination just so that we could figure out how to call it. And if you've ever looked at the XML of a serialized dataset you'd know immediately that this isn't something you should be exposing to your clients in the first place. It basically opens the kimono and says "here's my data model". So now there's zero abstraction from the database. If it changes then so does the web service. I can see that being nice and stable. Not!
Recommendation #3. Release often and change your external API.
Trying to write some code on top of something that changes all the time is like building a house on mud. Just yesterday, we discovered that their latest version of the app has a subtle change in the URLs for the web services. Suddenly none of our code worked. (BTW: I argued that we should test this thing before just dumping it on our servers but nobody listened).
Recommendation #4. Make ridiculous claims and milk your clients for consulting fees.
The vendor said it works with Oracle to make the sale but their consultant, who came onsite for a week to troubleshoot the performance problem, made the astounding pronouncement: "it works faster with SQL Server". What? What about the promises you made before and are you sure that'll fix anything? During our load testing we discovered that the CPU utilization on the database server is minimal regardless of database flavor. It's the application server that's pinned! How come they didn't mention that?
Conclusion Make crappy software for a niche market whose users are dumb enough to get dazzled by a flashy demo. Then sell a license for some exorbitant fee and just start milking them with expensive consulting served up by people who don't have a clue what they're talking about. Sure your users and their pathetic IT staff will grow to loathe you, but hey you already have their money and there's always another sucker knocking on your door just dying to buy your "enterprise software".
Or you could just Get Real...
Recommendation #1. Make it real ugly.
I commented earlier this year about the ugly UI, and since then things haven't gotten much better as I've started to dig around under the covers. The entire UI is driven via metadata. Nobody actually designs this interface to help the user solve his problem. Hell no! That's way too much work. Instead, tell it there's a new column and it just adds it the the grid. Wow. That's brilliant. Yeah it's ultimately flexible and configurable by every single client but then you end up with one ugly generic UI. Where's the dialogue between designer, developer, and user about what's critical?
Recommendation #2. Use .NET specific types in your Web Services
Because this is largely an integration project we tried to follow the vendor's recommendation to use their "platform-neutral, next-generation, SOA compliant", web services. Well that turned out to be a bust because their crappy implementation simply returns a serialized Microsoft .NET DataSet that no other toolset (including AXIS for Java) seems to be able to understand it. We ended up using a TCP/IP monitor to reverse engineer this abomination just so that we could figure out how to call it. And if you've ever looked at the XML of a serialized dataset you'd know immediately that this isn't something you should be exposing to your clients in the first place. It basically opens the kimono and says "here's my data model". So now there's zero abstraction from the database. If it changes then so does the web service. I can see that being nice and stable. Not!
Recommendation #3. Release often and change your external API.
Trying to write some code on top of something that changes all the time is like building a house on mud. Just yesterday, we discovered that their latest version of the app has a subtle change in the URLs for the web services. Suddenly none of our code worked. (BTW: I argued that we should test this thing before just dumping it on our servers but nobody listened).
Recommendation #4. Make ridiculous claims and milk your clients for consulting fees.
The vendor said it works with Oracle to make the sale but their consultant, who came onsite for a week to troubleshoot the performance problem, made the astounding pronouncement: "it works faster with SQL Server". What? What about the promises you made before and are you sure that'll fix anything? During our load testing we discovered that the CPU utilization on the database server is minimal regardless of database flavor. It's the application server that's pinned! How come they didn't mention that?
Conclusion Make crappy software for a niche market whose users are dumb enough to get dazzled by a flashy demo. Then sell a license for some exorbitant fee and just start milking them with expensive consulting served up by people who don't have a clue what they're talking about. Sure your users and their pathetic IT staff will grow to loathe you, but hey you already have their money and there's always another sucker knocking on your door just dying to buy your "enterprise software".
Or you could just Get Real...
Ruby on Rails demo
Yesterday I gave my co-workers a lunch time presentation about Ruby on Rails. Since these guys haven't even seen Ruby, never mind Rails, I kept it pretty basic and loosely based it on DHH's build-a-blog-in-15-minutes screencast at RubyOnRails.org. I coded live and in person and even the mistakes I made were good because they highlighted not only Rails' good error reporting but also the quick edit-and-refresh-the-browser style of coding. No Ant scripts, no compiling, no restarting the app server, no waiting for the VM, etc.
In the end I think I made the impact I wanted. I showed people some other ways of developing web applications that are fundamentally more productive than the endless configuration hell we Java developers tend to work in. Unfortunately, I also heard unfortunate statements like "that's cool but we're a Java shop and we'd never be able to deploy something like that". While that was disappointing, I kept my composure and plugged JRuby as a possible future solution (I can't wait to be able to a build a Rails app into a WAR and deploy it in WebLogic).
I planted the seed. Now all I have to do is continue to nurture the idea of Rails development, continue the education and hope for a brighter future.
In the end I think I made the impact I wanted. I showed people some other ways of developing web applications that are fundamentally more productive than the endless configuration hell we Java developers tend to work in. Unfortunately, I also heard unfortunate statements like "that's cool but we're a Java shop and we'd never be able to deploy something like that". While that was disappointing, I kept my composure and plugged JRuby as a possible future solution (I can't wait to be able to a build a Rails app into a WAR and deploy it in WebLogic).
I planted the seed. Now all I have to do is continue to nurture the idea of Rails development, continue the education and hope for a brighter future.
Saturday, November 11, 2006
Tim Bray: PHP, Rails, & Java

Tim Bray, of Sun Microsystems, set off a little bombshell with one slide from a presentation he gave at the International PHP Conference. The slide in question compares PHP, Rails, & Java on four separate criteria: Scaling, Dev Speed, Dev Tools, & Maintainability. Rails won on Dev Speed and Maintainability and PHP won the scaling contest!
The presentation even goes on to talk about the WS-* specs being too complex (he even borrowed DHH's WS-Deathstar slide). Who would have thought things like this would be coming out of the mouths of people at Sun? Can't say that I disagree... Fewer lines of more readable code should mean greater productivity and better maintenance. That seems like a no-brainer.
Monday, November 06, 2006
Code Generation with Ruby
I just watched some parts of a Google Tech Talk Video about code generation. It was a videotaped presentation by Jack Harrington, the author of "Code Generation in Action" to some of the developers at Google. I didn't find most of the presentation to be that interesting, but there was one snippet of Ruby code that I liked. It looked something like this:
My template file was a single line that contained this: "Hello <%=name%>". I think you can probably figure out what the result would look like ;-)
The real example he used in his presentation was slightly more elaborate in that he had a source of data, an XML file, and he used REXML (a great XML library in Ruby) to read the source to generate a SQL file.
I'm not a big advocate of code generation but if you find yourself in the unenviable position of needing to do it then this is a great place to sprinkle in a little Ruby magic.
require 'erb'
File.open('./test.txt', 'w+') do |f|
name='Darcy'
erb = ERB.new(File.new('template').read)
f.write(erb.result(binding))
end
My template file was a single line that contained this: "Hello <%=name%>". I think you can probably figure out what the result would look like ;-)
The real example he used in his presentation was slightly more elaborate in that he had a source of data, an XML file, and he used REXML (a great XML library in Ruby) to read the source to generate a SQL file.
I'm not a big advocate of code generation but if you find yourself in the unenviable position of needing to do it then this is a great place to sprinkle in a little Ruby magic.
Wednesday, November 01, 2006
Sucking the Fun Out of Software Development
Last week I found myself being subjected to one of the worst fates known to the North American cubicle dweller... the dreaded team building meeting. Acckkkk!!!
But even worse was that the typical mind-numbing "personality profiling exercise" was replaced with the excruciating "enterprise architecture presentation".
Where do these guys come from anyway? Who uses words like "end user vision", "long range target architecture", "governance board" and garbage like that?
Quite frankly I don't have the patience for it. If you get a thrill trying to out-merriam-webster a bunch of other like minded architecture zombies then all the power to you, but don't come to my precious team-building meeting and make things worse by spouting that meaningless drivel at me.
I tried to pay attention in order to show some respect for my fellow man, but before I knew it I felt like Charlie Brown listening to his teacher, mwah-mwah-mwah...
So I first started sketching to try and relieve the tedium but soon found myself writing down a bunch of words to describe the corporate architecture team and this crap presentation. Here's what I wrote:
Anyway, my point goes back to the stuff that DHH talks about all the time:

But even worse was that the typical mind-numbing "personality profiling exercise" was replaced with the excruciating "enterprise architecture presentation".
Where do these guys come from anyway? Who uses words like "end user vision", "long range target architecture", "governance board" and garbage like that?
Quite frankly I don't have the patience for it. If you get a thrill trying to out-merriam-webster a bunch of other like minded architecture zombies then all the power to you, but don't come to my precious team-building meeting and make things worse by spouting that meaningless drivel at me.
I tried to pay attention in order to show some respect for my fellow man, but before I knew it I felt like Charlie Brown listening to his teacher, mwah-mwah-mwah...
So I first started sketching to try and relieve the tedium but soon found myself writing down a bunch of words to describe the corporate architecture team and this crap presentation. Here's what I wrote:
- bureaucratic
- roadblocks
- undemocratic (appointed)
- not a meritocracy
- unrealistic
- double talk
- expensive
Anyway, my point goes back to the stuff that DHH talks about all the time:
- Beauty leads to happiness
- Happiness leads to productivty
- (therefore) Beauty leads to productivity
Sunday, October 22, 2006
RadRails Refresher
So I started working a bit harder on a rails project this past weekend (several hours a day) and discovered a few things about Ruby/Rails and my IDE that I thought I'd share (in no particular order):

- RadRails has the ability to automatically run your unit tests whenever you modify certain files. The AutoTest functionality is great but only if you realize it's there. I had been staring at a big red 'X' in the toolbar occassionally wondering "I wonder what that's for" and then suddenly saw a nice big green checkmark after I fixed a bunch of tests. Duh!
- ctrl-space is your friend. In the absence of any true "intellisense"-like functionality, RadRails' templates will save you a bunch of typing. In fact if you're a TextMate refugee then try Corban Brook's textmate-like templates for RadRails.
- Rake is cool, but I always forget all the tasks I can run. Yes even the simple ones like "rake migrate VERSION=3" or "rake db:fixtures:load" seem to continually elude me. Well RadRails has a Rake view. Just make sure you're in a Rails project and then Bob's your uncle.
- I like watching the development log. And lo and behold RadRails allows me to right click on the .log file in the Rails Navigator and select "Tail". This allows me to watch the end of the file in a console window. I recommend creating a new console view, displaying the tailed log file, and then pinning it. Then drag it somewhere where you can always see it.
- The servers view allows me to set up a mongrel view and then start, stop, and restart it with the click of a button. It also has a handy little globe button for opening a browser within RadRails that goes to your default URL. The browser's functionality is a bit anemic, but it's still a nice touch.
- Autotest is awesome but if you want to run a single unit test, just open it in an editor, right click and select "Run As -> Test::Unit Test"
- When I use Eclipse to do Java editing I often like to click the button in the toolbar that only shows me the selected element in my editor. That way I can focus on a single method at a time. RadRails has this button too but it seems to be permanently disabled. But if you have the outline view kicking around, try clicking on a method and watch what happens.
- I like to keep the Data Navigator view around to see the table structures. Comes in handy when I can't remember some detail about my data model.
- My console view doesn't work. Something abut the readline library on Mac OS X I think... Regardless, if it works for you either use it or keep a terminal window open. The console rocks.
- Thanks to the "has_many :through" blog I discovered that I can add a block to associations in ActiveRecord classes and add methods to these associations. For example, I added a find method to one of my has_many relationships. The cool thing is that the find method is scoped by its outer has_many definition. Not sure if I really understand what's going on under the covers (still figuring this Ruby thing out) but it seems like an elegant way to express something like this: user.blog_entries.find_all_by_tag( tag ).
- Now if I could only remember what the RadRails shortcut keys were for navigating between models and tests and navigating between controllers and views I'd be happy...(UPDATE: CTRL-SHIFT-V to go between controller and view, CTRL-ALT-T to go between model/controller and test)
Saturday, October 14, 2006
Google Reader
News Readers have been around for several years and like many other people I have my own collection of feeds to which I subscribe. The only problem was synchronization from computer to computer. It was fairly common for me to read through a list of published articles at work and then come home to do it all over again. It wasn't as time consuming the second time because I could just skip over the ones I'd already read but it was still annoying.
So finally, Google's listened to its users and upgraded its previously weak Google Reader and added the features I needed to use it full time. It's amazing to me what they can accomplish with a browser application. It's making me rethink what can be done with a web app.
So finally, Google's listened to its users and upgraded its previously weak Google Reader and added the features I needed to use it full time. It's amazing to me what they can accomplish with a browser application. It's making me rethink what can be done with a web app.
Wednesday, September 27, 2006
Digg, Ruby, & Cocoa
I recently discovered that Digg allows you to simplify story submission for readers by placing a "digg this" link on your website. That sounded like a reasonable thing to do for my blog entries and after reading Guy Kawasaki's blog about it, I decided to give it a whirl. It wasn't long before I found myself wanting to automate the generation of the anchor tag. So I immediately ran off to my Ruby editor and generated a little script:
require "erb"
include ERB::Util
title, description, url, topic = ARGV[0], ARGV[1], ARGV[2], ARGV[3]
puts <<EOS
<a href="http://adigg.com/submit?phase=2
&url=#{url_encode(url)}
&title=#{url_encode(title)}
&bodytext=#{url_encode(description)}
&topic=#{url_encode(topic)}">
<img src="http://digg.com/img/badges/91x17-digg-button.gif"
width="91" height="17" alt="Digg!" border="0" />
</a>
EOS
That worked reasonably well, but then I started thinking back to all the stuff I learned about Mac OS X software development with Cocoa and decided that I should really wrap up my cute little Ruby script with a Cocoa GUI!
So I immediately opened XCode, generated a Cocoa application, and started messing around with Interface Builder. Here's what I came up with:

From Interface Builder I stubbed out my controller class (MVC after all!) and wired the button to an action method. I also decided to use Cocoa Bindings to wire the text fields to NSString properties in my model without any code. Now since my model only needed to expose four string properties (one for each field in my window) I chose to cheat a bit and just added the four properties to the controller.
Since Objective-C doesn't have automatic memory management, you typically manage the memory allocation and deallocation in the accessors. Fortunately Accessorizor came to my rescue and generated that code for me. So the only thing left for me to code was to pass my four text values to my Ruby script. A simple Google search resulted in this page on Cocoa Dev Central that describes how to call the 'ls' unix command from Cocoa. I quickly adapted it for calling my Ruby script. The one change I made was that I added my Ruby script to my XCode project as a resource so that it would be included in the application bundle at build time. So I added this line for finding it:
NSString *path = [[NSBundle mainBundle] pathForResource:@"digg" ofType:@"rb"];
Finally I decided it would be nice to just put the generated anchor tag on the clipboard when I click on the "Digg It" button. So I perused my "Cocoa Programming For Mac OS X" book and added these three lines:
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
[pb setString:string forType:NSStringPboardType];
and voila:

require "erb"
include ERB::Util
title, description, url, topic = ARGV[0], ARGV[1], ARGV[2], ARGV[3]
puts <<EOS
<a href="http://adigg.com/submit?phase=2
&url=#{url_encode(url)}
&title=#{url_encode(title)}
&bodytext=#{url_encode(description)}
&topic=#{url_encode(topic)}">
<img src="http://digg.com/img/badges/91x17-digg-button.gif"
width="91" height="17" alt="Digg!" border="0" />
</a>
EOS
That worked reasonably well, but then I started thinking back to all the stuff I learned about Mac OS X software development with Cocoa and decided that I should really wrap up my cute little Ruby script with a Cocoa GUI!
So I immediately opened XCode, generated a Cocoa application, and started messing around with Interface Builder. Here's what I came up with:

From Interface Builder I stubbed out my controller class (MVC after all!) and wired the button to an action method. I also decided to use Cocoa Bindings to wire the text fields to NSString properties in my model without any code. Now since my model only needed to expose four string properties (one for each field in my window) I chose to cheat a bit and just added the four properties to the controller.
Since Objective-C doesn't have automatic memory management, you typically manage the memory allocation and deallocation in the accessors. Fortunately Accessorizor came to my rescue and generated that code for me. So the only thing left for me to code was to pass my four text values to my Ruby script. A simple Google search resulted in this page on Cocoa Dev Central that describes how to call the 'ls' unix command from Cocoa. I quickly adapted it for calling my Ruby script. The one change I made was that I added my Ruby script to my XCode project as a resource so that it would be included in the application bundle at build time. So I added this line for finding it:
NSString *path = [[NSBundle mainBundle] pathForResource:@"digg" ofType:@"rb"];
Finally I decided it would be nice to just put the generated anchor tag on the clipboard when I click on the "Digg It" button. So I perused my "Cocoa Programming For Mac OS X" book and added these three lines:
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
[pb setString:string forType:NSStringPboardType];
and voila:
Sunday, September 24, 2006
Rethinking the car

Here are two extraordinary cars that I discovered through the magic of the internet. One is the Tesla Roadster. The Tesla is fascinating because it redefines what an electric car can be. How does 0 to 60mph in about 4 seconds and 135mpg equivalent all wrapped up in a gorgeous sports car package sound? Nikola Tesla would be proud.
Then you have the Ariel Atom. A stripped down minimal sports car with a phenomenal power to weight ratio but no windshield. You have to see this one to believe it. It's amazing.
I'll take one of each. ;-)
Wednesday, September 20, 2006
Ruby User Group Meeting
Last night I attended my first Ruby user group meeting. I've been a member of a lot of user groups and so my expectations were (perhaps unreasonably) high. My initial impressions weren't that great and I left the meeting unsure whether or not I'd return the following month.
But then I started to think about it:
But then I started to think about it:
- Here were a bunch of geeks (me included) getting together to talk about a nascent technology in a city largely dominated by Java and .NET. The fact that these people cared enough about fostering the growth of the language and framework to set all this up is commendable.
- The presentation was actually quite good. I came out of there knowing something about Capistrano that I didn't know before I went in there. It inspired me enough to go looking at the Capistrano and Mongrel websites.
- The group was roughly 20-25 people. Not bad when you consider very few of us are actually getting paid for writing Ruby.
- There were door prizes (a couple books from O'Reilly and no, I didn't win). The people in charge are trying to entice people to come and learn and share.
Thursday, September 14, 2006
Set phasers to stun...
The last couple days have been a bit painful for me as I've endured exposure to the white hot burning effects of crappy UI design. My crap-block was only at an SPF level of 20 and I really should have just got the all-over environmental suit and properly protected myself.
Seriously, I don't understand why so many people undervalue good user interface design. At the very least, people should expect some consistency. Love 'em or hate 'em Apple set some pretty good keyboard conventions with:
Command-S == Save
Command-A == Select All
Command-X == Cut
Command-C == Copy
etc.
Even Microsoft's Windows 95 decided to copy Apple's Command key combinations with the likes of CTRL-S and CTRL-A (they even figured out CTRL-X, CTRL-C, CTRL-V for Cut, Copy, & Paste instead of that abomination that was Shift-Del, Ctrl-Ins, Shift-Ins in Windows 3.1).
Apple's human interface design was also heavily copied. For example, potentially destructive user actions were met with a nice little dialog box asking the user to confirm their action.
So imagine my surprise and frustration today when I pressed Ctrl-S to save my work and this ridiculous application promptly threw away my data and selected (as in SQL select) the data from the database again! What I don't understand is that a committee of people reviewed a number of these vertical market candidate applications and chose this one as the best. Good lord I can only imagine what the others looked like!
Seriously, I don't understand why so many people undervalue good user interface design. At the very least, people should expect some consistency. Love 'em or hate 'em Apple set some pretty good keyboard conventions with:
Command-S == Save
Command-A == Select All
Command-X == Cut
Command-C == Copy
etc.
Even Microsoft's Windows 95 decided to copy Apple's Command key combinations with the likes of CTRL-S and CTRL-A (they even figured out CTRL-X, CTRL-C, CTRL-V for Cut, Copy, & Paste instead of that abomination that was Shift-Del, Ctrl-Ins, Shift-Ins in Windows 3.1).
Apple's human interface design was also heavily copied. For example, potentially destructive user actions were met with a nice little dialog box asking the user to confirm their action.
So imagine my surprise and frustration today when I pressed Ctrl-S to save my work and this ridiculous application promptly threw away my data and selected (as in SQL select) the data from the database again! What I don't understand is that a committee of people reviewed a number of these vertical market candidate applications and chose this one as the best. Good lord I can only imagine what the others looked like!
Thursday, September 07, 2006
JRuby on Rails

It was only a week ago I was waxing philosophically about Enterprise Software and mentioned that Ruby was in the early stages of running on the JVM and .NET CLR and just today Sun announced that they're hiring the JRuby developers to continue their work full time at Sun. Wow! That's big news. Maybe mainstream Ruby on Rails development won't be far behind... Ahh the winds of change.
P.S. I tried JRuby a few weeks ago after Rails went to 1.1.6. The Gem system actually worked to fetch rails and I was able to create a skeleton rails app and start webbrick. It didn't work much more than that (which was still very impressive) and it was definitely slow but that proof of concept gives my high hopes for this project.
Tuesday, September 05, 2006
User Interface Development
Given the same amount of time, who is more productive... a small team of multi-talented developers? or a large team of specialists? Since I think the answer lies with the multi-talented crew, I took stock of my own skills and decided it was time again to strengthen my ability to create web user interfaces.
So here was my plan: design a web page or two in a graphics tool of some sort and then translate it to an xhtml/css implementation that I can then make dynamic at some later date with something like rails.
I started by perusing the css zen garden for inspiration. Then while keeping the goal of simplicity and efficiency in the back of my mind, I opened OmniGraffle and threw together some nice curves, a healthy amount of translucency, a decent colour palette and quickly had a design.
I then moved onto creating the browser implementation. It was simple enough to create the bare-bones xhtml to represent he text of my fictitious website. But then I ran into my biggest skill deficit, a weak understanding of css. I've read books and coded a lot of this stuff in the past, I just didn't have the big picture. I couldn't make the html tags do what I wanted. I even got so desperate that I almost resorted to the the evil "table" tag. Fortunately I stumbled across Mike Hall's BrainJar website.
He has some great descriptions (with diagrams!) of css positioning, the box model, selectors, etc. After absorbing some of that good information I was soon off and running again.
But no sooner had I started coding than I found myself in the nasty world of css standard unconformity. You see I wanted to take advantage of some of the css3 enhancements I was reading about and unfortunately they weren't working.
In the past I've always relied on Firefox to be the standards compliant browser, but I discovered that the nightly build of Safari/webkit has support for just the properties I needed (i.e., border-radius and multiple background-image properties). For the Firefox fans you probably know that it also supports -moz-border-radius, but Safari's anti-aliased rendering without artifacts is definitely superior.
So a couple "float:right;" properties here, a "-webkit-border-radius:15px;" there and I pretty much got what I wanted. I did discover however that content and style are not as cleanly separated as a I thought they would be. I still ended up nesting a couple div tags and placing content in a certain order so that the float property would do what I wanted but regardless I'm pretty happy with the end result. Next will be dealing with the various browser differences. And I bet Windows IE will be the big pain... PNG support sucks, CSS support is spotty, I'll let you know...
So here was my plan: design a web page or two in a graphics tool of some sort and then translate it to an xhtml/css implementation that I can then make dynamic at some later date with something like rails.
I started by perusing the css zen garden for inspiration. Then while keeping the goal of simplicity and efficiency in the back of my mind, I opened OmniGraffle and threw together some nice curves, a healthy amount of translucency, a decent colour palette and quickly had a design.
I then moved onto creating the browser implementation. It was simple enough to create the bare-bones xhtml to represent he text of my fictitious website. But then I ran into my biggest skill deficit, a weak understanding of css. I've read books and coded a lot of this stuff in the past, I just didn't have the big picture. I couldn't make the html tags do what I wanted. I even got so desperate that I almost resorted to the the evil "table" tag. Fortunately I stumbled across Mike Hall's BrainJar website.
He has some great descriptions (with diagrams!) of css positioning, the box model, selectors, etc. After absorbing some of that good information I was soon off and running again.
But no sooner had I started coding than I found myself in the nasty world of css standard unconformity. You see I wanted to take advantage of some of the css3 enhancements I was reading about and unfortunately they weren't working.
In the past I've always relied on Firefox to be the standards compliant browser, but I discovered that the nightly build of Safari/webkit has support for just the properties I needed (i.e., border-radius and multiple background-image properties). For the Firefox fans you probably know that it also supports -moz-border-radius, but Safari's anti-aliased rendering without artifacts is definitely superior.
So a couple "float:right;" properties here, a "-webkit-border-radius:15px;" there and I pretty much got what I wanted. I did discover however that content and style are not as cleanly separated as a I thought they would be. I still ended up nesting a couple div tags and placing content in a certain order so that the float property would do what I wanted but regardless I'm pretty happy with the end result. Next will be dealing with the various browser differences. And I bet Windows IE will be the big pain... PNG support sucks, CSS support is spotty, I'll let you know...
Subscribe to:
Posts (Atom)