Marzhill Musings

Bricklayer::Templater is on CPAN

Published On: 2007-08-14 16:20:30
And I have registered its namespace so it shows up in the module list. This means the Bricklayer::* namespace can now be used to begin build the various components of my evolving frameworks Bricklayer::Templater

Tags:

Would you like a little Moose with that?

Published On: 2007-03-20 15:57:54
I have found a great new tool in CPAN. Moose is an extension of the perl OO system. It implements metaclasses in an intuitive and easy to understand way. Getting started with Moose couldn't be easier. Make sure you use v0.18 though because the previous version has a few quirks that get in the way. Basically to get started all you need to get started is install Moose from CPAN. I recommend doing so from CPAN because a lot of the distros are behind a little and 0.18 has some fixes that will make your life a great deal easier when using Moose. Once you've installed Moose it's time to start building your classes. In this tutorial I'm going to highlight the most used (in my opinion) features of Moose.
  • has
  • after
  • subtype
A class is composed of attributes and operations for the most part. Some OO systems further divide these into private and public methods/attributes. For this tutorial though we will just keep it at those two. The first thing you have to do in your class is use Moose at the top to import the Moose package.
package MyClass; use Moose;
Now your commited. That use Moose statement has forever altered the way you write this class. Well not really you can turn it off but lets not worry about that right now. Moose does a lot of heavy lifting for you in the background so it's best to just use the moose feature set to build your class from here on out. The first thing we need to do is start writing your classes attributes. For this we will need our handy dandy 'has' function. 'has' will create our attributes for us and automatically do type restriction, create accessor methods, and police reading and writing to them. So what does 'has' need? It needs two arguments a scalar and a list of key value pairs with a minimum of at least one but I recommend 2 keys at a minimum. The scalar is the name of the attribute. The list describes the attribute for Moose so it knows how to set it up for you. The first key, and the absolute must, is the 'isa' key. This key tells Moose what type to restrict the attribute to. It can be a class name or predefined subtype. You can see a list of Moose's of already defined subtypes for us Here : http://search.cpan.org/~stevan/Moose/lib/Moose/Util/TypeConstraints.pm#Default_Type_Constraints You should be able to use those to get started. The second key Moose needs is the 'is' key. This key tells Moose how to police reading and writing to this attribute. A value of 'rw' in this key tells Moose this attribute can be read and written. A value of 'ro' in the key tells Moose this attribute can only be read and not written to. So lets add a couple of attributes to this class.
has 'Name' => (is => 'rw', isa => 'Str'); has 'Purpose' => (is => 'ro', isa => 'Str');
Now our class instances can have a name and a purpose. We can see that both attributes are strings and that the name is readable and writable while the purpose is only readable. This is actually a fully functional class now. It only works to store things since we don't have any operations yet but it is fully useable. A few things to keep in mind is that Moose automatically adds Moose::Object as your classes base class. So you do have a few operations: ->new() is a constructor that Moose::Object provides for you. This allows Moose to properly set up your classes accessors and constraints for you. We could use this class now by calling
my $obj = MyClass->new();
We can set our name by calling
$obj->Name('test');
We can retrieve that name by calling
my $name = $obj->Name();
But wait our Purpose attribute is not writable and nothing is stored in it. How on earth do we get something in there? Ahhh, now we come to Mooses little secret: You don't have to use the methods to access those attributes. $obj->{Purpose} = 'To Show off Moose'; will work just as well with a few caveats. (You see it really is just an extension of the Perl OO system.) Moose doesn't do any policing when you access them this way. This means people who use your class and regard it properly as a black box shouldn't be doing this. Which brings us to two more really handy keys in our descriptive list we are passing to has: 'default' and 'required'. Up to now our attributes have not been restricted from being undefined. setting the required => 1 key/value pair in our list takes care of that. If we do that though then we have to define a default value for the attribute or our class will error on compile with Moose telling us that the attribute is undefined. That's what the default key is for. default => 'To Show off Moose' will set the default value for the attribute to our string. Now our class looks like this:
package MyClass; use Moose; has 'Name' => (is => 'rw', isa => 'Str'); has 'Purpose' => (is => 'ro', isa => 'Str', default => 'To Show off Moose', required => 1);
When we create a new instance of our class with
my $obj = MyClass->new();
our Purpose attribute will be preset for us and not modifiable (without breaking the rules which you would never do of course). That's enough for this post. I'll be posting next on the benefits of after and subtype when it comes to your attributes and Object Integrity.

Tags:

Debugging Axiom #1

