Last time, I wrote some about learning a scripting language. Right now, I just use a compiled language for everything, and that strikes me as an inefficient way of doing quick jobs, like sysadmin tasks. Would a scripting language make that any easier? The only way to figure it out, I determined, was with a test, much like George Costanza's candy line-up on Seinfeld. Find a representative quick and dirty task, and then try it in a scripting language versus a compiled language. Whichever language's version was the easiest to write would then get to ride shotgun in my development rocket car. Well, the test is complete, but I'm having a hard time coming to any conclusions.
The task I selected was building a connection string. It seemed like a good choice; it's something that must be done frequently, and it's usually a minor inconvenience. I found a good Python example of this in Chapter 2 of Dive Into Python. Stripping it down a little bit, it comes out to 6 lines. Most of the code is pretty simple, but one line is awfully involved. Anyway, once I located that example, I decided I'd try to rewrite that in C# and see how many lines it took. The line count? *Drumroll please* 59 lines (code available if you're interested).
Now, about those 59 lines. Some of those are automatically generated by the compiler. Furthermore, some of those are OOP-related, which isn't very useful in this instance but it's a constaint imposed upon me by the language. Even taking those into consideration along with my undying love for whitespace, there's way more C# code than Python code for this example.
However, even though there's more code with C#, it's a lot easier to follow. For instance, I mentioned that the Python code contained one complicated line. That line:
return ";".join(["%s=%s" % (k, v) for k, v in params.items()])
In contrast, the C# code for that functionality is:
So, I present the big question: when doing tasks like these, it readability of code or writability of code more important? For regular code to which you often refer, readability definitely takes priority, or else maintenance becomes hell on earth. That's one reason why, I think, most major projects aren't written in scripting languages. For stuff like this though, just simple admin tasks that I prefer to automate, I don't really have to worry about maintenance. It's something I spend an hour on one afternoon, then maybe revisit 15 months later. There's really nothing to gain by combing through code and aiming for elegance; the point is to get it working and get it out there.
With that in mind, I declare scripting languages to be the winner here, meaning I need to actually start using something like Python for tasks like these. I don't particularly like that. If I had my druthers, I'd write everything in LOGO and Alf would be the #1 show on TV. Unfortunately, the real world is unwilling to go along with me on those. Tasks vary, and there's not language that fits them all perfectly. As developers, we have to be willing to be flexible with which tools we use. With our TV shows, that's another matter entirely.
Different tools for different jobs: this idea makes sense to me. Just like I would be slightly terrified if my car mechanic wanted to work on my fuel injectors with only a sledgehammer, the folks at Microsoft would feel similarly if I proposed we redo Windows XP entirely in LOGO. While I understand this idea, I don't implement it very often; this is largely because I'm an idiot. At least once a month I'll be facing a quick and dirty sysadmin task, and rather than coding something simple in a lightweight scripting language, I pick C#. In retrospect, this is kind of like buying a Ferrari to haul manure around town. (This is not to say that Microsoft products are Ferraris and sys admins are professional poo-handlers.) For these messy jobs, I need a dump truck that can handle pretty much anything without complaining. I need a good scripting language.
Looking at it now, my refusal to use scripting languages is a self-fulfilling prophecy. Since I hardly use something like Perl or Python, I'm not too comfortable with it. Thus, when the time comes to write a script, I'm much more likely to fall back on something I use often, like C# or Java. The next time one of these situations arises, I'm even rustier with the scripting language, so I'm less likely still to use it then. You see where my relationship with my scripting language is headed. Eventually, I get to the point where one of my coworkers mentions Python, and I run out into the parking lot with a machete, looking for a reptile to kill. No one wants to see that.
You may ask what the big deal is, why I'd want to add another language if I'm getting my work done as-is. Well, it seems to me that for some easy tasks, higher-level languages can introduce too much complexity. If I'm just writing a simple app to parse a text file, why should I have to put everything in a class? If I'm just parsing a text file, why should have to recompile if I want to make one little change? Why do I need to write so much code to do something so simple? As part of my relentless drive to do as little actual work as possible, I think I owe it to myself to see what my alternatives are.
So, where do I start? Well, before I get a tattoo of the Perl camel on my forehead, it seems to me that I need to verify my hypothesis that scripting languages are better for certain tasks. If I were wrong, not only would I then have the tattoo, but I'd be incredibly surly about it. People would come up to me on the street and ask about it, and I'd sputter out, "It was a mistake! And if I ever find the guy who wrote Perl, I'll karate chop him in the head until he's speaking in tongues!"
What I need then is to find a trivial task, write it in a scripting language, and then write it in a high-level language. The one that's the simplest to write will be the language best suited for these chores. I will stage, in other words, a programming version of Mad Max Beyond Thunderdome. Two languages enter, one language leaves! Much to everyone's dismay, I will not do all of this while dressed as Tina Turner. Check back next time for my exciting results.
One thing I often wonder about is code duplication. How many functions are floating around out there that determine if a string is a valid date? What about the number of functions that have been written to determine the last day of a month? I'm no professional counter, but I'd bet those functions have been written at least infinity billion times by the world's programmers. I conservatively estimate that I've contributed half of these. That's because every time I write something, I find it much easier to just rewrite those functions than to go searching through old code to see how I did it previously. Like a lot of the work I'm responsible for, I attribute this entirely to my own laziness and idiocy.
Clearly, that's a waste of time. If I devote 15 minutes each week to duplicating something that I've already written, that works out to be 13 hours worth of naps and tickle fights each year I'm missing out on. I've got to tell you, seeing that figure really steams my broccoli; nothing gets me more riled up than missing an opportunity for a tickle fight. There's got to be a way to avoid this code duplication. How do you do it, though?
Well, one idea would be to put all of your helper functions out on the web somewhere. Then, when you find yourself needing that particular bit of functionality, you could go to your favorite search engine, plug in a few terms, and locate what you've already done. There are some big flaws to this, though. First, you'd have to publish all your code to the web; that'd be hard to remember, plus your boss probably wouldn't like it. Second, you'd have to be able to locate the code once it's out there; it may take a few searches to get there. There's promise to this idea, but I will give it no higher than a bronze medal.
An alternative idea would be to create some sort of application to library your code. If you stick to some coding standards, you could have the library agent parse your code and automatically insert it into the library. Then when you need something, you query the library and see what's in there. This is more appealing in that the code doesn't have to be public anymore, plus there are no manual processes to remember. However, writing such an application could take a lot more time than you waste each year with duplicated code. Unfortunately, as cool as this idea is, it's a little too thorough. If you had a super-intelligent robot manslave, it'd definitely be the way to go, though.
What about putting all of these helper functions into a big class file that's included on all of your projects? Whenever you need a common function, you could just glance at that class to see if it's already in there. This would certainly be a lot quicker than writing a library application, but the downside is that you have to include that library file with everything you write. If it's a quick and dirty job, the library could be several times the size of the new code. That's not a very efficient use of resources, plus it's very unlikely that the programming groupies will flock to you if your Hello World! apps are 150MB. If you're not coding to impress the programming groupies, then I just don't think I have anything to say to you.
The best idea, I think, is to store all of this in a wiki. In just a few minutes, you can have a wiki installed and some categories set up to handle all of this. Also, the wiki could be private/public, depending on what you want. If you didn't want to remember to insert each function that you write, you could write something like the library agent that I mentioned earlier. It's easy to get going, and once you get it going, there's a lot you can do. In that respect, it's a lot like buying a deep fryer.
It's hard to tell whether this would save any time in the long run. Maybe it wouldn't, but at the very least, it'd keep me from wanting to bang my head on the keyboard when I discover I'm in need of a function that validates dates. Also, it's bound to win you a few points with the programming groupies.
I discovered something interesting today. Let's say you write a small app in C# or VB.NET to run in the background and perform some really important system service. Since it's important (maybe it polls the security cams to make sure no killer robots are on the premises), you want to know if this service ever goes down. Your idea is that this app will grab the administrator's email from a database, and then send her an email before it closes.
I spent a little bit of time today implementing something similar; being a total fancy lad when it comes to object-oriented programming, I figured I would just put the code in the destructor for my object. That way, when the app began to destroy my object as the application closed, the appropriate code would run. My idea was that it'd look something like this:
string from = "Polling Agent Application";
string subject = "I'm going down";
string message = "Sweet bearded Zeus, the end is near! Restart me ASAP!";
//then call a method to send this email. It's always a good idea
//to have one of these methods in your app, since users like email
//and it's a pain to rewrite.
this.SendEmail(from, adminEmail, subject, message);
}
Okay, so I planted that in my destructor and then tried it out, only to discover that the app made a mess in its pants whenever I tried to exit. Specifically, I got a "Handle is not initialized" exception, referring to the db method I call in the destructor. What's the dealio here? The code is sound; I played around for a bit and saw I could use that method in any other part of the program aside from the destructor and it'd work fine. Something is fishy here, and it ain't the tuna helper.
Well, a bit of research (and a really informative usenet post by David Browne) revealed that utilizing a SqlConnection in your destructor cannot work. This is because the final garbage collection tends to destroy objects in an indeterminate order, so your destructor may try to access an object that's already been destroyed. If you try to access a SqlConnection then, you may end up trying to use something that's being utilized by another thread entirely. That, as the Spaniards say, es muy mal. Rather than checking the state of all of these complicated objects, the CLR just limits what you can access in the destructor.
So, how can we do this? Well, what I ended up doing was making my adminEmail string a member of the class, and setting it to the proper value in my constructor. I could access that with no problems at all in destructor.
In conclusion, .NET's destructor presents a few hurdles to the developer; there's a lot of potential for functionality there, you just have to be very specific in the way you code. (I'd be interested in knowing whether Java is the same way, maybe I'll follow up on that a little later.) Luckily, the only type of pants we wear here on the vlog are our smarty pants.
On quite a few different sites lately, I've seen an ad for dice.com, which must be a tech jobs site or something. Anyway, the ad is in source code, which is a nice touch. Well, it would be a nice touch if it were well written. Let's take a look at the code.
It's a cool idea for an ad, but if it's going to pass muster with the raging dorks of the Internet, there needs to be some more attention to detail. The target audience here spends all day obsessing over minor details like that, so I think the only way to win us over is with a similar mania for correctness. Either that, or through gratuitous nudity; they're both highly effective choices.
Anyway, it just goes to show that the lesson applies to marketing just like it applies to coding: compile before checking in your changes. Even if it's a made-up language for a website ad, you can bet that some unfortunate soul with WAYYY too much time on his hands (see: Cody Powell) will eventually go looking for errors.
One of the classes I'm taking is a class on numerical methods of computing. Apparently, there's some pretty complicated numerical stuff going on inside of computers. This was surprising to me, as I figured my computer ran on jellybeans. Come on, where else are all the jellybeans going?
Anyway, the main application we're using for our labs/homework is MATLAB. I'd used Maple in previous math classes, but never MATLAB, so I was pretty jazzed to learn a little bit about it. Well, the first time our professor pulled up the application, something struck me. That something was a ceiling tile, and it hurt. At the same time, I realized that MATLAB looks very familiar. In fact, it looks like ... Python.
Por ejemplo, let's say you want to create an array and see how large it is.
In Python, it'd look like this:
In Matlab, it'd look like this:
A very simple example, but you get the point: the notation is kinda similar. Howevever, I didn't really know anything about Python's mathematical capabilities. After a cursory search, I didn't see any matrix functionality in the base or math libraries. When I got home from work that day, I decided to do a little research. Had the Python community created any libraries to make the language more Matlab-like? What about add-ons for matrices and graphing? Well, as I often do when I'm curious about something, I brought this question to the Oracle of Google, and the Oracle never fails to satisfy.
I found a few different items of interest. First, there's a library called NumPy, which has been around for a long time and offers all of the standard matrix functionality (it looks like it has since branched off into numarray). (I also found an older interface between NumPy and the Matlab engine: PyMat, which has very cool potential.) Second, there looks to be a nice library for Matlib-style plotting called Matplotlib. Third, and perhaps most impressive, is SciPy, a library of scientific tools for Python. From my cursory overview, it looks to be the most mature of the Matlab-like options for Python. Also, it looks like it is maintained here in Austin! Woo woo, 512 in the hay-ouse!
I had no idea that Python had such burgeoning scientific support. One of the issues I noticed thus far with Matlab is that it's not very programmatic in nature. For instance, if you're going to save a function to a file, it has to be named FunctionName.m. That's why I find all of these discoveries to be so exciting: combining the numerical capabilities of Matlab with the programmability and community of Python is a win-win. Not only that, but it's free!
To me, this is a great example of what can happen if a tool is extensible and open to the public. As a result of doing this, you may not be able to strut around town in a diamond-encrusted tuxedo, but you can successfully capture the minds of nerds around the world. To all of the programmers who made this functionality possible: thank you. To my professor: I have now found a whole new way to screw up my homework.
A question for the C# UI developers (a stunningly handsome bunch, from my experience): have you ever tried to display a sequence of dialog forms? Maybe you have a series of back and forward buttons that the user can cycle through. It makes sense to display some things in such a manner, but it's really hard to code the sequence straight, particularly if the user can cancel during the middle. It's not quite as hard as tracking and killing the Sasquatch, but probably around hthe difficulty of karate chopping a car in half.
Anyway, here's a good method I came up with, relying heavily on collections of forms. It's important to set the DialogResult of each button correctly: Forward is DialogResult.OK, Back is DialogResult.Retry, and Cancel is DialogResult.Cancel.
//next, populate the arraylist with the proper order.
frmOne myFormOne = new frmOne();
frmTwo myFormTwo = new frmTwo();
forms.Add(myFormOne);
forms.Add(myFormTwo);
//show the first form.
ShowChildForm(0);
}
private void ShowChildForm(int ithForm)
{
//actually show the form.
DialogResult temp = ((Form)forms[ithForm]).ShowDialog();
//then parse the result from the form.
ParseNavigation(temp, (Form)forms[ithForm]);
}
private void ParseNavigation(DialogResult temp, System.Windows.Forms.Form referrer)
{
//we've abstracted the form navigation so that there are only
//three base actions: cancel, ok, and cancel.
switch(temp)
{
case(DialogResult.Cancel):
CancelFound(); //delete your records or whatever.
break;
case(DialogResult.OK): //OK means move on to the next.
PerformNavigation(referrer, true);
break;
case(DialogResult.Retry): //Retry means Go Back.
PerformNavigation(referrer, false);
break;
}
}
private void PerformNavigation(System.Windows.Forms.Form referrer, bool moveForward)
{
int moveSpots;
//loop through our arraylist of forms
for (int i = 0; i < forms.Count; i++)
{
Type formType = forms[i].GetType();
Type referrerType = referrer.GetType();
//if the referrer matches the form we're looking at,
//let's go to work.
if (formType == referrerType)
{
if (moveForward)
moveSpots = 1;
else
moveSpots = -1;
ShowChildForm(i+moveSpots);
}
}
}
Well, as anyone who visits The Onion or SI.com could tell you, bizarro usability is alive and well. For the unaware, bizarro usability is my idiotic term for when a company makes the deliberate decision to move away from usability. Both SI and the Onion now break most of their longer articles into multiple pages, since more pages means more advertising. It's slightly annoying, especially if you, like me, built your own mouse from pine cones and mud, and experience great difficulties in following links. Nevertheless, it's not too bad. Not only that, but the decision is justifiable, since profitability usually carries more weight than usability. So, if it's not too annoying and the decision is justifiable, why are my panties in a wad? Do I just have permanently wadded panties? I'll leave the second question for your own personal speculation.
Bizarro usability is okay when it's motivated by profit, but it's never good, I think. Bizzaro usability annoys your users, and your users are where you get your revenue. Do you think then that it's sustainable in the long-run to annoy these people? Imagine owning an X Box game that shoots a little bit of tomato sauce on your carpet every time you play it. It's not that big a deal, but do you think you'd play that game several times a day? Well, if your carpet is made of spaghetti, then yes; otherwise, probably not. If you really, really wanted to play it, you'd grit your teeth and start it up anyway, but there's never a situation where you're happy to see that tomato sauce coming at you.
As a user, I can say that if I'm continuously annoyed by one site, I'll quickly find a similar site that doesn't annoy me. I'm rational like that, and I think most people are the same. Does SI really think they possess the only site where I can read which athlete was arrested for possession of panda tranquilizers? Continue to annoy me and we'll see how quickly I can add athletes-and-panda-tranqs.com to my list of bookmarks.
Bizarro usability like this forces me to think about going to the site. Before, when I visited the Onion, I would think, "Show me some funny!" Now I think, "Crap, it's time to do some clicking." Is that really what these sites want me to be thinking? In the short run, I'll put up with these minor annoyances. Give me a few weeks of it, and I will eventually get fed up and go elsewhere. As more people go away, these sites have to add more ads to make up for the lost money. Eventually, it's just one guy going to the site, and the site makers pay to have a billboard installed in his bedroom. Not a good situation.
I think then that this kind of bizarro usability can only be a short-term situation. It's just not sustainable for very long. You can't make it permanent policy to annoy your users from now on, because there's bound to be a less annoying alternative out there. You know, maybe one that shoots lemon juice onto the carpet instead of tomato sauce.