Monday, September 24, 2007

The Shining Armor is Rusty (on Rails)

{

Derek Sivers writes about switching back to PHP from Ruby on Rails after attempting to rewrite cdbaby. Raganwald references an intersting series from Chad Fowler on "Rewrites" and why they are so difficult.

}

Saturday, September 22, 2007

Beautiful Code

{

Although it seems to be a little disagreement over the existence of beautiful code, a refactor I did today was pleasant to my eye.

Starting with:

string result;
if (parameterLessCommands.Contains(commandName))
{
    result = RunArglessCommand(user, commandName);
}
else {
    string commandArg = RetrievePairCommandArg(commandData);
    result = RunArgCommand(user, commandName, commandArg);
}
return result;

Ending with:

return
(parameterLessCommands.Contains(commandName)) ?
            RunArglessCommand(user, commandName) :
            RunArgCommand(user, commandName,
RetrievePairCommandArg(commandName));
   

I'll take it. ()?: is your friend!

}

Tuesday, September 18, 2007

Meeting Time

{

I've always wanted to work for Microsoft. My first chance was right out of college when a professor of mine passed my resume to his friend up there.  I had some embarrasing crap about how I'd always wanted to work for "the company." It was all true but I can imagine the HR person directing anything that sappy to the trash. Instantly.

But it's just as well - Steve McConnell has an interesting comment about how much time at Microsoft may be spent in meetings - for developers:

When I was at Microsoft in 1990-91 I probably spent less than 5 hours a week in meetings. In contrast, I had a former Microsoft employee tell me earlier this year that on the team he was on he was booked in meetings from 10:00-4:00 5 days a week. Lots of managers at other companies have told me that they're in meetings all day every day and get most of their "real work" done during evenings and weekends, so obviously there's a big difference between Microsoft 1990 and Microsoft 2007, and among different companies.

}

Tuesday, September 11, 2007

Pivot, UDF, FizzBuzz!

{

As I hit "publish" from my previous post on pivot tables, a thought struck me on another most excellent use for them. No, really - for the next job interview:

SELECT
    CASE
        WHEN I % 5 = 0 AND I % 3 = 0 THEN 'FizzBuzz'
        WHEN I % 3 = 0 THEN 'Fizz'
        WHEN I % 5 = 0 THEN 'Buzz'
        ELSE CONVERT(VARCHAR(2), I)
    END
FROM dbo.fnPivot(100)

}

Pivot Tables with UDFs

{

I taught a T-SQL Programming class this week and in the process looked over some old books on the subject. One in particular I've enjoyed was the Transact-SQL Cookbook from O'Reilly - I have yet to find as novel an approach to SQL, coming from the ideas of set theory rather than tutorials on querying. I'm biased too, my best friend in highschool was Slovenian and one of the authors, Aleš Špetič, hails from that fine country.

A cool idea from the very first chapter is the pivot table, a numeric range that can come in handy for many different types of operations. The book, which is probably circa Microsoft SQL Server 7, demonstrates the building of a pivot table using some hardcoded insert statements followed with a cartesian join that generates the range.

It occured to me in SQL 2000 and higher one can use a User Defined Function and get all the benefits with a little bit more flexibility. Here is a simple approach to the same concept:

CREATE FUNCTION fnPivot(@BOUND INT)
RETURNS @Pivot TABLE(I INT)
AS
BEGIN
DECLARE @I INT
SET @I = 1
WHILE @I <= @BOUND BEGIN
INSERT INTO @Pivot VALUES(@I)
SET @I = @I + 1
END
RETURN
END
GO

The approach is different but the benefits are similar. A simple one from the first chapter is building a calendar of a given range of days. I've adapted it to use the function above:

SELECT
CONVERT(CHAR(10), DATEADD(d, i, CURRENT_TIMESTAMP), 121) [date],
DATENAME(dw, DATEADD(d, i, CURRENT_TIMESTAMP)) [day]
FROM
dbo.fnPivot(7)

date day
---------- ------------------------------
2007-09-13 Thursday
2007-09-14 Friday
2007-09-15 Saturday
2007-09-16 Sunday
2007-09-17 Monday
2007-09-18 Tuesday
2007-09-19 Wednesday

}

Wednesday, September 05, 2007

Nregex Kaizen vol. I

{

Kaizen is all about small improvements that never stop coming.  With respect to Nregex, I plan to keep it moving as a project by spending small amounts of time on new features that will hopefully make it more useful.

Tonight's new feature, though it was really something I did on Saturday morning, is a bookmarklet that should make it a little easier to get into the site from elsewhere (like your favorite IDE).

A few weeks ago my boss noticed some latency issues, especially with larger documents. I've added a "manual" mode that will let you press a button or just hit your enter key to evaluate a regex, rather than it being processed as you type.  Animated gifs give a little feedback on wait time.

If you have a request for a feature, please submit it here.  If you have a handy regex you solved some problems with, please submit it too. I'm currently at work on a "library" that I hope to cover some basic regular expressions (phone, zip, ssn, and so on) with.

}