Published On: 2007-02-28 13:02:04
There is an axiom coined I believe by Sir Arthur Conan Doyle in his Sherlock Holmes novels that every programmer should keep in mind while debugging his program.
When you have eliminated every other possibility; Whatever is left, however improbable, Must be the Solution.
There has been many a time when I could have arrived at the answer much sooner but was stuck because what the program was doing seemed to be impossible. When I accepted that it was possible then I was able to begin tracking down how it was possible and thus finding the solution. After one too many occurences of this I think I'm going to make a big poster with this axiom on it and hang it above my monitor.

Tags:

On the fly Perl Classes with Type restricted attributes

Published On: 2007-01-25 19:34:17
There is a CPAN module Class::Struct that can give you this same functionality. But fool that I am I like to do things the hard way. Now the differences in the useage of this implementation, while it may not do things as automatically as Class Struct does, will allow you to create simple type restricted attributes on the fly in your code with a simple one line class method. You could even bundle this in with an AUTOLOAD function to build the attributes as you need them. Also the class attributes are added at runtime and with a little extra work you can even specify such things as typed arrays or hashes. Ok enough Pro's and Cons lets take a look at the code. First we take a look at our base class that does most of the work. package Class::Builder; sub new { my $class = ref($_[0]) || $_[0]; my $self = {}; return bless($self, $class); } sub attribute { my $self = $_[0]; my $type = $_[1]; my $attribute = $_[2]; my $value = $_[3]; if ($value) { #handle INT case if ($type eq "INT") { if ($value =~ /^[0-9]+$/) { $_[0]->{$attribute} = $_[3]; return $_[0]->{$attribute}; } else { $_[0]->err("Not a $type value for $attribute"); return undef; } } elsif ($type eq "SCALAR") { #handle simple SCALAR case $_[0]->{$attribute} = $_[3]; return $_[0]->{$attribute}; } elsif (ref($value) eq $type) { #handle other types $_[0]->{$attribute} = $_[3]; return $_[0]->{$attribute}; } else { $_[0]->err("Not a $type value for $attribute"); return undef; } } else { $_[0]->err("No value passed for $attribute in ".ref($_[0])); } return $_[0]->{$attribute}; } sub err { $_[0]->{err} = $_[1] if $_[1]; return $_[0]->{err}; } return 1; Now lets see how we can use it. package Document; use Class::Builder; use Document::Section; use base qw(Class::Builder); #Attribute Methods # example of a SCALAR Typed Attribute implementation sub Name { return $_[0]->attribute('SCALAR', 'Name', $_[1]); } #Example of a ARRAY Typed Attribute with a further simple check #that the array elements are of type: Document::Section sub Sections { my $arraytype = 'Document::Section'; my $sections_old = $_[0]->Sections(); my $sections = $_[0]->attribute('ARRAY', 'Sections', $_[1]); foreach (@$_[0]) { if (ref($_) ne $arraytype) { #throuw an error here $_[0]->err("Invalid Array Element $arraytype"); $_[0]->attribute('ARRAY', 'Sections', $sections_old); # reset the Sections array return undef; } } # die "sections is a ".ref($sections); return $sections; } # example of a HASH typed Attribute sub Meta { return $_[0]->attribute('HASH', 'Meta', $_[1]); } # example of an INT typed Attribute; sub Cursor { return $_[0]->attribute('INT', 'Cursor', $_[1]); } I'm not finished modifying this concept so I may post some additional enhancments later. But you can get the idea now.

Tags:

Bricklayer Refactored and other news

Published On: 2007-01-16 23:42:54
Bricklayer has been heavily refactored for more modularity. You can see the much changed codebase at the new svn repository Instructions for SVN Checkout can be found here: SourceForge SVN Checkout Current is the trunk branch in the repository tree structure. Documentation and some examples for the new API will be forthcoming shortly. Including the new DataBase Access API concept I will be introducing. A preview of the proof of concept code is in the Bricklayer/Data libraries directory.

Tags:

Inception - The Distributed Community API

Published On: 2007-01-03 22:12:12
I have been noodling an idea lately that I think I will begin to implement in Bricklayer. A distributed MySpace/FaceBook of sorts. Think of it as everything you like about a Community Website with none of the Myspace pains. Your profile and content will be yours and under your control. But the network will still be there. It's distributed because its a network of individual unrelated sites. A Blog, Forum or Discsussion board perhaps. It will allow Disparate sites to network using similar technologies to trackback pings with less spam because a request for friend status with an identity will have to be explicitely allowed. In Theory with this API joining a community like Myspace would be as simple as requesting Friend Status with a Service Website. Leaving would be as simple as revoking the status with the Service Website. Each way you still keep the identity and Content and moving it from Service to Service or using it in Multiple Services would be simple and easy. My initial Design Notes can be found here.

