Archive for October, 2007

Interesting User Validation Problem

Friday, October 12th, 2007

Today another developer stopped by with a problem I've seen several times before - how to handle user validation of percentages. Specifically, let's say a user needs to put in how to subdivide something - 10% to this, 20% to that, and 70% to the other. Breakdowns like this are easy - until they get into factional percentages and numbers that are, by their very nature, impossible to represent exactly in a computer.

Take 0.12 - it seems easy enough to look at, but try to add it to 0.74 and 0.14 and you're going to find that a double is not exactly 1.0. That's because the numbers are not exactly what we typed in and there are representational errors in the doubles that make it something like 1.00000001. So how to fix this?

One way, which I've done for many cases, is to have an ε something like 10-6 and check to see if the value you want is some ε from the target value by:


    if (Math.abs(sum - target) <= 1.0e-6) {
        // close enough to be considered equal
    } else {
        // not equal
    }

which can be put into a method or function that makes it easy to call. But the idea is that if you get close enough, you're equal. The problem with this is that the ε that you should use is greatly dependent on the values you're summing, in this example. Say you have values like 10, 20, and 70 - in this case, ε should be 0.1 because there's no need to have it any smaller as all the numbers are integers. But if you had numbers like 10, 20.22, and 69.78 then you may need to have ε set to 0.001. The optimal value of ε seems to be directly related to the maximum precision of the data. Also, there's always the possibility that some oddball case will be just large enough a difference to not be 'equal' and then you're flagging a false positive. But there is an interesting way that this won't happen.

Look at the problem of the user input as if you were a third-grader. Break the problem down into the whole number and fractional components. This makes everything an integer, and adding integers is very easy indeed - with no rounding problems. What I mean to say is that if you had the set of numbers: 10, 20.22, and 69.78 then break the summation down into 10 + 20 + 69 + (00 + 22 + 78)/100.0. This means that you only have to look at the string representation of the numbers - separate out the parts to the left and right of the decimal, find the maximum precision to the right of the decimal (for scaling), and then go to town.

After we talked about this approach for a little bit, the developer went back and coded it up in no time. It's really very simple. But given that users can type in arbitrary precision in the numbers, it's important to sum them as exactly as possible, and using integers for the whole and fractional parts is really pretty sweet. There's no rounding (until you get to the final double) and by then, you're comparing it to the test value, and if it's another integer (in the case of percentages), then it'll be easy.

I giggled a bit thinking about this. It's not often that the best way of doing something is the way a third-grader would do it. But that's the point - not everything needs to be so overly complex and over-designed.

The Ancient Code of a Million Developers

Thursday, October 11th, 2007

cubeLifeView.gif

Today I had to spend a lot of time on a application that got dumped on my lap after the last developer working on it couldn't get a new price feed hooked into it and was asked to leave. Since I had done a lot of work on this price feed, it seemed natural that I get the app hooked up to the new feed. It took me a few days and worked great. Then there came the need to add in permissioning for fee-liable exchange data, so again I was the logical choice because I had done similar work for other apps. Ahh... that slippery slope.

It didn't take long for me to be the maintainer of this app. That typically meant that features that haven't worked in years suddenly working because I found mistakes in the code and/or database and then they magically started working again. Some I was specifically asked to fix, others were resurrected completely by accident when I was fixing something else.

Now I've been working on this code for about 9 months. Not full-time, more on an as-needed basis, so I don't mind too much. But I need to say that this code is a real mess. I mean the worst code I've ever seen.

It's primarily C++ on Windows using Visual C++ - but the build systems is GNU make on Cygwin. It uses JNI, so the JDK is involved and that's a mess. There is virtually no documentation, there are dozens of sub-projects. The database access is through a separate process on another machine that has it's own configuration, it's asynchronous and not easily followed. It's over-designed and poorly coded. In short, it's a mess, and it'd be easier to re-write it but the logic is so buried in the code that it'd be easier to sit down and talk to the users to see what it's supposed to do as opposed to how it does it.

One of the features of this app is the ability to create new views (browsers) on the data. This controls the columns shown in the table, their order, how the view is updated, etc. Yesterday one of the big users of the app asked me if it would be possible to make it so that you could create new browsers. The app looks like it's supposed to work, but it doesn't. So I said I'd look into it and see what I could find out. Yikes! what a mess.

The code was a mess and had been that way since 1999 - I found comments where they had hard-coded the name of the new browser to 'x' - literally an 'x', and it was commented as happening in 1999. What were they thinking? I have no idea. I tore that out, figured out what was being passed into the method by way of these odd notification objects, and realized that it wasn't that far from working - on the client side. It took less than 50 lines of code changed, but finding those lines was the challenge. The real problems were on the database layer configuration, and stored procedures.

