eyt*

Find your next scenic drive!

September 28, 2004

Lack of Standards Effects .NET?

In a letter to the editor of Visual Studio Magazine, Frank Molnar states that there is not much buy into .NET because of the lack of standards. The argument that he provides is that that previous model of was to standardize the language, thereby placing it in the public domain, and earn tools by providing compilers, interpreters, and other components that support this standard for various platforms.

Instead of this model, Frank says that Microsoft has completely changed its paradigm for the simple reason of increasing sales by making previous versions of its software not only obsolete, but also unsupported. By not standardizing the language, Microsoft is essentially selling its language, and this makes it difficult for people to buy into the language.

In Leveraging Frameworks, Douglas Schmidt et al mentioned that it takes up to nine months for developers to become productive with a framework (what .NET is). As such, for an organization to adopt Microsoft's latest tools, it must factor in at least six months in learning. This can obviously be shortened by hiring employees with experience with .NET and/or providing appropriate, timely training.

But Franks argument is really more that when a language is standard, this investment can be amortized over a number of products. When you take the time to learn a standard language like C++, the language remains the same, no matter the operating system and environments you work in (of course, techniques and culture pertinent to the domain may change your language usage habits). The only portion that needs investment is learning the new tools available in the new environment.

Another advantage to the standard language is portability. This is slightly touched upon in the above paragraph, but here I really mean source code portability. Per se that you require a real-time operating system, and you buy into a companies product. If that company fails, you probably do not want to rewrite your entire application and tools on a new platform. Instead, you would probably want to port these applications to another vendor's operating system. With standard languages and proper abstractions, this can easily happen.

If any other company had come out with .NET, it would probably have been a complete failure, but as Windows usage is high, it is unlikely that Windows would suddenly go away, so this protects it a bit. But per se that Longhorn license fees go up considerably or you just need another platform, it looks like Mono is your current bet, but based on experience with Samba, changes in the language or protocols (that are closed source) could take a little time before appearing here. Depending on what the hiccup is, this could be as simple as “Do not use feature X”, but if your software interoperates with other .NET software, it is possible that updates could render the program broken for sometime. Again, this is just looking at the worst-case scenarios.

There is, however, one place where Frank and I disagree, and that is in Java. He seems to think that it had a chance and now it is done, but I see Sun has been paying more attention to Java in the last year, and with the Tiger release probably coming on Thursday, I think it is just the beginning of the future evolution of Java. Of course, Java is not a standard language (they tried and failed), but it is freely available and there is the Java Community Process to change the language. And furthermore, there are a number of implementations that do not come from Sun.

Interestingly enough, also in the news today is Azul Systems, which plan to make a network appliance for plug-and-play boosting of applications. They are initially targeting J2EE over .NET, because “most of the market is J2EE”. Depending on what you read, the opposite phrase could easily be found, but I am sure part of the reason that J2EE is popular in this space is that no one is selling the Java language, just Java tools.

Thunderbird problem with receiving e-mail...

I have been using Mozilla-based e-mail products exclusively since around 0.7, in the days where it was no where as stable as it is now, but yesterday, I had a strange error at work, where Thunderbird 0.8 just stopped receiving e-mails. I had seen problems like this before, but after restarting it, it would work. But not this time.

After playing with it a bit, I decided to Google on it, and I found this discussion on MozillaZine, I tried the suggestion of deleting some messages via another mail program, but to no avail.

I looked through the configuration directory to see if there was anything locked or usual, but nothing seemed out of place. I then decided to rename my mail server to something that would not resolve, and after restarting, it still did not complain about the unresolvable mail server.

I decided to play a bit with the settings, and this is when I finally got it to work. Under the Account Server Settings, I:

  • Unchecked “Check for new messages at startup”
  • Unchecked “Check for new messages every X minutes”
  • Unchecked “Automatically download new messages”
  • Unchecked “Leave messages on server”
  • Checked “Fetch headers only”
  • Changed the server name to something that is not resolvable.

When I restarted Thunderbird after making these settings active, it complained about the server name not being resolvable. I then changed the server name appropriately, and tried it again, and it finally started receiving my mail! I changed my settings back to my normal settings, and it has been working ever since.

