Archive for the ‘Coding’ Category

Getting Caught by Java’s References

Wednesday, August 5th, 2009

java-logo-thumb.png

I was working on a problem today with the alerts in my web system and I was having a really hard time getting a handle on the problem. Basically, I had an object that did n-point moving average calculations on a data stream and I wanted to use that to feed a data aggregator where all the data from the n-point smoothing would be summed up across the firm to get "totals" that could be used in the alert expressions.

I had built the n-point moving average class to expose a 'previous' and 'current' array of data so that it looked just like the incoming data - an Object[]. I did this by having two such Object[] instance variables - one for the 'previous' and the other for the 'current'. When a new value came in, I'd copy the contents of the 'current' to the 'previous', add in the new, subtract out the old, and save the new as the old for this contributor. It worked like a dream.

What I was seeing was that the data going into the firm aggregator was showing the same values in the 'previous' and 'current' data arrays! This simply could not be. In the aggregator, I was saving the data from the n-point smoother, by contributor, similarly to the n-point smoother itself, so that we can add in the new, remove the old, save the new as the old, and get a nice running aggregation.

But it wasn't working that way.

And it took me several hours to figure it out. But I did.

References. Java references are somewhat deceptive. In C++ I'd know what I was doing more clearly because I'd have to be more careful with the heap variables. Stack variables were easy as they went out of scope and were gone. Copies were cheap, relatively.

But in Java, everything is a reference. So when I was getting the 'previous' and 'current' data from the n-point smoother, I was really getting the reference to the arrays I was using as storage. When I then got new data into the n-point smoother, I updated that data, and naturally, the data in the aggregator would change as well. After all, it's the same reference.

Ah!

So what I had to do was to make copies of the data coming out of the n-point smoother and into the aggregator. These, then formed snapshots of the data coming out and were exactly what I needed in the data flow.

In general, there's a lot to like about Java. Garbage Collection is one of them. But there are times that the visual warning of pointers in C++ makes it much easier to see issues - or potential issues. I've been coding for a while, and this guy flew right past me for several hours. That's tough to find.

Developing for the Mac or the iPhone

Wednesday, August 5th, 2009

xcode.jpg

I have to say, I do really enjoy my iPhone. It's the best phone I've ever had, and a wonderful mobile computing platform to boot. But when I think about developing for it, I have to look at the stories of App Store Rejection, and wonder if it's worth it. Sure, more apps are accepted than rejected, but is that because they are little productivity apps and games? They can't really push the envelope, or they'll get rejected. Simple things like dictionaries, game emulators, and such are all being rejected by Apple on grounds that seem, at least to many, to be nearly arbitrary.

Coding is a lot of fun, and you have to be passionate about it to do a great job. This "maybe I will, maybe I won't" situation could have you invest a good chunk of time into an app, and then find that it's not allowed to be presented to potential users. Free or not, the same rules seem to apply.

I'm just not convinced that I could go through that cycle. Writing for the Mac, however, has no such limitations. This represents a clear choice to me.

Goin’ Old School on Some Code

Monday, August 3rd, 2009

Professor.jpg

Today I was trying to figure out why an app I inherited was returning wild values and I came across code that I'd skimmed several times before, but hadn't really dug into. Since the running program wasn't generating any exceptions, I assumed that the problem had to be in the data we were receiving. I spent several hours digging into the data, logging it, checking for problems, all to come to the conclusion that it couldn't be the data, and had to be something in how it was being interpreted in the code.

So back to the processing code that was the first step in the program.

My goals were simple - put in logging and try/catch blocks to make sure that we caught the exceptions and group the processing into distinct groups: gathering data, converting it into values, and then organizing the data into objects. Seems simple. And then I looked, really looked at the code.