When moving to Sybase 12.5 the IDENTITY column had to change from an 'int' to a 'number', and in doing that, most all of their stored procedures were broken and never fixed. The access layer expected ints, and they weren't being returned that way - so basically, all the database work was getting dropped in the bit bucket. It was similar to what I'd seen before in this app, but what a striking example of poor updates and testing.

Then there's the bad UI, but that's just because it was created by so many developers over so may years there's no way it was going to have a consistent vision and style. Horrible. Which brings me to the point of this post - the code is ancient. It's been worked on by so many developers that had no idea what the point and architecture of the code was originally about. It's been slapped, hacked, poorly tested and given unworkable hard-coded hacks. It's amazing it still compiles. But this is what some people call developing. I can't imagine putting my name on this if I'd done it. I'm happy with the fixes I've made, but those are only in light of how bad it was to start with.

It's just amazing it works at all.

Historical MarketData Source and CKString Fun

Wednesday, October 10th, 2007

xcode.jpg

Yesterday afternoon one of the developers came by to ask me about finding historical prices for delisted symbols. "That's hard", I said - because it is. Bloomberg has historical data back some 20 years, but you have to know their symbology to get it out of Bloomberg, and one of the things my MarketData server does is to allow us to use our own symbology and it converts this to the symbology of the data provider (in this case, Bloomberg) and then requests the data. This is great so long as you can do the symbology mappings. The problem comes in with delisted symbols - they aren't in our mappings table so I can't convert from our symbology to Bloomberg's. This means that eventhough you might be able to get at the data, you don't know what to ask for.

I told him he'd have to investigate another data provider and get the data from them. This other provider needs to have the historical data and some sense of the re-use of tickers so that given a date and a ticker it knows that there was one - and only one instrument for that ticker on that date. This kind of historical data is not common, but it's available. You just have to know where to look.

So we started looking.

There's a project in the Bank that handles a ton of historical data from a lot of sources - one is Bloomberg. So we did a few tests to see if this source - which was in my MarketData server as a provider, had the data for a delisted company. Turns out it did. But at the same time, I found that there were problems with how I was calling and using this data source. So I dug into fixing them.

The first was pretty easy - when I requested data of this source, if I received nothing, then I assumed it was an error. In reality, if there's no data, they returned nothing. So if you asked for a delisted symbol after it was delisted, you'd receive nothing. I fixed those tests up to allow for nothing to be returned. Easy enough.

The second one was more interesting. The data fields you request should stay the way you request them - case-wise, but I wasn't preserving the case of some requests and mismatching the case of others. So I added several nice little methods to CKString to allow the user to copy a string and uppercase it (the only existing method uppercased the string in-place) and then I added equalsIgnoreCase() like Java's String to allow the code to not have to worry as much about case in the tests. When I put these in and realized that I needed an uppercase copy of the fields for getting data from the source, caching it, and then using the original field list to pull it out of the cache, things worked beautifully.

In the end, it was a lot of fun to add these things and see how they simplified the code I was trying to write to fix the problem. Lesson learned: add power to the underlying libraries and that will make any higher-level fixes much easier.

Sun’s Lack of a Java Plug-In for x86_64

Tuesday, October 9th, 2007

java-logo-thumb.png

Every now and then I give a look-see to Sun's Java web site to see if they have stated when they'll start to deliver a Java plug-in for x86_64. There's a bug report on Sun's web site, with a ton of comments blasting Sun for not getting a x86_64 64-bit plug-in working, saying that this is addressed in JDK 1.7 (Dolphin). I took this for a good sign as I went to the Java web site to see if there was a beta of JDK 1.7 available - and there was.

So I downloaded it and looked inside the jre directory to see that no plugin exists. It's amazing. They say they're going to have it, but then they don't follow-up and actually deliver it. Now, it's possible, I suppose, that this is going to be added in the final release, but I'm guessing not, as that would mean that something is in the final release that was not in a beta release - not very likely.

So I decided to see if this Blackdown 64-bit java plug-in would work, knowing that it was stopped at JDK 1.4.2. Interestingly, their site, http://www.blackdown.org/ comes back with nothing in the web page. I've googled for this site, and it keeps pointing me back to this empty page. There are several sites like this that tell you how to install it, but all their links to download it are pointing to bogus sites. I finally found a page saying that Blockdown is no more. That explains it. I did find a mirror site that had it still, but when I tried it with my FC5 box and BonEcho 2.0.0.3, it crashed. Too bad.

