Wednesday, January 19, 2011

Laziness, the new fad.

Today is an amazing time in the world of Web Development. We have so many tools at our disposal which speed us through those tasks which once consumed days of our time. These tools allow us to skip much of the trivial, repetitive work that we have all labored through time after time and instead focus our minds on the larger pictures, the bigger fish.

In today's environment, you can layout a domain and with a few keystrokes magically have persistence to a database taken care of. In some languages and frameworks, you don't even have to create the schema it persists to. A few more keystrokes and you can have a rudimentary administrative panel for that domain. For the custom development after that, in most MVC frameworks, model binding takes care of the laborious task of transcribing data from web forms.

Can you believe we once coded these very things by hand? Spending countless hours, time and time again writing the same functionality over and over. We must have been really dumb! But wait a second, we aren't dumb - nor were we back then. If this functionality truly was boilerplate stuff, surely we would have realized that we could simply copy/paste a project basis and started off half done, right? Well, why didn't we?

Here's my theory. I'll say that those features, and many others, proved each time we worked on them to be complex, challenging problems that were rewarding to solve in a better way than we solved them last time. But then something happened. Many bright and forward thinking peers of ours made their solutions generic and packaged them for the rest of us to use. I think, then, that we ultimately realized that we were a little tired of working on the same problems so many times. We rationalized to ourselves that these folks have it cold - they've put the real time in and truly solved these problems for good, and so we accepted their solutions.

Now, so far to this point, I really have no problem. I use these libraries, frameworks and tools on a daily basis and certainly wouldn't start a real project without them. It's the next step that I have noticed us taking that really hurts. I have watched numerous otherwise brilliant, thoughtful, careful developers rely on these tools as black boxes unworthy of scrutiny or even light questioning. It seems these tools are plugged into a project and all of a sudden the lazy switch gets thrown - we dust off our hands and move on to the next problem. Rarely have I seen my fellow developers truly think about what the tools they are using are doing, how they are doing it, and ultimately how it affects their product. In some sense, it seems that they forget that it is THEIR product they are building.

Ok, now for the tough love.
If a plugin you are using is slow, your product is slow. If the form handling framework you are using is insecure, your product is insecure. If the framework you are using is bloated and confusing your product is bloated and confusing.
Here's a quick example (what triggered this post, actually). In MVC.NET there is truly great support for Model Binding. With it, you rarely, if ever, need to touch the actual form post anymore. Simply add some domain arguments to your action, make sure the names match up, and you're good to go.

But wait a second:
How does this functionality work? It matches up the form element names to object and property names in your domain and transcribes the values to your domain objects.
How does this impact your product? This means any user of your product can manipulate the form to their liking, and directly influence not just the data you receive, but the type and relationship of objects you receive.

For instance, let's say you have a user information form: Name, Email, Favorite Food - that kind of thing. Then let's say that a malicious user knows or otherwise guesses that User.UserType determines whether someone is a "Member" or an "Administrator". By manipulating the form, and injecting a field named "UserType" with a value of "Administrator", they can trick you into making their user an administrator! This technique can be used to modify any data you treated with trust - from a user's account type, to a simple little setting you didn't expect them to have access to.

Now for the mind-boggling part. Every developer I bring this up to knows of both this behavior and effect. They also know of any number of things they could do to close this security hole - though not a single one of them addresses the problem!

So I find myself wondering... why? Why would these, as I said earlier, brilliant, thoughtful, careful developers take a shortcut on such an important issue - obviously weakening their product? I think it is because of the reason they are using the tool in the first place. In some way, if they spend time plugging up the holes left by the tool, they still aren't getting on to those bigger problems, those bigger fish that are so alluring in the first place. Pride in one's product, it seems, has taken a backseat to immediate gratification.

I challenge anyone reading this to revitalize your sense of pride in your work. Take a good look at the tools you use. Consider the impacts they have on your product, and plug up the problems you see. Then, post your solutions... I want to use it as a plugin :P