What I saw made me shake my head... and bring out the "Old School" in me. The original code looked something like this:

  public uploadData(StringTokenizer mainTokenizer) {
    // get the number of rows as a rough size for the maps
    int size = mainTokenizer.countTokens();
	// ...make some maps to store data
 
    while (mainTokenizer.hasMoreTokens()) {
      String row = mainTokenizer.nextToken();
      StringTokenizer columns = new StringTokenizer(row, "\t");
      while (columns.hasMoreTokens()) {
        String nameString = columns.nextToken().trim();
        String dateString = columns.nextToken().trim();
        String costString = columns.nextToken().trim();
        String qtyString = columns.nextToken().trim();
        // ...more of the same
 
        String name = nameString;
        Date transDate = dateFormat.parse(dateString);
        Double cost = Double.valueOf(costString);
        Double qty = Double.valueOf(qtyString);
        // ...more of the same
 
        Order ord = orderFactory.createOrder(name, transDate, cost, qty);
        orderMap.put(name, ord);
        // ...more of the same
      }
    }
  }

The goal was admirable - divide the processing into three sections: acquisition, conversion, and organization. It's an admirable goal. But doing it this way is not only a little redundant, it's downright dangerous.

Look at the most obvious things: reused variables. Get rid of them. Make it cleaner by using the variables where they are needed. No more, no less. it's an admirable goal, and a good design plan, but when you're processing 30 or more variables in a table of data, it gets to be a little much when you have to repeat these three times. Trim it a little and keep it readable.

But he subtle things really are the danger signs. Why is he using the StringTokenizer for the rows in the table and not checking the number of elements? There's the possibility for a major confusion here. What if you have a row of data that's malformed? There's nothing that's going to tell me what the problem was and where to look in the data stream to correct it. Also, if there's an exception thrown all the remaining data is lost. Not a good thing.