Well... I guess I'll have to wait for Sun to decide that 64-bit desktops are important enough to support. Thankfully, my laptop will have it with the new version of Mac OS X (10.5) due out this month. Good thing I don't have to wait for Sun for that.

Looking at both Sides of Java and Web Browsers

Tuesday, October 9th, 2007

java-logo-thumb.png

OK, I'm trying to be fair and even-handed about this, but this morning I got another gotcha from Java (1.6.0_02) and IE (6) and Firefox (2.0.0.7). It's this thin client development that is 90% of what's needed but when you hit that 10% it's a pain in the rear to try and get around it. This morning I spent several hours doing just that.

The problem came up because one of my servers uses a web client to maintain it's internal data. This is nice in that the previous 'editor' was a Java application and it was a lot heavier than the support staff needed to have. Plus, with the web delivery, it was easier to have these folks support the server from London and home. But there's always a cost.

One of the things I did a while back was to have the users able to edit start-of-day (SOD) positions for the instruments in the master file. In order to do this in a reasonably useful way, it meant that I had to have a Java applet. This was not the first Java applet on the editor, and I knew that there would be IE/Firefox issues and how to get around them to make sure that the applet launched, etc. Nothing new there. What was new was the fact that I needed to send back data when the user hit 'Save'. I'd probably have been happy enough with Java applets if I hadn't had to do that. But I did.

Moreover, I had to send these updates through CGI scripts where the old and new data were arguments to the GET request. Not terribly hard, but when you find that IE still allows JDK 1.6.0_02 to send URLs to a server and get back answers, and Firefox doesn't, then we get into the lovely realm of applet signing.

It's not that terribly hard, but I didn't want to get a certificate that would mean the users would have to manually accept, so I went on a search for the location of the certificate that the web developers have built to enable them to sign their applets. This way, I know the certificate is allowed on all the boxes, and I don't have to worry about that.

Easier said than done, and honestly, it wasn't Java's fault. But the idea that in these days of corporate intranets and apps deployed on them, it would seem reasonable to have the security system say "Hey, if it's on this domain, it's OK". I know that's not necessarily safe, but coupled with the fact that there's security in the assignment of IP addresses and the domain naming, it's very unlikely that someone is going to put a box on the net with the right IP and domain to publish fake jars. Could happen, but it's not likely.

So I had to sign the applet. Interestingly enough, Googling this revealed that it wasn't until a recent release of 1.6.0 that this difference in behavior between IE and Firefox came to light. Previously, the behavior of IE and Firefox was the same in that it'd allow the URL connections from the applet to a machine not hosting the applet. So this might change again in the future. Yum...

The next problem was NFS... and it's likely a linux problem, or a difference in the NFS system we have in the Shop, but it turns out that if you copy a file from one machine to a shared filesystem, there's about a 70% chance that the web server will think this is a corrupted file. So, after seeing that the ClassNotFound exception was on the Java console, I went to the web server and copied the file to the same shared location. This finally worked.

After all this, things started to click and I got all the issues worked out.

Now I know that Java isn't perfect, and it's a lot better than ActiveX, which came before it, and I'll even say that it's a alot easier to deal with than AJAX, but I keep thinking that there has to be a better way. I know that AJAX is making strides, but it's not really a revolution, more an evolution. I'm wondering where's the revolution in thin clients? Where's the easier system of making clients deployable easily and run cleanly. I've seen Java WebStart and its a lot like Marimba - you download the app and run it. Yeah, it makes deployment easier, but it's no different than fat clients.

Throwing together a Java RMI server would be possible, have the applet connect in and send the updates - that'd get rid of the CGI scripts, but it's not going to make the security issues with Java any more manageable. Make it easier to write powerful apps that are easily deployed remotely. Tons of OSs have done it - X, NeXTSTEP, even VNC does this. But these are for something large, like a desktop or a big app. I'm thinking small - like most applet work. That would be nice to find.

Lessons Learned as Hero Support

Monday, October 8th, 2007

