Sunday, February 26, 2006

Creating JDBC Templates With Java 5

Note: please excuse the code formatting. Apparently by beautifully formatted code, which looks great in Writely, looks pretty bad when I got it on to Blogger. I will try to clean it up in the next few days, but for now it will need to stay as it is.

In a recent Java project I was writing my Data Access Object which uses JDBC, and I wanted to simplify the code and promote code reuse. JDBC code typically contains a lot of duplicate code, which causes the following problems:

  1. Duplicate code means a lot of copy and paste.
  2. Duplicate code means more code to read and maintain.
  3. Duplicate code means that if you need to make a change to it, you need to change it in multiple places.

This results in a lot of code that is difficult to maintain and difficult to keep consistent. Here is an example of some JDBC code with the associated error handling.

01 Connection conn = null;
02 PreparedStatement ps = null;
03 ResultSet rs = null;
04 Account result = null;
05
06 try {
07 conn = dataAccess.getConnection();
08 ps = conn.prepareStatement("select * from accounts where accountid=?");
09 ps.setLong(2353676);
10 rs = ps.executeQuery();
11
12 if (rs.next()) {
13 result = new Account();
14 result.setAccountId(rs.getLong("accountid"));
15 result.setAccountName(rs.getString("accountname"));
16 }
17 }
18 catch (Exception e) {
19 log.error(e);
20 }
21 finally {
22 try {
23 if (rs != null) rs.close;
24 }
25 catch (Exception e) {
26 log.warn(e);
27 }
28 try {
29 if (ps != null) ps.close;
30 }
31 catch (Exception e) {
32 log.warn(e);
33 }
34 try {
35 if (conn != null) conn.close;
36 }
37 catch (Exception e) {
38 log.warn(e);
39 }
40 }
41
42 return result;
Out of the 42 lines of code in the example above, only 7 lines (those in purple) aren't the usual boilerplate code. So the focus of this article is how to allow for reuse of the 35 lines of code that are required each time we want to access the database. We can do this by taking advantage of Anonymous Classes and a new Java 5 feature that allows for variable length argument lists.

What we want to build is something called a template. This template is just an abstract class that will have several methods, one for each step of performing a JDBC call. Lets take a look at what the template looks like, then discuss it.

import java.sql.ResultSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class JDBCTemplate
{
private static Log log = LogFactory.getLog(JDBCTemplate.class);

public void receiveResults (ResultSet rs)
{
return;
}

public void handleError (Exception ex)
{
log.error(ex);
}
}
We could have defined more steps, but in most cases this is probably all we need. We have a receiveResults() method that takes the results of a query and builds objects from the results. We also have a second method handleError() which we can override if we want to add some special error handling other than the default.

We also need to build a utility class to handle opening the connection, creating the prepared statement, and all of the duplicated code. The utility class will take as an argument a class that extends the abstract JDBCTemplate class, and use the template as part of the routine. Lets first take a look at how we might call the utility method, passing it an anonymous class.
01 final Account result = new Account();
02
03 DBUtils.executeQuery(dataSource, new JDBCTemplate()
04 {
05 public void receiveResults (ResultSet rs) throws Exception
06 {
07 if (rs.next()) {
08 result.setAccountId(rs.getLong("accountid"));
09 result.setAccountName(rs.getString("accountid"));
10 }
11 }
12 }, "select * from accounts where accountid=?", 2353676L);
13
14 return (result.getAccountId()==0 ? null : result);
These 14 lines replace the 42 lines from the first example. Line 1 creates our result object. We must declare this variable as final, otherwise Java will not allow us to access this object within our anonymous class. Because of this the return statement on line 14 differs from the first example, because we know that result will never be null, so we must rely on the key value of the property instead. Lines 3 through 12 are where we are calling our utility method with 4 arguments.

The first argument is our data source which is where the executeQuery() method will fetch a database connection from. The dataSource variable is a standard JDBC javax.sql.DataSource object, which in most cases will be a connection pool. The second argument is the anonymous class, high-lighted in pink, which overrides the receiveResults() method of our JDBCTemplate class. We don't override the handleError() method since it already does what we want. The syntax for creating an anonymous class instance is similar to creating a regular object instance except that you add a block of code following the constructor arguments. So this code is really creating an unnamed subclass of JDBCTemplate and creating an instance of it.