Thunderbird somehow gets into a state that it cannot get out of, that stops mail from being received. Hopefully there will be someone who can find some real reproduction steps so that this bug can be squashed, as it seems to have been there for a while already. But it looks like an unlikely bug to occur.

I have been using Thunderbird exclusively and extensively since 0.2, and this is the first time anything like this has happened. This speaks for the quality of the program. If you have not yet tried, it is definitely worth a try!

September 27, 2004

Hang with Class Stereotypes...

As reported here, one problem that I have been experiencing with Poseidon was that when I would add stereotypes to a class, it would appear to do the right think, and as soon as I would click elsewhere, my processor would spike to 100% usage, and the tool would never come back.

I finally got around to opening a support call for this, and it seems that a simple workaround is to simply disable the Automatic Critics feature in Edit-> Settings -> Appearance. So try this if you get this problem.

Although the concept behind the automatic critic is interesting, I rarely really found this feature useful, so disabling it is a no-op. What would make this feature interesting would be to analyze your diagram and to make good suggestions about them, just like being mentored. To some level, you would want something similar to JLint, IntelliJ IDEA's critics, or Package Structure Analysis Tool, which analyze the entire code base to report on a variety of issues.

But in reality we do not need yet another tool to analyze code, but rather a tool to analyze the diagrams and designs to improve your relationships between classes and extending the diagrams in the future, such as recommending the Proxy pattern, recommending against inheritance, recommending an interface, and other such issues. But in order to do this, you need a lot more information than is probably in a diagram alone, let alone the artificial intelligence to analyze this information.

For this, though, there is still no replacement for working and collaborating as a team. The members of your team should know your domain well, and therefore be the best critics for the design. Furthermore, each member of the team has different experiences, and this can lead to a better design, as the members of the team can discuss their perspective and experience to change the design, and there really is nothing like direct experience.

September 21, 2004

Fixed a couple bBlog issues...

Over at the bBlog forums, Jonathan Weinraub requested the ability to be able to receive the comment text within the e-mail notification feature, which makes a lot of sense. Users that are using bBlog 0.7.3 can download an updated bBlog.class here, and simply copy it over their existing blog/inc/bBlog.class.

Also in the happens over on the forum, antarius had an issue with getrecentposts; Users of 0.7.3 can snag a new functions.getrecentposts.php here, and copy it over the existing one in bblog/bBlog_plugins.

Users that are using CVS-based versions will get these features for free on their next sync.

As always you have any questions, comments, or problems, please let me know :-).

September 20, 2004

Debug using Logs...