Tags:

Perl Tip - Chained encodings and binmode magic

Published On: 2006-10-07 14:42:04
OK how many of you have gotten those Wide Character in Print warnings while dealing with unicode text? especially UTF-16 files which don't get handled on the fly in perl. I finally figured out how to get rid of them thanks to, of all places, a MSDN blog. The gist of the post is a technique where you chain encodings together when changing the encoding used on a file handle. He used it on an open but for my purposes I wanted to change STDOUT's encoding not an opened file handle. So heres the magic line: binmode(STDOUT, ":raw:encoding(UTF-16):utf8"); Now your first thought is why couldn't you just use the encoding you want? Well here's why. First of all the utf8 encoding on the righmost tells perl that it is receiving it's default utf8 encoding. Then the encoding(UTF-16) in the middle performs the encoding conversion and finally the raw on the left tells perl to spit it out whithout changing. The three together result in a warningless conversion from utf8 to utf16 with no line feed conversion. I didn't even know you could chain these together until now but I'm going to remember this trick for the future, that's for sure. To break it all down for you. The chain is processed from right to left. Starting with utf8 got rid of my wide character warning. chaining that into the encoding(UTF-16) performed my conversion and chaining that into :raw made sure I got text and not octet encoded characters.

Tags:

Well Designed Software and the Last Hill

Published On: 2006-09-01 11:15:20
There comes a time in your development cycle where if you have designed your system well you start to see a payoff. If you have a good seperation between data, logic, and display and your system is logically laid out then near the end of the cycle as you approach launch date you will start to notice a trend. The customer will make a request and you will find that you can implement the change more and more quickly. If you need to make a business logic change you only have to go one place to make it and you don't have to double check a thousand other places to make sure the change didn't break something. Page layout? same thing. Database layer changes? Ditto. You start to experience 5 and 10 minute turnarounds on minor changes and 1-2 hour turnarounds on larger ones. Enjoy this period while you can. It's a very good place to be.

Tags:

Transactions as a debugging tool

Published On: 2006-06-07 14:13:13
Have you ever wanted to test a long sql DDL script for syntax errors but didn't want to actually create your db structure yet? I've found the easiest way to do this is through the use of transactions. simply begin a transaction at the start of the script and roll it back at the end of the script. For example:
 -- PostgreSQL DDL script BEGIN; -- begins our transaction block CREATE TABLE test_tbl ( pk numeric NOT NULL, data varchar(128), ); ROLLBACK; -- roll back everything this script just did COMMIT; -- use this instead of ROLLBACK to commit the changes 
This has the benefit of allowing us to test the script for errors and yet not actually run it on the DB. The EXPLAIN command can do this also on some DB's but you would need it for every statement you wrote in the script and some statements will error out if you use EXPLAIN on them. I've found the Transaction method to work best for what I want to do.

Tags:

Did you ever need to index an xml doc

Published On: 2006-05-18 16:26:57
and preserve the xml information in the index? May I present "the XML Indexer". My brother, who's very populer AJAX Bible app has been getting attention, needed an xml index of the KJV Bible. He asked if I could help him get it. We would be parsing the KJV in XML format and I needed to pull out the reference information for every occurence of every word. Well I thought an xml indexer might be useful in more than one capacity and there wasn't much on the net or cpan with the capability to do it. It needed to be light and fast because it was going to be parsing the entire bible so a DOM parser was out of the question. So I wrote my own. xml_indexer.pm is a module to index the words in an xml document and preserve the xml information about each occurence of the word. It's a little rough around the edges right now but it works. It uses the expat parser so it's light and fast. Look at the bible_index.pl script for an example of how it works. I'll do a tutorial on it later. Update: This baby has been confirmed to parse the entire bible in Zaphania xml format in under 3 minutes. That is a 16 MB file. It spits out a 23 MB index in that space of time. Quite honestly it surprised me.

Tags:

Mod_Perl 2.0 - First in a series

Published On: 2006-04-22 20:40:00
I have put up a new page on mod_perl development on the site. I hope it is of use to someone. If it isn't well at least I still have my own notes :-) You can find it here: Mod_Perl 2.0 - A Real World Guide - part I

Tags:

The Value of Open Source Platforms