The 3rd argument to the utility method is the SQL statement to execute, and the last argument is the value to be passed in the placeholder of the SQL statement. There is a really good reason why we made this the last argument. Java 5 introduced variable length argument lists. Below is a short example of a method that takes any number of String arguments.
public void doStuff (String ... args) {
// do stuff
}
The ellipses (...) tells Java that this method takes any number of String arguments, and rolls them into an array variable named args. This means that this method can be called with no arguments (i.e. doStuff()), or one argument (i.e. doStuff("foo")), or even five arguments (i.e. doStuff("a", "b", "c", "d", "e")). The only special rule is that the variable length argument list must be the last parameter of the method. We will use this feature to allow for any number of arguments to be passed to our method.

Now, lets take a look at the DBUtils.executeQuery() method, the last step of our JDBC framework.
01 import java.sql.Connection;
02 import java.sql.PreparedStatement;
03 import java.sql.ResultSet;
04 import org.apache.commons.logging.Log;
05 import org.apache.commons.logging.LogFactory;
06 import javax.sql.DataAccess;
07
08 public class DBUtils
09 {
10 private static Log log = LogFactory.getLog(DBUtils.class);
11
12 public static void executeQuery (
13 DataAccess dataAccess,
14 JDBCTemplate tmpl,
15 String sql,
16 Object ... args)
17 {
18 Connection conn = null;
19 PreparedStatement ps = null;
20 ResultSet rs = null;
21
22 try {
23 conn = dataAccess.getConnection();
24 ps = conn.prepareStatement(sql);
25
26 for (int i = 0; i < args.length; i++) {
27 Object arg = args[i];
28
29 if (arg instanceof String) {
30 ps.setString(i+1, (String)arg);
31 }
32 if (arg instanceof Long) {
33 ps.setLong(i+1, (Long)arg);
34 }
35 if (arg instanceof Integer) {
36 ps.setInt(i+1, (Integer)arg);
37 }
38 }
39
40 rs = ps.executeQuery();
41
42 tmpl.receiveResults(rs);
43 }
44 catch (Exception e) {
45 log.error(e);
46 tmpl.fail(e);
47 }
48 finally {
49 try {
50 if (rs != null) {
51 rs.close();
52 }
53 } catch (Exception e) {
54 log.warn(e);
55 }
56 try {
57 if (ps != null) {
58 ps.close();
59 }
60 } catch (Exception e) {
61 log.warn(e);
62 }
63 try {
64 if (conn != null) {
65 conn.close();
66 }
67 } catch (Exception e) {
68 log.warn(e);
69 }
70 }
71 }
72
73 }
I hope that most of this will make sense, but there are a few key areas to point out.

  1. Line 42 is where we call out template method receiveResults(). On line 46 we call handleError() in case an error occurs.

  2. On Line we see that the last parameter of our method is Object ... args. We talked about variable length arguments above, but it might not be obvious why we made this an array of type Object, and why Java allows us to pass value of the primitive type long as a value. Parameters may be numbers or strings, so we chose type Object as the parent of the type of value that may be passed. In Java 5 we can now use primitive values where in Java 4 it was required to encapsulate it in an object. Java 5 allows this via a procedure called auto-boxing and auto-unboxing. Auto-boxing means that when you use a primitive where an object is required, Java will automatically convert the primitive into an object. For example the primitive value 3 will be converted to new Integer(3). Auto-unboxing is the exact opposite, where Java 5 will convert an object into a primitive, for example an Integer becomes an int.

  3. On lines 26-38 we set the parameters of the prepared statement. We inspect each argument to determine the type of object, then use the appropriate set statement.

Although it took us quite a bit to build the framework, we can now reap the benefits. For example, if you wanted to added additional debugging to print out the SQL being executed, we now only need to do this in one place.

I hope that this article give you some ideas on how you can clean up not only your JDBC code, but other duplicated boilerplate code in your projects. For more ideas you might also want to take a look at the Template Method design pattern, which offers a similar mechanism to clean up your code.

Monday, February 20, 2006

I Am A Wikipedia Newbie

It wasn't until a few weeks ago that I realized the company for didn't have an entry in Wikipedia. My employer is a fairly large networking solutions and managed services provider that is publicly traded, so I was a little surprised. A little over a week ago I decided that my company needed to have a Wikipedia entry, so I seeded it with a small snippet.