Last weeks Developer Central newsletter (#79) had a piece entitled “Improving Software Development: Logging Strategies” by Mike Gunderloy which discusses some of the things that I have been meaning to write here myself.

When you talk to developers about logging, it really means different things to different developers. Generally developers who have the luxury of working with a good logger really want one, whereas those who have either never used a logger or used a poorly designed logger are generally in the camp that it is not particularly useful.

Even with the excellent tools that we now have available, there are a number of developers that still prefer printf() style debugging. In this style of debugging, a developer generally inserts some printf()s in the code, recompiles, runs, evaluates the output, and repeats the process.

This style of debugging is perhaps tried and true, especially in development environments where you know exactly what you are tracing down. Generally you know what you were doing, or the tester can generally give you enough context to narrow it down. Martin Fowler states in his Refactoring: Improving the Design of Existing Code that “Whenever you are tempted to type something into a print statement or a debugger expression, write it as a test instead;” in other words, instead of extracting energy in writing a printf() function to ensure that the variable you think is 10 now is, write a test program to ensure that it is that value. Martin's premise is that the test program does not go away, whereas your printf() statement will be removed when you merge the code, or perhaps at some point in the future, hopefully before a customer sees some cryptic debug message.

While this approach is interesting, the problem with the approach is that it is only useful in the development environment, presuming that the test programs are executed and inspected regularly. That is a lot of conditions to be true. All too often, the software works perfectly in-house and once released, it fails. This phenomenon rarely fails, especially when it is important that the software works perfectly. But, how do you debug this problem?

While some problems are easily reproduced in-house such as different work flows, some other issues can be extremely difficult to trace, such as those that involve timings, and this is really where good logging will be the difference between finding the bug quickly, and, well, not.

As Mike highlights, there are a number of things that log files are good for. Because log files provide the history (hopefully) surrounding the problem, it allows developers to understand the actions that were actually done and the sequence of those actions. These two items alone are extremely important. There are many times that people will overlook something that they have done that is actually very important in the grand scheme of things, which changes the conditions for the bug. Logging such conditions will ensure that this information is recorded to help in reproducing the problem.

One of the hardest types of bugs to catch are timing related bugs, and debuggers are notorious for making the software behave differently, which usually makes the bug change behaviour. However, since you will be shipping with the logger in the source code (perhaps in a different state), the behaviour of the software should be similar regardless of the surrounding conditions.

Another feature of log files is that you can sample the information within them to either look for patterns, and this search for patterns does not really need to be related to a bug. While you can look through the file and say that after X operations, the bug always occurs and try to see some conditions of why that could be or anything that was different before that time, it could also be used to come up with some real-life usage information to guide optimizations and understand work flow. There are sometimes where the work flow that developers envision is not really the work flow that users use. While there is no better way that to talk with customers to learn how they use the application and what they would like to see differently, sometimes people only think in the current context and do not realize all the potential that software really has, and gathering information from log files is a great idea to get useful statistics on the application. This information not only helps the current developers of the project, but also support and future developers on the project.

In one of the last Journal of Object-Oriented Programming (October/November 2001), Jerry Gao, Eugene Y. Zhu, and Simon Shim wrote “Tracking Software Components” which discusses distributed logging. Of the many things that they mentioned, one of the most interesting ideas presented was the ability to be able to play-back a log file. In other words, the application would record a number of events, and using a supplementary tool, the events could be executed in the same sequence to try to reproduce the bug. This obviously requires some careful planning and in some cases, significant effort to write a playback tool, however, this example is simply provided to demonstrate some of the power that a properly used logging system can do.

As with many techniques, adding logging to new code is usually easier than adding it to existing code, but deciding what to log makes the difference. As mentioned here, error conditions and exceptions should, at the very least, by logged. While the condition is potentially of mediocre concern today, as the software evolves, it can become more important in the future, and logging such conditions will allow you to see some areas that may have gone wrong.

In addition to this, you will want to know some of the user's actions, such as the command-line arguments, the buttons pressed, menus selected, et cetera, as well as information about the environment, such as environment labels, hardware, memory, et cetera. This will allow you to see what the user has done and see the errors in relation to the operation that was being performed. Likewise, information about the internal state or length operations should also be logged, but probably at a lower level to allow developers to see them, but clients to disable them.

One of the things that I mentioned above is that the logger is not removed from the shipping software, but it can be disabled, in many fashions. Mike actually mentions disabling the logger completely, but in my opinion, this is not a good idea, as you never know when an issue can pop up. Besides, the logger can easily be integrated with your user interface and provide users with more context of what is happening within the system.

A better approach is to actually use a logger that filters messages based on some configuration option. Most loggers present some way of assigning a level to a log message, and this determines how the error message is propagated. The range of available levels, however, ranges from logger implementation to logger implementation.

Off-the-shelf loggers are available for most programming languages available, and many modern languages come with a logging service (such as Java 1.4's java.util.logging). No matter which logger you decide on using, it is important to select a flexible logger. The flexibility is usually obtained by using levels to discriminate the messages, the option to be threaded or not, and the ability define an Observer that allows for custom reporting services, such as presenting certain messages in the status bar. The log file utilized must also provide a wrapping feature after either a certain number of messages or a particular file size, and must contain, at the very least, a time stamp, a level, and a message, but more context is always desirable, such as the filename and line number where the error is logged, and the host name and/or thread identifier that the error message is from.

Debugging client applications is much easier with the proper context. Logs provide context in an application with minimal overhead. The advantages greatly outweight most excuses people will bring against them; there are few applications where loggers do not make sense, and usually all that is needed, if anything, is a better logger.