After reading Joel's article
, I thought I'd give it a try. Normally, I am not a fan of web applications. However, this web application is incredibly well done. The GUI is rather impressive, with wizards, dialogs, menus, drop downs, and the like. It still feels nothing like the responsiveness of a desktop application, but the features are so good that I may have to overlook this.
This online calendar application has almost all of the features that I need. Things like: group calendars, integration with Outlook, SMS notifications, good permissions, and search. It also has features that I like that weren't necessarily part of my requirements, like blog content, shared contacts, lists, and links, and tight integration with most cell phone providers to provide an application that runs on most cell phones.
I looked at Office Calendar by Lookout Software, and I liked the concept very much, but the price tag seemed a bit steep. All in all, I am quite pleased with the features of Airset, and the price of free is hard to beat.
I've spent a lot of time here at my current place advocating refactoring. The concept of "code smell" is one that continually comes up. My esteemed colleague, Rich Werning, just came up with "Rich's ultimate code smell test". One simple question: if the project you are working on was to be released as open source, and thus available to the scrutiny and review of hundreds or thousands of other developers, would you want your name and professional repuation associated with the source code? If not, your code stinks.
100% agreed, and brilliantly stated.
As a follow up from my post yesterday
, I have some work-arounds to get me past the problem. I still don't have the ultimate answer for why Math.Log(0.0) throws an exception only when called from COM interop, but I can at least move forward again.
I started out by changing the actual code in Lucene to simply avoid the Math.Log(0.0) statement. However, I started to worry about forking the code. I don't want that kind of maintenance headache as new versions of Lucene continue to come out. I was able to work things out so that I could descend a couple of classes, override some methods, and plug these into my API layer, and everything worked fine.
The one problem left was the arithmetic overflow that I got later on in the Lucene code. I was talking with Chris Bensen, and he recalled running into something similar before and sent this link to MSDN on _controlfp documentation. I implemented the following code in .NET in the constructor of my API layer, and the overflow error went away, but of course, I end up getting NaN results due to the new FPU masking behavior. I'll have to test thoroughly to make sure that this doesn't impact calculations further down the line.
[DllImport("msvcrt.dll")] private static extern int _controlfp(int IN_New, int IN_Mask); // this imports the call
private const int _MCW_EM = 0x0008001f;
private const int _EM_INVALID = 0x00000010;
// Add this code to squelch arithmetic overflow/underflow exceptions spawned from the FPU.
// See comments in the FixedDefaultSimilarity class for more information.
I still would like to find out the technical details for why I need to do any of this, but at least I have things running.
It seems that COM interop isn't always a good thing. I have a problem that I don't have a solution for right now, so if you have any feedback, I'd sure appreciate hearing it.
I wrote a wrapper around Lucene.Net to provide simple API access to some very basic operations (index, search, delete) that will be used by a Delphi Win32 application. Everything was working fine, but deep in the bowels of the Lucene code, in one code path, I encountered a line like this:
return (float) (System.Math.Log(numDocs / (double) (docFreq + 1)) + 1.0);
When there are no documents in the index, this essentially evaluates to a call to System.Math.Log(0.0), which according to the MSDN documentation, should return NegativeInfinity. In fact, when this library is called from a .NET client, it does just that. However, when called via COM interop, this results in an exception, "Attempted to divide by zero". I started to modify the Lucene source to do a check for this condition and just manually return NegativeInfinity, and that did get me past that point, but then later on in the Lucene code, I end up getting an "Arithmetic overflow/underflow" error when Lucene tries to do some math on the returned value. So rather than continue to band-aid this problem, I thought I'd try to dig to the root of the problem to see why this is happening.
You can find an extremely simple test case with a .NET Class Library, .NET test client, and Delphi test client here. Just build the .NET solution, and then you can run the createtlb.bat file in the LogClient directory to get the Delphi project ready.
When creating .NET classes that will be accessible via COM Interop, you need to be sure to add a default constructor to the class. If you don't, regasm will end up generating the tlb without the CanCreate flag for that class, and therefore, when registering the tlb, those classes will not be registered.
Yes, this makes sense, and yes, this is covered in MSDN, but I thought I'd mention it here, as it recently tripped me up for a little while.
Since I'm a programmer, I don't always keep up to date on other areas of software because it's always more fun to write your own tools.
I can find my way around Excel some, but I am not exactly a power user. I had a need to highlight the maximum cell value in a column today, and it turned out to be not entirely obvious. Fortunately, here's a Google post
to walk you through this exercise if you need to do the same thing.
I've been tasked with adding text searching through documents to our application. Since we need to support multiple databases, I didn't want to use the native DBMS indexing options. Looking around, I came across Lucene.Net
. It is an open source port of the Java version of Lucene, which is a lightning fast search engine over indexes of documents. The list of features is rather extensive, but my favorite feature would be the advanced search capabilities, including proximity search. There is also a very impressive open source project based on Lucene.Net called SeekAFile
which adds functionality over Lucene.Net, and works extremely well, too.
I wanted to centralize the index storage of Lucene.Net, though, since it would be possible to have multiple app servers located in different physical locations, and allowing access from one machine to another could prove problematic. This meant that storing the index to the central database. I found a source code sample that would do this on a Firebird database. I have now converted that to work with MSSQL and Oracle, and it works very well. Yes, it's a bit slower than using the native file system directory provided with Lucene.Net, but it solves the problem we set out to solve.
I came across a link to COMTrace
from Scott Hanselman
. This tool allows for interception and logging of COM traffic. I just tried it out, and it mostly works on some of my more complex MIDAS applications. Granted, it is far from perfect (e.g. I needed to start a new process multiple times before I could get it to work when tracing an app server, or it would hang when starting a client process), but I was able to eventually use it to get tracing information on all of the round-trips that the application makes, including seeing parameters being passed from client to server. From the history log, it appears that the last change was in 2002, so it's a bit dated.
A while back, I was going to develop a tool like this, and actually had some things working on the Delphi level by intercepting VarDispHandler, but that would only work within an application, and for late-bound calls. That didn't sit well with me, as I wanted all traffic intercepted, be it early-bound or late-bound, and I didn't want to necessarily instrument my applications with my tracing/hooking code. I started looking at Keith Brown's Universal Delegator, and associated tools, and was going to go down that route, but the priority changed on having this tool, so it got shelved. It's nice to see that something is out there, even if it is imperfect.