Published On: 2006-04-03 22:34:45
People ask me at times why I like Open Source so much. It's true that OSS can sometimes take a little more work up front. Sometimes, however, OSS is the only way to solve a problem quickly and with the least amount of trouble. Take my current project for example. I have a client with legacy code on an IIS server written in ASP/VBScript. Now I have nothing particular against ASP. In many ways I cut my teeth on ASP. However IIS CGI scripting has a nasty little bug which is rare but just happened to affect me. Certain Database connections will cause the IIS and the CGI application to get out of sync. The result of which is that the webserver sends absolutely nothing to the browser. No error page. No data. Nothing. Now how are you supposed to fix that? The client can't just ditch his legacy code. He can't upgrade IIS without a significant cost. And there is no Patch. There are some workarounds but none of them work predictably 100% of the time. So what is an enterprising Programmer to do? Introducing Apache as a backend server. Apache just happens to be completely unaffected by this little problem. So my solution? Set up Apache2 and Modperl to serve out the data to the IIS server. Use an MSXML object in the ASP code to retrieve the page and display it right along side the legacy code to the browser. Now the legacy code can exist side by side with the new code and In addition we can kill two birds with one stone by taking one more step toward the goal of migrating the application to an Apache/Perl/Mysql orPgSQL infrastructure. What was the advantage of OSS in this situation? It provided a solution that I could implement immediately with no licensing changes, no cost, and no problems. I didn't have to talk to a sales rep. I didn't have to talk to tech support. I just went ahead and implemented it. Now try doing that with a closed source solution. OSS has readily available solutions with little or no overhead. I guess that's why so many hacker types like the environment to work in. We like to solve problems. We don't like waiting on other people to solve them for us.

Tags:

Beauty, Artistry, and computer code.

Published On: 2006-02-21 10:08:57
I'd like to take a moment to wax poetic. Code hackers have a term for well written code. Elegant. We appreciate elegant design and algorithms in code. It's a pleasure to work on code like that. We will stop and just think "Man, that's beautiful" Even our quick and dirty scripts somehow turn out to be pieces of art. So what makes a piece of code beautiful? It's a little bit hard to describe but there are usually several elements that contribute to code's beauty. Those elements that compose what I perceive as beauty in code are:
  • Efficiency
  • Cleverness
  • Style
  • Flow
Efficiency Efficiency is perhaps one of the most important elements in the percieved beauty of code. Code that is streamlined, sleek, and targetted is beautiful. This kind of code does one thing and does it well. There is no wasted effort or duplicated work in efficient code. Efficient code knows what it needs to do and gets down to business. Many times this equates to less code though not always. Cleverness Cleverness is a close second in the elements of code beauty list. Cleverness as defined by "Now, that's a cool way to do it!!" It's coming up with a better and heretofore unconsidered method or algorithm to get the job done. It's similar to those paintings in art with surprise built into them. Like the excercises in perspective where you don't realize it's a painting till you get close. It makes you stop and go Wow! Now that's cool. Code cleverness usually has a lot to do with Efficiency. If your clever hack makes the code less efficient it may actually decrease your codes beauty. It can be a double edged sword. Style Style along with Flow are the subjective parts of the beauty equation. It means different things to different people. It's part of what makes someone love perl and hate python while a different person loves python and hates perl. Style encompasses such things Indenting, code organization, and naming conventions. Everyone has a different opinion of what looks good. Similar to art where one person likes modern art and another thinks it looks ridiculous. Flow Flow is also a highly subjective part of the beauty equation. Some people like to flowchart for days before even touching the keyboard. Others prefer to let the programs logic structure sort of organically grow. Still others prefer a balance somewhere between the two. Flow covers how your code handles the various tasks that it is responsible for. It encompasses reusability. And it can increase or decrease your code's efficiency. Like Art everyone has their own definition of what is beauty when it comes to Flow. So how do you classify beautiful code? Let me know in the comments.

Tags:

Bricklayer Subversion Repository is up

Published On: 2006-01-30 10:27:57
I have finished moving my bricklayer subversion source code repository to a public location. you can find it at the following link. If your browser recognizes the svn protocol you can just click the link below. For all others you'll need to copy the link location into a subversion browser of some sort. Now you can get the cutting edge copy :-) enjoy!! BrickLayer Subversion Repository

Tags:

BrickLayer RC2 is out

Published On: 2006-01-25 13:41:38
Bricklayer RC2 Download it while it's hot. I have added a number of bugfixes and enhancements. But it's still in testing so don't plan on using this in a production environment yet :-)

Tags:

What's your Development process?

Published On: 2006-01-20 16:08:01
I've tried all those development process programs and tools. UML, Case Tools, Flowcharting. You name it I've investigated. Just part of my nature I guess. I like new toys and investigating or learning about new things. When it comes to serious development work though I've really only found one process that works for me. Just Code It. I start creating the structure of my app. Code the Class and Object definitions. Identify the needed functions. While doing this I write pseudocode in the form of comments in these structures. Then I start coding. It's a highly iterative process but it works for me and makes me far more productive than anything else I've found. I also tend to write Black Box code. Each of the pieces has a clear way of being used and each can be coded without knowing the internals of the other pieces. This way I can test and code each piece easily without having to worry about the rest of the app. I'm not sure what you'd call this process. It bares some similarity to Agile or Extreme programming processes I suppose but really it's just an extension of the way I think. So... What's your development process?