This past weekend Liza ran the Chicago Marathon, and it was an experience. First, it was a disaster as a good race as the temperature was >95°F. and there were problems with sufficient water on the route, and after a while they cancelled the race but told the runners they had to walk back in. The transportation that was to be provided to get the runners back to the starting line was not available, and so many runners, like my wife, had to walk it in. This added several hours to her time and I had no idea where she was. So... there are several things that we, as a Team, learned about this, her first marathon:

  1. The Runner Needs a Cellphone - until the time that they have GPS on each runner, or the Chips mark each mile and an easy way for each support person to know where their runners are, a cell phone is a necessity. Had I been able to call her, or she to call me, we would have known that she was falling off her pace as early as mile 9, and I would have waited at mile 13 for her, and updated my expectations of her arrival time at mile 16.5. As it was, I was a bit frantic not being able to find her past mile 2.5.
  2. It Doesn't Hurt to Carry Water - there were water stops that had no water at them when she arrived. This was a serious problem in the >95°F. weather. So, she and I talked about her wearing her water belt, and discounted it. Next time, if that heat is up there, she'll carry it just in case this happens again.
  3. It Helps to Have Support Crew by the Phone - had they used the Internet to track her progress better - more Chip splits, then it would have been really nice to have someone at home with a computer that could monitor her and update me to her progress. As it was, the kids didn't know what to do, and the only splits the system sent out was her ending time. Hardly worth it.
  4. Have a Go/No Go Point, with a Backup Marathon - we had the back-up marathon as many people had recommended, in case of injury, but there wasn't a point we had that she'd pull herself out of the race because it wasn't an enjoyable experience. For example, had we said "If you drop below a 5:30 pace by the 13.1 mark, it's time to pull out because you've trained at the 4:15 level and this would mean you're getting beat up by the weather or the course."

I'm sure there are a lot of things she's learned about running in a marathon, but these are the big things I've learned supporting her. Until I can take the time to train with her - or at least train for the same race like her, these are the things we're going to have to keep in mind if she hits the pavement again for another 26.2.

What Makes a Great Development Team

Monday, October 8th, 2007

I was talking to a vendor consultant that is here at the Shop helping us integrate their product into our systems. Happens all the time, we tell them what we have, they know what they need and we work together to hook up all the hoses and pipes so that their product fits as smoothly as possible into our systems, and in the end, becomes yet another one of our systems. So I was taking to this consultant letting him know what I did, as his product had to fit into my systems in a very smooth way.

We talked for about 2.5 hours... him asking me what my products were, how they worked, where the data flows were - nothing unusual. But then he asked me how many people were working on all this. I told him that there was a Team of seven on this part, and a few guys on this part, and there's a Team in the other part of the Bank for this part, but the rest of the whiteboard was me. He was shocked.

Which lead him into the question of what makes a really high-performance Team. Seeing as how I'm here to make this integration project succeed, I humored him and let him lead the conversation. His background, it seems, is in leading large-ish group efforts within the very large vendor's suite of applications. He said he was constantly trying to figure out what made Teams really special. Why did some groups seem to just walk in the light, and others were stuck constantly trying to stay off the Dilbert comics.

His take was experience and clarity of focus. He believed that if you had really experienced guys that knew the problem domain, who could look at an issue and easily distill it down to it's elemental key components, then that Team was going to be a winner. And the problem was having to deal with all the customer support and that meant that lesser talented developers had to deal with those issues. That lead to the problem of morale, and that lead to the fact that in any vendor group, 20% or less to the work and 80% are always the focus of the manager's efforts to make them productive.

I told him I thought he was all wrong. I also told him that if he had 80% of his developers that weren't contributing like the other 20%, he should fire them. And I went on to tell him why.

Maxim #1: People Rise to the Level of Your Expectations - as an educator both in one-on-one sessions and in small and large classes - both in the lab and the classroom settings, I believe this with all my heart. If you set your expectations high, people will achieve them. You have to do your part - you can't make them seem unattainable, you have to assist those willing to learn to get the knowledge, and you have to be fair, honest, and communicate these expectations, but if you do that, then people will rise to that level. I've seen it happen so many times, to me it's a universal truth.

So, for the manager that is trying to get the best out of the 80% - he needs only to expect the same from them as the others, and if those expectations aren't met, then those people have to leave the Team. Maybe they don't need to leave the company, but they need to know that they will not being doing development (cool work) with this group because it simply has expectations of each member that are beyond what this person is willing to do. In the end, you will loose a few, but the number won't be large, and even if it is, the Team will perform better because of it.

Maxium #2: Seek those with Commitment, and Everything is Possible - while many may disagree that this is true I'll put it another, less controversial way: If you find people that can acquire your commitment, they will be able to acquire anything else they need to see those tasks through to their ends. Education, experience, assistance - all these are available to the person with commitment. The consultant I was talking to spoke of experience and the ability to have a clear vision of the task at hand. Those are two qualities of a person with commitment, but those two qualities are not by themselves a complete indicator of commitment.

You can have people who are brilliant and do nothing. You can have people who see, and do not do. True, it's most often the case that people who can do these things are doing these things not because they are naturally good at them, but because they have worked to be good at them - natural talent or not. So while I understand what the consultant was saying, I think he was looking in the wrong place for it. Look for the traits that create and inspire the effects, as opposed to looking for the effects.

