Saturday, December 15, 2007

I am a five-year-old ass-kicking machine

Through digg, I found this amusing site... You complete a shorty survey and it indicates how many five year olds you could take in a fight.

I'm proud to say that I could take 32 of the little jerks in a fight.


32

Check out your score over at their website. (Oh, but make sure you edit the HTML they give you before you post it somewhere, they include a link to a payday advance website. boo).

Thursday, September 27, 2007

Integration strategies

We use perforce at work. Although people talk a lot of smack about perforce, I actually find it to be generally quite acceptable at what it does.

However, I've been hitting some snags as of late. Ultimately, the issue comes down to branching, and how to keep multiple trees in sync for a particular set of tools.

Although the perforce website has a lot of white papers on various subjects, I haven't really found anything there that describes what I'm looking for. Even the white paper on branching describes exactly what I don't want. What I really want is a way to say: "Hey, even though I need to have this file replicated to these 17 different locations, they're really the same file. And if someone changes one of them, I want you to think of that as changing all of them."

Unfortunately, this is functionality that perforce adamently denies has any place in the real world. Well, here I am, maintaining around 17 trees, and I'm telling you that this functionality would probably remove about three hours a day from my work day.

The usual way we deal with this is to relocate the relevant tools outside of the branched codebase, and then point everything at the new location. Unfortunately, this is a manual, time consuming process. It sucks, and I don't like repeating work again and again (which is pretty much what I'm doing now).

So the question I put out there is: does anyone have a better way than these two methods? To sum up, here they were:
  • Code lives in an area that's branched, and changes need to be propogated everywhere to keep everything in sync.
  • Code lives in an area that isn't branched, but this is usually a hindsight realization so it requires manual updates of all related tools to pick the tool up from the new location.
Oh, and as an added complication, what do you do when 99% of the code is independent of the release branch, but the last little bit depends on code in a branch? What then?

Wednesday, September 26, 2007

Where are the books for experienced programmers?

Recently, I've been reading books on how to develop websites using "Web 2.0" techniques (basically AJAX). What I've noticed about these books--and even other coding books in my library--is that there is a serious lack of books for the experienced, well-disciplined programmer.

I honestly find it a little insulting that every book on C++ feels the need to re-explain to me APIE (Abstraction, Polymorphism, Inheritance, Encapsulation). As does every Java book. As does every Python book. Even books that claim to cater to the experienced or advanced programmer always recover these topics.