Monday, August 27, 2007

Graham, On Point

{

I was just missing the old Paul Graham, the one who would write wisdom for the type of programmer that I imagined myself to be. The most recent essay, Holding A Program In One's Head, is that treat I've been waiting for.

}

.NET 301 Redirect

{

Scott Hanselman was noting that many people who'd updated the locations of their tools on his 2007 Ultimate Developers Tools List had emailed or contacted him asking him to update his reference.

He lamented the fact that they didn't simply use HTTP 301 redirects (Moved Permanently) which tools can easily use to update referenced links.

I must confess, I was one of those people.  I just lazily made a default.asp that had one line:

Response.Redirect("http://www.nregex.com")

But 301 redirect are pretty simple whether you use .NET or lazily throw an ASP script somewhere.

'classic ASP
Response.Status="301 Moved Permanently"
Response.AddHeader "Location", "http://foo/bar.asp"

'.NET

Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://foo/bar.asp");

Source: seoconsultants.

}

Friday, August 24, 2007

NRegex

{

I embarrassed myself today (yelling at the work desk, telling everyone I'd take them to McDonalds) but with good cause: a tool I wrote some time back made it to Scott Hanselman's 2007 Ultimate Developer/Power User Tools List. The goal of the tool was simple: to do browser based evaluation of regular expressions using the .NET engine.  Prior to writing it I would frequent Rexv.org but because the engines supported there were different, I'd usually have to do some conversion to get things to the .NET world.

There are quite a few .NET Regular Expression tools: Expresso, which is my first and favorite since I've used it longest, but also tools like Roy Osherove's The Regulator. The problem with these tools, however, was that as fat clients I wasn't always easily able to use them: I work on different machines (home, work, client sites) and also assist people quite a bit away from my desk.

There are also quite a few Regular Expression tools for the web, Rexv, which I mentioned before but also RegexPal. But these tools support either javascript or alternate implementations so patterns like (?<foo>\w+) usually return some kind of error. 

The way Nregex works is pretty straight forward: I'm using YUI for the Ajax library and working with the .NET implementation of the regular expression on the server.  A simultaneous goal of mine is to get into more of YUI because I'm always building little knick-knacks in javascript and I think it's the library to beat right now.

Of course it's a fledgling: I worked on it a few nights when I could and fixed bugs here are there when I had a moment.  Please use it and give me feedback since that will be my biggest help in making it better.

One more thing: I'm trying to collect useful regular expressions. I'd like to build a good library of expressions to help users of the tool. Use the feedback form and let me know if you've got one you've found handy. Don't worry if it's not .NET specific, I'll do the translation.

}

Sunday, August 12, 2007

What Comes First?

{

Although it's an older essay (November, 2004), The IDE Divide made for some good Sunday reading. Not only is the author, Oliver Steele, engaging but his visualizations are exceptional. I'd like to think of myself as a "language maven" - that is a person who puts the emphasis on language capabilities before tools - but I know that growing up in the Microsoft world as I did, I understand how big of a difference good tools can be.

One item I don't recall seeing in the essay was how tool mavens are responsible for their own obsolesence. It makes perfect sense to focus on language first and be flexible with tools - and to have a good text editor you can rely upon. I started using Textpad first with Java and nowadays I usually don't pass a day when I don't open something with it - either for quick inspection of a file or to write something in perl or python.

I know there are other good text editors out there but it seems like having good regex support and the ability to attach shell commands to keyboard shortcuts is most important. Syntax highlighting is a nicety too although as time passes it's not really as important to me.

}

Tuesday, August 07, 2007

!Normalize

{

Some time ago Jason Kottke posted an entry for which quite a few people bashed him about unnecessary database normalization. I've thought a lot about it since it represents some of my own internal sentiments and instincts. The two things I observe on a regular basis that I find annoying are bad naming conventions within databases and unnecessary complexity because of overzealous normalization.

It's hard to have an argument discussion on the topic with people lacking experience because the penalties for bad normalization are usually paid in the long term whereas the "effeciency" of storage with normalized data seems to be an ideal to strive for when one's perspective is short.

I was therefore heartened to see some caution from Patt Heland (courtesy of Dare Obasanjo who elaborates) on the topic. It may be a good idea to have a meeting at work and discuss some of the details given... maybe not to come to some "conclusion" or "database standard" that can apply to every situation, but more to generate good discussion and ideas.

}

Wednesday, August 01, 2007

Upsert Properly

{

For the longest time, my approach to update/insert logic has been the following:

IF EXISTS(SELECT...) BEGIN
UPDATE...
END
ELSE BEGIN
INSERT...
END

So courtesy of .NET Kicks this gem was very informative which is the same logic but with a cleaner approach. Instead of selecting records first, you attempt to do an update and check afterwards if the @@rowcount is greater than zero - if not the record doesn't exist so you can move logically to an insert.

UPDATE ...

IF @@rowcount = 0 BEGIN
INSERT...
END

Nifty, very nifty.

}

Tuesday, July 31, 2007

Fast Learning, Norvigian Thinking

{

I was looking over Justice Gray's post on becoming a better developer in 6 months and noticed that he had listed Freidl's Mastering Regular Expressions as a one week reading project. I'll preface my comments by admitting I am not the quickest read - unless I'm reading something I don't particularly care about I tend to go it slow no matter what the subject matter.

However.

Not really thinking of connecting the dots I checked in on Jeff Freidl's blog and digging around saw it took him 2.5 years to complete the first edition of the book.

It strikes me as funny that there would be such a disparity in creation and consumption. Of course I may be slow - a big part of my wanting to learn Perl was the desire to have the capacity to "think" in regular expressions - but over the last few years as I've gotten better and better I find it hard to think I could compensate the little projects and tools I've written without the pain and grit of using what I read slowly.

But then again we can all rest assured that there's no rush.

}

Sunday, July 29, 2007

Remove Duplicate Lines In Python

{

I had posted about the set operator in Python with some questions. All that changed today when I wrote a little script to remove duplicate lines from a file. The set operator takes a list and automatically gets rid of duplicate items. Very useful for situations like this:


#!/usr/bin/env python

f = open("c:\\temp\\Original.txt")
f2 = open("c:\\temp\\Unique.txt", "w")
uniquelines = set(f.read().split("\n"))
f2.write("".join([line + "\n" for line in uniquelines]))
f2.close()


}

Saturday, July 21, 2007

Shuffled Arrays

{

One of my weaknesses is that I love puzzles. And once I'm puzzle solving, I usually dwell on the problem beyond its worth. I recently saw a job ad - I'll leave this post disconnected - that had a quiz associated with it. The quiz amounts, basically, to shuffling items in an array (javascript).

My first stab was intuitive, but I wonder if it's the most optimal because it relies on a lot of discarded data. In my loop generating a random order, I essentially go through an undetermined amount of times discarding results that already exist in the randomized array. Additionally the array with random numbers is just for positioning and is probably unnecessary.
Here is the code:


function BuildArray(){
// just builds a random array to work with
var testArray = new Array();
testArray.push('Test 0');
testArray.push('Test 1');
testArray.push('Test 2');
testArray.push('Test 3');
return testArray;
}

function GetShiftOrder(testObject){
// this is what sorts things out
var upperBound = testObject.length;
var newOrder = new Array();
var shuffledArray = new Array();
builder:
while(newOrder.length < upperBound){
n = parseInt(Math.random() * upperBound);
for(i=0;i<newOrder.length;i++){
if(newOrder[i] == n){
continue builder;
}
}
newOrder.push(n);
shuffledArray.push(testObject[n]);
}
alert(newOrder + '\n' + shuffledArray);
}


I was thinking about this today and it may be more effecient to make a random number of passes at the array swapping pairs of items. A shuffling cards approach may be slightly more effecient although to have meaningful swaps there would need to be a minimum number of passes - and additional complexity with making sure pairs were swapped in random pattern.

Anyway, it was interesting and I'm always curious about more elegant solutions.

}

Thursday, July 19, 2007

CodePress

{

I'm taking a serious look at CodePress. Very, very, very cool.

}

Sunday, July 15, 2007

Sieve of Eratosthenes, Python, Set Operations

{

I pretty much broke down after TechEd. I thought I'd be patient enough to wait for Ruby but because Python is most mature I have started to learn it, whitespaces or no.

The first thing I did was check out Guido van Rossum's tutorial for programmers, which was an excellent first step. I've followed that up with some random programming - a lot of fun so far.

I was wondering about the set operations in python and how that made a difference in programming since there aren't syntactical equivalents in .NET. Incidentally at the time I was reading The Man Who Loved Only Numbers and ran across a short description of the Sieve of Eratosthenes as a way of finding primes. I thought it would be a good way to check out the set operations of Python.

I wrote the following:


from System import *

def multiples(num, thresh):
multi = []
for i in range(2,thresh):
m = num * i
if(m < thresh):
multi.append(m)
else:
break
return multi

primeThresh = 5000
print DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")
nums = range(2,primeThresh)

for n in nums:
nums = set(nums) - set(multiples(n, primeThresh))

print nums

print DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")


Interesting, but slow. The way I may do something like that in C# (which also works just fine in Python) would be this, which I wrote later:


from System import *

primeThresh = 5000
print DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")
nums = range(2,primeThresh)

for n in nums:
for m in range(2,primeThresh):
try:
mult = n * m
if(mult > primeThresh):
break
nums.remove(mult)
except:
pass

print nums

print DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")


It's a lot faster than the previous approach which makes sense - doing set algebra on large sets should take a long time... but that begs the question: are those set operations dangerous (ie. so slow as to be costly).

I'm wondering what's "pythonic" and how a jedi would write this most effeciently.

}

Saturday, July 14, 2007

Being Better

{

I probably won't be officially "tagged" but a meme is going around about what one would do in the next 6 months to become better. Hanselman, in his podcast, spoke of a few things and the responses seem to be going up around the blogs.

How will I be better? Most of the things people mentioned are things I already try to do: reading technical books, working on my software, looking at open source, training others... but one thing I want to do is to start posting code.

I write a lot of code and much of it doesn't make it here because I'm sheepish about looking foolish. But getting better is about having courage to show my work because without that, how could it get any better?

I'm going to start with my JAPH, a program that prints "Just Another Perl Hacker." It's meant to be novel and I actually like mine since it leverages some language features that don't exist in my mainstay, C#. The map operation can visit each item on an array performing some opertion - in this case I'm using a regular expression on each item and grabbing alternating characters! I haven't been writing perl for a long time so hopefully over time I can claim a better one but at least this is my own thinking at play, destined for improvement. I did post it on usenet (a first version which had some foolish mistakes) but this is after a little bit of massage:

#!/usr/bin/perl -w
# David's JAPH, volume 0.1
map(print(/(\w)\w/g," "),
qw(Jaubsctd Aenfogthhiejrk Plemrmln Hoapcqkresrt));


The original JAPHs, from Randall Schwartz, were not really about obfuscation but more about language features. The use of map, regular expressions, and $_ in the above are what make it interesting to me.

}

JLam on DNR

{

I never mind a long drive with a podcast. A few days ago I listened to John Lam on Dot Net Rocks. I'll admit that sometimes the DNR people can be annoying to me (think Richard Campbell saying over and over like it's a joke "Managed JavaScript??") but it was all worth it to hear some of the internal goings on with the Iron Ruby project.

Gleaning: Iron Ruby is a ways off. I got somewhat impatient and have been using IronPython in the meantime, but more on that later. That's not a small decision for me because I am of the Norvig perspective on learning a new language - it takes the length of time needed to think in terms of the idioms of that language, as opposed to just writing your code with different syntax and keywords (ala writing C# in Ruby).

Gleaning: Ruby is a powerful language for creating domain specific languages. That meme has been floating in my head for a while - listened to a good Software Engineering Radio podcast on the topic sometime back.

Gleaning: JLam talks a bit about how the learning curve for new languages these days revolves around the frameworks for languages - I think the idea of Ruby combined with .NET is that the .NET libraries will fill a gap that Ruby has always missed in library support. Dangerous or brilliant? In other words, I'm sure the open source crowd (is/will be) up in arms because this will, in their minds, dilute the community effort behind a language. Brilliant because the Mort you know (who is probably your boss) will have a better level of confidence about using it.

Gleaning: Iron Ruby is implemented in C# but Managed Javascript for Silverlight is a VB.NET implementation!

}

Monday, July 02, 2007

True Story: The Cat Ate My Source

{

A security issue prompted my ISP to change passwords for all users. Normally, this wouldn't be a problem - I'd go to my repository of code, divided at present by year in a "Code05," "Code06," "Code07" format and update a constant in my Constants class and *presto* the connectivity would be back.

Problem is, what if I have to go back more than 3 years?

I'm usually not that irresponsible. In fact, I'm fiendish about backing things up. Yes, I use source control, even on my own little-bitty projects that matter to no one but me. But my mistake was using an external drive - a flakey one - which died after I'd had to reformat/reinstall. I'd backed everything up to it, and my data was gone.

Edge case since I'd after the reinstall I'd moved what was important back to the machine. Edge case because it was in a "code archive" that was something like 6 years old - code that was so long forgotten it was like a head bludgeon when I got a phone call from the client saying that their site was down.

After panicking and looking for some accidental backup (why do we look for things when we know they're gone for good?) I had an epiphany.

I downloaded the *.aspx pages and the site dll - I then used Reflector to disassemble and - I kid you not - 15 minutes later the client was up and running.

And yes, I kept the source...

}