I was very happy indeed to see my company listed on Wikipedia, and emailed a colleague of mine. He responded to my email asking why the entry was marked for deletion. Exactly one hour and two minutes after I added my entry it was flagged as nominated for deletion by one of the Recent Changes Patrol. The RC Patrol is a group of volunteers that review recent changes and additions for harmful edits. In my case this experienced patroller has over 5000 Wikipedia edits, and an award.

At this point my entry had not been deleted, it was only nominated for deletion. The notice on my entry linked to a discussion page about deleting the entry, and there were already two votes for deletion. I of course added my vote to keep the entry, and gave a single sentence explanation. Several other users followed suit, voting to keep the entry. The part that surprised me in this whole matter was that I didn't know the other people voting, but they somehow found the deletion discussion page, and made their vote.

Five days later the nomination for deletion was removed from my entry, with the final vote being to keep the entry. This same user also did some minor cleanup of the entry and marked it as a stub. With my entry being maked as a stub, it appears on a special pages where users can quickly browse all entries marked as a stub. My next step was to add some substantial content.

Thanks to Google search and the Way Back Machine, I was able to find a lot of information on my company. Today I went to add the content to the page, and it looks like someone else made some edits to the page. He added quite a few links to other Wikipedia entries and also categorized by entry as a Company.

During my research I found that my company had supported H.O.P.E. , a hacker's convention, in the late 90's. The Wikipedia H.O.P.E article noted that the conference was supported by "Bell Technology Group", the prior name of my company. I wanted to link the two articles, but because the name had changed, I didn't want to link them directly. I decided to instead set up a redirect. There is a whole help page on this, and lists many of the reasons you might create a redirect, one of them being to redirect from an alias. So I set up a redirect from "Bell Technology Group", then edited the H.O.P.E. page to point to that entry.

In summary, I found that Wikipedia is very easy to contribute to, and once you contribute you just want to contribute even more. It is somewhat addictive once you figure it out. I also learned that I will make mistakes, that I will post content that isn't quite up to Wikipedia's standards. I also learned that there are thousands of people that have my back, that will clean up my entries and make them sweet smelling. And lastly, I learned that not everyone will agree with my new entries, and that systems are in place to ensure proper discussion prior to deletion.

The latest version of the entry can be found here.

Friday, February 17, 2006

Java 5 Generics - Aiding The IDE

I found an article on OnJava.com from last year about Generics. In the article the author Budi Kurniawan states that...

  1. "Generics are the most important feature in J2SE 5.0"
  2. "generics make two contributions..."
    • "they add type checking to collection types at compile time"
    • "generics eliminate the need for type casting when retrieving an element from a collection"


Let's start with the first point. I think that the most important feature of Java 5 are annotations. Annotations by themselves are not too exciting, but the tools and frameworks that will use annotations I think will be very exciting.

The author's second conclusion I think misses the mark as well. Yes, I agree, it is very useful to have type checking for collections at compile time, but it is fairly rare to see this type of bug make it into production code. His second point about eliminating the need for type casting is only useful because programmers are lazy creatures. I contend that both of these are useful, but I think that there is a more important contribution. The contribution I am speaking of is that generics now makes it possible to increase the usefulness of the IDE.

<flashback>
I have worked with many languages over the years, and dealt with a lot of editors and IDE's. One of the biggest improvements in IDE's that I ever witnessed was when the Visual Basic IDE added code completion. Code completion (for those living under a rock) is when the IDE can list the methods and properties available to an instance of an object. This allows you to code more quickly because code completion means less keystrokes and it makes it easier to use a library that you aren't too familiar with. In dynamic languages like Perl, Python, JavaScript, and Ruby you don't see good support for this, if any support at all. That is to say that dynamic languages are very useful, but it does make it a little harder to use because you need to either know the library calls by heart, or have a good reference available.
</flashback>

Generics not only aids code completion, but also code documentation. The tools available can now document what type of objects a list can hold without the programmer documenting this by hand. All of this is tied to ease of use, greater productivity, and greater accuracy.

I strongly believe that the future of programming will be about the tools. It won't be rapid development tools (like Ruby on Rails) that will dominate the future, it will be IDE's that can bear the brunt of the coding and design task. The more advanced the tools get, the easier it is to build an maintain larger and complex applications. I am a fan of static languages like Java and C# for large applications because of the tool support. I am also a fan of dynamic languages like Perl and Ruby, but only for smaller applications, because the tool support is lacking.