Of course, I've heard of projects like Rosetta Code, but that's not really what I'm looking for either. For one thing, there are only 87 examples, not even covering topics I'm really interested in. (An example of a topic I'd like to see is, "How to remove items from a collection based on a predicate?") Yes, it's wiki. Yes, I could go write the article myself. No thanks.

I guess what I really want to find are books that tell you the right way to perform tasks in a certain language, or why you would prefer one method over another. For example, in which situations should I prefer to use a vector instead of a map? (I'll give you a hint, even in key-value situations there are reasons to sometimes prefer a vector to a map).

For example, let's say I'm writing a new piece of C++ code. Should I use the stl? Almost always. Is there a good logging subsystem out there that I could use to avoid rewriting a new one? Are there any libraries I should avoid? Boost.

I don't need to relearn why I should write objects or what should go into an object. Tell me how to define an object, how to use inheritance, how abstraction is implemented. Give me actual, realistic costs of making design tradeoffs. For example, how much will it cost me to call a virtual function? Is there a way I can mitigate this inside of a single class, if I really know what the type of the class is?

I'm sure, one of these days, someone will get it. Till then, I'll just continue to suffer in silence.

Thread-safe printing in Python

Recently, a coworker was having issues printing from multiple threads in his python program.

After a little googling, I came upon this discussion which covered this exact topic.

At the lowest level, python appears to be threadsafe wrt a single file handle, which is good. Unfortunately, when you use the print statement, an implicit '\n' is added for you, and this apparently results in a second low-level write call, which is a seperate mutex grab.

As a result, you often get lines of text that look like this:


This text comes from Thread 1.This text comes from Thread2.
< Empty Line >
This text comes from Thread 1.This text comes from Thread2.
< Empty Line >


In this situation, you basically have two choices. You could replace your print statements with a custom written print function that grabs a mutex and adds a trailing '\n', or you could use the logging module. Even though the threadsafe print module is very short, I'd still suggest that the 'right thing' to do here is to just use the logging module.

When you decide in the future that you want to log to a tcp connection on another server, your future self will pat yourself on the back that you just used logging up front.

Cheers,

Tuesday, September 25, 2007

Olivier could be a Visual Studio Installer Model

One of my fellow nvidians, Olivier, writes in his blog Mutable Conclusions. Prominently on his website, he features a picture of himself. I've included a copy here:

Olivier, in the flesh.

I've teased him about this mercilessly, but I think his picture would've been a perfect include in the Microsoft Visual Studio installer. Judge for yourself.

(Thanks, diditwith: http://diditwith.net/default,date,2007-03-15.aspx)

Monday, September 24, 2007

I'm a comic!

A friend of mine is a (yet undiscovered) great artist. She does phenomenal 2-D work, and keeps up a daily sketch site. I only recently discovered her site, but I was excited to see that I'd been rendered as a comic.

I feel the representation is fairly accurate.

Sunday, July 15, 2007

Python: Enforcing Interface Requirements

I write a moderate amount of Python code for work. Not necessarily as much as I'd like, but that's a topic for another post.

A short while back, one of my coworkers asked this question at lunch: "If I'm writing an interface that I want other people to be able to use with their own new types, how do I ensure that I write my code in such a way that they can clearly and easily understand the interface that they need to implement? As an additional problem, how do I ensure that I don't accidentally break my interface requirements?"

Now, if you've written much python code at all, you're probably familiar with the term 'duck typing', which basically exerts that "if it quacks like a duck and walks like a duck, it might as well be a duck." This is probably one of python's greatest strengths as it reduces the syntactic complexity of 'templated' code; by default all functions work with all types that match the implicit interface that is their implementation.

The unfortunate side effect of duck-typing is that in order to see the exact interface that you would need to implement for an API to work with, you'd have to pore through the entire codebase of the API (!!). Clearly, that wouldn't work at all. After a bit of discussion, we came up with the following solution:
  • API Interfaces should begin by asserting that the arguments passed in match a specified, required Interface. This takes care of the first half of the problem, because a developer needs only to look just inside the function to determine which Interface class needs to be implemented (or derived from, if the developer so chooses).
  • The objects passed in should be limited (for the duration of the function) to only expose the explicit members that the interface allows for. This solves the second half of the problem, because it makes it impossible to peek under the covers other than what the Interface allows for.
After some discussion (and mail on the topic), we came up with the following implementation:
class __frozen_iface (object):
def __init__ (self, ifspec, instance):
for member in inspect.getmembers(ifspec):
if member[0].startswith ("__"):
continue

if not inspect.ismethod (member[1]):
continue

instance_attr = getattr (instance, member[0])
if instance_attr.im_func == member[1].im_func:
raise AttributeError, "Class '%s' has interface class implementation of attribute '%s'" % (instance.__class__, member[0])

# bypass our internal __setattr__ since that will raise an exception
object.__setattr__ (self, attr_name, instance_attr)

def __setattr__ (self, name, value):
# prevent anyone from accidentally assigning new attributes
raise AttributeError, "Attempt to set an attribute '%s' for frozen interface class '%s'" % (name, self)

def UseInterface(ifspec, instance):
return __frozen_iface (ifspec, instance)
Then, client code would do something like this:
class Renderable(object):
def Draw(self, context):
abstract # Raises an execption if we get here.

def RenderObject(someRenderable):
someRenderable = UseInterface(Renderable, someRenderable)
dir(someRenderable) # Outputs only 'Draw'
This could also be trivially wrapped into a decorator so your code could look like this:

class Renderable(object):
    @Interface(Context)
def Draw(self, context):
abstract # Raises an execption if we get here.

PS: Thanks to JimR for the cool implementation of __frozen_iface.

Friday, May 4, 2007

Structured Cleanup: Avoiding gotos

I think everyone in our profession has to write code, at some point, that grabs multiple resources, then do something.

And unconditionally, that code needs to make sure to back out any resource acquisitions in cases of intermediate failure, and only back out the resources that are actually grabbed.

Normally, you see this kind of code for that purpose:


int doStuff(void) {
char* a = (char*) malloc(100);
if (!a) goto failure_a;

char* b = (char*) malloc(100);
if (!b) goto failure_b;

// do some stuff

// Want to keep a and b around.
return 0;

// Future proofing, for when we add c.
free(b);
failure_b:
free(a);
failure_a:
return -1;
}


I have two problems with this code:
  1. Updating this code requires updating both the allocation semantics and the 'free' semantics.
  2. This doesn't lend itself towards any sort of 'pattern' which we can reuse for other things, like grabbing a mutex, semaphore, etc.
Instead of the above code, I propose that we use a system of Rollback objects. I haven't seen these in Design Patterns, but maybe they'll make their way into the next release of the book. :)


template <typename T>
class RollbackAllocator
{
RollbackAllocator(int countToAlloc) : mAllocated(0) { mAllocated = new T[countToAlloc]; }
~
RollbackAllocator() { if (mAllocated) delete [] mAllocated; }

// For easy-to-read client code, no one should take ownership of allocated
// objects until there are no further failure conditions possible. This same
// technique can be used for
// ANY resource acquisition, whether it's an allocation of memory,
// grabbing a socket, mutex, semaphore, reading a file, etc.
T* TakeOwnership() { T* retVal = mAllocated; mAllocated = 0; return retVal; }

T* mAllocated;
}

int doStuff(void)
{
// If any fails, it'll throw an exception and the others will be cleaned up.
RollbackAllocator<char> aAlloc(100);
RollbackAllocator<char> bAlloc(100);

// do additional things that could fail.

a = aAlloc.TakeOwnership();
b = bAlloc.TakeOwnership();

return 0;
}



The beauty of this code is its simplicity. By taking advantage of the guarantee that destructors will always be called upon exiting scope*, we ensure that a and b will always either be dealt with properly, or will be freed. Furthermore, while we do have to update the function in two places when we add a new resource acquisition, we do not have to worry about what order we TakeOwnership! Additionally, this pattern lends itself towards all sorts of resource acquisitions, whether they are mutex grabs, file reads, allocations as we've done above, etc. We can make this pattern fit virtually any resource acquisition pattern, and ensure that we have consistent, future-proof, goto-free code.

Don't get me wrong, gotos have their place. Just not in structured cleanup code.


* C++ doesn't always guarantee that destructors will be called. Any abnormal program termination, including explicit calls to exit, abort, terminate, pure virtual calls, exceptions thrown from exceptions (or destructors), or infinite loops will prevent destructors from being called.

Wednesday, April 25, 2007

I don't normally do this...

... journaling (I refuse to call this blogging) is not something I normally do.

Anyways, my actual website, Lexical-Ambiguity is perpetually down because I'm too busy with other things to actually spend time making it work.

Here, the three of you that read this will probably find the following categories of information:

  • Code related topics
  • Exercise, fitness and weight-lifting information
  • Stuff about gaming
  • Stuff about books
That's pretty much all I've got right now. Maybe this will become more natural soon-ish. Don't color me hopeful, though.

Monday, August 28, 2006

Oh my God!! Are you serious?!

On Saturday, Jim and I attempted to summit Handies.

We got up at 6:30 am, and finished prepping for our trip: filling our Camel Backs and eating a light breakfast of cereal. We commented on how neither of us had slept well. In addition to the fact that we both were really excited about attempting to climb our first fourteener of the trip, a large cold front moved into the area around 3:00 am, bringing lots of rain with it.

We left the house just after 7:00 in the Tahoe, and headed towards American Basin and Handies. As we came into view of Lake San Cristobal, we saw a sight that neither of us were prepared for: snow atop all of the mountains in the distance. I was concerned that the snow might prevent us from even reaching the trailhead, let alone summiting.

We drove on, shocked at how much snow had fallen, and arrived at the trailhead around 9:00. There wasn’t any snow in the basin itself, but all of the mountains surrounding the basin were totally covered. Shortly after we geared up for our hike, another vehicle arrived. We spoke with the driver for a few minutes, and he was also planning on hiking Handies. I joked with him that he would pass us in a few minutes, and he laughed but said he certainly wouldn’t. He said he was from Denver and the extra 5000′ of elevation was hard on him.

We started our hike up at 9:15, and signed into the log book about 10 minutes later. Five minutes later, a thunderstorm–complete with sleet–blew into the basin from the southwest. The storm totally snuck up on us, and we had just about decided to go back down and wait it out in the car when it cleared off. Jim and I discussed giving up for the day so I could go back and get more equipment (gloves, rain pants and my waterproof boots), but we decided to push on.

About 30 minutes later, we came to a fork in the trail. Unfortunately, neither of us had remembered to bring a map, so we were at a loss as to which way to go. Jim decided to go on up and scout ahead, and I said I’d wait for “Denver” to catch up with us, as he appeared to know what was going on. After “Denver” caught up with us, we decided to all hike together. We introduced ourselves, and “Denver” became Joe. We learned that Joe was an experienced 14er, and we were glad for the company. (At the time, he had summited 28 fourteeners, with plans to do seven more during the week).

The next two hours were largely uneventful, except that Jim and Joe were able to keep better pace than myself. I’m not the most physically fit person on earth to begin with, but being 10-14,000′ higher than my normal stomping grounds was hard on me. Plus the fact that my shoes were totally waterlogged and provided little traction on the 2-4″ of snow we were encountering made for a trip where I was roughly 1/2 a rest behind Jim and Joe.

About 200′ (vertical) from the summit, it got very interesting. We heard thunder coming in over the same southwestern portion of the basin. Only this time, instead of being surrounded by cliffs, we were one ridge from the summit. We discussed for a minute or two whether we should turn around and go back or whether we should press on to the summit. I wanted to go back, but said nothing because I really, really wanted to finish up Handies. Jim and Joe clearly also had summit fever and we decided that with 10 minutes of effort we could be at the summit. We would stick around at the summit for a minute or two, rest, and then head back down as quickly as possible.

Jim and Joe started heading up, when we heard another thunderclap, even closer than the last. Joe turned and began to run towards us, indicating that it was time to go. He asked us quickly if we knew what to do for lighting. For those of you who don’t, (I’d be with you), I’ll reiterate what he said:

  • If you feel a tingling, static charge feeling, that means that the ground around you is charged for a lightning strike.
  • Assume the lightning strike position. The position is crouched on the balls of your feet, your heels together, your hands over your ears and your eyes closed. You want to form a ball balancing on your feet.
  • Direct strikes are generally fatal.
  • Lightning travels along the ground. An indirect strike can cause your heart to stop, but usually (70%) you can be revived with CPR.
  • When caught in a thunderstorm, members of the party should keep at least 100′ between each other. The reason is that if one person is struck, the other members of the party can revive them.
Jim and I were, needless to say, terrified. Joe took out his hiking poles and began to run down the mountain. Not down the trail, the way we had come up, but straight down the mountain. After a single switchback, I realized that Joe was getting down the mountain significantly faster than I was, and I decided to take off straight after him.

I fell several times, and my hands began to get tingly. Remembering his warning, I yelled an expletive and tucked into the crouch position. I threw the metal walking stick I was using as far as I could away from me (horizontally, so I could recover it later). From behind me I heard Jim yell “Oh my God!! Are you serious?” I yelled back that I was and waited for the worst.

It never came. Thirty seconds later I realized that the tingling I was feeling in my hands was the result of their being wet and cold–from falling in the snow–not static buildup. I ran over and grabbed my walking stick and again began running down the mountain. The storm intensified, sending sleet nearly horizontally at our faces, and dark, frightening clouds up the basin towards us. I can safely say that I’ve never run for my life before… This was a first for me.

Twenty-nine minutes after we had began our descent we all caught up with one another. We had managed to drop 1000′ (vertical) in less than half an hour–the ascent up the same distance had taken us nearly three hours. By this time, the storm had almost entirely abated.

Although we weren’t technically out of the woods, we all felt much safer as there were now many more advantageous lightning targets than ourselves. We had a reasonably comfortable walk the rest of the way down the trail, back to the register and to the car.

Back at the car, we met up with some other folks who had been chased off of Redcloud due to the first thunderstorm (that had nearly sent Jim and I back home). We spoke with them for a few minutes and traded numbers with Joe, offering to buy him a meal if he called us when he came to Lake City in the next week.

I learned a few important things on this trip:
  1. Thunderstorms while hiking at altitude are not something to mess around with.
  2. The best path down might not be the path taken up, especially in cases of emergency.
  3. Having a map with you is key at all times.
  4. There are more important things than summitting. (Like living to summit another day).

Although we didn’t make it to the summit, I felt we made the right decision in turning around. My only regret is that we didn’t turn around and start back sooner.