Friday, September 3, 2010

Cross Browser Web Workers

After some time of hearing about the awesome new HTML5 Web Workers but having no particular need for them, I was finally presented with a problem that they could help me with. I promptly sat down with a handful of Google search results and went a-learnin. Turns out they're basically pretty simple. ( except for a small syntactic gotcha in Chrome, more about that later )

There is one major flaw with them though. As far as I could tell, there's no good way to write your javascript code once, in one form, and have it gracefully degrade to non-Worker enabled browsers (If someone knows differently, please let me know in the comments).

So, the gist of the Workers setup is that your main javascript code will "kick off" a "thread" in the background, telling that thread a separate javascript file to download and execute. This seemed to me to be the first interesting compatibility breaker. What was once written in one file, would now be separated into two files. Secondly the two "threads" communicate through messages, something that doesn't much exist pre-HTML5.

For my needs, the code in the "Worker" should still execute and function if Workers are not available in a user's browser. Sure the user will have a performance impact, but the page should still function. All that I could find around the web were statements like:
if( Worker ) {
// algorithm with workers
} else {
// algorithm without workers
}
That would cause me to duplicate considerable amounts of my codebase, and be a case-by-case solution. Anytime those come up, there must be a better solution!

I quickly modified what I was working on to function via the native Worker implementation in Chrome and Firefox, but then my attention immediately turned to creating a wrapper that would behave like a native Worker (albiet far less efficient) in browsers which had no native implementation.

Turns out, it wasn't all that difficult - due to the simplistic nature of the interface between the two threads. I've bundled it up as a jQuery extension here (sadly the extensions site is down due to spamming).
(function($){
$.worker = function(path) {
if('undefined' === typeof(Worker)){
function IWorker() {
var __w = this;
var messageq = [];
__w.postMessage = function(m){messageq.push(m);};
this.__bindBody = function(data){
var __win = { postMessage : function(m){
if(__w.onmessage){
setTimeout(function(){ __w.onmessage({data: m});}, 1);
}
}
};
with(__win){
eval(data);
__w.postMessage = (onmessage)
? function(m) { setTimeout(function() {onmessage({data: m});}, 1); }
: function(){};
for(var i=0,msg;msg=messageq[i];i++){
__w.postMessage(msg);
}
}
}
}

var iworker = new IWorker();
$.get(path, function(data) {
iworker.__bindBody(data);
});
return iworker;
} else {
return new Worker(path);
}
}
})(jQuery);

To use it, simply replace new Worker("myfile.js") with $.worker("myfile.js"). If the browser supports Workers natively, it'll just fallthrough and use it. Otherwise, it will grab the worker file via ajax, wrap it in a scope that simulates a worker and provides the needed postMessage and onmessage API hooks.
// pre-plugin
var w = new Worker("myfile.js");
w.onmessage = function(e) { alert(e.data); }
w.postMessage("Hi");

// post-plugin
var w = $.worker("myfile.js");
w.onmessage = function(e) { alert(e.data); }
w.postMessage("Hi");
One glaring omission that I have yet to need, is that this implementation does not mimc the onerror event that is possible with Workers. I plan to implement this, but likely won't until either I need it, or someone else asks me to :)

Oh, and the "syntactic gotcha in Chrome" that I mentoined before, kept me spinning for a good hour or more....
In your worker.js file, in order to capture incoming messages, you define a method:
onmessage = function(e){
// do something with e.data
};
That seems straight-forward, though, it is interestingly NOT equivalent to
function onmessage(e){
// do something with e.data
}
in Chrome (though it works fine in Firefox). So, be sure to use the first syntax.

Tuesday, January 12, 2010

PHPUnit on Windows, phew!

Wow, sometimes things can be so friggin difficult! I think I finally have phpUnit installed on my Windows development machine, and figured I'd record my actions here both for my own reuse and hopefully for anyone traveling down the same road.