One note about Ruby on Rails. RoR has one advantage that helps propel the tool, and that is that it hides a lot of complexities of coding a web application. This means that instead of having to write database code, RoR does it for you. I don't think that this is enough for some applications though. As the application lets larger and more complex it may be impossible to avoid writing the things that RoR tries to hide, and at that point RoR loses it's advantage.

<disclaimer>
The web is evolving, as are the languages and tools. There is also so much currently available it is impossible to know everything. Thus, I proclaim that this article is based on my opinion at this particular point in time. As I learn more I will almost undoubtedly change my mind.
</disclaimer>
Tags

Saturday, February 11, 2006

You Can't Sell "Everything"

[begin dramatization]
My car was a bit old, and giving me the usual troubles like old cars do. I went down to the local car dealership to see what they had. I wasn't quite sure what I wanted, so I was hoping that someone there could give me some ideas. When I got there I was greeted by a nice sales guy named Jim.
Jim was very enthusiastic about their products, and asked, "so what what kind of car were you looking for."
"Well, I'm not sure exactly, I just need something reliable to get me to and from work."
"Well, here at Jim's Motors we can build you exactly you need, we just need to know what you need", said Jim.
"Nothing fancy really, just something roomy with good gas mileage, and maybe in a dark blue."
"We can do all of that, but what about the engine, and the tires? What kind do you need?", asked Jim.
I started to look a little perplexed, but decided to play his game, "What kinds of engines do you have?"
Jim gleefully stated, "We have all kinds of engines. I don't know much about engines though, that is a little technical for me, but I can tell you that we can give you any engine that you might want."
"Well, can you suggest one?", I asked.
"Let me get one of the mechanics, maybe he can help you out here."
I decided to go to another dealership.
[end dramatization]

When buying a car, most people don't know what kind of engine that they want, or what brand of tires. Consumers like choice, but sometimes too much choice is a bad thing. If Jim, our happy salesman, had shown me a few cars that fit my criteria (roomy, good mileage, blue), then I could have let him know if any of those were right for me or if he should show me some more.

The second problem is that Jim is a salesman, he doesn't know about the different engines or tires, he isn't technical. This makes is difficult for Jim to sell anything. Jim, just like the customer, needs a smaller set of choices.

I guess my point is that you can do "everything", but it is difficult to can't sell it. The solution, I think, is to find interesting products that you can sell, and teach your sales force on how to sell them. This will give the sales people and customers a list of products to start with, that has prices attached. From this list the sales person can work with the customer to customize one of the base solutions to best fit their needs and budget.

Thursday, February 09, 2006

Programmer's Cookbook and An Apology

Programmer's Cookbook

I was thinking about all of those snippets of code that I often collect, as I expect that most other programmers do as well. I wanted to start posting them here on this blog, but I decided to instead start a second blog specifically for these types of entries. The new blog is called Programmer's Cookbook, and I hope that it will be useful resource as it starts to fill out.

An Apology

A week or so ago I was listening to a podcast on the way to work called Boagworld, a rather funny podcast about building and maintaining websites, hosted by two Brits. In their last episode, #21 Working with web stats they discussed among other things Google Analytics and AJAX. I am very familiar with both, and had issues with some of the information they were providing. When I got to work I sent off an email to Paul Boag, one of the hosts, and expressed my concerns. In this week's episode #22 How your website sells, I was very surprised when he started discussing my email and expressed his apology for the misleading information.

Anyway, Boagworld is not only informational, but is also very entertaining. I strongly recommend listening, especially if you are interested in overall site development from both a design and marketing perspective.

Wednesday, February 08, 2006

Estimation: What We Don't Know

