2008
Yearly Archive
Teaching23 Dec 2008 09:38 am
On Learning to Build or Buy
I recently had the opportunity to sit on a panel that was reviewing proposals by IS majors at Fairfield University. Teams of three or four students were tasked with evaluating three options for creating a registration system for a conference to be held on campus next summer. An open source conference registration system was considered, along with a hosted option and an open source CMS.
All students rejected the idea of an open source CMS, correctly expecting that customization would not be feasible within the time constraints. Interestingly though, nearly half of the students felt the open source conference registration system would be less costly than the hosted option. I found this latter alliance interesting because the costs involved with open source aren’t obvious to those without experience developing with open source software.
Even the most polished open source packages often require unexpected efforts. Whether WordPress or MySQL, something I want to do inevitably leads to hours of Google searches. Hours become days when a user (or developer) is less experienced. These startup costs have to be factored into any decision that involves build with open source.
I’ve been using Spring.NET since before .NET 2.0. I built a medium-sized web site for a group using Spring’s Web framework. The early costs came as I was trying to learn from message boards. The documentation was, at the time, very sparse (it has sense become top-notch). Adoption was limited, so Google searching wasn’t helpful either.
A later point of stress came as Microsoft released .NET 2.0. That horrifying decision to eliminate Web projects in Visual Studio brought some new magic that broke Spring’s Web data binding. Specifically, the server controls were no longer declared in the code behind. Spring used attributes on control declarations to facilitate bidirectional data binding. To make Spring compatible with the new style of ASP.NET webs, Spring Web dropped the declarative binding for programmatic binding. This switch made for a painful upgrade path for this project. Dozens of attributes had to be removed and recoded.
The tendency of open source bits to change frequently and unexpectedly is something I’ve learned to live with. ASP.NET MVC has changed for the better from preview to beta. But the changes have been worthwhile. The Castle stack changed plenty over its RC2 to RC3 period. Even Python recently changed its most basic bits – print “Hello, World!” to print(“Hello, World!”) in version 3.0. Each time, these upgrade costs hurt a little.
Students who assume that open source is free and therefore cheaper than a hosted solution are erring from lack of experience. That open source conference registration system would probably require support from install to the end of the conference. The hosted solution had a nominal charge and numerous features. The trade off, as always, is lack of control.
It’s certainly not the case that all hosted or paid options are better than open source alternatives. The open source conference registration system may have been the better option, with the right skills available. My experience has taught me to assume all first projects with an open source package will add at least 20% to the development effort. This ramp up time may be more or less, but is almost always there.
It was great to see many of my former (and other) students digging into this problem. Learning how to evaluate build versus buy options is an incredibly valuable lesson for college seniors and juniors to have.
iPhone12 Dec 2008 10:37 am
On Getting Things Done
I started using David Allen’s Getting Things Done system about two years ago. Like many GTD devotees, my adoption has been piecemeal. At it’s simplest, GTD is a clever way to organize life’s projects into the most minute of next actions. A project such as “Learn Italian” might have a next action “Order Rosetta Stone software.” That next action might have a context (where it’s done) “shopping.”
I’ve tried a few different ways of implementing GTD in my life. A Hanselminutes podcast turned me onto Moleskines. For a time, I used to carry one of these handy little notebooks around everywhere I went. But not surprisingly, a notebook is hard to keep organized. Such a system also works best when wearing cargo pants…
I gave the GTD Tiddly Wiki a try. I found it to be an effective tool, but it lacked portability (no mobile access). I’ve recently started using Monkey GTD for organizing work projects. I’m growing fond of it. But it’s still doesn’t have the mobility I want for managing my non-work life.
For about a year, I used an online service called Vitalist. This site, until recently, was by far my favorite way to implement GTD. Vitalist has a nice, uncluttered interface. It’s quick and responsive (typical AJAX-y site). It has a nice feature that allows reminders (at custom times) to be sent via SMS or email. There’s a sharing feature to allow some basic collaboration.
I grew more attached to Vitalist when I got my Motorola Q. Vitalist has a pretty usable mobile site. Mobile Vitalist got me back to the portability I enjoyed with the Moleskine, but was much easier to keep organized. After I got my iPhone, I continued to use Vitalist. But there was something about having an iPhone and having to use a web app built for any mobile phone that juts didn’t feel right.
A couple of months ago a coworker introduced me to Things, by Cultured Code. Things is a desktop app for Mac OSX and for the iPhone. This app is brilliant. It’s simple and intuitive. It has an incredibly feature complete GTD implementation. The mobile app seamlessly syncs with the desktop app over your wireless network. Things nailed navigation. It’s amazingly simple to add a next action, whether to the Inbox, to a project or any other GTD standard location. Actions may be given a due date, starred or tagged or just left in the inbox for later processing. Things got it right.
Since installing Things, I’ve realized there are certain types of software that simply don’t work as well on the Web. Task management and calendaring are two such apps. Even with a bookmark to Vitalist’s mobile site on my iPhone’s homescreen, there was a lack of immediacy to allow it to be truly effective. Having to load Safari, occasionally login and then navigate the site was too cumbersome. Reviewing and adding next actions needs to be fast and extremely convenient.
I use Things most often while on the train commuting to and from work. Having the iPhone client allows me to manage my actions even when under Grand Central and without access to a data network. The badge option (turned off by default) allows Things to show a little red circle on the app’s icon. The circle contains the number of items due for the day. I find this is a much better reminder tool than email. Vitalist’s reminders started to add to my email noise and I started to ignore them. The badge greets me whenever I look at my phone’s homescreen.
Things has already made me more productive. Vitalist had a similar effect early on as well. But the sheer number of next actions I’ve already pushed through Things is more impressive to me. And of course, while writing this post, I added a next-action to put it online when I am off the train…
C# & Python & IronPython & JavaScript06 Dec 2008 12:33 pm
On Inequality in JavaScript
It’s easy to code through life without giving much thought to operator precedence. Of course we wax parenthetical from time to time, remembering my dear aunt sally. But for the most part, we can typically rely on the compiler to keep us safe from all sorts of logical missteps. For example, consider the following snippet:
“rose” == “rose” == “rose”
In C#, this simply doesn’t compute. The compiler asserts that it cannot apply the == operator to operands of type bool and string Fair enough. The first equality operation produces a bool and that bool is compared to a string. But Python’s (and therefore IronPython’s) egalitarian nature allows it to produce a True value from this statement. Each operand is as important as the other. After all a rose, is a rose, is a rose…
JavaScript sits somewhere in the middle. And that’s why I’m writing this post… I had a logical error in a script I had written and it was caused by my failure to recognize JavaScript’s operator precedence. JavaScript acts like C# in that it first evaluates a bool for the two most left operands. But it then allows the comparison to the string (it is not a statically typed language after all). So the above code returns false in JavaScript.
Minor details often cause the most headaches. This is one such example. As we increasingly become language switch-hitters, it’s that much more important to pay attention to the details.
Uncategorized09 Nov 2008 10:41 pm
On a Boo Object Validation DSL
employment & LongTailVideo29 Oct 2008 01:58 pm
On Hiring at LongTail Video
LongTail Video (where I work) is hiring. If you have a solid, diverse set of programming skills, click below:
http://newyork.craigslist.org/mnh/eng/898219236.html
ALT.NET types are especially welcome…
Tri-state (NY, NJ, CT) applicants only please.
Apple & AT&T & iPhone03 Sep 2008 08:43 pm
On the Unpolished Apple
This post might be a little of topic for this blog, which typically deals with matters of interest to software developers. But since we’re geeks who love our Internet to be everywhere we are, I’ll go down this consumer-ish path…
In the month or so since I left Verizon for an iPhone, I’ve been very patient. I’ve endured dropped calls and a mostly fleeting 3G experience. Why have I been so patient? It’s one hell of a phone. It’s such a great device that it’s easy to forgive the shortcomings of AT&T’s network. But at some point the constant struggle to find service with AT&T makes the iPhone lose some of its shine. As I write this, I’m staring at the iPhone’s email app and it refuses to send or to receive. I’m told by the phone that I’m connected to the 3G network.
When at work or home, I use WiFi connections and everything is brilliant. But out in the wild, getting a good connection is a crap shoot. Looking only at voice service, Verizon simply destroys AT&T in coverage. There were virtually no dead zones on Verizon’s network (I live in the southwest corner of Connecticut) when they were my carrier. Even in some remote locations where one would expect not to have a signal, Verizon came through. That’s definitely not the case for AT&T, which has vast stretches of dead zones that can last for miles. More bars, but where?
The situation with data is much worse. That the iPhone reports having a connection to AT&T’s 3G network is not sufficient proof that one will enjoy high speed Internet. I frequently have problems connecting. To receive or send emails, I often have to restart the phone (maybe that points to a problem with the iPhone’s software?). On my daily train travels in and out of Manhattan, I pass through suburbs of Connecticut and New York. It’s rare that I get a good stretch of network availability – and when I do it’s often the Edge network, not the 3G network. In and around the City, I have few complaints.
The iPhone crushes the Motorola Q (my old phone with Verizon) in terms of usability and overall user experience. I still think the Q is the best Windows Mobile device I’ve seen, but again it’s no iPhone. When it’s working , the Web on Safari is untouchable (no pun intended). I’ve played with the new touch devices that Verizon offers. The iPhone still kills. But again, we’re talking about when it works. As of this moment (a few days after I originally started this post) I haven’t been able to connect to AT&T’s data network for several hours due to a major outage affecting AT&T’s customers in the Northeast.
This past weekend, I also made the mistake of signing up for Apple’s MobileMe, lured by the promise of a push life. After several wasted hours with online tech support, I still don’t receive my MobileMe emails unless I manually fetch them. Scheduled fetch doesn’t work either. Contacts and calendar do thankfully sync over the air. The problems with MobileMe and the constant battles to connect to AT&T’s network are making me lose faith in Apple.
My original plan for this post was an optimistic rant on how I had totally given myself over to Apple. I recently purchased a MacBook Pro. It’s a beautiful machine, with brilliant features. The screen is the best I’ve used (go matte not glossy). The keyboard lighting is both entertaining and functional. I had even started to use Safari on my Windows machines.
But my planned transition to Mac is on hold. They had me at hello, but lost me on 3G. This iPhone purchase has turned out to be one of the most frustrating tech purchases in recent memory. Surely a company that prides itself on itself on its innovation and ease of use could do better. It’s simply not enough to be “not Vista.”
Bottom line, if you’re thinking of buying an iPhone anytime soon - don’t. You may not be disappointed if you will primarily be a WiFi user, but then why not just buy an iPod Touch? Maybe in 6 months to a year, the iPhone will be on a capable network, but for now it’s just not worth the headache.
CodeVoyeur & Boo26 Jun 2008 12:00 am
On A Boo DSL for Transforming Objects to RSS
My recent experiences with Ruby’s Rake have me interested in non-XML DSL usage. Boo seems to be emerging as the language of choice for building a DSL in .NET (IronRuby will surely follow suit). My most recent Code Voyeur article is my first attempt at building a non-XML based DSL.
A Boo DSL for Transforming Objects to RSS
It is admittedly not pretty at times…
NAnt & CruiseControl.NET12 Jun 2008 12:34 am
On NAnt Really Being a Neat Tool
I realize it’s not popular to champion anything XML these days, but I have to admit I’ve recently become a fan of NAnt. I understand the criticisms. I won’t argue that
<fileset id="assemblies">
<include name="**/*.dll" />
</fileset>
is better than
assemblies = FileList['*.dll']
I freely acknowledge that a DSL-based build system like Rake is far more expressive and extensible than an angle-bracket system like NAnt.
Writing blocks of C# in XML is strange.
<script language="C#" prefix="util" >
<code>
<![CDATA[
[Function("concat")]
public static string Concat(params object[] args) {
return String.Concat(args);
}
]]>
</code>
</script>
Calling these C# blocks in XML is even stranger.
<echo message="${util::concat('foo', 'bar')}" />
Over the past couple of weeks, I’ve started replacing a CruiseControl.rb/Rake continuous integration solution with one that uses CruiseControl.NET and NAnt. The reason for the switch is a combination of scalability (20+ ruby.exe instances really have a negative impact on a box) and adoption (try to get a team of MS types to learn Ruby in their free time).
CC.NET makes it really easy to checkout a project from Subversion and to run MSBuild against a solution. So there’s really no reason for using NAnt for project compilation, but rather packaging and deployment. NAnt has tasks (just XML blocks) for all sorts of file operations ranging from copying to zipping. NAnt will read and write XML. NAnt can run executables or be extended with custom tasks. NAnt supports includes for reuse and targets for modular task execution. Simply put, NAnt does good things with those less-thans and greater thans. While you may have heard that MSBuild has made NAnt unnecessary, I have to disagree. Your builds don’t have to stop at compilation.
Being a fan of Boo, I’m eventually going to have to see how far along the Boo Build System is. But those build file extensions would not be easy to introduce into a corporate environment…
Here’s a great post that served as a starting point for my CC.NET/MSBuild/NUnit/NAnt solution.
Hosting02 Jun 2008 09:41 pm
On Shared Hosting - Part IV
I host dllhell.net at WebFaction. They’re a shared Linux host that I use for this blog and my non-ASP.NET experiments. I moved this blog there after my well documented troubles with this site when hosted at Ultima Hosts.
On Saturday, I noticed the site was down. It stayed that way for about 48 hours. Normally I’d be pretty livid, but… So when a transformer explodes and takes out three walls in the data center, I’m a little more forgiving. Also, they were and always have been transparent about their outages. I like that in a host. Ultima covered its tracks after its last major outage. I don’t like that in a host.
As for WebHost4Life… These guys are still pretty solid. I check my sites several times throughout the day to make sure things are running. I’ve yet to catch a single second of downtime. With Ultima, I could find downtime weekly or worse.
Castle & MySQL27 May 2008 10:59 pm
On ActiveRecord and MySQL Full-Text Search
I tend to agree with those who believe that a good ORM will give you 90% of what you need. For me, with NHibernate and ActiveRecord it’s been closer to 95%. The remaining 5% tends to involve getting a DbConnection instance and executing some legacy stored procedure or something of that nature. For this post, I’ll describe a recent scenario that fell into that lesser bucket…
I recently decided to add full-text search to Jeopardy Story. I’d previously used full-text search for my articles on Code Voyeur (wow, two shameless plugs in one paragraph). Code Voyeur uses Spring.NET and SQL Server for data access. So a simple DAO implementation worked seamlessly. Jeopardy Story by contrast is built on Castle ActiveRecord and MySQL, which makes Full-text search a little more challenging.
First, MySQL supports full-text search only in tables using the MyISAM storage engine. MyISAM is really fast, but doesn’t support referential integrity or transactions. My full-text search was to be against a table that needed both. I chose not to give up InnoDB and its features. Instead, created a table to mirror the content of the transactional table, minus the columns not needed for the search. The MyISAM table is populated through a scheduled task. Admittedly, this is less preferable than a real time solution (triggers, etc.), but it works well enough and has minimal overhead. Also, triggers require SUPER privileges with MySQL. That privilege isn’t going to be handed out (hopefully) on a shared host… I did read on some forum that this requirement will change with the next release though.
The next challenge I had was trying to write the HQL query to execute the full-text search. Long story short - NHibernate (more accurately its SQL dialect providers) doesn’t support full-text search. After struggling with the HQL for a while, I finally looked at the Castle support forum and somewhere found a post informing me that full-text isn’t supported in the dialects (NHibernate uses SQL dialect providers to ensure the generated SQL is compliant with the target database). The only practical option I had was to use AR to get a DbConnection instance and run the SQL using plain-old-ADO. Something like:
ISession session = ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(YourType));
string sql = @”SELECT your_columns_here
FROM your_table
WHERE MATCH(columns_in_your_index) AGAINST (?searchText)”;
IDbCommand cmd = session.Connection.CreateCommand();
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new MySqlParameter(”searchText”, text));
IDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
doYourStuffHere();
}
cmd.Dispose();
cmd.Connection.Dispose();
session.Dispose();
My actual query returns an ids from the copy table that I then use to get the actual ActiveRecord class instances through standard AR calls (e.g. FindAll). It’s a two step query I’d rather perform in one, but I’ve yet to work through an alternate solution. Should I find one, I’ll of course post it or reference it here…
Also, it’s a good idea to take a look at MySQL’s stop word list. Your unit tests might appear to fail when all that really happened is that you just chose the wrong word for a search…
Finally, it’s worth noting that MyISAM issues aside, it’s really easy to create a full-text index with MySQL - especially when compared with SQL Server. OK, SQL Server full-text isn’t all that difficult to setup. But with the MySQL GUI tools, it was click -> Add Index -> select type full text index -> drag and drop columns for the index. Done.
Next Page »