If you want to jump straight to the instructions, feel free. Otherwise, here's a little backstory.

Backstory

First, to note, I have PHP installed from the thread-safe Win32 installer packages available from http://windows.php.net/download/. I am on version 5.3.1, though I believe this process has very little to do with the version of PHP.

The thing about installing PHPUnit, is that it first requires that you have PEAR installed. The thing about PEAR on Windows, is that the installers for PHP do not ship with a valid way of installing PEAR. All the instructions I could find on the web start with something like:

Install PEAR using c:\PHP\go-pear.bat
This script, however is broken, as it goes looking for PEAR/Pear5.php and just dies there. I tried numerous attempts at patching together the files it says it needs, but alas in the end I decided it just wouldn't work.

After much searching, I came across a go-pear.php script on pear.php.net's own site (http://pear.php.net/go-pear). Not to be confused with go-pear.bat, mind you.

This was the turning point to it all. There were still a few hiccups along the road that hopefully these instructions will help you overcome. Also note that I am working on a Windows 7 machine, so I also had some issues with having to run certain parts as an administrator. If you're on XP, you can ignore the "Run as Administrator" notes, I believe.

Instructions

  1. Copy the go-pear script ( http://pear.php.net/go-pear ) and save it as go-pear.php somewhere,
    I chose %temp% and will use that throughout these instructions

  2. Open a command prompt as an Administrator
    ( Start -> All Programs -> Accessories -> Command Prompt, right-click and select "Run as Administrator )

  3. Change to the directory where you saved go-pear.php
    cd %temp%

  4. Run go-pear.php
    php go-pear.php

  5. Set the prefix path to your PHP directory by selecting #1.
    For me this was: C:\Program Files\PHP, apparently lots of people also install PHP directly in C:\PHP

  6. Let PEAR install, the other defaults were fine for me

  7. The last bit of instructions encourage you to run the PEAR_ENV.reg file to include PEAR in your command path. I did just that, feel free to or not.
Yay, now you should have PEAR installed. Moving on to PHPUnit now:
  1. Tell PEAR where to find PHPUnit
    pear channel-discover pear.phpunit.de
    Note: that this still needs to be performed as an Administrator

  2. PHPUnit apparently depends on a YAML package maintained in a different channel, so also tell PEAR where to find that package
    pear channel-discover pear.symfony-project.com
    Note: that this still needs to be performed as an Administrator

  3. Now, you can install PHPUnit.
    Since I am a sucker for dependencies, and Love to install them all blindly just in case they'll make my life a little easier, I opt to install all dependencies.
    pear install --alldeps phpunit/PHPUnit
Yippie! Now you should have PHPUnit finally installed. The PHPUnit script should now be available in your PHP directory. For me this was C:\Program Files\PHP\phpunit.bat

I hope this helps at least one other person in the world not waste their morning figuring through these steps. If you find that your experience is different that this in any way, please post a comment here so that others may benefit as well.

Good Luck, and happy Unit Testing!

Wednesday, December 16, 2009

Hello World

As any developer knows, one must always start with "Hello World."

I am very excited to enter the world of maintaining my own blog. I have blogged in the past here and there for others, and found it to be a very personally rewarding task. The idea of your thoughts and your take on matters being available for anyone who is interested to read, that's pretty cool. Definitely a triumph of our era, I'd say.

I've spent a good number of years now "learning to code", along with my handful of mentors - but I've been learning in a handicapped way, that is, disconnected - hiding in a back room somewhere.

I've recently stopped ignoring the hype of things like Twitter and started participating in sites like Stack Overflow, rather than just gleaning from it the answers I need. I have to tell you, it's a whole new ballgame.

This new level of involvement in my learning, and through learning, also teaching, is so much more fulfilling and humbling. It's Awesome!

So I say to whoever happens by this blog post, "Hello World!". I'm glad to have met you.