I was listening to a talk about prediction given by Nassim Nicholas Taleb, and I felt that it has a strong correlation to project estimation. He talks about how we focus on what we know when making a prediction, and not what we don't know. This makes sense, as you can only estimate based on past experience. Poor estimation on the other hand is often due to things that we didn't know or expect.
"You can not forecast unless you know the error rate"
- Nassim Nicolas Taleb
To be able to better estimate what we don't know, we need to know at know how badly we have estimated in the past. To do this we need to be diligent in providing estimations with copious notes prior to starting a project. During the project we need to update this estimate as we start to learn those things we didn't know. Following the project we need to review the estimates against the actual time, and try to make some conclusions from this. This still won't make us great estimators, but it will give us insight into the rate of error, which can be tacked on to an estimate for the next project. This rate of error is to cover things that we don't know, and is unpredictable.
"Most software estimates are performed at the beginning of the life cycle. This makes sense until we realize that estimates are obtained before the requirements are defined and thus before the problem is understood. Estimation, therefore, usually occurs at the wrong time."
- Robert L. Glass, Facts and Fallacies of Software Engineering
Part of the problem, as Robert Glass points out in his book, is that we estimate at the wrong time, and it is often by the wrong people. The job of estimation should never lie with management, as it is unlikely that they will understand the true difficulty of the problem being solved. Management is influenced by timing to market, and other factors that have nothing to do with the real time involved to solve the problem.
"Awful suspicion: Projects that set out to achieve "aggressive" schedules probably take longer to complete than they would have if started with more reasonable schedules"
- Tom DeMarco, The Deadline
Even when we provide good estimates, we may be forced to follow an aggressive schedule, which can actually increase the time to deliver a product. It is up to management to provide an atmosphere that is productive and sustainable. If this isn't the case, it is likely the estimation is wrong no matter how well it had been assessed. This is one of those things that we don't know when estimating a project, so all we can do is rely on the error rate from past experience.
"...refrain from hiring implementers until the specifications are complete. This is what is done when a building is constructed."
- Frederick P. Brooks Jr. , The Mythical Man-Month
Nearly 35 years ago Frederick Brooks had a team of 10 architects and 150 implementers, and 7 months to complete the system specification. The architect's manager said that it would take 10 months, not 7 to compete the specification. The implementer's manager said that his team could complete the task on time. In an effort to save time and keep people busy, Frederick Brooks put the implementers on the task. It took the 150 implementers 10 months to complete the specification, not 7 as promised, and it was poor quality.

The lesson here is that dumping unqualified people on a project at the wrong time does not make it happen faster, in fact it costs more and hurts the quality of the project. It is important that when estimating a project it is not adequate to just throw out a number of man-hours (or days/months/years) to completion. We must take into account timing and required skills into our estimates.

I recall a certain staffing session where a project estimated to be around 450 man-days was being discussed. I don't think it is fair to say that people were assigned to the project with disregard for their skill level, but they were being given specific tasks that they didn't have a high level of knowledge in, thus requiring additional training time. The issue here is that management wanted to be able to assign a given task to any programmer and expected the estimate to remain the same.

I don't think that this scenario is uncommon, and given the nature of the management of a largish project, I think it would have been very difficult to handle differently. After all, if you only have a certain number of programmers available, you don't have a lot of choice. Perhaps the estimate would have been better if it had been detailed as to the specific knowledge required and the timing for adding programmers to the project. Perhaps then it would be realized that the estimate is based on the ideal staffing scenario, and would require adjustment if actual staffing differs.

In the end, there is no way to estimate a project with any precision. You need to estimate based on what you know, trusting your gut. Add to this your error rate based on past performance. Then estimate the project, and detail the staffing that it relies on. Make notes on why you estimated what you did, and make additional notes as the project proceeds, especially when you face the unexpected. When the project is over, compare your initial estimate with the actual time to completion, and make a note of the difference for inclusion into your error rate.

Good luck.

Sunday, February 05, 2006

Meticulous Specification

Like most programmers I disliked long specifications. I didn't like reading them, and more importantly I didn't like writing them. For me, all of this has changed, and I believe that this is a positive change.

In my line of work we typically deal with fairly small projects. These are fairly easy to estimate, and more often than not we are being paid by the hour, and not by the job. Recently we were implementing a specification that weighed in at almost 200 pages, a project much larger than we usually deal with, and unlike most of our projects it required a fixed price. On top of this we needed to put a price on it with only a few days of review.

What happened is that we later found that the specification had much in the way of ambiguity, holes, and errors. On one page it made a statement just to be reversed in another part of the document. There were also many changes that were required by both the designers on the client's end, and the engineers on ours while the product was being developed. Basically we had rushed to start work, but never really had a solid specification to build from.
Building a large system without a specification is impossible, building a large system with a poorly written specification is even harder.
This same project had a second part to it, and I was convinced that we could do better. I spent a little over a week reviewing the specification of just my part of the larger project. I held several sessions with the client to review the specification, remove ambiguity, and document any items missing from the specification. This also included updating the specification for client review and approval.