Let's try something a little different.

  public uploadData(StringTokenizer mainTokenizer) {
    // get the number of rows as a rough size for the maps
    int size = mainTokenizer.countTokens();
	// ...make some maps to store data
 
     // processing variables used in the loop
    String name = null;
    Date transDate = null;
    Double cost = null;
    Double qty = null;
 
    // keep track of what I've done for logging at the end
    int    uploadCount = 0;
    int    uploadErrors = 0;
    while (mainTokenizer.hasMoreTokens()) {
      String row = mainTokenizer.nextToken();
      String[] columns = row.split("\t");
      if ((columns == null) || (columns.length != SIZE)) {
        log.error("No columns or wrong number.");
        ++uploadCount;
        ++uploadErrors;
        continue;
      }
 
      String nameString = columns[0].trim();
      String dateString = columns[1].trim();
      String costString = columns[2].trim();
      String qtyString = columns[3].trim();
      // ...more of the same
 
      try {
        name = nameString;
        transDate = dateFormat.parse(dateString);
        cost = Double.valueOf(costString);
        qty = Double.valueOf(qtyString);
        // ...more of the same
      } catch (NumberFormatException nfe) {
        log.error("While parsing " + name + " got a "
            + nfe.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      } catch (ParseException pe) {
        log.error("While parsing " + name + " got a "
            + nfe.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      }
 
      try {
        Order ord = orderFactory.createOrder(name, transDate, cost, qty);
        orderMap.put(name, ord);
        // ...more of the same
      } catch (Exception e) {
        log.error("While organizing " + name + " got a "
            + e.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      }
 
      // update the count of rows processed
      ++uploadCount;
    }
 
    // log what we've done
    log.info("Processed " + uploadCount + " with "
        + uploadErrors + " errors");
  }

Now the logging messages are far too simplistic here, but they're where you need to log what's happening. First, forget that StringTokenizer and it's loop. What if you're wrong about the count? Use a simple String[] and then check the count. To maintain the style, you can leave the intermediate values, but another scheme is to have static final int values for each column header and then use them as opposed to the temporary variables:

      String nameString = columns[0].trim();
      String dateString = columns[1].trim();
      String costString = columns[2].trim();
      String qtyString = columns[3].trim();
      // ...more of the same
 
      try {
        name = nameString;
        transDate = dateFormat.parse(dateString);
        cost = Double.valueOf(costString);
        qty = Double.valueOf(qtyString);
        // ...more of the same
      } catch (NumberFormatException nfe) {
        log.error("While parsing " + name + " got a "
            + nfe.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      } catch (ParseException pe) {
        log.error("While parsing " + name + " got a "
            + nfe.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      }

becomes:

      try {
        name = columns[NAME_COL].trim();
        transDate = dateFormat.parse(columns[DATE_COL].trim());
        cost = Double.valueOf(columns[COST_COL].trim());
        qty = Double.valueOf(columns[QTY_COL].trim());
        // ...more of the same
      } catch (NumberFormatException nfe) {
        log.error("While parsing " + name + " got a "
            + nfe.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      } catch (ParseException pe) {
        log.error("While parsing " + name + " got a "
            + nfe.getMessage());
        ++uploadCount;
        ++uploadErrors;
        continue;
      }

and what's left is as readable as the original, but uses half the variables. This is important if we're in a tight loop and getting hit with a ton of data. Garbage Collection is a killer for Java apps, and the fewer variables you can use the better.

When I put this code into the system I had an immediate hit: the data coming from the other app was leaving a column field empty when it meant to send a zero. I saw this with the NumberFormatException and it clearly labeled the row in the table where the error occurred. I looked in the multi-thousand line upload and sure enough - a blank. Given that it was meant to be a zero, I just put that into the code on the uploader so I wouldn't have to worry about other such occurrences. Easy.

So what have we learned?

Well... I've learned that it's better to have less code that does the same thing so long as it's readable and well commented. Both of these attributes were missing in the original version. Secondly, check everything - there's no reason not to, it'll save your bacon more times than you can imagine. Third, care about the code you're writing. It's a craft, after all. Be proud of it.

Something to Really Like in Java – VarArgs and Arrays

Friday, July 31st, 2009

java-logo-thumb.png

I've been so jaded about Java that the last few years I really haven't worked to keep up with all the syntactical candy that has been added. The new for loops are a great example - as are templates: things that are in other languages that reduce typing a bit but don't really add to the power of the language.

So imagine my surprise when I started digging into varArgs in Java. First, I could see how they were used by a method:

  public void printAll(Object... things) {
    for (Object thing : things) {
      System.out.println(thing + ", ");
    }
  }

that's a pretty standard take on the C/C++ varArgs, and I'll admit, it's really nice to have. Makes the signatures of a lot of classes a lot simpler. But I needed to be able to call something with varArgs based on a stack.

For example, I have a parser that calls my code with all the arguments on a stack. I need to pop off the values - LIFO order, and then call the String.format() method with the fmt and then a bunch of Object values. But how to do that?

Thankfully, the Java guys really extended the language here. I'm really glad. They made the idea of Object... synonymous with the array: Object[]. This means that I can put all the values in an Object[] and then call the method, like this:

  /**
   * Get the format and all the args and then generate the string
   */
  public void run(Stack aStack) throws ParseException
  {
    // Check if stack is null
    if (aStack == null) {
      throw new ParseException("Stack argument null");
    }
    // see if we have a reasonable number of arguments
    if (curNumberOfParameters < 1) {
      throw new ParseException("You need at least a string format for "
            + "this call.");
    }
 
    // create an array of the proper size to hold all the args
    Object[]  varArgs = new Object[curNumberOfParameters - 1];
    if (varArgs == null) {
      throw new ParseException("I was unable to create an array to hold "
            + "the arguments. Check on it.");
    }
    // get the parameter from the stack
    for (int i = (curNumberOfParameters - 2); i >= 0; --i) {
      varArgs[i] = aStack.pop();
    }
    // finally, get the string format to use with these args
    String    fmt = (String) aStack.pop();
    // now we need to do the work... it will auto-convert the array
    aStack.push(String.format(fmt, varArgs));
  }

Needless to say, this is making the method within the parser very powerful. I now have the complete printf-like formatting available to my expressions, and while my original code worked (assuming a maximum size), this is far more flexible, and a far far better solution.

So I'm going to lighten up on Java for a while. Someone is still working on it in good ways that are just syntactic sugar.

CoRD – a Cocoa Remote Resktop Client

Thursday, July 30th, 2009

CoRD.jpg

I'm currently working in a tri-OS world. Lots of developers are using Mac laptops, linux workstations and Windows workstations. Things run on all these, and we need to be able to get to one from another. We have Cisco VPN, but I use Shimo for VPN control as it's so much nicer. But one of the things I've been concerned about is the ability to use RemoteDesktop into my Windows boxes (I need to monitor/control about 11 every day) from my Mac.

Enter CoRD 0.5.0.

It's an Open Source project on Sourceforge that places a Cocoa client to the Windows RemoteDesktop API and gives me the ability to show windows displays back on my Mac. That's something really nice. I can't wait to try it out.

Adding Transactions to a Servlet-Based System

Wednesday, July 29th, 2009

WebDevel.jpg

Today I had the difficult task of trying to add in transactional integrity to a web system where the data is coming in as posts to the web server. If each post was a transaction, that wouldn't be so bad, but if I needed to have transactional integrity over multiple posts, then we get into a lot of trouble. Face it, web servers aren't noted for their state-maintenance - that's something you add on top of the web server in order to create the illusion of saved state for the user.

But in this case, we had one program feeding another. The sender wasn't passing in real markers for the beginning and end of a transaction, and that was the first thing that needed to change. We then needed to do something with this information, so I added that in. Now I had a place to handle the meat of starting and ending a transaction - but I needed to know what to put there.

The next problem I attacked was a little simpler, the market data service wasn't handling the blocks of data in a unit. Rather, as it was parsing data, it was sending it to it's cache. This would allow for inconsistent data as the instrument prices move but the greeks were in a buffer until the entire block was read. Also, the market data cache had no locking on it. So I added the locking and the buffering so that the market data was "clean" for each block.

But that still didn't solve the real problem - how to put multiple blocks in a transaction?

After thinking about all the alternatives, I came to realize that the only good way to do this is to have the sender "mark" each block of a transaction - including the BEGIN and END, so that the receiver can buffer the data by transactionID, and then release all that data and update the reports on the END. So I needed to figure out a way to get these transactionIDs.

From the UUID work I've done in the past, the IP address turned into a long was a good start. I didn't need to add in the time, as I wanted to have a transactionID per sequence, and not per transaction. So no need for the time. I did add in a simple three-digit sequence number on top of the IP address, and that should do it just fine.

Now the transactions needed to be tagged with this number. That meant modifying the payload format. Not something I was fond of doing, but it could not be helped. Did that, and decoded it on the receiver (web) side. Then I had to modify the buffering of the market data and the greeks to buffer by transactionID. I had to thread the transactionID into the code - passing it from the decoding through all the method calls all the way to the market data methods and greek cache methods. It wasn't more than three levels, but it required a ton of changes to the unit tests.

I then had the transactionID to the right places. I added that to the buffering in the market data and greeks cache, and then was ready to update the way the update events were sent. Previously, after each update of a block, the values would be recalculated. This almost guarantee problems with updates as the values would be recalculated within a "transaction". Bad. So I changed all that to only update if there was no transaction active - or at the end of a transaction.

The results are really impressive, but I want to do more testing tomorrow. It was really pretty simple once I had decided the best approach.

Hammering Away Until the Rock Breaks

Thursday, July 23rd, 2009

cubeLifeView.gif

If someone asked me what I felt was the most important thing to have to be a successful developer, I'd say it was determination. I was beating my head against these production configuration problems today and when I finally got them figured out, a new problem of a JavaScript menu bar popped up to bang at until I got it working.

In the end, the JavaScript menu bar I was looking at didn't really work as nicely as I'd have hoped. It worked, but the style was just too different from what we'd been using. So I re-organized the menus and that gave me the room I needed to make the page render nicely.

I'm pooped. There's not doubt about it. But as with all the other things I've been tackling lately, it's about not giving up. Working and working at it from different angles, from different ideas, to come up with some little crack that you can exploit to get the system to do what you want. It's just plain effort.

Digging into Noisy Data

Wednesday, July 22nd, 2009

cubeLifeView.gif

I've been digging into this problem of 'noisy' data coming out of one of the systems I've inherited here, and at first I thought it was a problem of loss of significance due to subtraction, but that turned out to be part, but not all of the problem.

Today I was digging again, trying to find out what was possibly causing this. I was looking at trade flow... and greeks being sent in... nothing seemed to explain it. I talked to the original developer of the system for a while and together we didn't some up with anything.

I left thinking that the best I was going to do was to shotgun the problem and hope I hit something that might be close enough to the problem to point out the solution.

I sat down and started to look at the code again, and then it hit me. At least I think it hit me. I have a very plausible reason in mind, but in order to know for certain, I'm going to have to reconfigure some machines and run them tomorrow.

Basically, I think we're getting into a situation where the multitude of portfolios are feeding data into a single collector for P/L calculations. The problem might be that because several of these portfolios are normalized to the same contract, we're get an increased feed rate on that normalizing contract, and that is upsetting the calculations.

My limited understanding of the messaging of data might be off. That's why I need the isolation test. If the data from my test is smooth, and the data in Test and Production is noisy, then we'll know that we have a solution to the problem. The wrinkle here is that this solution is going to mean that we need to have a lot more hardware to run these portfolios than originally thought.

We'll have to wait and see tomorrow.

Utter Shock and Amazement

Tuesday, July 21st, 2009

cubeLifeView.gif

Today has been spent primarily on getting the PRIVMSG capability working on this custom-developed chat system. Because of the nature of the system, that is not allowing private chats, it was a lot more difficult than it needed to be. While I might have done things differently in the implementation, I wasn't involved and this system is in place and there's very little interest in really looking at this critically. It's "done", it "works", let it go.

I had to work with what I had.

That included the sum total of the code. It was a combination of C#, Python and assorted scripts and was virtually undocumented. It was a mess. But as far as messes go, it was something that I could dig into and get a few hints.

My primary debugging tool was the log of the socket data coming from the IRC server. It was literally invaluable. In the end, this is the interchange I discovered I needed to use in order to get person-to-person chatting, and therefore code-to-person chatting, working.

First, my code had to issue a special command to a particular "Overlord" bot that controlled the users on the IRC server. This in and of itself was interesting. They chose not to implement the rules in the server, but rather in a Bot that existed alongside the server.

When I send the appropriate command to this bot, I need to include the nick of the user I want to talk to. The Overlord then creates a channel just for the two of us with a special prefix, and the two user's names separated by a special character. Both users then get INVITEs to this new channel.

I have to wait for the INVITE, parse the channel invitation into the two user names, see which one is me, and which one is the "other guy", and then cache this data so that when I want to chat to the particular user, I can look up the special channel for this guy, and chat there, instead.

There were a ton of wrinkles with this scheme. First, because the process is asynchronous, I have to buffer my chats to this person if I need to create this channel. That is a pain, but doable with a little thought. Once I get the INVITE, I simply see if I have any buffered messages for this guy, and if I do, then I send them in order to the (newly JOINed) channel and we're back up to date.

Another one was the reconnection scheme - I simply took the point of view that on reconnection we'll do the minimum and each operation will ensure that everything is set up for that operation. It works, but it might be doing a little more "lazy" set-up than a different approach that would cache the channels, etc.

I have to say that everyone I've talked to in this place about these technical details is amazed that it has been done this way. The simplest way would have been to log everything in the server. Period. Database or flat files, or MySQL (combination of the two) would have worked. Then add in a simple authentication method on the server and you're done. Leave private chats as-is, but log them. Done.

It wasn't done this way, and I'm not sure what's going to happen in the long run. I've got this working, and that's the most important thing.

Who’s Really Keeping an Eye on This?

Monday, July 20th, 2009

cubeLifeView.gif

I've spent the day working on getting a decent chat interface into a custom-developed chat server that a vendor wrote for us in response to the compliance regulations. I certainly am no stranger to this, having worked with MindAlign in a previous position. These are all chat systems where the logging and authentication is such that you can't spoof being someone you're not, and all conversations are logged. It makes sense for a place moving money.

Problem is, the system we're working with here (which can remain nameless) is really pretty horrible. First, there's no documentation on the protocol at all. None. Zippo. There was nothing in the code either. I could not find a thing to help me.

Thankfully, someone else had been working on this and realized that there was an XML file for the client that had what was needed. Basically, a bot would send a challenge PRIVMSG and you had to respond with the proper response PRIVMSG to this bot. If not, the bot would kick you off the server. Effective, if a little trivial. There's no server-level authorization so that's a hole, and there's no changing of these challenge/response phrases so that's not very secure either.

But after this is done, you can send messages to IRC channels without any modification of an IRC client. Pretty easy. Sending PRIVMSGs is another thing entirely, and I didn't get this solved today. Hopefully tomorrow.

But Boy! would some documentation have really helped.

There seems to have been no one at the time asking for this. I can't imagine what they were thinking.