Tags:

Are You a Data Middle Man?

Published On: 2006-01-17 16:29:22
Not too long ago, before the bubble burst as they say, one of the HOT new things was B2B technology. Hooking businesses together for their mutual profit. You don't hear a whole lot about that anymore. I think probably because those companies lost their focus and consequently never made any money. You see the real power of the "network" is in sharing data. B2B really was all about sharing that data. If you could emphasize that feature you could have made money. Becoming the middle guy in the selling and purchasing of data could become a very powerful and lucrative business. Especially since the new "emphasis" on standards is helping the process along. If you look at a lot of the hottest things in the web right now they all talk about sharing data of some sort. Flikr, Techdirt, Blog aggregators. All of them provide ways to access and share their data easily. And the investors are salivating. Notice I said "their" data. If you never have data to share no one uses your API/Standard. The reality is that Standards only work if someone shows you how to use them and uses them themselves. The Data Middle Men are the ones who will define these standards of exchange. They will be brokering the transfers and more importantly providing the infrastructure for those transfer. I've been thinking about this a lot lately because one of my customers has an opportunity to become one of the first of the Homecare Data Middle Men. It's gonna be a fun and wild ride :-)

Tags:

First Draft of the Bricklayer Documentation

Published On: 2005-12-07 23:44:39
I just finished the first draft of the Bricklayer development manual. You can see it here: Bricklayer Manual Take a look and tell me if you see any thing that might need more clarification or spelling correction.

Tags:

Using Reusable AJAX Gateways