And this brings me to the core of the issue: Character. If you have it, you'll go far, and a Team with a critical mass of it will infect the others that might be a little low, and the result will be a Great Team. I've been on Teams where I'm the weakest person, and I worked very hard to not be the weakest person. I strove to be the person that could be relied upon to carry the day, if needed, but most times it was just a friendly competition to see who could do better - today. Tomorrow, the race starts again.

Gotta Watch Those Hotkey Combinations

Saturday, October 6th, 2007

Yesterday I was playing with Skitch and FlySketch and saw that when I tried to do a screen snap in Skitch with the hotkey Cmd-Shift-5, I got a lot of problems and then didn't get the snap I wanted. The screen seemed to freeze, I couldn't get it to stop, and then I hit Enter, and I got a snapshot, but it wasn't what I wanted. I was convinced that this was just a conflict in the two applications - both of which use some kind of hotkey combination for their behavior. Not a terrible thing, but I don't like these conflicts as they sacrifice stability, so I picked Skitch over FlySketch, and wanted to give it a shake.

Well... overnight I thought more about it and wondered if it were possible to get the kind of things I liked in Skitch in FlySketch. So I flipped open the laptop and started looking at the preferences of FlySketch. When I saw that it's full-screen snapshot hotkey was Cmd-Shift-5 I knew that I'd found the problem. So since I have FlySktech set to pop-up on Cmd-Ctrl-F, I made the full-screen snapshot in FlySktech be Cmd-Ctrl-Shift-F - something easy to remember. Then the Cmd-Shift-5 would be Skitch's and there would not be a problem.

Or so I had hoped.

So I fired up Skitch again and along with the newly-configured FlySketch I tried the Skitch snapshot - Cmd-Shift-5. It worked!

Wonderful lesson to learn: Always check for hotkey conflicts.

There’s Nothing Quite Like Planning Ahead

Friday, October 5th, 2007

cubeLifeView.gif

OK, this weekend we have our disaster/recovery testing and while I've been ready for a while, several people are using today - yes, the last 24 hours before the test, to get things "set up" for the test. Now to be fair, there are some applications that don't need a lot of preparation, or there may be very limited expectations for some groups. But when those folks that decide to "check on things" at the last minute start to hammer me with requests for my systems to make their disaster/recovery testing go more smoothly, I don't really like it.

I have to agree that a lot of these are good things - mostly edge conditions related to what might happen in a disaster. And I have to say I'm happy to get these changes in no matter when, it's just that it would have been a lot nicer not to have to worry that I can get them fixed this afternoon, and had - oh... I don't know... maybe just another 24 hours... to get them in, tested and to production.

Alas, there are people that like to do things at the last minute. I, however, am not one of them.

Finally got a Skitch Invitation

Friday, October 5th, 2007

This morning I received my Skitch invitation. I read about Skitch from one of the new feeds I read daily, and the demo movie looked like it had a lot of nice features for image capture and sharing - though I'd be a lot more interested in the capture than the sharing, but there's stuff to share, and I guess they make their money off the adds they run on the viewing pages. Anyway, this morning I got he email saying I had received an invitation. So I decided to go back to the site and see if I was still interested.

Since I had put in the request many months ago, and I've started using FlySketch more, I wondered if I'd still think it was as "cool" as I did when I asked for the invite. Well... I have to say that it really is an amazing little tool. FlySketch is nice and small, and it can do a lot of things, but the ability to drag from Skitch to an app without saving (they save the image to /tmp and then 'drag' it in) and the ability to do more drawing than FlySketch is capable of makes Skitch a good upgrade from FlySketch.

Then when you look at the ability to put the images on their servers, allowing people to look at your sketches without you having to store them - well, that's just a nice bonus. Now I'm not sure I'd ever really trust a service that's free to keep my important images, but it's a place to throw stuff up there, and then decide if I need to keep a copy on my machine(s) later.

It's integration with OS X is really stunning and the mouse-over help is nice, but I hope as they mature the product it's able to be shut-off in the preferences. It works wonderfully well on my MacBook Pro - fast and snappy. I like the organization of the preferences even if it's a little against the Apple HIG. I have to say they did a nice job. I'll be running this and see where it'll take me.

UPDATE: it's a good idea to not have FlySketch and Skitch running at the same time. I've found some incompatibilities with the snapping in Skitch if you do. Since they both are about the same, I can see this as a limitation. I'm not really happy with it, but I can see it.