<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1499008639029127945</id><updated>2011-10-31T05:46:25.264-07:00</updated><category term='mvc'/><category term='snippet'/><category term='accessibility'/><category term='css'/><category term='rant www web http'/><category term='javascript'/><category term='java'/><category term='plugin'/><category term='flickr'/><category term='php'/><category term='oo'/><category term='orm'/><category term='article'/><category term='symfony'/><category term='xhtml'/><category term='rdbms'/><category term='post'/><category term='rant'/><title type='text'>sjohnr's rant pages</title><subtitle type='html'>Not just rants, really &lt;em&gt;good&lt;/em&gt; rants!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-1987171636123379954</id><published>2011-02-01T17:42:00.000-08:00</published><updated>2011-02-01T18:34:38.915-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>STFU Problem Solving</title><content type='html'>You are an idiot...&lt;br /&gt;&lt;br /&gt;STFU Problem Solving (otherwise known as "Shut the !@#$ Up Problem Solving" is a technique that lazy no-good completely inept barely-technical wannabe-good-programmer manager types employ to screw their team members over in order to get executives off their back so they can keep on doing nothing useful and making money while doing it. It usually comes with a lot of buzz-words, worthless analysis, copy-and-paste descriptions from the websites of open-source technologies barely worth their weight in crap, and a lot of sunshine-up-your-@$$ bull**** about how it'll solve every problem under the sun, without any thought as to how it solves any problems whatsoever, let alone the one that actually needs solving. It's almost always synonymous with under or over-architecting through in-place hackery and bastardizing of existing code to the point where it is barely recognizable, not that it ever was in the first place because your code sucks and you're an idiot to boot.&lt;br /&gt;&lt;br /&gt;As an example, can someone PLEEEEEEEEEEEASE enlighten me as to how the technology that Google uses to index search results in html pages can be of ANY use for inline processing or distributed caching. If you can split up backend batch processing of large vats of data (such as 4 PB of html pages), such a technology might be of considerable use. The distributed nature of such a technology is useful for splitting up those vats of data into smaller vats. But processing data inline, using such a distributed file-system to organize totally independent processing engines, and using the distributed nature of said file-system to maintain the option to somehow consider those data-sets "contiguous" is completely asinine and serves no purpose whatsoever.&lt;br /&gt;&lt;br /&gt;And the best part about such ideas is the no-talent waste-of-space worthless two-face lying no-good sack of crap that they came from. A manager type leader who can't help but lie through their teeth every chance they get. For instance, acting as though an open dialogue about the inherent flaws of most half-@$$ed open-source technologies is completely appropriate until the day you are overheard by someone important in the company, and it turns out you should've shut the crap up a long time ago. This type of two-faced act demonstrates with great transparency the true nature of such an individual and the fact that most of the promises made by them were empty and the statements made by them were complete hokum. It really puts in perspective just how stupid successful people can become, especially when their sole concern becomes rising in the ranks at the expense of everything meaningful, whilst telling lies and destroying hope at every turn.&lt;br /&gt;&lt;br /&gt;You. Are. An. Idiot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-1987171636123379954?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/1987171636123379954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=1987171636123379954' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1987171636123379954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1987171636123379954'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2011/02/stfu-problem-solving.html' title='STFU Problem Solving'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-1378044761189370315</id><published>2008-08-28T00:17:00.000-07:00</published><updated>2008-08-28T01:02:31.471-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant www web http'/><title type='text'>To www Or Not To www</title><content type='html'>You are an idiot!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.yes-www.org/www-is-not-deprecated/"&gt;Are you kidding me&lt;/a&gt;? The author of this article at yes-www.org completely misses the mark, as well as all (or at least most) of the commenters. Why are all the "experts" actually idiots? Anyway...&lt;br /&gt;&lt;br /&gt;First, I would like to say that I completely agree with the statement made by the author. http://www. should &lt;span style="font-weight: bold;"&gt;always&lt;/span&gt; be at the beginning of a root domain URL (http://www.example.com). The reason has nothing to do with &lt;span style="font-weight: bold;"&gt;protocols&lt;/span&gt;, however. Nor does the reason have anything to do with &lt;span style="font-weight: bold;"&gt;hosts&lt;/span&gt; (at least not strictly speaking). First, let's examine some ridiculous claims about this debate.&lt;br /&gt;&lt;blockquote&gt;The main reason I argue for leaving the www. in URLs is that it serves as a gentle reminder that there are other services than the Web on the Internet. Some of these, such as FTP and DNS, users typically use transparently without even realizing it. Others, such as e-mail, users access through separate applications. Even so, I know of many users who will claim with a straight face that e-mail is not part of the Internet.&lt;/blockquote&gt;This is just plain wrong.  http://www. has nothing to do with protocol. When using a &lt;span style="font-weight: bold;"&gt;web browser&lt;/span&gt;, people intend to browse the &lt;span style="font-weight: bold;"&gt;web&lt;/span&gt;. Therefore, http:// is completely unnecessary, in terms of entering an address. However, www has nothing to do with the protocol. Web is presented as http protocol requests. www is a concept indicating a network. As several comments on this post stated, if you want something other than http:// then &lt;span style="font-weight: bold;"&gt;enter it&lt;/span&gt;!!! (ftp://example.com)&lt;br /&gt;&lt;blockquote&gt;I think you just made my argument for me, and betrayed your lack of knowledge of how the Internet works. :) First off, www is not a “subdomain,” it’s a “host.” Second, how do you intend to disambiguate the HTTP server and the FTP server, which may well be located on different hosts?&lt;br /&gt;&lt;/blockquote&gt;This too is just plain wrong. I love it when people are quick to point out others' ignorance when they themselves possess unsurpassed ignorance. Of course, their ignorance is based on arrogance, so that must not really count, right? &lt;span style="font-weight: bold;"&gt;*ahem*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We are talking about &lt;span style="font-weight: bold;"&gt;URLs&lt;/span&gt; here people!!! Remember what that stands for? Uniform Resource Locator. URLs are easily memorable names that are translated to IP addresses via DNS. The concept of a subdomain is simple. A top level domain (com, org, net, etc.) is prefixed with a domain name (example.com, something.org, etc.). This domain name--as a URL--can have many subdomains (images.example.com, mail.example.com). In terms of URLs, these are subdomains.&lt;br /&gt;&lt;br /&gt;However, a URL is translated to an IP address, so images.example.com could--but is not required to--be a different address (or host) from mail.example.com.&lt;br /&gt;&lt;br /&gt;As for http://www. in the URL, the reasoning for its use is simple. If a site is using subdomains, it would be consistent for the root website (under http protocol, duh--no one cares about this fact for this debate) to be at the subdomain www. Why, you may ask? Historical reasons? No! And yes!&lt;br /&gt;&lt;br /&gt;Historically, the www subdomain indicated a website on a domain, or the host on a network serving the website represented by a domain (www.pepsi.com). Today, it could indicate a root website or a root/default host (www.google.com vs. mail.google.com). Therefore, for consistency if nothing else, www should always be in the URL! So the question remains, do we force our users to remember/understand/use http://www??? Absolutely not!!! What a waste of time and effort by everyone involved. Redirect, for the love of God! If someone visits http://example.com, they should be 301 redirected to http://www.example.com.&lt;br /&gt;&lt;br /&gt;Finally, another extremely good reason to use www as a subdomain involves shared hosts and multi-faceted websites. If you have a brain, and you're using a shared host (or even a home-grown server for that matter), you organize your websites properly. For example, let's say you own example.com and something.org. In your html root directory (where all html content is stored and served from), you ought to have two folders, like this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;example/&lt;/li&gt;&lt;li&gt;something/&lt;/li&gt;&lt;/ul&gt;Most likely, example.com is not the only site/host/domain you will use for example.com. You will likely have blog.example.com or images.example.com or something! But of course, you have a site at example.com itself (that is, on the default subdomain www.example.com). So your folder structure should be like this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;example/&lt;ul&gt;&lt;li&gt;www/&lt;/li&gt;&lt;li&gt;images/&lt;/li&gt;&lt;li&gt;blog/&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;something/&lt;ul&gt;&lt;li&gt;www/&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;Your organization scheme should map one-to-one with your subdomain scheme. And for consistency, you should always be using subdomains (ie. www, images, blog). Notice how all of these subdomains are web related. If you happen to have other hosts using subdomains, everything will still play nice (mail.example.com). See?&lt;br /&gt;&lt;br /&gt;If you disagree with me, you're an idiot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-1378044761189370315?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/1378044761189370315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=1378044761189370315' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1378044761189370315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1378044761189370315'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/08/to-www-or-not-to-www.html' title='To www Or Not To www'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-2817104059007485925</id><published>2008-02-28T21:52:00.000-08:00</published><updated>2008-02-28T21:54:57.654-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='post'/><title type='text'>Javascript Inheritance, v3</title><content type='html'>Apparently, I'm an idiot. Ironic isn't it? &lt;a href="http://sjohnr.blogspot.com/"&gt;You're not the idiot anymore&lt;/a&gt;.  Anyway, my javascript inheritance, methodology #4 below doesn't actually work.  Go figure.  I recently re-read &lt;a href="http://javascript.crockford.com/inheritance.html"&gt;Doug Crockford's inheritance in javascript&lt;/a&gt; article and realized that his solution had the missing salt I needed.  I'll post the code soon, once I can figure out if it's actually foolproof.&lt;br /&gt;&lt;br /&gt;Yeah yeah, laugh it up.  I am!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-2817104059007485925?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/2817104059007485925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=2817104059007485925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/2817104059007485925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/2817104059007485925'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/02/javascript-inheritance-v3.html' title='Javascript Inheritance, v3'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-3330822173571098120</id><published>2008-02-17T21:03:00.000-08:00</published><updated>2008-02-17T21:20:54.419-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Javascript default parameters</title><content type='html'>I for one absolutely hate the feature of untyped languages that forces only one method signature to be defined.  Not necessarily the part where there's only one signature, so much as the inability to define parameters as optional.  In php, one can specify certain later parameters to have default values.  If omitted, those parameters will default, allowing the function to perform as expected.  In javascript however, as in perl and other untyped languages, the developer must deal with this issue when defining the function, documenting it, and then calling it.  This is just absolutely unacceptable.  It allows for sloppy coding on either end, and the ability for "loose" functions which take ridiculous combinations of parameters which are so unintuitive as to render the function utterly useless.  Still, it can be done clean enough for some likes, but it could be handled so much better.&lt;br /&gt;&lt;br /&gt;For this reason, I decided, through inspiration and necessity, to engineer a helper for this issue.  It can be used as a utility of the Function global object, or refactored to be applied to the Function prototype.  It is largely the same either way.  To make the function short, I'm using a prototype-like utility function, $A, which casts an array-like object into a proper array.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Function.default = function(__method) {&lt;br /&gt; if (!arguments.length || arguments.length &lt; 2) {&lt;br /&gt;  return __method;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; var args = $A(arguments).slice(1);&lt;br /&gt; return function() {&lt;br /&gt;  return __method.apply(this, $A(arguments).concat(args.slice(arguments.length)));&lt;br /&gt; };&lt;br /&gt;};&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;As a note, if the caller or function enhancing code itself is passing the wrong number of arguments, the function will perform as if the wrong number of arguments was passed to the original function.  Which, as we all know, is the developers fault, not mine.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;function fn(var1, var2, var3) {&lt;br /&gt;    alert(var1 + "::" + var2 + "::" + var3);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var fn2 = Function.default(fn, "test", "test2", "test3");&lt;br /&gt;&lt;br /&gt;fn2(); // all defaults are used&lt;br /&gt;fn2("a", "b"); // last default is used&lt;br /&gt;fn2("a", "b", "c", "d"); // final argument ignored, as expected&lt;br /&gt;&lt;br /&gt;var fn3 = Function.default(fn, "test");&lt;br /&gt;&lt;br /&gt;fn3(); // first default used, final two parameters undefined, as expected&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-3330822173571098120?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/3330822173571098120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=3330822173571098120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/3330822173571098120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/3330822173571098120'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/02/javascript-default-parameters.html' title='Javascript default parameters'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-6832660752552076467</id><published>2008-02-09T19:11:00.001-08:00</published><updated>2008-02-10T18:19:22.589-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='article'/><title type='text'>Javascript Inheritance, examples</title><content type='html'>Ok, so here we are.  We've seen the code to actually achieve true object orientation in javascript, albeit a simulated variant of the paradigm, but still, there it is.  Now, as most developers think their stuff is the right, I had neglected to see who has thought like I had, "What if javascript &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; simulated OO, not just gave you a cheap knockoff," (see methodology #3 below).&lt;br /&gt;&lt;br /&gt;In an attempt to rectify said foolish ambition, I decided to do a little research.  I probably haven't done enough yet, but I found several articles dealing with this exact topic. The site twologic has two (&lt;a href="http://twologic.com/weblog/2006/05/23/object-inheritance-with-javascript/"&gt;one&lt;/a&gt;, &lt;a href="http://twologic.com/projects/inheritance/"&gt;two&lt;/a&gt;), as well as &lt;a href="http://dean.edwards.name/weblog/2006/03/base/"&gt;dean edwards&lt;/a&gt;, and of course, &lt;a href="http://javascript.crockford.com/inheritance.html"&gt;douglas crockford&lt;/a&gt;. Now, I'm really sorry to say it, but none of these examples really comes close. I mean, twologic has done a decent job of making the super calls accessible, but making it first for prototype was a really bad idea, since it can be made much simpler from scratch.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Examples&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now for some examples of use. Here is a somewhat classic example, using our favorite subject on basic object oriented principles, the animal.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;var Animal = function(name, sound) {&lt;br /&gt; this.sound = sound;&lt;br /&gt;};&lt;br /&gt;Animal.prototype = {&lt;br /&gt; makeSound: function() {&lt;br /&gt;  alert(this.name + " says " + this.sound);&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;var Cat = function() {&lt;br /&gt; this.superclass("Cat", "meowwww!!!");&lt;br /&gt;};&lt;br /&gt;Cat.prototype = {&lt;br /&gt; makeSound: function() {&lt;br /&gt;  this.superclass.makeSound();&lt;br /&gt;  &lt;br /&gt;  alert("... meow?");&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;var Dog = function(owner) {&lt;br /&gt; this.superclass("Dog", "woof!");&lt;br /&gt; this.owner = owner;&lt;br /&gt;};&lt;br /&gt;Dog.prototype = {&lt;br /&gt; makeSound: function() {&lt;br /&gt;  alert("I wuv " + this.owner);&lt;br /&gt;  &lt;br /&gt;  this.superclass.makeSound();&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Object.inherit(Cat, Animal);&lt;br /&gt;Object.inherit(Dog, Animal);&lt;br /&gt;&lt;br /&gt;var cat = new Cat();&lt;br /&gt;var dog = new Dog("Bob Dylan");&lt;br /&gt;&lt;br /&gt;cat.makeSound();&lt;br /&gt;dog.makeSound();&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, there should be a fair amount of familiarity with this if you come from most any background, I assume.  However, fellow java programmers will recognize it rather quickly. The only real difference is the need for &lt;span style="font-style: italic;"&gt;this&lt;/span&gt; which is a basic javascript requirement, and &lt;span style="font-style: italic;"&gt;superclass&lt;/span&gt; instead of &lt;span style="font-style: italic;"&gt;super&lt;/span&gt; which was just a whim (or perhaps influenced by some library, like YUI, I dunno...).&lt;br /&gt;&lt;br /&gt;At any rate, I hope you can see the differences between my implementation, which is completely intuitive to programmers familiar with other oo languages, and everything else, which at present, doesn't seem to go the full distance for one reason or another.  Also, you should notice my implementation is very small, and makes twice as much sense to anyone wishing to learn from the code.&lt;br /&gt;&lt;br /&gt;Any time now, I may be told I'm quite out of line, or have made some dumb mistake... if so, I'll simply edit this post and claim I knew it all along.. Until then, check out &lt;a href="http://www.iconium.org/js"&gt;my site&lt;/a&gt; for the developing base of clean code just like this, and please leave comments so I know what you're thinking.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-6832660752552076467?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/6832660752552076467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=6832660752552076467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/6832660752552076467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/6832660752552076467'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/02/javascript-inheritance-examples.html' title='Javascript Inheritance, examples'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-2065369211557370275</id><published>2008-02-09T09:24:00.000-08:00</published><updated>2008-02-09T19:41:45.607-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='article'/><category scheme='http://www.blogger.com/atom/ns#' term='oo'/><title type='text'>Javascript Inheritance, v2</title><content type='html'>In an earlier post, I presented a mechanism for simulating javascript inheritance. It was, of course, incorrect. I tested the implementation and believed it to work, but found out shortly thereafter that I was wrong. However, this leads me into a discussion about javascript simulated inheritance, and a presentation of the correct solution also.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Inheritance, methodology 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are several approaches that exist to simulate inheritance, ranging from simple and effective, to extremely complex. This first method is quite simple, and is a feature that, were it in formalized object oriented languages in some form, would be quite useful, though possibly destructive in regards to the standard oo features.&lt;br /&gt;&lt;br /&gt;This method involves simply copying properties (namely functions) from one object to another. This can be used to temporarily enhance an instance of an object, or to perform "mixins" of one function group into another function group. The mixin feature would, in a formalized oo language, be referred to as multiple inheritance.  It is of course mostly impossible to do in said languages because of its implications on polymorphism. Here is the borrow mechanism in javascript.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Object.borrow = function(destination, source) {&lt;br /&gt; for (var key in source) {&lt;br /&gt;  destination[key] = destination[key] || source[key];&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; return destination;&lt;br /&gt;};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Inheritance, methodology 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second method resembles the first, except that it specifically targets the prototype of two existing classes (constructor functions).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Object.augment = function(destination, source) {&lt;br /&gt; for (var key in source.prototype) {&lt;br /&gt;  destination.prototype[key] = destination.prototype[key] || source.prototype[key];&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; return destination;&lt;br /&gt;};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Inheritance, methodology 3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The third method involves something slightly more complex, for much grander results. This approach is what I consider to be the most popular and classical implementation of javascript simulated inheritance. It is known by most as constructor chaining. In my opinion, this is actually a convenience around constructor chaining, since you could do that without any implementation at all. In fact, the real heart of this implementation is creating a class (constructor function) whose prototype is in fact an instance of another class. Using the instanceof operator would yield expected results when operating on an instance of the child class. However, the constructor chaining feature is provided for simple convenience, and doesn't add anything to this implementation.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Object.extend = function(destination, source) {&lt;br /&gt; var obj = function() {};&lt;br /&gt; obj.prototype = source.prototype;&lt;br /&gt; &lt;br /&gt; var proto = destination.prototype;&lt;br /&gt; destination.prototype = new obj();&lt;br /&gt; destination.prototype.constructor = destination;&lt;br /&gt; for (var key in proto) {&lt;br /&gt;  destination.prototype[key] = proto[key];&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; destination.prototype.superclass = source;&lt;br /&gt; &lt;br /&gt; return destination;&lt;br /&gt;};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Inheritance, methodology 4&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The final method is where I've attempted to go, and had at first failed miserably. This final attempt has yielded the true implementation I was looking for, though it contains one very small but disappointing drawback.&lt;br /&gt;&lt;br /&gt;First, you should notice immediately that this implementation allows for more than just constructor chaining (which is always via the Function.prototype.call or Function.prototype.apply methods in the ECMAScript standard). In fact, this implementation does all of that for you, and so in my opinion truly simulates inheritance, where the other implementations were just a hearty attempt to bring (in)convenience to something that was already altogether inconvenient in the first place.&lt;br /&gt;&lt;br /&gt;Unfortunately, this approach does call for one stipulation. The function called &lt;span style="font-style: italic;"&gt;superclass&lt;/span&gt; is added to the prototype of the subclass, which is analogous to the &lt;span style="font-style: italic;"&gt;super&lt;/span&gt; keyword in java. This function MUST be called as the first thing the subclass constructor does, or else nothing works that you intended to work with inheritance. Well, that's not completely true, but the true features of this implementation would not be present. This is because javascript scoping is terribly painful, and there would be no way to bind a superclass function to being executed in the scope of a subclass without access to the instance of the subclass. This instance can only be obtained at instantiation time, or sometime thereafter. Apropos, an instance of the subclass will be dynamically added to the &lt;span style="font-style: italic;"&gt;superclass&lt;/span&gt; variable, and all dynamically bound functions of the superclass will be called in the scope of this &lt;span style="font-style: italic;"&gt;subclass&lt;/span&gt; variable when called using the &lt;span style="font-style: italic;"&gt;superclass&lt;/span&gt; variable from the subclass. &lt;span style="font-weight: bold;"&gt;*whew*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Object.inherit = function(destination, source) {&lt;br /&gt; var obj = function() {};&lt;br /&gt; obj.prototype = source.prototype;&lt;br /&gt; &lt;br /&gt; var proto = destination.prototype;&lt;br /&gt; destination.prototype = new obj();&lt;br /&gt; destination.prototype.constructor = destination;&lt;br /&gt; for (var key in proto) {&lt;br /&gt;  destination.prototype[key] = proto[key];&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; var constructor = function() {&lt;br /&gt;  this.superclass.subclass = this;&lt;br /&gt;  this.superclass.prototype.constructor.apply(this, arguments);&lt;br /&gt; };&lt;br /&gt; &lt;br /&gt; destination.prototype.superclass = constructor;&lt;br /&gt; destination.prototype.superclass.prototype.constructor = source;&lt;br /&gt; &lt;br /&gt; for (var key in source.prototype) {&lt;br /&gt;  destination.prototype.superclass[key] = (function(__method) {&lt;br /&gt;   return function() {&lt;br /&gt;    return __method.apply(this.subclass, arguments);&lt;br /&gt;   };&lt;br /&gt;  })(source.prototype[key]);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; return destination;&lt;br /&gt;};&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-2065369211557370275?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/2065369211557370275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=2065369211557370275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/2065369211557370275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/2065369211557370275'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/02/javascript-inheritance-v2.html' title='Javascript Inheritance, v2'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-3089250293509098284</id><published>2008-02-03T13:39:00.000-08:00</published><updated>2008-02-03T13:45:23.751-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Javascript Snippets Project</title><content type='html'>On my website, I've recently launched a project to catalog and collect all worthwhile enhancements and snippets to the javascript scripting language.  The project is first and foremost an effort to clean and standardize these modules to be more useful on a piecemeal basis, for those who need a solution to a common problem but don't want a whole library.  Also, the project could serve as a fundamental grounding for those who are learning javascript, and want to learn how to accomplish common tasks using functional and object oriented programming.&lt;br /&gt;&lt;br /&gt;This section is powered by php using a flat file structure to store the backend posts.  Eventually, the javascript section will include mixin documentation for each post, as well as a comments section.  Since I'm currently not using a db for my site's backend (I'm using rss feeds from blogger and flickr), I may not get around to this for a few.  Not that it will be hard to add a db, but I wanted to see how many much dynamic content I could add to my site without a db.  &lt;a href="http://www.iconium.org/js"&gt;Check it out now&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-3089250293509098284?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/3089250293509098284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=3089250293509098284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/3089250293509098284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/3089250293509098284'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/02/javascript-snippets-project.html' title='Javascript Snippets Project'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-8746964651159328748</id><published>2008-01-30T21:36:00.000-08:00</published><updated>2008-02-09T10:57:04.904-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Javascript Inheritance</title><content type='html'>Today, as I was working on developing an inheritance hierarchy based chain of classes in javascript, I realized just how truly possible OO was.  Of course, it remains the world's giantest (yep, I know it ain't a word) hack.  But, that being said, it's still cool.&lt;br /&gt;&lt;br /&gt;Now, I can't take 100% claim for this, as I borrowed small segments of inheritance implementations from several javascript libraries, namely &lt;a href="http://protoypejs.org/"&gt;prototype&lt;/a&gt; and &lt;a href="http://developer.yahoo.com/yui"&gt;YUI&lt;/a&gt;, as well as the O'Reilly Definitive Guide to Javascript.  However, this implementation is much better than all of those.  To set it up, here is an example of use:&lt;br /&gt;&lt;br /&gt;&lt;code id="js-snippet-1"&gt;var C1 = function(var1) {&lt;br /&gt; this.var1 = var1;&lt;br /&gt;};&lt;br /&gt;C1.prototype = {&lt;br /&gt; test: function() {&lt;br /&gt;   alert(this.var1 + " is in C1");&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;var C2 = function(var1, var2) {&lt;br /&gt; this.superclass(var1);&lt;br /&gt; this.var2 = var2;&lt;br /&gt;};&lt;br /&gt;C2.prototype = {&lt;br /&gt; test: function() {&lt;br /&gt;   this.superclass.test();&lt;br /&gt;   alert(this.var1 + " + " + this.var2 + " is in C2");&lt;br /&gt; },&lt;br /&gt; stuff: function() {&lt;br /&gt;   alert("stuff is just a regular function");&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Object.extend(C2, C1);&lt;br /&gt;&lt;br /&gt;var c1 = new C1("arg1");&lt;br /&gt;var c2 = new C2("arg1", "arg2");&lt;br /&gt;&lt;br /&gt;c1.test();&lt;br /&gt;c2.test();&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Doesn't that look familiar?  Reminds me an awful lot of OO in a real OO language, like java.  Here you go!&lt;br /&gt;(&lt;span style="font-weight: bold;"&gt;edit: See "Javascript Inheritance, v2" above for the correct implementation.&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;code id="js-snippet-2"&gt;Object.borrow = function(destination, source) {&lt;br /&gt; for (var key in source) {&lt;br /&gt;   destination[key] = destination[key] || source[key];&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return destination;&lt;br /&gt;};&lt;br /&gt;Object.augment = function(destination, source) {&lt;br /&gt; for (var key in source.prototype) {&lt;br /&gt;   destination.prototype[key] = destination.prototype[key] || sour$&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return destination;&lt;br /&gt;};&lt;br /&gt;Object.extend = function(destination, source) {&lt;br /&gt; var obj = function() {};&lt;br /&gt; obj.prototype = source.prototype;&lt;br /&gt;&lt;br /&gt; var proto = destination.prototype;&lt;br /&gt; destination.prototype = new obj();&lt;br /&gt; destination.prototype.constructor = destination;&lt;br /&gt; for (var key in proto) {&lt;br /&gt;   destination.prototype[key] = proto[key];&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; var constructor = function() {&lt;br /&gt;   this.superclass.prototype.constructor.apply(this, arguments);&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; destination.prototype.superclass = constructor;&lt;br /&gt; destination.prototype.superclass.prototype.constructor = source;&lt;br /&gt; for (var key in source.prototype) {&lt;br /&gt;   destination.prototype.superclass[key] = source.prototype[key];&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return destination;&lt;br /&gt;};&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-8746964651159328748?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/8746964651159328748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=8746964651159328748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/8746964651159328748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/8746964651159328748'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2008/01/javascript-inheritance.html' title='Javascript Inheritance'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-2726956706265936096</id><published>2007-12-16T12:27:00.001-08:00</published><updated>2007-12-16T13:10:15.013-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='orm'/><category scheme='http://www.blogger.com/atom/ns#' term='rdbms'/><category scheme='http://www.blogger.com/atom/ns#' term='oo'/><title type='text'>Object Orientation v. The World, Round 1</title><content type='html'>*ding* Announcer: Begin round 1!&lt;br /&gt;&lt;br /&gt;You are an idiot!&lt;br /&gt;&lt;br /&gt;I recently read an article attempting to bash the hype out of OO, and kill it for good.  Of course, the guy was born in 1750 BC or something, and hasn't even bothered to update his knowledge on recent advancements in programming and data technology in 15 years or so.&lt;br /&gt;&lt;br /&gt;Even so, it was a decent read, and had many astoundingly good observations about the differences between OO, and say... relational paradigms.  However, these arguments did little to promote his pet paradigm, that of procedural.  Granted, his real aim was to bash OO regardless of what that happened to promote.  Furthermore, he wasn't able to provide anything that fixed problems with OO but provided all its benefits.&lt;br /&gt;&lt;br /&gt;The first interesting observation about procedural programming that has come into my head involves the primitive idea of a class, versus any combination of concepts to achieve something similar in procedural.  The idea of a struct comes close to producing what has been perfected in classes for data encapsulation.  Programmers very typically grouped their data into structs for transfer and ease-of-use.  Similarly, function groups, typically organized in a physical file structure, sought to make functions or subroutines easy to use and manage.&lt;br /&gt;&lt;br /&gt;I am convinced that a reasonably intelligent procedural programmer from the '70's, locked in a room for 20 years, would come out with OO as his "revelation" for time spent; of course only to be introduced to the real OO which was invented by ambitious procedural programmers who were sick of having sucky code organization and very little programmatic power.&lt;br /&gt;&lt;br /&gt;Unfortunately, you talk to an older programmer who wasn't locked in that box, and had no interest in paying attention to advances in computing for those 20 years, and he will scorn OO because... well... because it's different!  He'll use arguments like the Object Relational Impedance Mismatch to claim that OO just plain sucks.  You are an idiot!&lt;br /&gt;&lt;br /&gt;On that note, here's something to chew on: If the gap between OO and relational paradigms is so vast and irreconcilable, then why are technologies like JPA (Java Persistence API) so incredibly successful.  People have for many years doubted the ability of Object Relational Mapping to be of much use in bridging the chasm.  However, with an incredibly well written mapping technology, the gap seems to have been successfully bridged.  Proponents of old school relational algebra claim that the power of this paradigm has been lost.  Interesting... So, when my ORM tool uses joins (probably in SQL) to create a beautiful object graph from my Object Model using its mapping metadata, and I can traverse my object graph in OO without any loss in the power behind Set Theory, that would be... what? A lucky break?&lt;br /&gt;&lt;br /&gt;Furthermore, the advances in persistence and ORM technology create a very interesting case for the success of OODBMS's.  From the application point of view, and even from a scalability point of view, the data source powering my application is an OODBMS.  This, of course, has DBA's hopping mad, because they don't have a job anymore.  No longer will the application rely on proprietary features of an RDBMS vendor to provide essential functions like security, concurrency control, and transactions, to name a few.  They claim that we waste the power in those vendor products, by implementing them on top of our application technology.&lt;br /&gt;&lt;br /&gt;This isn't a case for high-level layer confusion.  No, this is a case of proper technology advancement.  All the concepts embedded into state-of-the-art RDBMS technologies have paved the way for properly bridging the gap between relational and OO, by moving said features from the DBMS to the application, and leaving the RDBMS to be simply a persistence store, optimized to deal with disk access only when needed for scalability optimization.  The first 20 years of DBMS work were on perfecting that very issue.  And now that those products also support concurrency, transactions, etc. you're sad to see those functions re-engineered into a more applicable layer of the application.  Hmm... touch luck.  If you're a dba, I'd say you ought to get more than a business degree, and move on with your less-than-average life.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-2726956706265936096?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/2726956706265936096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=2726956706265936096' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/2726956706265936096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/2726956706265936096'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/12/object-orientation-v-world-round-1.html' title='Object Orientation v. The World, Round 1'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-1047910650188598516</id><published>2007-08-15T20:07:00.000-07:00</published><updated>2008-01-30T22:12:17.291-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='article'/><title type='text'>The Need for Separation, Part 2</title><content type='html'>As mentioned previously, a framework of sorts is the solution for adding power to the &lt;span style="font-style: italic;"&gt;servlet controller + jsp view&lt;/span&gt; approach.  To free the developer up from managing urls, and allowing them to have units of controller logic automatically tied to corresponding views (html, xml, txt, csv, etc.) is a decided improvement in application design.  In the realm of &lt;a href="http://en.wikipedia.org/wiki/Rapid_Application_Development"&gt;rapid application development&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Agile_software_development"&gt;agile&lt;/a&gt; programming practices, the ability to free the mind of these cumbersome tasks, with a standard organization structure improves the ability of the programmer to provide maintainable applications quickly and in a cost-effective manner.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Front Controller&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The cornerstone of an MVC framework is the front controller.  This approach requires commitment to using one, and only one, entry point into the application for a given client type.  For instance, a web browser client would be given access to every page of a web application through some standard url, like &lt;code&gt;/MyServletController&lt;/code&gt; or &lt;code&gt;/index.jsp&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The reasoning behind this approach is simple.  First, it gives the software, and therefore the programmer, the ability to handle url management internally, instead of externally.  Any mechanism for decomposing and rationalizing urls is available to the programmer.  This eliminates the need to maintain url mappings.  Also, in the context of agile, it allows for the rapid deployment of web components, with no more administrative tasks required than adding an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag pointing to pages in the module component.  The url would be automatically translated by whatever code sits behind the front controller, and control of the application can be routed to the appropriate module or component for processing--in a word, "automagically."  In the servlet world, the request object gives the front controller the power to later forward control to a jsp page for view processing, so both the controller logic and the view logic can be handled in independent sections of the application.&lt;br /&gt;&lt;br /&gt;Without further ado, let's see an example of a front controller servlet.  This example uses (at this point) mystical java classes to do most of its' work.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;public class DispatcherServlet extends HttpServlet&lt;br /&gt;{&lt;br /&gt;    /**&lt;br /&gt;     * Processes requests for both HTTP &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; methods.&lt;br /&gt;     *&lt;br /&gt;     * @param request servlet request&lt;br /&gt;     * @param response servlet response&lt;br /&gt;     */&lt;br /&gt;    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException&lt;br /&gt;    {&lt;br /&gt;        ServletContext context = getServletConfig().getServletContext();&lt;br /&gt;        WebController controller = new WebController(context, request, response);&lt;br /&gt;        &lt;br /&gt;        // dispatch the request to the "framework"&lt;br /&gt;        String view = controller.dispatch();&lt;br /&gt;        &lt;br /&gt;        // forward control to the jsp view for processing&lt;br /&gt;        request.getRequestDispatcher(view).forward(request, response);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * Handles the HTTP &lt;code&gt;GET&lt;/code&gt; method.&lt;br /&gt;     *&lt;br /&gt;     * @param request servlet request&lt;br /&gt;     * @param response servlet response&lt;br /&gt;     */&lt;br /&gt;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException&lt;br /&gt;    {&lt;br /&gt;        processRequest(request, response);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * Handles the HTTP &lt;code&gt;POST&lt;/code&gt; method.&lt;br /&gt;     *&lt;br /&gt;     * @param request servlet request&lt;br /&gt;     * @param response servlet response&lt;br /&gt;     */&lt;br /&gt;    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException&lt;br /&gt;    {&lt;br /&gt;        processRequest(request, response);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next article: The Controller&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-1047910650188598516?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/1047910650188598516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=1047910650188598516' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1047910650188598516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1047910650188598516'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/08/need-for-separation-part-2.html' title='The Need for Separation, Part 2'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-7994352112527528568</id><published>2007-08-04T16:31:00.000-07:00</published><updated>2007-08-04T18:42:11.293-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='article'/><title type='text'>The Need for Separation, Part 1</title><content type='html'>In the first article in a series, dealing with MVC separation using the Java Platform, Enterprise Edition, we will explore available technologies in Java EE.  Then, we will see how using them without structure causes immense problems in the exact type of application Java EE was built for: big ones!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;The Problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Core technologies for presenting dynamic web pages in Java EE are Servlets and JSP (Java Server Pages).  For the sake of this article, I will assume familiarity with both technologies.  Two organization structures of these technologies is naturally apparent.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Straight JSP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first approach in the context of a large application is to manage a number of jsp pages, which make use of java beans and scriptlet code to make calls to java classes in the main portion of the application.  These types of calls and code will be sprinkled throughout the jsp, whose predominant purpose is to put together the html response to a client request.  As mentioned before, this is in the context of a large web application.  When dealing with a simple, small, and relatively static web application, this organization structure is easy to use, and typically doesn't present a large maintainability problem.  As soon as the application grows beyond a few pages, it becomes largely difficult to keep this sprinkled logic mixed with html organized.  If you analyze an application built this way, you should also immediately be aware of the poor form and design of the application.  Also, the urls in the application are strongly tied to the file organization, which is a particular problem for the purposes of search engine optimization.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Servlet Controllers&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since jsp is simply a page that is compiled into a servlet, saving the programmer the hassle of managing html through println() calls, the second obvious approach is to use servlets to perform these calls to the main portion of the application (where the "business logic" lies).  Once the calls to the business tier of the application is complete, the programmer can pass some variables to a jsp "view" using the request object provided by the servlet container.  This is a decidedly better organization for an application, because you no longer have the unwieldy mix of logic and presentation code.  This practice of separating presentation from logic is a common and well understood practice by many programmers.  The use of templating engines in several scripting languages like php is testament to the popularity of this approach.  In fact, the modern version of jsp was created for just such an approach, and would explain the ability for a servlet to forward control to a jsp page.&lt;br /&gt;&lt;br /&gt;The problem with this second approach is not obvious until the front end (the web tier) is being built.  Each servlet needs a url mapping in an xml file before it can be used to serve responses to client requests.  This presents several technical challenges.  First, while the mapping capability means that urls can be freely formatted and remain unrelated to the underlying file structure, the maintenance of these urls is not particularly desirable, as not just url patterns (groups of urls) need to be maintained, but every url in the entire application.  What's worse, each url mapping needs a corresponding servlet mapping, so the url can map to a servlet, and the servlet can map to a physical java class.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;The Solution&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The popularity of MVC frameworks is testament to the success of stacking a little bit (or a lot) of code on top of a language to provide automated functionality.  No matter your disposition on frameworks, some sort of magical functionality needs to take place in order for the manual process of mapping urls to resources to go away.  Unfortunately, this magical functionality is one step farther than the Java EE specifications have gone.  It's easy to see why it would be ineffective to provide this at the api level.  The Java EE specifications already provide (or specify how an app server should provide) a world of automatic functionality in the form of containers, factories, persistence management, etc.  To force a given organization on the code would be to destroy the power of the programming language itself, and ruin the chances of innovation for future generations of programmers.&lt;br /&gt;&lt;br /&gt;Next article: &lt;span style="font-size:100%;"&gt;The Front Controller.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-7994352112527528568?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/7994352112527528568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=7994352112527528568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/7994352112527528568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/7994352112527528568'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/08/need-for-separation-part-1.html' title='The Need for Separation, Part 1'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-9179056412729868360</id><published>2007-08-02T07:36:00.000-07:00</published><updated>2007-08-04T16:27:58.887-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='post'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><title type='text'>Java MVC Tutorials</title><content type='html'>Over the next few weeks, I will post several tutorials investigating and demonstrating transforming the Java Platform, Enterprise Edition (Java EE, previously J2EE), into an MVC platform.&lt;br /&gt;&lt;br /&gt;I will do this without the use of currently available (and rather unpleasant) MVC frameworks--like Struts, Spring, and JavaServer Faces--and with very little code.  I will also demonstrate the need for such an organization to a java project, and why Java EE out of the box (unless using an additional framework) does not provide a ready MVC organization.  If this isn't enough, I will also show how to incorporate several common web best practices into this MVC structure using standard technologies in the Java EE APIs.  Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-9179056412729868360?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/9179056412729868360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=9179056412729868360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/9179056412729868360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/9179056412729868360'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/08/java-mvc-tutorials.html' title='Java MVC Tutorials'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-986554181323683287</id><published>2007-05-01T10:22:00.000-07:00</published><updated>2007-05-07T22:25:32.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='orm'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><title type='text'>Why ORM?</title><content type='html'>Why ORM (Object-Relational-Mapping)?&lt;br /&gt;&lt;br /&gt;You are an idiot!&lt;br /&gt;&lt;br /&gt;I am getting sick and tired of having this discussion.  You think you know something about how things work, but you're not facing the facts.  If you honestly believe that using a completely procedural approach to database programming is a good idea, even in a web-based system, you are absolutely wrong!  If you think that scalability issues when hitting 100,000 users has anything to do with what database layer you're using to serve a simple page, you are absolutely wrong!  Let me break it down.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Scalability Concerns&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;High number of records&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A page that will serve a high number of records in a single load, now or in the future, must be designed as such.  It is not a complicated task to understand that a page may be used to view 25+ records, at any given time.  If this is the case, &lt;span style="font-style: italic;"&gt;very simple &lt;span style="font-weight: bold;"&gt;standard&lt;/span&gt;&lt;/span&gt; approaches should be used to solve the problem.  Pagination is your solution.  The page will scale as well as can be expected, and will not run into load issues (large amount of html data transfer), and certainly will not have memory issues, that arise simply because of the technology being used to hold data.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;High number of users&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is simply a hardware concern.  If your system expects very large numbers of users, a page that loads one record, but is hit 100,000 times a second, will have scalability issues &lt;span style="font-style: italic;"&gt;on the environmental side&lt;/span&gt;, &lt;span style="font-style: italic; font-weight: bold;"&gt;not the software side&lt;/span&gt;!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Batch processes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Any process that will do heavy lifting and operate on high numbers of records, without the use of block processes and where the concept of pagination does not apply, scalability will be of concern.  In these cases, the high learning curve of using an ORM versus procedural approaches will come into play.  The programmer simply needs to understand how to bypass the ORM in order to use procedural approaches, and the batch process operating on hundreds or thousands of records will perform fine.  Alternatively, you can hydrate objects one at a time, and discard them once used.  This will scale your memory footprint much better, and will likely make moot the issue of time scalability for hydrating those objects.&lt;br /&gt;&lt;br /&gt;Why does a batch process usually scale badly in an ORM based system?  The process of loading thousands of hydrated objects into memory suffers from the law of diminishing returns.  You get less benefit for more work performed, and as memory gets eaten up holding all the objects in memory, the process slows down.&lt;br /&gt;&lt;br /&gt;Why doesn't this concern come into play with high numbers of users, and low numbers of records?  Because a request serving one record will load an object, use it, and discard it just as quickly as the request can be processed.  The only scalability concern you will face, as discussed above, is hardware and environmental scalability.  This leads us to the conclusion (even without the need for benchmarking, which has been done, BTW) that discarding objects and allowing for memory management of the PL to take its course, will allow an ORM to be used in most situations with only minor adjustments to the approach and tactics.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Using an ORM has astronomical benefits to code organization and programmatic power in systems, including web-based ones.  Forcing procedural programming to be used in web-based systems will destroy your organizational power, making your code a complete mess, and only gains you the ability to ignore learning how to use an ORM.  You will not have a system that is any more scalable than the system written by a properly versed ORM programmer.  Comparative analysis in all other areas of these same systems will indicate that the ORM based system kicks your programs @^%$*, so shut up, idiot!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-986554181323683287?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/986554181323683287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=986554181323683287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/986554181323683287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/986554181323683287'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/05/why-orm.html' title='Why ORM?'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-87124430504442730</id><published>2007-04-24T11:55:00.000-07:00</published><updated>2008-01-30T22:28:23.353-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='flickr'/><title type='text'>Flickr Widget</title><content type='html'>I thought I'd be nice and post a flickr widget I developed in response to the fact that other flickr widgets really sucked.&lt;br /&gt;&lt;br /&gt;Here's the code for mine, to start things off:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;function jsonFlickrFeed(json)&lt;br /&gt;{&lt;br /&gt;  document.writeln('&amp;lt;ul style="margin-bottom: 0;"&amp;gt;');&lt;br /&gt;  var tpl = '&amp;lt;li&amp;gt;&amp;lt;a href="{link}"&amp;gt;&amp;lt;img width="150" src="{media}"/&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;';&lt;br /&gt;&lt;br /&gt;  for (var i = 0; i &amp;lt; 5 &amp;&amp;amp; i &amp;lt; json.items.length; i++)&lt;br /&gt;  {&lt;br /&gt;    document.writeln(&lt;br /&gt;      tpl.&lt;br /&gt;      replace('{link}', json.items[i].link).&lt;br /&gt;      replace('{media}', json.items[i].media.m)&lt;br /&gt;    );&lt;br /&gt;  }&lt;br /&gt;  document.writeln('&amp;lt;/ul&amp;gt;');&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script src="http://api.flickr.com/services/feeds/photos_public.gne?id=33268241@N00&amp;format=json" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;a id="flickr_www" href="http://www.flickr.com"&amp;gt;&amp;lt;strong style="color: rgb(57, 147, 255);"&amp;gt;www.flick&amp;lt;span style="color: rgb(255, 28, 146);"&amp;gt;r&amp;lt;/span&amp;gt;.com&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;|&lt;br /&gt;&amp;lt;a href="http://www.flickr.com/photos/sjohnr/"&amp;gt;&amp;lt;strong style="color: rgb(57, 147, 255);"&amp;gt;my flick&amp;lt;span style="color: rgb(255, 28, 146);"&amp;gt;r&amp;lt;/span&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The important thing is really the url to the json feed for your flickr site.  Mine is: http://api.flickr.com/services/feeds/photos_public.gne?id=33268241@N00&amp;amp;format=json&lt;br /&gt;&lt;br /&gt;The id in the url is not too logical, so check your flickr site (look for the "Feed" link at the bottom for the id parameter of the url).&lt;br /&gt;&lt;br /&gt;Also, the link to my flickr site is http://www.flickr.com/photos/sjohnr/ so change that link in the code to point to your site.&lt;br /&gt;&lt;br /&gt;Otherwise, I'll let you figure out how to customize the other portions of the widget, since it's not that hard.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Demo&lt;/h3&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;function jsonFlickrFeed(json){document.writeln('&lt;ul style="margin-bottom: 0;"&gt;');var tpl = '&lt;li&gt;&lt;a href="{link}"&gt;&lt;img width="150" src="{media}"/&gt;&lt;/a&gt;&lt;/li&gt;';for (var i = 0; i &lt; 5 &amp;&amp; i &lt; json.items.length; i++){document.writeln(tpl.replace('{link}', json.items[i].link).replace('{media}', json.items[i].media.m));}document.writeln('&lt;/ul&gt;');}&lt;/script&gt;&lt;script src="http://api.flickr.com/services/feeds/photos_public.gne?id=33268241@N00&amp;format=json" type="text/javascript"&gt;&lt;/script&gt;&lt;a id="flickr_www" href="http://www.flickr.com"&gt;&lt;strong style="color: rgb(57, 147, 255);"&gt;www.flick&lt;span style="color: rgb(255, 28, 146);"&gt;r&lt;/span&gt;.com&lt;/strong&gt;&lt;/a&gt;|&lt;a href="http://www.flickr.com/photos/sjohnr/"&gt;&lt;strong style="color: rgb(57, 147, 255);"&gt;my flick&lt;span style="color: rgb(255, 28, 146);"&gt;r&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-87124430504442730?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/87124430504442730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=87124430504442730' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/87124430504442730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/87124430504442730'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/04/flickr-widget.html' title='Flickr Widget'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-6786006609978256029</id><published>2007-04-19T09:51:00.000-07:00</published><updated>2007-04-19T09:53:57.328-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='post'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><title type='text'>Symfony plugin - sfDateTimePlugin</title><content type='html'>I submitted my first plugin to symfony.  It's a very sexy date manipulation library, which trumps even the pear date library as far as I can tell.  It has a long list of nice features, which I will formally type out later.  The &lt;a href="http://trac.symfony-project.com/trac/wiki/sfDateTimePlugin"&gt;sfDateTimePlugin&lt;/a&gt; is currently available on the symfony wiki, and pending validation in the pear channel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-6786006609978256029?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/6786006609978256029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=6786006609978256029' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/6786006609978256029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/6786006609978256029'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/04/symfony-plugin-sfdatetimeplugin.html' title='Symfony plugin - sfDateTimePlugin'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-1496787199168395795</id><published>2007-03-29T21:29:00.000-07:00</published><updated>2007-04-05T19:10:25.166-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xhtml'/><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><category scheme='http://www.blogger.com/atom/ns#' term='article'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>[b] and [i] versus [strong] and [em]</title><content type='html'>I think it has finally reached critical mass.  The concept of separating presentation from content is a widely accepted practice.  So why do we have &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;?&lt;br /&gt;&lt;br /&gt;I imagine a few will like a rehash of this concept, just for the sake of discussion, if nothing else.&lt;br /&gt;&lt;br /&gt;The driving force behind separation of presentation and content, and the phenomenon known as the semantic web, come from a singular source: accessibility. But what does accessibility mean or entail?&lt;br /&gt;&lt;br /&gt;Thinking of accessibility is useful even if our audience does not consist of blind folks using screen readers. Accessibility is a driving force that can be used to help us forge a new path towards a cleaner, more efficient web. Accessibility as a concept reveals weaknesses in any non-compliant website in such a way that it has become useful as a synonym for compliance. Therefore, if you approach designing a website's source code from the perspective of it being read by a screen reader, you will be able to write compliant and semantic websites from the start, and your content will have meaning outside the scope of a modern visual web browser. This is an good and important start.&lt;br /&gt;&lt;br /&gt;So back to the point. Why &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;? If we examine the trends of the w3c in defining new web standards over the last four to eight years, you will notice that tags that add semantically meaningful information to documents have been introduced, while tags that only specify presentation have been purged from the standards. The &lt;code&gt;&amp;lt;font&amp;gt;&lt;/code&gt; tag is the best example of this. In the late 90's, the web was so cluttered with horrendous html documents that were so bogged down with presentational markup that they were virtually useless, not to mention unmaintainable. The new standards have saved us from a slow and horrible fate, and for that we are thankful.&lt;br /&gt;&lt;br /&gt;However, the final two truly presentational tags, &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;, are still around and in high use. What makes them different, and why haven't they gone away? If you examine how a person would go about designing a document that has lots of &lt;b&gt;bold&lt;/b&gt; and &lt;i&gt;italic&lt;/i&gt; text that should not be read with emphasis in a screen reader, you will begin to see the usefulness of these tags. You can theoretically imagine that &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; are simply synonyms for the longer and messier &lt;code&gt;&amp;lt;span style="font-weight: bold;"&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;span style="font-style: italic;"&amp;gt;&lt;/code&gt;. Since they are so absolutely useful, they have been allowed to remain in the standard, though they are likely going away in XHTML 2.0, which may make this entire thing a moot point. Even so, as long as they remain, one could argue that they can and should be used for presentation, since they are about the only presentational tags imaginable that don't clutter up and bog down your document.&lt;br /&gt;&lt;br /&gt;Basically, keep accessibility in mind when designing documents. Imagine how you would want your document read in a screen reader, and you will come out ahead. If you have trouble with &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; tags, just use css. The only trouble that you could come across is making your styles too specific. For example, if I wanted to replace &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;, I may make some css styles like:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;span.bold {&lt;br /&gt;  font-weight: bold;&lt;br /&gt;}&lt;br /&gt;span.italic {&lt;br /&gt;  font-style: italic;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;To do this, however, would make your document pretty stupid. If you insist on using this approach (which is certainly your prerogative, and not a bad idea at all), you could do something like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;span.attention {&lt;br /&gt;  font-weight: bold;&lt;br /&gt;}&lt;br /&gt;span.notice {&lt;br /&gt;  font-style: italic;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;By doing this, you would be declaring that you have visually impactive sections of your document that are still simply text, and shouldn't be interpreted as anything else, except visually. However, one could still argue that maybe you should have just used &lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; in the first place, but there are always reasons you don't want that semantic baggage in a certain situation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-1496787199168395795?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/1496787199168395795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=1496787199168395795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1496787199168395795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1496787199168395795'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/and-versus-and.html' title='[b] and [i] versus [strong] and [em]'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-1309971714686626491</id><published>2007-03-28T16:28:00.000-07:00</published><updated>2007-03-29T15:30:15.270-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Why phpDoc?</title><content type='html'>Ok. So this one is just personal. Most people don't have a problem with &lt;a href="http://www.phpdoc.org/"&gt;phpDoc&lt;/a&gt;, and don't argue against using it–at least not that I'm aware of. But I'm lucky. I know some of the rare few.&lt;br /&gt;&lt;br /&gt;Before I begin, let me just say that this rant is totally inspired by the fact that people need to be more open-minded. I don't want to point fingers, as this blog is public and I wouldn't want to alienate those that I know of whom I'm referring to, but c'mon people! We really need to be less haughty and ditch our I'd-like-to-pretend-I-know-tons-just-because-it-makes-me-feel-better attitudes. And by "we" and "our" I mean "you" and "your." Now, let's begin.&lt;br /&gt;&lt;br /&gt;You are an idiot.&lt;br /&gt;&lt;br /&gt;You knew it was coming. I just really get annoyed by this whole closed-minded thing that I seem to get the blunt end of all the time. It is so ridiculous to look at a piece of software, notice that there is one piece of functionality that–on the surface–seems to be missing that you think ought to be there, and freak out and create a de facto doctrine banning it from use and scorning those who do use it. There are so many more sides to any argument for the clincher to be a one-issue, end-of-discussion coffin-nailer.&lt;br /&gt;&lt;br /&gt;Now, in response to your question, I must ask one of my own: "Why the frak NOT!?" If you don't document your code using a JavaDoc like syntax, WTF are the rest of us supposed to do with your code. We have no idea what's going on, and can't see what the individual pieces of code are supposed to be doing. More importantly, of course, there's no way to tell what the "big picture" is.&lt;br /&gt;&lt;br /&gt;The point I'm trying to make is this: JavaDoc makes absolute and perfect sense, and there's not a &amp;*%# thing you can say to change that fact. If you insist on being ignorant, that's your choice but I don't want to hear about it, and it had &lt;em&gt;better&lt;/em&gt; not affect me.&lt;br /&gt;&lt;br /&gt;Even if I never intend to generate documentation using the phpDoc tool, I am going to use JavaDoc like comments in my code. There's no other way to comment functions, classes, includes, defines, and pages any better, so why would you not do it. Furthermore, why would you try and define some alternate syntax, which sucks, and will eventually lead you back to JavaDoc anyway. Remember, machine readable is the key here, and JavaDoc is absolutely machine readable. You can do anything you want with it.&lt;br /&gt;&lt;br /&gt;It's like when you try to develop your own tool for doing anything that has already been done, thinking: "I'll just code my own. In house is better, and I know how to program, so how hard can it be? blah blah blah..." &lt;strong&gt;No!!!&lt;/strong&gt; Everything you try to do is going to lead you back to the tool that you were trying to replace in the first place. If you want a framework, use a framework, don't try and invent your own. It's been done already, and you're not coming up with new concepts, so just stop trying! There's not a $&amp;amp;%# thing you are doing that will be an improvement if is all you're trying to accomplish is getting a certain type of functionality working. If you actually had good ideas that had never been done, maybe it is worth it to "roll your own" XYZ functionality, but when it's been done before, &lt;strong&gt;use it&lt;/strong&gt;! I'll say it again: &lt;strong&gt;Stop trying!!!&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-1309971714686626491?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/1309971714686626491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=1309971714686626491' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1309971714686626491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1309971714686626491'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/why-phpdoc.html' title='Why phpDoc?'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-7588159029984924158</id><published>2007-03-18T11:53:00.000-07:00</published><updated>2007-03-18T13:06:59.367-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Symfony Templating</title><content type='html'>A common problem that needs solved in any web application environment is templating. There are numerous templating engines available for web languages, and php is no exception. The need to create templating engines is driven from two things:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Traditional c-syntax code mixed with html is unreadable (usually).&lt;/li&gt;&lt;li&gt;It is a good practice to separate your logic from your presentation.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Of course, #2 is only the first step in creating an MVC based project, where the "view" is just one of three layers of the application, and by its nature separates logic from presentation. However, even without MVC, templating engines have provided some relief from issue #1 and usually provide a means for solving issue #2.&lt;br /&gt;&lt;br /&gt;A common gripe against symfony is its lack of templating engine. Symfony instead uses php as a templating engine. So how can this possibly be a good idea?&lt;br /&gt;&lt;br /&gt;First, it is important to note that issue #1 is strongly tied to a lack of awareness of the alternate syntax provision in php. Traditional c-syntax code for basic constructs is as follows:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;if ($x &amp;gt; $y)&lt;br /&gt;{&lt;br /&gt;// ...&lt;br /&gt;}&lt;br /&gt;foreach ($ar as $elem)&lt;br /&gt;{&lt;br /&gt;// ..&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;You get the picture. The alternate syntax, which in my opinion only makes sense, and therefore only exists for use embedded in html, is as follows:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;if ($x &amp;gt; $y):&lt;br /&gt;// ...&lt;br /&gt;endif;&lt;br /&gt;&lt;br /&gt;foreach ($ar as $elem):&lt;br /&gt;// ...&lt;br /&gt;endforeach;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Or, embedded in html:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?php if ($x &amp;gt; $y): ?&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;X&amp;lt;/strong&amp;gt; is greater than &amp;lt;strong&amp;gt;Y&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;?php endif; ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?php foreach ($ar as $elem): ?&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Elem:&amp;lt;/strong&amp;gt; &amp;lt;?php echo $elem ?&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;?php endforeach; ?&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Second, a common illusion among programmers who only have a basic understanding of the "view" layer of an application--or in a flatter php project, simply the "template"--is that absolutely no logic can be performed at the view level. These purists will sometimes even object to looping over values in an array, claiming such logic cannot be present in a "logic-less" view layer. You know what I'm going to say.&lt;br /&gt;&lt;br /&gt;You are an idiot.&lt;br /&gt;&lt;br /&gt;The goal of separating presentation from logic is to isolate all work that is performed in translating user requests to state information manipulation, and then retrieving state information to hand over to the view layer for display. There is a large amount of "logic"--that is lines of code to do "stuff"--involved in displaying state information (data) in the view. For this purpose, symfony (and likely several other frameworks and packages preceding symfony) has defined a standard format for the view layer to package all of its logic up in a clean, reusable, and extensible way. These are referred to in symfony as "helpers."&lt;br /&gt;&lt;br /&gt;Helpers simplify and standardize the amount of code that needs to be placed in the template itself, so that there really is very little logic visible. However, in these helpers, all kinds of things can go on that is strictly related to rendering the display of an application. Symfony bundles a plethora of helpers that perform common tasks, such as generating &amp;lt;a&amp;gt; and &amp;lt;form&amp;gt; tags (which also gain standard url routing provisions through the helper system), &amp;lt;select&amp;gt;, &amp;lt;input&amp;gt; and other form element tags, &amp;lt;img&amp;gt; tags, javascript code and ajax functionality, as well as including chunks of reusable template code, etc. Several community contributions provide additional helpers that clean up other common messy tasks, such as generating pagination links, creating standardized CRUD record navigation, or simplifying new techniques for integrating hot-off-the-market best practices into your application.&lt;br /&gt;&lt;br /&gt;Since symfony has adopted a pure php templating methodology, these helper functions are exactly that, pure php functions. Sometimes, the helpers plug into symfony to make use of various tools provided by the framework, but other times the helpers perform simple string manipulating and literally augment built-in php functions. Typical templating engines have the ability to directly call php functions disabled, and therefore have to implement their own helper systems, which are not reusable outside the templating engine. Symfony helpers, except for ones that specifically use symfony tools, could be repackaged in the php world at large with minimal effort.&lt;br /&gt;&lt;br /&gt;The result of solving issues #1 and #2 in this way result in templates that look like the following:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;span&amp;gt;&amp;lt;?php echo link_to('home', '@home', 'class=nav-link') ?&amp;gt;&lt;/code&gt;&lt;code&gt;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?php foreach ($users as $user): ?&amp;gt;&lt;br /&gt;User #&amp;lt;?php echo $user-&amp;gt;getId() ?&amp;gt;: &amp;lt;?php echo link_to($user-&amp;gt;getName(), 'user/view?id='.$user-&amp;gt;getId()) ?&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;?php endforeach; ?&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Imagine what that would have looked like in a flat php world. Even in a templating engine...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-7588159029984924158?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/7588159029984924158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=7588159029984924158' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/7588159029984924158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/7588159029984924158'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/symfony-templating.html' title='Symfony Templating'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-4034204609716784683</id><published>2007-03-17T14:25:00.000-07:00</published><updated>2007-03-17T14:27:49.440-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='post'/><title type='text'>Personal Blog</title><content type='html'>Hey all. I've set up a &lt;a href="http://for-the-shire.blogspot.com"&gt;personal blog&lt;/a&gt; elsewhere.  I've decided to make this a technical blog only, so I won't post any personal messages here whatsoever.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-4034204609716784683?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/4034204609716784683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=4034204609716784683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/4034204609716784683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/4034204609716784683'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/personal-blog.html' title='Personal Blog'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-5587971843617643443</id><published>2007-03-16T19:08:00.000-07:00</published><updated>2007-03-16T19:12:20.708-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='post'/><title type='text'>Someone Noticed!</title><content type='html'>Finally someone commented on a &lt;a href="http://www.symfony-project.com/snippets/snippet/157"&gt;symfony snippet&lt;/a&gt; of mine. I've been posting fairly nice code regularly, but nobody says a thing. At least a few of the snippets have high ratings... Anyway, it's pretty sad when I care very much about such things, but you know, I want to be noticed for more than my violin playing (though that's nice too). I'm a darn good programmer!&lt;br /&gt;&lt;br /&gt;Anyway, that's all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-5587971843617643443?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/5587971843617643443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=5587971843617643443' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/5587971843617643443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/5587971843617643443'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/someone-noticed.html' title='Someone Noticed!'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-6519546733347897819</id><published>2007-03-16T07:57:00.000-07:00</published><updated>2007-03-17T09:28:22.286-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Why symfony?</title><content type='html'>You are an idiot.&lt;br /&gt;&lt;br /&gt;Er... Maybe I need a new one.&lt;br /&gt;&lt;br /&gt;Get a frickin' clue!&lt;br /&gt;&lt;br /&gt;Symfony does two things, which are themselves inextricably bound in origin.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Implements MVC in the most logically productive way possible.&lt;/li&gt;&lt;li&gt;Provides tools to use every productive best-practice available on the web today.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Symfony is currently the best php framework available for obvious reasons. If you ask anyone what the best (or at least the coolest) framework out there is, everyone says Ruby on Rails. So why is Rails successful? Best practices up the wazoo! If you don't buy into best practices for programming, then you need to read my last post, and assume every derogatory comment is aimed at you. In fact, I'll put some of it here too.&lt;br /&gt;&lt;br /&gt;Get a frickin' clue! You are an idiot.&lt;br /&gt;&lt;br /&gt;Programming, web development and computer science are continuously evolving fields and require constant innovation in order to be useful and complete. There are several absolutely amazing best practices out there that speed up development ten-fold, and most old-timers (anyone who rejects good ideas because someone younger thought of them first) ignore this fact. Instead, such people assume the web hasn't changed and that they have the capability to create all of the stuff they need to be successful off the top of their retarded heads. Reinventing the wheel is for no-talent losers from podunk land.&lt;br /&gt;&lt;br /&gt;This is arguably the worst mistake a programmer can make, ignoring all of the work by hundreds of thousands of developers who have spent countless hours putting their past experiences into the public arena as improvements in the form of libraries, packages, and frameworks.&lt;br /&gt;&lt;br /&gt;Symfony has succeeded in packaging all of the best practices from several successful frameworks including Struts, Ruby on Rails, Mojavi, and many others.&lt;br /&gt;&lt;br /&gt;Now, the final question relating to this would be "If these other frameworks are successful, why symfony?" These frameworks have several good features, but have drawbacks in the way they are used, or they are missing other essential features. Symfony has been thought out so well, that every single iota of functionality in the package is in harmony, the code quality is beyond excellent, and it packages &lt;span style="font-style: italic;"&gt;every&lt;/span&gt; best practice available without suffering from scope-creep and project bloating.&lt;br /&gt;&lt;br /&gt;90% (plus) of the reasons why flat php projects are difficult to manage is taken care of in symfony, allowing the programmer to think about things that really matter. The impossible header/footer issues (including redirecting after outputting part of it) are dealt with through the decorator process. Templating has a helper function system for providing complicated logic that belongs strictly in the &lt;span style="font-style: italic;"&gt;view&lt;/span&gt; layer, while keeping the templates themselves free of logic. The naming coventions for helpers especially are logical, and blend into harmony with the php function naming conventions, making it feel a native part of the language. The framework makes a small memory footprint, due to autoloading classes on demand. A feature available in the framework isn't loaded unless you use it. Configuration is completely granular, and all symfony configuration is available at every level of the project from global on down to an individual action. The enforced project structure and naming conventions allow for free functionality, and force you to adhere to logical organization that is difficult to bungle (though you'll find a way, idiot). The ability to add your own standardized helper functions, configuration handlers, extended core classes with custom functionality, logic in the model layer, cli tasks, code generators, execution filters, proprietary classes, plugins, multiple layouts, reusable code fragments in several varieties, layout zones, etc. gives your project the customized edge while maintaining strict organization, code quality, and standards. The documentation is extensive, and the source code makes almost perfect logical sense without an ounce of familiarity.&lt;br /&gt;&lt;br /&gt;Why symfony? That's why, you idiot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-6519546733347897819?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/6519546733347897819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=6519546733347897819' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/6519546733347897819'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/6519546733347897819'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/why-symfony.html' title='Why symfony?'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-1212048851886427509</id><published>2007-03-15T20:20:00.000-07:00</published><updated>2007-03-15T20:34:14.340-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><title type='text'>Why MVC?</title><content type='html'>&lt;p&gt;You are an idiot.&lt;br /&gt;&lt;br /&gt;The fact that you are asking me that question indicates two things:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;You have not done your homework.&lt;/li&gt;&lt;li&gt;You are either not a developer (in the true sense, not the hobby one), or you are an ignorant, closed-minded fool of a Took... er.. developer!&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Now, that feels better...  So let me attempt to answer your question.&lt;br /&gt;&lt;br /&gt;MVC (Model-View-Controller) organization of a software code-base has one singular purpose. To make your sucky, wannabe, look-at-me-ma-I'm-a-developer project stop sucking quite so badly.&lt;br /&gt;&lt;br /&gt;Is it possible to have a non-MVC web-based app not suck? Sure, but there's this little thing that we in "the biz" like to call "best practice" that argues this point for me. Look at every successful framework being written for the web. Every single one is using MVC.&lt;br /&gt;&lt;br /&gt;"But I separate my code into templates and logic, isn't that the same thing?"&lt;br /&gt;&lt;br /&gt;You are an idiot.&lt;br /&gt;&lt;br /&gt;If your project does not talk to a database, or some other persistent storage repository, then be my guest and ignore MVC. It won't help you. However, for most of us, separating out the templating code is a good start, but not nearly enough. Not convinced? Let me give you the "hello world" introduction to MVC.&lt;br /&gt;&lt;br /&gt;I have an employee table in my database. Every time I print an employee's name, I print first_name + ' ' + last_name. What an incredibly simple thing to do. But I do it A LOT! So where do I put the generalized function to perform this repetitive task for me? I know! I'll create a class (or script) to store useful functions that I use a lot, and I'll just put it wherever other such classes/scripts go (these would sometimes be referred to as "includes"). If I get lots of these types of functions, I'll just start creating classes/scripts whose name reflects the types of functions contained therein. I must be a genius! Nobody's ever thought of that before.&lt;br /&gt;&lt;br /&gt;You are an idiot.&lt;br /&gt;&lt;br /&gt;The second you start just throwing general functions into a bin (more like a vat) of crap, the next guy to come in and modify your code will disagree on its category and move it, rename it, not know where to look for it, or add unrelated functions next to it. Now you're pissed because you're the team lead, but you have to go in and enforce your proprietary conventions (really just preferences) for how such things should be organized. Then he's pissed because you didn't like his idea. Before you know it, your project sucks! It's disorganized, and has no guaranteed structure, or the structure you started with doesn't reflect the needs of the project six months later.&lt;br /&gt;&lt;br /&gt;Back to our example. What if (and please try to ignore the Object-Relation Impedance Mismatch problem for this discussion) I had a class that represented a record from the employee table. Clearly, I have some way to access fields from the table (now data members in the class) in some standardized way, like &lt;code&gt;getMyField()&lt;/code&gt; / &lt;code&gt;setMyField('er...')&lt;/code&gt;. So, instead of &lt;code&gt;getFirstName() + ' ' + getLastName()&lt;/code&gt;, I have &lt;code&gt;getName()&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Apply this example to the six million different situations where you need logic performed that explicitly involves the database and its contained data, and the only way to organize this type of code is to put it into a model layer in your project.&lt;br /&gt;&lt;br /&gt;Why MVC? That's why, you idiot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-1212048851886427509?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/1212048851886427509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=1212048851886427509' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1212048851886427509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/1212048851886427509'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/why-mvc.html' title='Why MVC?'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1499008639029127945.post-8270947236728373716</id><published>2007-03-15T20:18:00.000-07:00</published><updated>2007-03-15T20:20:23.342-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='post'/><title type='text'>New Blog</title><content type='html'>I just created this blog.  Do you know why? Because, dangit, blogs are for ranting, and I need to rant...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1499008639029127945-8270947236728373716?l=sjohnr.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjohnr.blogspot.com/feeds/8270947236728373716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1499008639029127945&amp;postID=8270947236728373716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/8270947236728373716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1499008639029127945/posts/default/8270947236728373716'/><link rel='alternate' type='text/html' href='http://sjohnr.blogspot.com/2007/03/new-blog.html' title='New Blog'/><author><name>sjohnr</name><uri>http://www.blogger.com/profile/02268041621788232871</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