In the end I was able to submit a task list to the project's manager, and a good estimate of how many hours each item would take to complete. I am now fully aware of what I need to build, and because system is well documented, I could pass off work to other programmers without having to explain too much. I am also seeing that the client is a little more confident of the outcome because they know exactly what to expect in the way of deliverables and schedule.

From this experience I have formed a few simple rules that will guide my work on larger projects.
1. Review the specification, and resolve ALL questions before any coding begins.
Having your questions answered before implementing an incomplete specification will ensure that you only code what the client needs and not those things that were incorrectly stated. Nothing is worse than finding out late in the game that a client decided to not build in a feature, but forgot to remove it from the specification.
2. Review the design, and verify that ALL of the content and links are documented before any coding begins.
If you look at the design, and you aren't sure where a piece of content comes from, then the client might not know either. Get these issues resolved before coding begins, because not fully understanding where data comes from will usually create more work for you.
3. Update the specification as you receive clarifications from the client, and get approval on the changes before any coding begins.
Make the client take the time to review and approve the changes to the specification. This gives them one last opportunity to catch any problems with the specification. Once approved you can be pretty sure that the specification will stand on it's own two feet.
4. List all of the tasks that will be required to implement the specification, if any task is more than 8 hours worth of work, break the task into smaller pieces.
If you completed the first three steps, creating a valid task list is fairly trivial. If you find that you can't put a number of hours on a task, or if your "tasks" are specified in days and not in hours, then you probably need to revisit the first three steps and try again. A comprehensive review of the specification will give you the confidence in your estimates and task list because you will know exactly what you need to build.

When done properly, a meticulous specification review can save you both time and frustration.


I can't do Ruby (a.k.a. strict typing)

I took another stab at getting into Ruby this weekend, as it has long been on my list of things to learn. I have attempted this in the past, but something always drives me away. I guess one of the things that draws me to the language is all of the hype about Ruby on Rails, but I just can't seem to do it. This time what drove me away was the lack of strict typing, for reasons I will try to explain.

Let me first explain the world I come from. I have been writing code professionally for 10+ years, and coding for fun for almost 10 years before that. During my professional career I had worked almost exclusively with Perl for 5 years, and now I work with Java. Coming from the Perl world, and being a strong advocate of the language, you would think that I would easily latch on to Ruby. The problem I think is that I have been tainted by Java.

With Java I need to declare the specific type of value that a variable can hold, and over time I have started to see this as a feature as opposed to a nuisance. When I was writing Perl, the last thing I wanted to do was to waste keystrokes telling the interpreter what type of values a variable would hold. With Perl I wanted the interpreter to do what it was told. Now that I have worked with Java for nearly five years I see things a little differently. The Java compiler is my friend, as it 1) makes me document my code by declaring variable types, and 2) stops me from potentially adding a difficult to trace bug.

With Perl, I can perform near miracles with a couple lines of code. Even now, when I am asked how some list of files can be altered in some specific manner I will quickly whip up a Perl script. Perl is my programming companion, and I could not imagine working without it. I suspect that if I ever did learn Ruby, it would fill this same need.

For large projects though, I would never user Perl, or even Ruby I would expect. The difficulty is that when I pull out my favorite IDE, it can't perform adequate autocompletion or refactoring with these languages. I remember the joy I felt when I started using the Eclipse refactoring tools for Java. With these tools I was able to effortlessly move methods up to parent classes, rename methods, encapsulate variables, and perform other refactorings with ease. I can now dive into an old nest of poorly written Java code, and quickly clean it up so that I can add needed enhancements. It is also failry easy to use an unfamiliar library when the IDE's autocompletion tool can display properties and methods of any variable.

Maintenance typically consumes 40 to 80 percent (average, 60 percent) of software costs. Therefore, it is probably the most important life cycle phase of software. - Robert Glass, Facts and Fallicies of Software Engineering

The bottom line is that I love languages like Ruby, Perl, and Python... but they hurt me more than they help me when I am maintaining a large project with thousands of lines of code. The word maintenance is the important point here, as maintenance is the majority of the software cost over it's life. So for me, my choice is to spend the extra time with a verbose language like Java when working on a large project that will hopefully have a long life.


Saturday, February 04, 2006

Pre-Release Book Programs

Last month O'Reilly and Associates started their Rough Cuts program. It is essentially a beta program for books, where you can pay for immediate access to the book in PDF format, months before the book is released. In fact it looks like the one title Ruby Cookbook won't be on the store shelves until September.

I think this is a great idea because it gives you access to new technologies sooner rather than later, saving you time, and in turn money. The pricing isn't too bad either. For the Ruby Cookbook it is $33 for the book only (when it comes out), $25 for immediate access to the PDF in progress, or $55 for both.

O'Reilly isn't the first to come up with this idea, although the are the largest publisher that I know of that is doing this. A few months ago I was looking for a book on AJAX, and there wasn't much available. The local book store had no AJAX books, nor my O'Reilly's online Safari service. After doing some looking I found that the Pragmatic Programmers had their own beta book program (FAQ), and their upcoming title Pragmatic Ajax was already available. Although the book was incomplete it gave me the information I was looking for. The price was actually a bit better than O'Reilly's offering, at $20 for the online PDF, and $37.50 for both the PDF and book at release.

In conclusion, I like the concept of beta books, because I don't always have the time to research a new technology myself.

Tags

Friday, February 03, 2006

Using the Scriptaculous JS Library

This is a very short introduction to Scriptaculous, explaining what it is, why you care, and a few short examples. I am currently using this in a project, and will post additional entries as I begin to use more and more of the library.

Scriptaculous is a JavaScript library that is makes it relatively easy to add drag-and-drop functionality, dynamic drop-down menus, and visual effects. Unfortunately the documentation is fairly light, so there is a bit of a learning curve. You will also need to use the Prototype JavaScript library as Scriptaculous relies on some of it's tools.

You will care about this library if you want to develop rich user interfaces, and don't currently have some other JavaScript library that you rely on. It can save you an incredible amount of time.

As promised, I will share a few short examples. All of these require the following script includes in the HTML:

<script type="text/javascript" src="js/prototype.js"></script>
<script type="text/javascript" src="js/scriptaculous.js"></script>

Example 1: If you have taken a look at some of the newer web apps using Ajax, you will find some of them will highlight a part of the page to make it obvious to the user that something has changed. See Digg Spy for an example. The following code will flash the DIV yellow when it is clicked.

<div id="highlight_this" onclick="new Effect.Highlight('highlight_this')">Hello World</div>

Example 2: This DIV will slide up slowly and disappear when clicked on. Note that the sliding up feature only works under Firefox, in IE it will just disappear after a short delay.

<div id="blindup_this" onclick="new Effect.BlindUp('blindup_this')">Hello World</div>

Scriptaculous has another dozen or so effects beyond this, and makes it possible to alter them in various ways. For example, you may want change the duration of the Highlight effect. I will cover these in a bit more detail in further entries.

Podcasting Comedy

I have been quite a bit of time sampling the incredible number of podcasts that are available. Some I come across because I head about it somewhere, and others I just stumbled across by pure coincidence. My time is short today, so I will only cover a couple of these for now, specifically non-technical podcasts that I found interesting.

Ask A Ninja

Format: Video
Length: about 2 minutes
Frequency: every 4-5 days so far
Site: http://askaninja.blogspot.com/
Feed Links: http://feeds.feedburner.com/AskANinja

In this podcast a friendly ninja takes answers questions about ninja that have been submitted via email. Some of the questions that have been answered thus far include how to become a ninja, and whether or not ninjas can love. The masked ninja in the video has the strong personality of a professional wrestler, and a wit to match. A very funny show.

Happy Tree Friends

Format: Video
Length: ~3 minutes
Site: http://happytreefriends.atomfilms.com/index.html
iTunes Feed: http://happytee.mondominishows.com/ipod_sitepromo.html

This cartoon is not for children!! It was rather disturbing when in one episode the poor little forest creature's eye popped out of his head, just to be pecked at by a woodpecker, all the while still attached to him via a long optic nerve. It was so disturbing that I watched it again. If you are into violent cartoons, this one is for you.

The Little Buzzers

Format: Video
Length: ~4 minutes
Site: http://www.littlebuzzers.com/
Feed Links: http://feeds.feedburner.com/TheLittleBuzzers

This cartoon doesn't rely on violence for it's comedy content... and actually it doesn't even rely on any voices either. This cute little creatures talk to each other using cartoon bubbles that you would expect to see in a comic strip. If you plan on wathing these I suggest going all the way back to the first episode so that you can find out how Greevil got his name.

If you know of any other comedic podcasts that really stand out as different for you, drop me a line at iamroberthanson AT gmail.com.