Duplicity and the Duplo Generation

Matt Aimonetti, author of the Rails on the Run blog, recently posted a controversial article in which he asserted this belief that new Rails developers are being sabotaged by the multitude of pre-written and reliable components available to them:

The problem is that a generation of Rubyists has grown up being used to getting everything pre written for them. They haven’t yet passed the “Duplo stage” and basically write applications putting a few blocks together, only writing 10 to 20% and barely understand 5%. 

Unfortunately, Matt is wrong - and not only that, but he’s being elitist.

Fractal Wrongness

 OK, so maybe he’s not that wrong. But he’s definitely not correct. This line of thinking is harmful to the Rails community at large, and much more so than any clueless newbie could be. Though this argument, Matt is separating the community into two sides: on one hand, those like DHH, Jamis Buck, and Michael Koziarski, who know Rails inside and out (and not just how to build Rails applications, but the inner workings of Rails), build Rails components, and have a fundamental grasp on the advantages and disadvantages posed by the Web, and on the other the Typical Newbie, who mashes pre-assembled parts into a hideous, insecure conglomerate of which he has only the most superficial understanding.

This is not true. There are many people - I count myself among them - that use components not because we’re too lazy or stupid to understand how they work, but because we’re focused on creating things that nobody else has yet. Reinventing the wheel is immensely frustrating, boring, and a waste of time; Rails components allow us to avoid reinvention and focus on what matters, and to condemn this mindset simply because not all developers have the time or energy to understand every tool they’re using is absurdly foolish.

My Common Sense

Fundamentally, Matt is also hurting himself with this statement, as in condemning the low end of Rails development he’s furthering the stereotype that Rails developers are either cretins or douchebags. Jeff Atwood put it a little too bluntly when he stated (somewhat in jest) when he stated the following:

when you’re using Rails and OS X, you’re using the platform of choice for douchebags. 

But frankly, attacking newbies who are attracted to Rails by the promise of never having to write Yet Another Damn Authentication System is going to make you seem like a douchebag. And sure, there is a problem with newbies who refuse to understand that programming is not merely a matter of snapping components together. But that isn’t a problem specific to Rails; it’s everywhere, in server-side, desktop, and enterprise software, in Python, C++, and Ruby, on OS X, Windows and Linux. To blame an entire community for allowing this to happen is ludicrous and ultimately harmful.

Don’t think. 

Addendum: Matt published an extension of his ideas in this post, in which he clarifies certain aspects of his ideas. Go! Read it! 

2 comments March 21, 2008

Death to the Singleton

Even those like myself who haven’t had the occasion to work through Design Patterns should no doubt be familiar with the Singleton Pattern. Though it’s one of the most used software patterns, especially in API’s like the JDK and Cocoa, it’s also attracted its fair share of flak for a myriad array of reasons, chief among them being that they’re simply a global variable with a nice name.

Now, it’s none of my business how you implement your classes, and I’m a member of the school of thought that global variables (especially in scripting languages) are often necessary. What really frosts me about singleton classes is their verbosity. Take, for example, this snippet of Nu code:

(if (((NSFileManager defaultManager) fileExistsAtPath: somePath))
    ((NSFileManager defaultManager) copyItemAtPath:otherPath toPath:somePath error:nil)
    (else
        ((NSFileManager defaultManager) createDirectoryAtPath: somePath)))`

This is, needless to say, ugly and repetitive. One could create a temporary variable to hold the NSFileManager, but that would not be a remedy for the verbosity associated with singleton classes like this - it’s merely a stopgap measure, and adds more code that you have to read. What I’d really like to do is this:

(if ((NSFileManager fileExistsAtPath: somePath))
    (NSFileManager copyItemAtPath:otherPath toPath:somePath error:nil)
    (else
        (NSFileManager createDirectoryAtPath: somePath)))

that is, have every instance method on the default NSFileManager become a class method. Were I totally brain-dead, I would declare an extension to NSFileManager and create a class method for every instance method that I wanted to represent. Luckily, I’m not - there is a better way, and it involves the oh-so-magical handleUnknownMessage: withContext: message that every Nu object has.

(Incidentally, this trick requires the most recent revision of Nu from the git repository. Previously the handleUnknownMessage: withContext: message only worked with instances of classes, not class objects themselves - but one line of Objective-C fixed that!)

By declaring handleUnknownMessage: withContext: as a class method on NSFileManager, we can tell the NSFileManager class to forward any messages it can to the shared instance of NSFileManager. Here’s the code that allows one to do that:

(class NSFileManager
    (+ (id) handleUnknownMessage:(id)cdr withContext:(id)ctx
        ((NSFileManager defaultManager) sendMessage: cdr withContext: ctx)))

Beautiful. Now every unknown message sent to NSFileManager will be forwarded to (NSFileManager sharedInstance); this can be implemented with any other singleton class that you please. It’s dynamic behaviors like this that make Nu such a pleasure to work with (and Java so painful - I once wrote an equivalent of Ruby’s method_missing in Java. It was not pretty).

Add comment January 17, 2008

Announcing Nuki 0.1 (VoodooPad, watch out!)

Dear interwebs,

Today I finished the first release of a simple, database-backed and web-accessible Wiki software written entirely in Nu and making use of the NuHTTP and NuMarkdown libraries. I call it Nuki (pronounced ‘nookie’), and I wrote it to teach myself how to integrate Core Data and NuHTTP in a simple application.You can check it out from Subversion here. Read on to see what I learned whilst writing this application. 

(more…)

2 comments January 6, 2008

NSDate Weirdness (and Nu!)

Now that Nu is released to the public in all its glory, I’ve been doing a lot of coding exercises in it. As is my wont, I wrote a program that prints out the current Discordian date, and in the midst of looking at the NSDate and NSCalendarDate documentation, I found this fascinating class method on NSDate:

+ dateWithNaturalLanguageString:(NSString *)string:

Creates and returns an NSDate object set to the date and time specified by a given string.

Parameters
string
A string that contains a colloquial specification of a date, such as “last Tuesday at dinner,” “3pm December 31, 2001,” “12/31/01,” or “31/12/01.”

Return Value
A new NSDate object set to the current date and time specified by string.

Discussion
This method supports only a limited set of colloquial phrases, primarily in English. It may give unexpected results, and its use is strongly discouraged.

This piqued my interest in a big way; it reminded me of the way Lotus Agenda could recognize date input such as “next Thursday” and “eight days from now”, as detailed in the fantastic book Dreaming in Code. I couldn’t just leave it alone, so I whipped up a little Nu script for you. Run it and it will present unto you a prompt, at which point I invite you to enter such phrases as:

  • next Tuesday
  • September 22, 1988
  • 3 hours from now

You will see that those phrases - and a multitude of others - are parsed correctly as NSDates, leaving you free to actually work on other things rather than futz around with NSScanners. Give it a try! And look at Nu as well!


(global readline (NuBridgedFunction functionWithName: “readline” signature: “**”))
(puts “Press Ctrl-C to quit.”)
(while 1
(set input (readline “>>> “))
(set date (NSDate dateWithNaturalLanguageString: input))
(if date
(puts (date description))
(else
(puts “Your input of ‘#{input}’ could not be parsed. Try again!”))))

Add comment December 27, 2007

15 Programming Exercises

Being what could be charitably described as a programming language junkie, over the past few years I’ve amassed a number of programming exercises aimed towards establishing fluency with a new language; some of these are barely beyond Hello World or FizzBuzz, while some can get quite tricky. Mackenzie Morgan expressed interest in improving her Python-fu; after listing half-a-dozen of these ideas, I said “Hey, maybe this would make a good blog post.” As such, I present to you a list of programming challenges. Many of these have been culled from various sources on the Internet, and I have endeavoured to provide credit where due.

  1. In general, each language treats collections differently - some (Nu and Smalltalk) start indexing from 1, whereas most start indexing from 0; Ruby returns nil when one tries to access an element outside of an array index, whereas most others throw some sort of an exception; each language has its own set of ideals that it deems best. Your challenge is to take your favorite language and turn this paradigm on its head - if you use a relaxed, permissive language such as Ruby, write a NeuroticArray class that panics at the slightest opportunity; if you use a stricter language such as Java or Haskell, write a RelaxedArray structure that throws as few errors as possible. Bonus points will be awarded if the public interface to your new collection is nearly identical to that of the original type.
  2. Write a text munger, as detailed in this Ruby Quiz link. The most obvious solution to this problem is to remove the head and tail characters of each word, shuffle the remaining letters, and replace the head and tail characters; as such, this teaches character manipulation, sequence shuffling, and string concatenation.
  3. Implement a collection-backed regular expression matcher, as detailed in this Ruby Quiz. This teaches about object-orientation (strictly speaking, OOP is not necessary for this exercise), regular expressions, and increases awareness of the limitations of languages (Ruby’s built-in limit on regular expression length inspired this quiz).
  4. Write a simple script that obfuscates English text by adding any possible accent or umlaut to each letter in a sentence. This teaches the basics of regular expressions and associative arrays.
  5. Write a high-level input library, as detailed in this Ruby quiz. Not only does it teach how to write a good API, but it also forces you to consider the various needs of the people who use your API’s. Can you satisfy everybody, or will you be forever mediocre?
  6. Write a tool to turn Hacker Keys into English-readable strings. This is an excellent situation in which to learn about the power (and limitations) of regular expressions, and also shows programmers about the dangers of constantly-changing specifications. Bonus points will be awarded if your solution reads in the hacker key specification from configuration files; even more will be awarded if you write a tool that parses user input into a hacker key dump.
  7. Write a parser for HQ9+ or HQ9++. These exceedingly simple esoteric languages are very useful for learning the basics of regular expression usage, and implementing an REPL is always challenging and interesting.
  8. Build your own Scheme interpreter. Scheme’s syntax is extremely minimal, as such, with a good parsing toolkit - please, if you value your sanity, do not try to write a parser using nothing but regular expressions - writing a Scheme interpreter is far, far easier than you’d think. The fantastic Haskell tutorial Write Yourself a Scheme in 48 Hours is an excellent introduction to a language that is, at times, terrifying. (In a conversation with my mom about the ambitious scope of this particular exercise as applied to Haskell, I said “Imagine, Mom, if immediately after learning how to say ‘Hello’ in Japanese, the second assignment was to write a Russian-Japanese dictionary.”)
  9. Write an ID3v1 tag parser, as detailed in this Ruby Quiz. The ID3v1 format is extremely simple, and a parser can be written easily and understandably in even a very low-level language. This will teach about file input and output, and also present the difficulties associated with programs that deal robustly with malformed input.
  10. Write a graphical frontend to a system tool such as fortune. In lightweight scripting languages this task will be much easier than with heavy-duty languages such as Objective-C or Java; however, no matter what langauge you choose this will teach you about construction of a simple GUI and how to interface with the operating system. Bonus points will be awarded if you write a cross-platform tool that invokes the correct tool for a particular task no matter its operating systme - e.g. a tool that invokes the tracert tool on Windows and the traceroute command on *nix.
  11. Most programming languages have support for more than one GUI toolkit; write a program that compares the widget support for as many different toolkits as possible. Not only will this illustrate the sheer magnitude of the difference between a good and a bad API, but programming a GUI correctly provides a very visceral satisfaction. The difficulties of building a project that links into multiple heavy-duty libraries may play a part in this project, depending on the language used. You could also contrast GUI builders with writing the widget-placement code manually in this project.
  12. Finish the Ruby Quiz (yes, I do realize that half of these ideas are links to the Ruby Quiz, now will you shut up?) metakoans.rb exercise. If you can’t finish it - I sure couldn’t, on my first try at least - look at the solutions that other people submitted and try to understand them. If you’re feeling brave, implement the quiz and the solution in your language of choice. If you’re feeling like a goddamn hero, solve the continuation koans.
  13. While programming in any language, one will build up an often-used set of useful functions and modifications; clean up, comment, and publish these extensions. You never know who might find them useful!
  14. Take a simple program you’ve written - for example, one that prints out the lyrics to the 12 Days of Christmas - and remove all familiar concepts from it. If you’re working in C, don’t use a for loop. If you’re using an imperative language, recurse rather than iterate. If you’re using a language with mutable state, program in a purely functional style.
  15. Solve all the Project Euler problems that you can - and make sure that you pick the right algorithm for the job. There is a world of difference between what you learn when you write a brute-force solution that takes the whole night to run and a complicated but effective solution that takes 10 seconds to run.

Have any more ideas? Did I leave out your pet exercise? Leave a comment.

4 comments November 11, 2007

Programming Limericks

GOTO Considered Harmful

GOTO makes your code like spaghetti
Please don’t throw it around like confetti
A conditional clause
Has far fewer flaws
So just structure your program, already.

Good Agile, Bad Agile

It’s hip to use Agile scrums
To prepare for change (when it comes)
But, frankly, it seems
To be harmful to teams
Excepting my Googler chums.

What’s Nu?

We fused Cocoa’s power with Scheme
To produce a language supreme
Of glorious beauty
That kicks Ruby’s booty
And makes Python look powered by steam.

2 comments November 4, 2007

Compensating for the Suckage of OS X Terminals

Every terminal in OS X that I’ve tried (Terminal.app, iTerm, Terminator) refuses to send a myriad array of valid keystroke combos over SSH. This wouldn’t be a problem except for the fact that I use Emacs, the Uber-Editor.One of these unsupported keystrokes is Control-Meta+any key (for those not fluent in Emacs, Meta is Alt); considering that this is one of the key commands in Emacs, the only alternative - pressing Escape to activate the Meta key, then entering the desired key command - is very inefficient and tends to interrupt the flow of typing. 
Until I can figure out the proper incantation to get Emacs to recognize a key as pressing Control-Meta, this shortcut will help with the inefficiency: 
(global-set-key "\C-c\C-v" 'ESC-prefix)
If anyone on the Lazyweb has any suggestions on how to fix this problem, please leave a comment. 

4 comments September 12, 2007

“Haskell Curry? Yes, I dated his daughter.”

Last week I had the opportunity to talk with Alonzo Church, Jr. (he prefers to be called “Al”), son of the Alonzo Church (you know, the one who only invented the freaking lambda calculus). We had a lovely conversation; we talked about Alan Turing, Fortran, COBOL, the future of computer science, and all sorts of other interesting topics. The highlight of our conversation, though, was this:

Me: “So, I’m learning a new-ish programming language named Haskell right now. It’s very strange.”

Al: “Did you say Pascal?”

Me: “No, Haskell. It’s named after a logicial named Haskell Curry –”

Al: “Oh, Professor Curry! Yes, I knew him! My father worked with him!”

Me: “No way! That’s awesome!”

Al: “Yes! In fact, I dated his daughter!”

Me: “You DOG!”

11 comments August 21, 2007

How Tim Burks and Nu Stole the Show at C4[1]

Edit: Fixed some factual inaccuracies about the language itself.

Tim Burks, noted contributor to RubyCocoa and creator of RubyObjC, gave a talk at C4[1] about his experiences with creating a Ruby <-> ObjectiveC bridge, and the problems he overcame in doing so. It was an interesting presentation, and we were all suitably appreciative when he showed his custom visual chip-design software written in Ruby with a Cocoa interface.

And then he dropped a bombshell.

For the past year, Tim’s been working on a new dialect of Lisp - written in Objective-C - called Nu. Here are its features (more precisely, here are the ones that I remember; I was so awestruck that many went over my head):

  • Interpreted, running on top of Objective-C.
  • Scheme-y syntax. Everything is an s-expression (data is code, code is data). Variable assignment was done without let-clauses (which are a pain in the ass) - all one has to do was (set varname value).
  • Variable sigils to indicate variable scope.
  • True object-orientation - everything is an object.
  • True closures with the do-statement - which, incidentally, is how Ruby should have done it.
  • Macros. HOLY CRAP, MACROS! When Tim showed us an example of using define-macro for syntactical abstraction, Wolf Rentzsch and I started spontaneously applauding. His example even contained an example of absolutely beautiful exception handling that should be familiar to anyone with any ObjC or Ruby experience.
  • Symbol generation (__) to make macros hygenic and prevent variable name conflicts.
  • Nu data objects are Cocoa classes - the strings are NSStrings, the arrays NSArrays, etc.
  • Ability to create new Obj-C classes from inside Nu.
  • Interfaces with Cocoa libraries - you can access Core Data stores from within Nu in a much easier fashion than pure ObjC, thanks to Tim’s very clever idea of using a $session global to store the NSManagedObjectModel, NSManagedObjectContext, and NSPersistentStoreCoordinator.
  • Ruby-style string interpolation with #{}.
  • Regular expressions.
  • Positively drool-inducing metaprogramming, including a simulation of Ruby’s method_missing functionality.
  • A web-based templating system similar to ERb in 80 lines of Nu code - compare that with the 422 lines of code in erb.rb.

Tim showed us a MarsEdit-like blog editor written entirely in Nu, using Core Data as its backend - and then showed us the built-in Nu web server inside that program, complete with beautiful CSS/HTML/Ajax.

As F-Script is to Smalltalk, so Nu is to Lisp. Tim said that he hopes someday to open-source Nu; if he does, he will introduce what is quite possibly the most exciting development in the Lisp-related community in a long time. I don’t think I speak for just myself when I say I cannot wait to get my hands on it.

3 comments August 12, 2007

rlist: A Python container class modeled on Ruby Arrays

Edit: Thanks to Carl for helping me fix my flatten() method. I are gud coder. In my never-ceasing quest to Rubify Python (don’t worry, Pythoneers, I often try to Pythonize Ruby), I offer this latest gift up to the Interwebs: relaxed.py.What does it do? Read the documentation:Offers a relaxed, Ruby-esque version of a list, much like the Python defaultdict object. Features include:

  • Accessing non-existent elements returns None instead of an error
  • Setting elements out of the array’s range appends None as needed
  • Strict and non-strict flattening algorithms* first(), last(), join()
  • Minty fresh breath


Thanks to: http://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks for flatten().
Implementation notes:
Instead of extending the built-in list type, I wrote a simple object that wraps an encapsulated list. Why?Check the Python documentation: 
http://docs.python.org/ref/sequence-types.html
for loops expect that an IndexError will be raised for illegal indexes to allow proper detection of the end of the sequence.
Since the point of this was to have a container that raised as few errors as possible, I chose to have an object serving as a frontend for the list thatintercepted invalid indexes. I know that it isn’t pretty, but it’s the best I could do.  You can check it out from http://tools.assembla.com/svn/importantshock/, or look at the code here.Please let me know in the comments if anything needs sprucing up (if anyone actually uses this, I’d be thrilled!) 

4 comments July 20, 2007

Previous Posts


About Me



I'm a college freshman, passionate about technology, programming (especially Cocoa and Python), and Apple.

By the way, 'important shock' is an anagram for 'Patrick Thomson'.

Meta

Links

Categories

Top Posts

Blog Stats