Published On: 2005-12-02 15:43:31
So now I have a reusable ajax gateway. Just what exactly am I supposed to do with it? If you look around for a while you will start to notice everyone describing how you can use XSLT, SOAP, and all these other things to pass Objects back and forth. And again they all have suggestions for libraries you can use to do this in. But what if your not quite that ambitious? What if you wanted the speed and power and downright fun of using AJAX without all the huge libraries? Well as usuall I have an idea. You see what I really want to do with this is to retrieve pieces of html pages from the server to put into my current page. Simple enough right? Why I could just use cloneNode from the DOM api to do that. In fact if you looked at my example code from before you saw that I did exactly that. There's just one problem though. The cloned elements and test show up on your page alright but they aren't part of you html document. In fact the element don't obey any of your html rendering engines rules. It's as if you just went about making up fake tags to put in there. They don't do anything. What we need is a way to take our xml document and duplicate it's structure in our html document. duplicate_nodes() to the rescue!!! I wrote a small function that takes our html fragments (as I call them) and duplicates them in our pages document. Here is how I did it: function duplicate_nodes(node) { // get our node type name and list of children // loop through all the nodes and recreate them in our document //alert('calling duplicate_nodes: ' + node.nodeName + ' type: ' + node.nodeType); var newnode; if (node.nodeType == 1) { //alert('element mode'); newnode = document.createElement(node.nodeName); //alert('node added'); newnode.nodeValue = node.nodeValue //test for attributes var attr = node.attributes; var n_attr = attr.length for (i = 0; i < n_attr; i++) { newnode.setAttribute(attr.item(i).name, attr.item(i).nodeValue); alert('added attribute: ' + attr.item(i).name + ' with a value of: ' + attr.item(i).nodeValue); } } else if (node.nodeType == 3 || node.nodeType == 4) { //alert('text mode'); try { newnode = document.createTextNode(node.data); //alert('node added'); } catch(e) { alert('failed adding node'); } } while (node.firstChild){ if (newnode) { //alert('node has children'); var childNode = duplicate_nodes(node.firstChild); //alert ('back from recursive call with:' + childNode.nodeName); newnode.appendChild(childNode); node.removeChild(node.firstChild); } } return newnode; } Now this functions currently only handles elements, their attributes, and text or cdata nodes. entity and other node type support can be added easily however. Also I still need to do some testing on the attribute handling to see if it correctly handles stuff like eventhandlers and id attributes but it works. (Edit: It handles event handlers with no modification on firefox) Lets do like all good code hackers do and take it apart :-) Our first task in this function is to see what kind of node we are handling. This is contained the in the nodeType property of the node object. When this is a 1 it's an element. When it's a 3 or 4 it's CDATA or a Text node. Thus our if statements: if (node.nodeType == 1) { } else if (node.nodeType == 3 || node.nodeType == 4) { } Elements and Text or CDATA have to be handled very differently so we check for these two types before doing anything else. In the case of an element node (type 1) we need two more peices of information: node.nodeName and node.nodeValue These provide us with the details we need when recreating our element in the html document. They are pretty well self explanatory one is the name or tagName of the element and the other is the elements value. Now we are ready to start creating our new element in the current document like so: newnode = document.createElement(node.nodeName); //alert('node added'); newnode.nodeValue = node.nodeValue Now how do we handle it's attributes? A simple for loop will do that for us. the attributes property gives us a list of the nodes attributes. The calling the length property for that list gives us how many attributes there are. And the for loop loops through each one duplicating it in our newnode like so: //test for attributes var attr = node.attributes; var n_attr = attr.length for (i = 0; i < n_attr; i++) { newnode.setAttribute(attr.item(i).name, attr.item(i).nodeValue); alert('added attribute: ' + attr.item(i).name + ' with a value of: ' + attr.item(i).nodeValue); } And that's all we need to recreate our element and its attributes. Text nodes are even easier to handle. you just need one piece of information for them. The data property. create a new text node using the document.createTextNode method with the node.data property and your good to go: //alert('text mode'); try { newnode = document.createTextNode(node.data); //alert('node added'); } catch(e) { alert('failed adding node'); } There is just one last thing to take care of though. What if our node has children? What do you do then? Function Recursion to the rescue!! The firstChild property of a node will tell us if there are any children and a while loop will keep looping as long as it returns true. All we have to do is:
  • call duplicate_nodes recursively with that child as an argument
  • append the returned node to the newnode
  • remove each child from the node
  • and keep looping till no more children exist
Here is the while loop: while (node.firstChild){ if (newnode) { //alert('node has children'); var childNode = duplicate_nodes(node.firstChild); //alert ('back from recursive call with:' + childNode.nodeName); newnode.appendChild(childNode); node.removeChild(node.firstChild); } } The last task of our function is to return the duplicated node return newnode; our duplicate function does not append the node anywhere in our document so it won't show up. That is the job of the calling function. It can append the new node where ever it wants.

Tags:

Reuseable AJAX gateways

Published On: 2005-11-28 16:13:20
Everyone knows about AJAX these days. You just about can't go anywhere on the net whithout hearing about it. And if you're a coder who want's to know more than just what library you should download to start using it you've probably done a little googling and came up with this site: XMLHttpRequest Objects [developer.apple.com] You even played around with the examples and made a few demo apps then realized. Hey!! How can I make these things reusable without ugly global variables and functions that check to see if the response came back yet? In short: how do I use this in a real app? Apple has done a really good job of showing how the xmlhttprequest object works. They even do a good job of showing some useful ways to use it. But if you're like me you want to go a bit farther. I like reusability. I also don't like using Global variables as a gatekeeper. So lets take a look at how we can make this code a little more reusable. The first thing to do is come up with a way to use multiple different functions as the handler for that onreadystate property. Using the same handler really cramps our style. Additionally having to write all that code to test our object's state is a real drag. It would be nice if we could avoid having to write that for every single function we use as a handler. Here is the solution: Let's start with this function here: function loadXMLDoc(url) { req = false; // branch for native XMLHttpRequest object if(window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch(e) { req = false; } // branch for IE/Windows ActiveX version } else if(window.ActiveXObject) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } if(req) { req.onreadystatechange = processReqChange; req.open("GET", url, true); req.send(""); } } Now for this to do what we really need it to we need a couple of different things. That processReqChange function needs to be able to change dynamically. So lets add another function argument that will hold a function passed in to be used here. Like so: loadXMLDoc(url, func) then you can change req.onreadystatechange = processReqChange; to req.onreadystatechange = func; This will allow us to pass any function we want as the state change handler. Don't go deleting that processReqChange function yet though. We still need it. In fact lets take a look at that one right now shall we? function processReqChange() { // only if req shows "loaded" if (req.readyState == 4) { // only if "OK" if (req.status == 200) { // ...processing statements go here... } else { alert("There was a problem retrieving the XML data:\n" + req.statusText); } } } We need this to keep checking our state and tell us when our response came back. We also need it to use any xmlhttprequest object we want it to. What we don't need it to do is retrieve our response for us. In short we need it to recieve a request object in it's arguments and return a response saying it's ok to process our response. So lets modify it a little shall we? function processReqChange(req) { // only if req shows "loaded" if (req.readyState == 4) { // only if "OK" if (req.status == 200) { return 1; // it's safe now go ahead } else { alert("There was a problem retrieving the XML data:\n" + req.statusText); } } return 0; //it's not safe yet } now when we pass this function a request object it returns 1 when we have our response and 0 when the response is not ready yet. Both of these functions are now reusable. But how exactly do we start using them? I thought you would never ask. lets build an example: function append_to_id(el, contents) { var element = document.getElementById(el) ; //alert('appending: ' + contents.nodeValue ); element.appendChild(contents); } function append(url, el) { //alert('starting append operation'); var func = function() { if (processReqChange(req)) { var ajax_return = req.responseXML; while (ajax_return.hasChildNodes()) { append_to_id(el, ajax_return.firstChild); ajax_return.removeChild(ajax_return.firstChild); } } } var req= loadXMLDoc(url, func); } In the append function we create a dynamic function that we can pass to our loadXMLDoc function. That dynamic function contains the meat of what we are wanting to do. It uses an if statement that checks our processReqChange function for a valid return. When it gets a valid return the if statement processes our request. It couldn't be any eaiser. you can see full example code here: Example Script

Tags:

BrickLayer RC1

Published On: 2005-11-19
My first release of BrickLayer. is ready. I'm still writing some of the documentation, but I couldn't resist giving you a peek. You can get it here: BrickLayer And here is the documentation I have written so far: Using BrickLayer BrickLayer Templating BrickLayer Plugin Development The BrickLayer DB Interface documentation is in progress.

Tags:

New Article: Non-Discriminatory Databases

Published On: 2005-10-07 00:35:57
Non-Discriminatory Databases An article about MetaData and Database Design. Mostly just a look inside my thoughts recently on Database design and on the fly expandability.

Tags:

MetaData and Database design

Published On: 2005-09-27 00:36:36
Recognizing the difference between your Data and your Metadata can go a long way toward keeping your data formats extensible. Theoretically keeping your data generic and using metadata to describe it can allow for much greater flexibility in your application's design. Planning for, and accounting for, the ability to add more metadata on the fly can allow you a much greater capacity for growth in the types of data your application can handle. I'm experiencing this in a current project in fact. The company in question is growing and is faced with a need to change their current application to allow for that growth. A massive refactoring of the application is going to be needed. They will have to be able to add new "products" (otherwise known as data) to the application and present more ways for customers to get access to said product. A metadata based design in their data format will give them that kind of flexibility.

Tags:

custom dtd modular - Google Search

Published On: 2005-09-12 21:12:24
custom dtd modular - Google Search Apparently I'm ranked just below a-list-apart on the subject of Modular XHTML and custom DTD's. How I got there I don't know. Go check out the article if you want It's kind of interesting in an esoteric way :-)

Tags:

RAP with me now...

Published On: 2005-09-08 02:19:36
Rapid Application Prototyping, or RAP(ing) as I will calling it is a fantastic way to be sure you meet your design goals for a project. Furthermore, with AppKit (my own personal Web Application development Framework), it is greatly simplified through the use of an "advanced" plugin and templating engine. How so, you ask? Well I'll tell you... Application Logic vs UI Flow What's the difference in these two things? Application Logic is all about how your application handles user input and data. UI Flow is all about how the User sees and inputs data. When the two are seperated you can work on each without disturbing the other. This allows you to, for instance, quickly prototype your UI screens and workflow without worrying about how that application logic works behind the scenes. That way you can get valuable feedback from customers and assistance in your requirements gathering process. Templating: (develop that unique look before you do the behind the scenes stuff) When I first got started in this web development thing I didn't know there was such a thing as templating. I developed logic right alongside my UI. In fact in a lot of ways my UI was driven by my application logic. That meant changing something required recoding and reworking my apps logic. This, while challenging and fulfilling, wasn't a particularly useful way of going about things. It was, however, fashionable at the time and everyone was doing it. Nowadays I've grown up and use a much more efficient system. I build my UI seperately using a templating engine. This lets me attach logic to it later (I can detach logic too, or even rework logicall without once touching the template) . I can change the template (rework or even drop the template all completely) all without once touching the logic or even having any logic behind it. In essence I can create a mockup of the programs UI flow demonstrate it, tweak it, test it and then attach the backend. RAP is definitely the way to go. Plugin Architectures (add a piece here add a piece there) So you can create your UI without once touching the logic. All well and good you say, but what then? Ahhh, that is the beauty of it. Once you have your UI in place start attaching actions to the UI. Then develop the logic that handles that action. If you framework has plugin functionality then you can do that piece by piece. AppKit dynamically loads the plugin you need to do the action you requested. If no plugin fits the action it will tell you so. Need an action? Develop an interface for it. Think of plugins as the hooks for your UI into the Application. And all you have to do is drop them in one at a time or by the wheelbarrow full if you want. Complete separation of logic and program flow/UI. It's a beautiful thing trust me.

Tags:

SQL Stupidity part II

Published On: 2005-09-07 21:31:35
I am working on a legacy web application right now that is giving me fits. I'd say about 90% or so of the application is done in SQL. Yes you got that right. The business logic is almost completely written in a huge number of stored procedures, sql functions, and scheduled database tasks. This makes tracking down the parts of your app you are trying to work on very difficult. Every time I turn around there is another stored procedure, function, or scheduled database task that needs tweaking. I'm starting to go a little crazy. The problem is it obfuscates what your application is really doing. You think a perl obfuscation contest produces difficult to follow code? They got nothing on this. I realize stored procedures were the cat's meow at the time but this is beyond all human decency. I have got to start refactoring this thing before it gets out of control.

Tags:

WikiWyg

Published On: 2005-08-26 01:03:28
Wykiwyg With the higher profile, dynamic javascript pages are getting, look to see a lot more folks working on this stuff. And this is a wonderful example of what you can do.

Tags:

SQL stupidity

Published On: 2005-08-25 04:03:39
Let me let you in on a secret. SQL is a great language for getting information out of a database. But if your writing a long string of stored procedures that call functions which use a view that ties several tables together just to find out what particular piece of data is linked to your piece of data then you need a good talking too. Not only does all this unnecessary complexity make debugging hard for you. But it makes folks like me want to beat you up with a baseball bat. So do us all a favor. See if you can reduce the number of steps and keep the squirming pathway a little straighter. Then you can scream and rant and pummel the brains out of your fellow coders (who didn't heed this warning) with the rest of us.

Tags:

The Eclipse is here!!!!

Published On: 2005-07-25 00:02:50
Eclipse 3.1 has been released. I am a big fan of Eclipse. It is quite possibly the best all around IDE for developers out there. It may be a bit slow compared to a non java app, but has all the features you need.
  • It handles pretty much every language you can think of.
  • Works on most every platform.
  • Supports multiple versioning systems out of the box.
  • Has built in debugging support. Including a lot of great features for the web developer. Like running a web server process with the ability to step through your code.
What more can you ask for. The Eclipse GUI interface (SWT) is significantly faster than its java counterparts also. I'd highly recommend taking it for a spin. It even supports a sophisticated update and patch downloading system to make keeping it up to date easy. That's something a lot of Open Source systems are lacking lately.

Tags:

The Perl Deployment Kit

Published On: 2005-06-02 01:30:17
So work has bought me the perl deployment kit from ActiveState. It allows me to compile perl scripts into executables. I think it builds on the experimental perlcc and family of utilities. All I can say is wow is that cool or what. It allows me take perl scripts I design to make administration tasks easier and turn them into executables for use elsewhere without installing perl on the target computer. I can make system tray applications, system services, and standalone executables. I am going to have a lot of fun with this.

Tags:

The Power of Modular XHTML Yet another old article popping up

Published On: 2005-05-17 04:13:43
Over at A List Apart They are talking about custom DTD and Modular XHTML So I thought I'd dig up an old article I wrote on the subject and share it with you yet again. The Power of Modular XHTML

Tags:

Old Article Back up

Published On: 2005-05-04 01:30:17
I am slowly getting some of my old article's back up and online. You will start to see them in the links under pages on the sidebar. As I determine they are useful or helpful I will put them back up. The first is Perl and CGI part I I really should do part II of that one I suppose :-)

Tags:

App VS. Page

Published On: 2005-04-11 22:49:33
Software Development on the Web is undergoing a revolution. We've had the ability to build responsive, useable, dynamic applications for quite a while now. But no one has capitalized on it. No one has been building those applications. Most web developers are still stuck in the WebPage mode of design and not the WebApp mode of design. Thankfully, companies like Google are starting to give the WebApp design philosophy some high profile attention with apps like Gmail and Google Maps. So what exactly is the difference? There are a number of radical differences between WebApp and WebPage Design modes. Each has a use in website designing. Webpage Design is about presenting information. It focuses on making the content readable, understandable, and locatable. Reference sites, and online literature sites do well with this design philosophy. Blogs are another instance where the WebPage Design philosophy works well. \ WebApp Design, on the other hand, focuses on responsive, dynamic, realtime action. Sites that allow the user to do something benefit the most from this approach. The Administration front ends to Reference sites, a WebMail site, and Online Game sites are all excellent candidates for the web app approach to design. Elements of these approaches to design are now getting combined in interesting ways. Google's autocomplete feature is one example. A melding of the two can only be beneficial to Web Development trends. In future articles I will be talking about some of the technologies that make these trends possible.

Tags: