Find your next scenic drive!

September 18, 2004

The Rise and Continued Rise of Object Orientation...

Over at Informit, Danny Kalev has an article entitled “The Rise & Fall of Object Orientation.” I find that this the article is trying to suggest something, but does not provide any real substance to support the idea.

For example, in the examples that he presented for the inheritance flaws, in all of these cases it seems that the rule to only use inheritance as a Is-A relationship was not held, and the real reasons for inheritance was code reuse. The realization of reuse comes from more than simply inheritance; it comes from the fact that a class should be written to do a single function, and therefore, this representation can be reused for multiple projects. This is not limited to an object-oriented paradigm, but this can be easier to do in object-oriented languages. As mentioned in Leveraging Frameworks, writing frameworks is not easy, and many framework projects fail; as such, using examples that are frameworks is probably not the best example. What about other object-oriented projects, such as ACE, for example. This project has been around for a while, and to my knowledge, has not had a huge rearchitecture, rewrite, or was renamed, such as the examples that he provided.

C++ has historically been known for having shallow class hierarchies, whereas other object oriented languages such as SmallTalk and Java generally have deep class hierarchies. The lack of derivation should not been seen as bad, but merely a different approach that C++ culture prefers. The argument of inheritance propagating bugs is also lame, as your classes should have some genre of test cases, and per se that there is a bug in a class that has five classes that derive from it, in this case, you have just fixed bugs for all of them. When a class hierarchy, containment, or generic algorithms are not preferred, this will usually result in classes maturing at different rates, as bugs will usually only be resolved in portions of the code instead of the entire code base.

The example of avoiding member functions is also weak, as a library of containers should probably be deriving the from a base class of some sort for the size() function, with the possibility of being specialized. While it is true that you could implement this via the std::distance algorithm, this could be optimized by having a member function. As a complete counter to the argument, think about Item 44 of Effective STL, which prescribes that you should prefer member functions to non-member functions. If member functions were included in each container, then it would be easier to implement code using an std::list and then change it to a std::vector with minimal changes.

This article appears to be suggesting that everything should be generic, but interestingly enough, Danny also wrote an article on over-engineering, in which talks about being over generic. This appears to be a mixed message. Personally, I think it generic programming and object-oriented development are techniques that developers should know how to use, and when developing code, choose the technique that is the best for the situation.

September 15, 2004

Web Viewer Eye Movements...

Meryl Evans has posted an her comments (full comments here) on a recent study called Eyetrack III. This study evaluated the eye movements of a number of people on various web sites to see the areas of a web page that are most valuable and the styles that are most eye-catching.

Some of the results are a little surprising, such as smaller fonts in short paragraphs encourage reading instead of skimming. The article also mentions how users spend more time on text-based advertisements than on graphical advertisements; I would think this is natural, since your brain can evaluate the page very quickly and identify graphical advertisements faster than textual advertisements, and so we probably need to look at text advertisements longer to process that it is an advertisement.

While the old saying states that a picture is worth a thousand words, it is interesting to note that this particular article states that graphical representations are better to clarify concepts that readers do not understand, whereas data is more likely to be absorbed when read.

The analysis on the web site hot spots was interesting, but this also seems that this is our instinct. In addition to the fact that many languages are read from left to right and top to bottom, most web sites are also setup in this fashion, and while some of these sites may have done their own usability studies, I am sure that a good portion of this is applying a similar look-and-feel used on other web sites, since introducing a completely new interface could discourage some users from using the service.

While this information is important and very interesting, I whole hearted agree with Meryl's comments on her blog, which essentially is use the above as an influence, not a rule. Even in the articles preface, the surveyors indicate that the study was “wide” instead of deep, but nevertheless, I think it is worth a read.

September 14, 2004

The Tools of Software Development...

A little while ago, Andrew Koenig and Barbara E. Moo wrote an article in C++ Users Journal discussing some of the parallels between house construction and software engineering, as they were doing some renovations. One of the differences they highlighted and that others have also highlighted is how construction works own their own tools and software developers, well, our tools are different, to an extent.

The major difference is with tool sharing. When a carpenter does not have a particular tool, they can generally borrow the said tool from another craftsman, since the tools are easily portable and shared. When a software developer does not have a particular tool, however, sharing another developer's tool is not always easy. For small tools like scripts, these can generally be copied or shared, and other tools need to be installed, presuming that it can be installed on your workstation workstation. In the latter category, licenses sometimes need to be obtained.

This can be very painful, especially with floating licenses of popular software. Imagine a world where software developers were like carpenters, and went to work with their own tools; could this approach work?

I do not think out tools are mature enough yet to do this, and this is one of the goals behind Eugene Eric Kim's A Manifesto for Collaborative Tools. By this, I mean that the interoperability of the tools is not there yet. Take, for instance, UML tools; the standard interchange format for UML is XMI, and most UML tools available support one version or another of XMI. But even when your applications understand the same versions of XMI, the interoperability of the products really depends on their interpretation of the standards; for example, I saw an XMI file generated by Visual Paradigm for UML's C++ reverse-engineering module that generated a document that was not a valid XML file. Furthermore, for some elements in the XMI, Visual Paradigm had put the visibility attribute to none, however, according to the DTD, the only allowed values for this attribute are private, protected, and public. Only once these issues were resolved was I able to import this model into Poseidon. It is for reasons like these that products like XMI exist, but this is unfortunate.

In addition to inconsistencies such as the examples aforementioned, it is possible for some features of a tool to not directly map into the interchange format. In cases like these, the vendor has two choices: do not export those features, or export them in a non-compatible fashion. Depending on the feature, not exporting the feature may go unnoticed, but it could also be a main reason for using the product. In cases like these, this must be documented clearly. But extending a standard interchange format that prevents other tools from accepting the file is obviously not a good idea. These decisions, coupled with what services the tools provide, directly effect how a piece of work in one tool will look in another tool, therefore, interoperability is rarely guaranteed.

As another example, if we consider IDEs, one thing that IDEs do is generally create some type of project file. When all developers are using the same IDE, it is very easy to stay in sync with the team, since when you update your view, you can immediately use the project file that is in the view. However, if you were using two different IDEs to build the same source code, it is possible that the additions of files, changes of settings, and differences in compiler could go unnoticed, incompatible, or new build issues could occur. Please note, however, that using different tools is different than targeting different environments. More to the point, if you are targeting multiple compilers, then you must build each branch on each compiler prior to merging; but supporting various developer's preferences is a non-problem, as the released software will only be built by one of those configurations, and therefore, must only work on that one configuration.

Another issue with supporting multiple development tools for a single target environment is the question of support. When a problem occurs or a developer is unsure how to use a particular feature, talking with the team members will likely help get an answer, instead of a “why don't you just use my tool.” Also a point in this is purchasing tools. You could not simply purchase X seats of a tool without ensuring that it is compatible with most developer's environments. In the event that it is not, you either have to select another vendor or purchase a few copies of this and a few of that, which will eventually end up with the same problem that it started with.

Sharing a UML tool, for instance, is more complicated than sharing a hammer. In addition to the installation and licensing issues, the time to get comfortable within the tool can be more time consuming than learning how to use another drill. In the instance of having no standard development tools, however, developers will generally procure their own (hopefully legally), and what will generally occur is that many different development environments will be created. But until Eric Eugene Kim's vision is realized, true collaboration will suffer.

September 11, 2004

Controlling Creativity...

In Debugging Java, Will David Mitchell states that creativity comes from the right hemisphere of the human brain, whereas organization comes from the left hemisphere. To produce solid software, he argues, you must be creative and organized, as most projects that fail do so because of poor organization.

Will states that to develop software, you must be both creative and organized. The problem is, however, that the left hemisphere is a control freak, and when it is in control, it is difficult to be creative, but when you are creative, it is easy to go back into the organized mode and hence, out of the creative mode.

To become creative, therefore, something must be done with the left hemisphere of the brain, and the easiest way to do that is to be relaxed or bored. Once that you are creative, just write, code, whatever. Do not evaluate what you doing; do not fix your syntax, spelling, anything. Just be creative. Let yourself go, and once that you are finished, then it is time let your organizational portion of your brain take over. Fix your syntax errors, semantics errors, add comments, refactor your code, etc., letting your organizational portion of your brain do its magic.

This may seem a little insane to some people, but in the Mythical Man Month, Frederick Brooks mentions that you should be prepared to throw a version of your software away, since you will anyhow. This could be explained by stating that the first version of a tool is created in a creative but disorganized process. The disorganized code is generally unmaintainable code, which can warrant a complete rewrite.

As a non-software related example, children's book author Judy Blume recommends rewriting. The first time you write, you are essentially getting your thoughts down, and Judy states that when you rewrite (refactor), you get to reorganize your thoughts and link them together to make them complete, and this directly correlates to software development.

Recently, Miguel de Icaza's predicted this for Longhorn' Avalon framework, in his recent Avalon analysis (and Part II), since he states that the first version is not the foundation to build applications on; this could be rephrased by, although it may be creative, it is not organized. You can see this distinguishment in Miguel's analysis in Microsoft's ability to reinvent the wheel (creative-ish), but the code has some poor factorings, security, and missing tools (lacking organization).

Some people argue that excessive coding standards, code reviews, and process removes some creativity from the developer, but nothing could be further from the truth. The developer is the one that controls their creativity, and as Will describes, there are many ways to force yourself to be creative. However, once you have completed a creative task, it is not time to merge your creativity into the end product. Instead, it is time to organize your code, by refactoring, commenting, and bring your code up to the coding standards of your organization, and only then merge it.

Software is frequently compared to buildings and architecture, and in this regard, an architect must both be creative to build a stunning looking building, but also must be organized to ensure that the building it solid and meets the local building code standards. Software is no different.

September 10, 2004

Great Exceptions Descriptions Are Gold...

Last night, I was implementing a database method that would update a field within a database. The database I am presently working with is MySQL, using the MySQL Connector/J JDBC driver. I have been using this configuration for quite sometime, but generally my interaction with the database are more disconnected, in the sense that I load some information, do some potentially lengthy processing on it, and update the database, so I generally implement this as two separate methods.

The application in question, however, does not have this same lengthy processing period, and so it lends it self rather well to JDBC's ResultSet update feature. I implemented it, and give it a whirl, and I got an exception:

com.mysql.jdbc.NotUpdatable: Result Set not updatable.This result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE, the query must select only one table, and must select all primary keys from that table. See the JDBC 2.1 API Specification, section 5.6 for more details.
  at com.mysql.jdbc.UpdatableResultSet.generateStatements(UpdatableResultSet.java:1817)
  at com.mysql.jdbc.UpdatableResultSet.syncUpdate(UpdatableResultSet.java:1938)
  at com.mysql.jdbc.UpdatableResultSet.updateString(UpdatableResultSet.java:1642)
  at com.mysql.jdbc.UpdatableResultSet.updateString(UpdatableResultSet.java:1684)

OK. So that is pretty indicative, I thought, of the problem, complete with a little checklist.

  1. The first criteria is that the statement must be updatable via ResultSet.CONCUR_UPDATABLE, so I double checked, and sure enough, that is what I had:

    statement = connection.createStatement( java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_UPDATABLE );

  2. The second item must only select from a single table, as I discuss next.

  3. The third criteria is that you must select the Primary Keys. This is where my problem was. My table looked something like:

    | Field        | Type       | Null | Key | Default | Extra |
    | UserName     | varchar(8) |      | PRI |         |       |
    | Handle       | varchar(8) |      | PRI |         |       |
    | Data         | longblob   |      |     |         |       |
    ... more ...

    However, I had mistakenly written my query as SELECT Data FROM Reports WHERE UserName="user" AND Handle="handle";, instead of SELECT UserName,Handle,Data FROM Reports WHERE UserName="user" AND Handle="handle";

Such an example of an exception is the exact opposite of the ClassCastException I recently mentioned, that required a Google to resolve. It contained all the information I needed in order to resolve the issue. Such exceptions are the best.