<?xml version='1.0' encoding='windows-1252'?><?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'><id>tag:blogger.com,1999:blog-5772872</id><updated>2009-10-19T05:57:38.334-05:00</updated><title type='text'>Positronic Vibrations</title><subtitle type='html'>Making the ugly elegant one day at a time</subtitle><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default?start-index=26&amp;max-results=25'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.blainebuxton.net'/><author><name>Blaine</name><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>965</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5772872.post-8980114474671708568</id><published>2009-10-17T20:17:00.004-05:00</published><updated>2009-10-17T21:10:58.989-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Devilishly Clever</title><content type='html'>I was doing my usual research on Python when I ran across this recipe to make tail recursive calls not blow the stack in Python: &lt;a href="http://code.activestate.com/recipes/474088/"&gt;Tail Call Optimization Decorator&lt;/a&gt;. I read through the code and thought, "Wow! This is devilishly clever!" As a thought exercise, I think it's awesome. But, it got me thinking about clever and production code. In my opinion, clever is never good or wanted in production code. It's great to learn and understand clever code though. It's a great mental workout to keep you sharp.&lt;br /&gt;&lt;br /&gt;So, what's my point with all of this besides to say that clever is bad? The example in the above link is factorial (which as everyone knows is hated by me, but that's another story). But, the amazing thing about factorial examples are that they are dead simple, yet there's several ways to get the answer. Here's a few that I came up with:&lt;br /&gt;&lt;pre&gt;def reg_fact(x):&lt;br /&gt;    if x is 1:&lt;br /&gt;        return 1&lt;br /&gt;    return reg_fact(x - 1) * x&lt;br /&gt;&lt;br /&gt;def tail_fact(x):&lt;br /&gt;    def func(acc, x):&lt;br /&gt;        if x is 1:&lt;br /&gt;            return acc&lt;br /&gt;        return func(acc * x, x - 1)&lt;br /&gt;    return func(1, x)&lt;br /&gt;&lt;br /&gt;def not_rec_fact(x):&lt;br /&gt;    result = 1&lt;br /&gt;    for each in range(2, x + 1):&lt;br /&gt;        result *= each&lt;br /&gt;    return result&lt;br /&gt;&lt;br /&gt;def not_rec_fact_fancy(x):&lt;br /&gt;    return reduce(lambda result, each: result * each, range(1, x + 1))&lt;br /&gt;&lt;br /&gt;import operator&lt;br /&gt;def not_rec_fact_super_fancy(x):&lt;br /&gt;    return reduce(operator.mul, range(1, x + 1))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Each of these compute factorial. Amazingly, there's even more ways than what I listed (the math wizards in the audience know what they are). Now, think about this: Computing factorial is dead simple. What happens when we get to harder problems? Being clever can actually get in the way of making the code easy to understand. It might even kill performance. Let's think back to the devilishly clever code. The performance of making Python tail recursive is awful. Sure, it's pure and tail recursive, but in production code that is deadly. What we want is simple and to the point. It's why I generally like solutions that need less code. There's less noise to get in the way of understanding and generally can mean better performance as well.&lt;br /&gt;&lt;br /&gt;Real world problems are hardly ever as straightforward as factorial. The balancing act comes when you drop a solution because it's not working for whatever reason. Raising and catching exceptions so you can have a tail recursive factorial is overkill. It took more code than the non-recursive version. It begs for the programmer to know their tool set and to know how to solve problems in that tool set that are straightforward. Tail recursion is powerful in languages like Haskell and Erlang. But, there's always another way of doing things that can make more sense in the language you are using. In our case, the other ways were just as easy yet more scalable for our tool set. Food for thought the next time you go down the path of clever and end up writing more noise than solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-8980114474671708568?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/8980114474671708568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=8980114474671708568' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8980114474671708568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8980114474671708568'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/10/devilishly-clever.html' title='Devilishly Clever'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-850214506054851332</id><published>2009-10-10T20:45:00.000-05:00</published><updated>2009-10-12T19:46:11.718-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Freezing Objects in Python</title><content type='html'>Someone stop me. I like freezing simple objects or what Eric Evans calls "Value Objects" in his excellent "Domain Driven Design" book. Python doesn't have immutable objects (ala freeze in Ruby) explicitly, but we can easily create it. Python gives us the power to get under its covers. Here's my implementation:&lt;br /&gt;&lt;pre&gt;class ValueObject(object):&lt;br /&gt;    def __setattr__(self, name, value):&lt;br /&gt;        if name == 'value' and hasattr(self, 'value'):&lt;br /&gt;            raise AttributeError("Can not change value attribute")&lt;br /&gt;        else:&lt;br /&gt;            self.__dict__[name] = value&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Do you have to ask? Yes, I made a test. Here they are:&lt;br /&gt;&lt;pre&gt;import unittest&lt;br /&gt;class Test(unittest.TestCase):&lt;br /&gt;&lt;br /&gt;    def testSimple(self):&lt;br /&gt;        class Cents(ValueObject):&lt;br /&gt;            def __init__(self, value):&lt;br /&gt;                self.value = value&lt;br /&gt;            def __str__(self):&lt;br /&gt;                return str(self.value) + " cents"&lt;br /&gt;        subject = Cents(5)&lt;br /&gt;        self.assertEquals(5, subject.value)&lt;br /&gt;        def set_value():&lt;br /&gt;            subject.value = 6&lt;br /&gt;        self.failUnlessRaises(AttributeError, set_value)&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-850214506054851332?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/850214506054851332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=850214506054851332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/850214506054851332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/850214506054851332'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/10/freezing-objects-in-python.html' title='Freezing Objects in Python'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-2941573612963136192</id><published>2009-10-05T21:40:00.000-05:00</published><updated>2009-10-05T20:41:00.322-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>method_missing in Python</title><content type='html'>OK, I know there is a few implementations of this knocking around on the net already, but I'm in learning mode. So, here's my implementation of Ruby's method_missing:&lt;br /&gt;&lt;pre&gt;class PossibleMissingAttribute(object):&lt;br /&gt;    def __init__(self, object, name):&lt;br /&gt;        self._object = object&lt;br /&gt;        self._name = name&lt;br /&gt;&lt;br /&gt;    def __call__(self, *args, **kwargs):&lt;br /&gt;        return self._object._method_missing(self._name, *args, **kwargs)&lt;br /&gt;    &lt;br /&gt;    def __str__(self):&lt;br /&gt;        return self.__class__.__name__ + ": " + str(self._object) + "." + self._name&lt;br /&gt;    &lt;br /&gt;    def __getattr__(self, name):&lt;br /&gt;        return None&lt;br /&gt;    &lt;br /&gt;    def __nonzero__(self):&lt;br /&gt;        return False&lt;br /&gt;    &lt;br /&gt;class MethodMissingError(Exception):&lt;br /&gt;    def __init__(self, object, name, *args, **kwargs):&lt;br /&gt;        self.object = object&lt;br /&gt;        self.name = name&lt;br /&gt;        self.args = args&lt;br /&gt;        self.kwargs = kwargs&lt;br /&gt;&lt;br /&gt;    def __str__(self):&lt;br /&gt;        return repr(str(self.object) + "." + self.name)&lt;br /&gt;&lt;br /&gt;class Missing(object):&lt;br /&gt;    def __getattr__(self, name):&lt;br /&gt;        return PossibleMissingAttribute(self, name)&lt;br /&gt;    def _method_missing(self, name, *args, **kwargs):&lt;br /&gt;        raise MethodMissingError(self, name, *args, **kwargs)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Three objects and that's it! One to be a placeholder when an argument is missing. One object to represent the MethodMissingError and the last to be an abstract class to inherit from. But, you could easily just put these methods anywhere. Here's my tests:&lt;br /&gt;&lt;pre&gt;import unittest&lt;br /&gt;&lt;br /&gt;class TestMissing(unittest.TestCase):&lt;br /&gt;    def test_missing(self):&lt;br /&gt;       class TestClass(Missing):&lt;br /&gt;           def __str__(self):&lt;br /&gt;               return self.__class__.__name__&lt;br /&gt;           def existing(self):&lt;br /&gt;               return "i am"&lt;br /&gt;           def _method_missing(self, name, *args, **kwargs):&lt;br /&gt;               return args[0]&lt;br /&gt;       self.assertEquals("am not", TestClass().missing("am not"))&lt;br /&gt;       self.assertEquals("i am", TestClass().existing())&lt;br /&gt;       self.assertEquals(None, TestClass().missing.something_else_missing)&lt;br /&gt;       self.assertFalse(TestClass().missing)&lt;br /&gt;       self.assertEquals("PossibleMissingAttribute: TestClass.missing", str(TestClass().missing))&lt;br /&gt;       &lt;br /&gt;    def test_exception(self):&lt;br /&gt;        class TestClass(Missing):&lt;br /&gt;           def __str__(self):&lt;br /&gt;               return self.__class__.__name__&lt;br /&gt;        self.failUnlessRaises(MethodMissingError, lambda: TestClass().missing())&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You've seen my implementation. Here's another one that I found on the net: &lt;a href="http://log.chemica.co.uk/?p=13"&gt;method_missing in Python&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;class MethodMissing(object):&lt;br /&gt;    def method_missing(self, attr, *args, **kwargs):&lt;br /&gt;        “”" Stub: override this function “”"&lt;br /&gt;        raise AttributeError(”Missing method %s called.”%attr)&lt;br /&gt;&lt;br /&gt;    def __getattr__(self, attr):&lt;br /&gt;        def callable(*args, **kwargs):&lt;br /&gt;            return self.method_missing(attr, *args, **kwargs)&lt;br /&gt;        return callable&lt;/pre&gt;&lt;br /&gt;Um, this version is much shorter than mine. It gets the same job done and is more obvious of what it is doing. Simply returning a function on __getattr__ is the best way to go. It's what my PossibleArgumentMissing was doing. But, where I tried to get all fancy using __call__ to mimic a function which caused my version to be longer. I was also trying to get the argument to come back to return false in if conditions and be almost like None (again, I'm learning and was looking at what was possible). Simplest is best.&lt;br /&gt;&lt;br /&gt;This was a fun thought exercise. I love all the hooks Python provides to allow you to get underneath the hood if need be. I will be soon doing a post on descriptors and even decorators. I find Python tends to sway heavier on the functional side of programming versus object-oriented. I'm loving the succinct, yet readable code. Too many languages get into the being so terse that they sacrifice readability or debugability (is that a word? Is now!).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-2941573612963136192?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/2941573612963136192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=2941573612963136192' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2941573612963136192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2941573612963136192'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/09/methodmissing-in-python.html' title='method_missing in Python'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-8351826223694012036</id><published>2009-09-29T18:54:00.003-05:00</published><updated>2009-09-29T19:26:58.600-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prototypes'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Prototypes in Python</title><content type='html'>I'm in love with prototype-based languages, but there only a few to play with ECMAScript (Javascript) and Self. Since I'm learning Python, I thought it would be a good experiment to implement prototypes in Python. For one thing, I would get to learn some of the meta capabilities and other advanced features. A pure thought experiment just for learning and seeing how far I could push another paradigm onto Python. Here is what I came up with:&lt;br /&gt;&lt;pre&gt;class Prototype(object):&lt;br /&gt;    def __init__(self, *args):&lt;br /&gt;        self._parents = []&lt;br /&gt;        for each in args:&lt;br /&gt;            self._parents.append(each)&lt;br /&gt;        &lt;br /&gt;    def clone(self, *args):&lt;br /&gt;        return self.__class__(self, *args)&lt;br /&gt;    &lt;br /&gt;    def __getattr__(self, name):&lt;br /&gt;        for each in self._parents:&lt;br /&gt;            try:&lt;br /&gt;                return getattr(each, name)&lt;br /&gt;            except AttributeError:&lt;br /&gt;                pass&lt;br /&gt;        raise AttributeError(name)&lt;/pre&gt;&lt;br /&gt;The implementation is suprisingly simple: three methods! &lt;br /&gt;&lt;br /&gt;The first is the initialize method for new instances. It takes a list of objects that we will use as the parents of our new object. Of course, by simply calling Prototype's constructor with no arguments, we get a clean object. I made the ability to have multiple inheritance simple because of Self.&lt;br /&gt;&lt;br /&gt;The second method is the clone method and it simply calls the constructor for another object makes itself the first parent with the rest of the arguments becoming the other parents. Nothing to it!&lt;br /&gt;&lt;br /&gt;The last method is the real meat. It only get called by the Python engine when an attribute fails to be looked up. All I do is call each parent and if one succeeds, it returns the answer. This is a depth first search of the parent hierarchy. Simple.&lt;br /&gt;&lt;br /&gt;And that's all we need to implement prototypes in Python. Now, I just need to explain some practical uses of this in some later blog entries.&lt;br /&gt;&lt;br /&gt;How do I know all of this works? Here's my tests:&lt;br /&gt;&lt;pre&gt;import unittest&lt;br /&gt;class Test(unittest.TestCase):&lt;br /&gt;&lt;br /&gt;    def testSimple(self):&lt;br /&gt;        parent = Prototype()&lt;br /&gt;        child = parent.clone()&lt;br /&gt;        &lt;br /&gt;        parent.value = 0&lt;br /&gt;        self.assertEquals(0, child.value)&lt;br /&gt;        child.value = 1&lt;br /&gt;        &lt;br /&gt;        self.assertEquals(1, child.value)&lt;br /&gt;        self.assertEquals(0, parent.value)&lt;br /&gt;        &lt;br /&gt;        self.failUnlessRaises(AttributeError, lambda:parent.unknown)&lt;br /&gt;    &lt;br /&gt;    def testMultipleParents(self):&lt;br /&gt;        parent1 = Prototype()&lt;br /&gt;        parent2 = Prototype()&lt;br /&gt;        child = parent1.clone(parent2)&lt;br /&gt;        &lt;br /&gt;        parent2.value = 2&lt;br /&gt;        self.failUnlessRaises(AttributeError, lambda:parent1.value)&lt;br /&gt;        self.assertEquals(2, child.value)&lt;/pre&gt;&lt;br /&gt;If anyone sees anything wrong in my implementation or un-Pythonic let me know. I'm still learning, but I thought it would be cool to show my progress.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-8351826223694012036?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/8351826223694012036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=8351826223694012036' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8351826223694012036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8351826223694012036'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/09/prototypes-in-python.html' title='Prototypes in Python'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-1492978342642582106</id><published>2009-09-13T14:55:00.006-05:00</published><updated>2009-09-13T19:28:43.278-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Constraints in Python</title><content type='html'>With every language that I learn, I pay close attention to my work flow. I take note of anything that gets in the way of getting my task accomplished. In a perfect language, I should never have to worry about the language ever. A free flow of ideas should come out. Whenever I find myself totally immersed in a problem, I keep track of what made it so. Recently, the one feature that surprised me the most was Python's forced indention. At first I thought, how nice not to use curly brackets to denote scope, but what about that white space? But, I put my best foot forward and worked on some code. I must admit that I love it now! It makes code more readable by keeping the rules consistent (you have to be or your code will have bugs). Formatting my code is now one less worry I have. I am forced to indent as I go along. This constraint is liberating in the fact that it allows me concentrate on the problem at hand and is one less thing to worry about. No more worrying about if the curly braces go on the same line or not depending on local coding standards. It makes code easier to read across Python programmers. In fact, I have yet to meet a Python program that I could not understand easily from first glance which is a rare accomplishment in other languages.&lt;br /&gt;&lt;br /&gt;I also love the constraint about one line lambdas. I thought it was going to drive me crazy, but I have embraced completely. It keeps your lambda functions short and sweet like they really should be. But, the best side effect is that if that lambda needs to grow, you simply move it out to a named function automatically making your code more readable. Excellent.&lt;br /&gt;&lt;br /&gt;Both of the features that I just mentioned are merely constraints that take away thinking about the language and force you to write readable code. I always like and embrace the design decisions to constrain the coder to make more maintainable code. The less I have to think about the language, the more time I spend on the problem I am trying to solve and that's the way it should be. It just amazed me that sometimes I find them in the strangest of ways. I would have never thought that forced indention or one lined lambdas would bring me so much coding pleasure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-1492978342642582106?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/1492978342642582106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=1492978342642582106' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/1492978342642582106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/1492978342642582106'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/09/constraints-in-python.html' title='Constraints in Python'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-8555391352317992865</id><published>2009-09-12T07:48:00.003-05:00</published><updated>2009-09-12T08:00:15.510-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='misc'/><title type='text'>The Dead Year</title><content type='html'>This blog has been dead for a year and it's not been a lack of passion. I had some rather large life changing events to deal with. I have emerged stronger than ever before and I plan to start posting regularly here again. To let you know what to expect, I hope to do some new articles on my exploration of Python and Django. I've been enjoying my time with Python quite a bit. I also hope to spend some time digging into Google's V8 ECMAScript. It's time for me to kick this blog back into gear. Hold on!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-8555391352317992865?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/8555391352317992865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=8555391352317992865' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8555391352317992865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8555391352317992865'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/09/dead-year.html' title='The Dead Year'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-5342945128336325010</id><published>2009-01-04T13:21:00.004-05:00</published><updated>2009-01-04T18:30:15.083-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='misc'/><title type='text'>Domain Change</title><content type='html'>Update your bookmarks from &lt;a href="http://www.blainebuxton.net"&gt;blainebuxton.com&lt;/a&gt; to &lt;a href="http://www.blainebuxton.net"&gt;blainebuxton.net&lt;/a&gt;. The new blog address is: &lt;a href="http://blog.blainebuxton.net"&gt;blog.blainebuxton.net&lt;/a&gt;. I plan on to start blogging again soon in the next year. Things are going on that I'd rather not discuss in a public forum. But, I will be back soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-5342945128336325010?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/5342945128336325010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=5342945128336325010' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5342945128336325010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5342945128336325010'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2009/01/domain-change.html' title='Domain Change'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-754245571082525377</id><published>2008-10-11T18:34:00.004-05:00</published><updated>2008-10-11T19:12:55.144-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><title type='text'>Forced Pairing</title><content type='html'>Let's be honest. I'm not a big fan of "forced" pairing. I believe in active collaboration between cooperating team members. In other words, two people should pair if they want to. The energy of pairing is incredible when both partners are engaged and having fun. The code is better and so is the resultant design. It's the other side of the coin that I don't like and think the results are worse, even if the two programmers were working separately. A good pairing starts with the pair liking to work with one another. They don't have to see eye to eye, but they must enjoy the journey of working on code together. They will push and encourage each other to do better. A fun competition that will result in another problem being pushed past and the winner being a well-maintained system.&lt;br /&gt;&lt;br /&gt;"Forced" pairing is what XP advocates and I see a huge problem with it. The reason is if the pair doesn't like or respect one another, the code quality will be on par with that of the worst of the pair. When pairs don't get along, one side will disengage. When this happens, you get none of the benefits. The team still thinks its safe from doing code reviews because they had four eyes on all code. Not so. To ignore the effects of "forced" pairing is to ignore that the team is human.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-754245571082525377?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/754245571082525377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=754245571082525377' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/754245571082525377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/754245571082525377'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/10/forced-pairing.html' title='Forced Pairing'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-3018303539351681085</id><published>2008-08-24T19:30:00.002-05:00</published><updated>2008-08-24T19:59:40.467-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='inspiration'/><title type='text'>Mentoring</title><content type='html'>One of the round table discussion at Des Moines Bar Camp was how to get students excited about our field. The discussion went from how to get students interested in non-coding aspects of software development like QA testing to finding the passionate students. One thing that I suggested was that we needed to mentor more. I think we need not only to mentor students, but people within in our industry. &lt;br /&gt;&lt;br /&gt;Let's face it. There's no way to know everything about software development. I would even say it's impossible to know everything about Java (the number of frameworks and new ideas is overwhelming) which is a small part of the entire computing realm. &lt;br /&gt;&lt;br /&gt;Getting back to mentoring students though. In the user groups that I attend, it's been rare to come across a student. We are they not coming? Could we be scaring them away? Are user groups too advanced? What?! I think it is none of those things. I just don't think we are marketing to them. How do we do that? I think simply putting up posters and targeting students is a start. Reaching out to teachers is another avenue. Embracing students who come to these meetings is also needed. We need to keep those passionate about what we excited.&lt;br /&gt;&lt;br /&gt;Which leads me to that we need to mentor everyone. I've been blessed in my career to have several mentors and I try to be a mentor when asked as well. I want to give back to those that have given me so much. There's only so far that books can go. Experience is best handed down through mentorship. I think it also allows us to feel freedom to try out new things. As we move to move functional programming languages, wouldn't be nice to be mentored by the people with the most experience?&lt;br /&gt;&lt;br /&gt;I would love to see our industry to move to an apprentice model. I think the caliber of developers, testers, and leaders would increase dramatically. We're an industry that is just starting to tap into networking (Bar Camps are excellent for this) and embrace sharing (open source). It's exciting times right now and I can see where everyone needs to be mentored. I'm always learning and love talking with people who have more experience in a technology. We need to keep the learning going.&lt;br /&gt;&lt;br /&gt;I think the new social networking tools could be used to great effect for setting up these relationships. So, let's get together and start mentoring. Create the developers we would like to work with and be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-3018303539351681085?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/3018303539351681085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=3018303539351681085' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/3018303539351681085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/3018303539351681085'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/08/mentoring.html' title='Mentoring'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-2672433784689202358</id><published>2008-08-24T11:14:00.003-05:00</published><updated>2008-08-24T11:21:38.608-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bar camp'/><title type='text'>Bar Camps</title><content type='html'>In the past week, I've attended both the Omaha and Des Moines Bar Camps. At each, I gave my Seaside and advanced Javascript talks. The responses and turn out was incredible. Interest is growing in Seaside and Javascript is being viewed more as real language than a toy. It makes me a happy person. Everyone I met was passionate, articulate, and excited. I can honestly say that all of the Bar Camps I have attended thus far have been incredible. I've met many new friends and I can't wait to go to another. They are addicting! Hope to see everyone again! Check out my &lt;a href="http://www.blainebuxton.com/presentations"&gt;presentations&lt;/a&gt; page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-2672433784689202358?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/2672433784689202358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=2672433784689202358' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2672433784689202358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2672433784689202358'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/08/bar-camps.html' title='Bar Camps'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-5883865790047233444</id><published>2008-08-06T20:44:00.006-05:00</published><updated>2008-08-17T09:49:40.963-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javvascript'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Update on Javascript</title><content type='html'>I've been meaning to write an update to &lt;a href="http://blog.blainebuxton.com/2008/05/javascript-stop-fighting-it.html"&gt;my post on Javascript prototypes&lt;/a&gt;. Let me just show the updated code and then I'll explain what's changed.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Base = new Object();&lt;br /&gt;Base.clone = function() {&lt;br /&gt; var creator = function() {&lt;br /&gt;  this.constructor = arguments.callee&lt;br /&gt; };&lt;br /&gt; creator.prototype = this;&lt;br /&gt; var result = new creator();&lt;br /&gt; if (result.initialize)&lt;br /&gt;  result.initialize.apply(result, arguments);&lt;br /&gt; return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Base.mixIn = function(properties) {&lt;br /&gt; for ( var each in properties)&lt;br /&gt;  if (properties.hasOwnProperty(each))&lt;br /&gt;   this[each] = properties[each];&lt;br /&gt; return this;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ZipCode = Base.clone().mixIn( {&lt;br /&gt; initialize : function(standard, extension) {&lt;br /&gt;  this.standard = standard;&lt;br /&gt;  this.extension = extension;&lt;br /&gt; },&lt;br /&gt; toString : function() {&lt;br /&gt;  return this.standard + "-" + this.extension;&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;print(ZipCode.clone('56777', '4567'));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;First thing you will notice is that I got rid of Object.prototype. I'll admit all of my recent Javascript code has been scripting on the server side. I do sometimes forget about all of the legacy code running on the browser(Adding properties to the Object.prototype can cause bugs in naive for loops). Not to fear, I created a Base object and put the clone and mixIn functions on it.&lt;br /&gt;&lt;br /&gt;The next change is to the clone function where I introduced code that will setup the new clone if an initalize function is present. It calls the initialize function with the arguments passed into the clone function. I love doing things like this with Javascript.&lt;br /&gt;&lt;br /&gt;Lastly, I had mixIn return itself. The reason is so that I could put the clone and mixIn on one line and only name the prototype once. This means I'm not duplicating the names of my objects and can more easily refactor the names. It also makes it easy to see the name and what prototype it is inheriting from.&lt;br /&gt;&lt;br /&gt;I've always been infatuated with prototype-based programming languages. Javascript makes it possible to play with a real life prototype-based language. It saddens me to know that the next release of the standard introduces classes and that so many frameworks force classes into it. Once you get into using prototypes, you don't want to go back. You can use prototypes for a primitive versioning system, change tracking, and more that I haven't thought of yet. If you find more, let me know. Have fun using Javascript in new excting ways.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-5883865790047233444?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/5883865790047233444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=5883865790047233444' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5883865790047233444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5883865790047233444'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/08/update-on-javascript.html' title='Update on Javascript'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-6772629319943279217</id><published>2008-07-13T19:56:00.003-05:00</published><updated>2008-07-13T20:58:08.501-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='squeak'/><title type='text'>Functional Programming Has Warped Me</title><content type='html'>Look at this method that I recently wrote in a class for describing my database. The responsibility of this method is to commit the current session (which is encapsulated from the user) after x number of database events (adds, updates, deletes, etc). I need his functionality because I was bulk inserting objects that I had read from an XML feed. Here's what I first came up with:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;commitEvery: aNumber during: aBlock &lt;br /&gt; | count |&lt;br /&gt; count := 1.&lt;br /&gt; [self session beginUnitOfWork.&lt;br /&gt; aBlock value: &lt;br /&gt;   [count := count + 1.&lt;br /&gt;   count &gt; aNumber &lt;br /&gt;    ifTrue: &lt;br /&gt;     [self session commitUnitOfWork.&lt;br /&gt;      self session beginUnitOfWork.&lt;br /&gt;      count := 1]]].&lt;br /&gt; self session commitUnitOfWork&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The method takes a one argument block that will be called with a zero argument block that when called will increase the count and decide whether to commit and start a new transaction if it has reached the number given. At the end, I commit whatever active transaction there is. The thing I like about this is that I put the logic of counting and when to commit in one place. Here's how it would be used:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;populate&lt;br /&gt; | db |&lt;br /&gt; db := self new.&lt;br /&gt; [db &lt;br /&gt;  commitEvery: 1000&lt;br /&gt;  during: &lt;br /&gt;   [:afterAdd | &lt;br /&gt;   ITunesSAXHandler readUsing: &lt;br /&gt;     (ITunesTracksHandler onEachTrackDo: &lt;br /&gt;       [:each | &lt;br /&gt;       db addTrack: each.&lt;br /&gt;       afterAdd value])]] &lt;br /&gt;   ensure: [db disconnect]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice how "afterAdd" is used. It is passed into the block that will handle all of the transaction adds. It is called after an item has been added. I like this code because it doesn't worry about anything, but adding things to the database. It also makes it obvious how often we will commit. But, I'm unhappy with commitEvery:during:. The reason is because it just seems like I could make it more generic and at the same time easier to test without resorting to mocks. I abstracted out the counting and put it as a method on BlockContext (this is Squeak):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;duringDoEvery: aNumber onBegin: beginBlock onEnd: endBlock &lt;br /&gt; | count result |&lt;br /&gt; count := 1.&lt;br /&gt; beginBlock value.&lt;br /&gt; result := self value: &lt;br /&gt;  [ count := count + 1.&lt;br /&gt;  count &gt; aNumber ifTrue: &lt;br /&gt;   [ endBlock value.&lt;br /&gt;     beginBlock value.&lt;br /&gt;     count := 1 ] ].&lt;br /&gt; endBlock value.&lt;br /&gt; ^result&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This turns our first method into this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;commitEvery: aNumber during: aBlock &lt;br /&gt; ^aBlock &lt;br /&gt;  duringDoEvery: 1000&lt;br /&gt;  onBegin: [ self session beginUnitOfWork ]&lt;br /&gt;  onEnd: [ self session commitUnitOfWork ]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's a mini-DSL! Let's write a simple test. Note, this is not an SUnit test, it simply writes to the transcript. But, I wanted to show it without all of the assertions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[:afterAdd | &lt;br /&gt; | count |&lt;br /&gt; count := 0.&lt;br /&gt; 10 timesRepeat: &lt;br /&gt;  [Transcript show: (count := count + 1) printString; cr. &lt;br /&gt;   afterAdd value]]&lt;br /&gt;   duringDoEvery: 5 &lt;br /&gt;   onBegin: [Transcript show: 'begin'; cr] &lt;br /&gt;   onEnd: [Transcript show: 'end'; cr]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Gives this output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;begin&lt;br /&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;end&lt;br /&gt;begin&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;end&lt;br /&gt;begin&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Everything looks wonderful until we hit the last two lines. It seems pointless and unnecessary to do a begin and end with nothing in between. Our code will need to get a little bit more complex. Here's my next try:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;duringDoEvery: aNumber onBegin: beginBlock onEnd: endBlock &lt;br /&gt; | count result hasBegun |&lt;br /&gt; count := 1.&lt;br /&gt; hasBegun := false.&lt;br /&gt; result := self value: &lt;br /&gt;  [ :eachBlock | &lt;br /&gt;  count := count + 1.&lt;br /&gt;  hasBegun ifFalse: &lt;br /&gt;   [ beginBlock value.&lt;br /&gt;     hasBegun := true ].&lt;br /&gt;  eachBlock value.&lt;br /&gt;  count &gt; aNumber ifTrue: &lt;br /&gt;   [ endBlock value.&lt;br /&gt;     hasBegun := false.&lt;br /&gt;     count := 1 ] ].&lt;br /&gt; hasBegun ifTrue: [ endBlock value ].&lt;br /&gt; ^ result&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's more complicated. And now, I'm passing another block around to get its value. The reason was because to properly remove empty begin/end combinations, I needed to know when the before was and when the after was. This means passing a block to the afterAdd from before. So, now the test code looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[:onEachAdd | &lt;br /&gt; | count |&lt;br /&gt; count := 0.&lt;br /&gt; 10 timesRepeat: &lt;br /&gt;  [onEachAdd value: &lt;br /&gt;    [Transcript show: (count := count + 1) printString; cr]]]&lt;br /&gt;   duringDoEvery: 5 &lt;br /&gt;   onBegin: [Transcript show: 'begin'; cr] &lt;br /&gt;   onEnd: [Transcript show: 'end'; cr]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I renamed afterAdd to onEachAdd which is a better name and indicates its role better. Now, the reason I wrote this post is that I sat back and went, "Wow. I have something easily testable, but might hurt some brains." My next thought was, "Why would this hurt someone's brain?" The answer is all of the indirection of the blocks. I will be quite honest at this point, I would normally start turning all of these blocks into objects and have better names for what they were doing. Blocks worked perfectly in this context and if you think about it. This code is not much different than what Collection&gt;&gt;streamContents: does.&lt;br /&gt;&lt;br /&gt;This is one of the things that learning functional programming has done to me. The above code looks and feels natural. Passing a block into a method that will accept another block doesn't bother me at all. I love the DSL-like nature of the implementation too, but I can see where it might confuse (Hell, inject:into: still does). This is where objects come in because now we can create our small objects with more meaningful names than just value or value:, this will at least make the indirection less painful. Thought this was fun exercise to show off something else that you can do with higher order functions. Squeak on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-6772629319943279217?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/6772629319943279217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=6772629319943279217' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/6772629319943279217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/6772629319943279217'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/07/functional-programming-has-warped-me.html' title='Functional Programming Has Warped Me'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-6169856356216005703</id><published>2008-06-30T07:19:00.003-05:00</published><updated>2008-06-30T07:34:02.235-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Too Complex?</title><content type='html'>There's a lot of features of Ruby that I like, but there are some that just drive me nuts like blocks not taking blocks and the ampersand operator. Raganwald did a great job of explaining blocks, procs, and the ampersand in this blog post: &lt;a href="http://feeds.raganwald.com/~r/raganwald/~3/321574803/what-does-do-when-used-as-unary.html"&gt;Explanation of Ruby's Unary operator&lt;/a&gt;. I came away with the feeling, "Wow! It took that much explanation just to tell how to send blocks around?" If blocks were first-class citizens, Ruby would be more elegant. Raganwald would not be writing huge blog posts on block vs. proc because it would be unneeded.&lt;br /&gt;&lt;br /&gt;Ruby has all it needs right now. Ruby 2.0 should be a pruning of features and removing special cases. Get to the things that help you concentrate on your design and not on the language. Ampersand is nothing more than noise in your code and brain. Remember elegant is simple.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-6169856356216005703?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/6169856356216005703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=6169856356216005703' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/6169856356216005703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/6169856356216005703'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/06/too-complex.html' title='Too Complex?'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-853404481539354392</id><published>2008-06-29T16:51:00.003-05:00</published><updated>2008-06-29T17:25:45.632-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Weakest Link</title><content type='html'>&lt;span style="font-weight:bold;"&gt;"The deliberate use of a weak element that will fail in order to protect other elements in the system from damage." - Universal Principles of Design&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Unit tests could be seen as a form of weakest link in that we want the system to fail in our tests instead of in our production environment. Pre-condition and post-condition assertions (remember Bertrand Meyer don't you?) are the perfect example of weakest links in software design.  The assertion fails, then the program stops or does something intelligent about the detection: logging the anomaly or dropping an incorrect record. We have more options available to us when our weak link fails in software than other domains. I would even put exception handling under the weak link design umbrella.&lt;br /&gt;&lt;br /&gt;So, why don't we use it more? It's rare I see pre-condition assertions at all. I know the performance overlords declared them to be bad. But, when you have Rails running high traffic websites, does a few extra assertions really matter? I think not. I would rather have my program run slower with safety belts than doing something catastrophic with my data. Brian Foote once gave a talk where he equated pre and post conditions to the goalie in a game of hockey. And asked the question, "Would you want to play with or without the goalie?" It's a statement that's lived with me since.&lt;br /&gt;&lt;br /&gt;With that being said, are they places in your current design that could use a few more fuses?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-853404481539354392?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/853404481539354392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=853404481539354392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/853404481539354392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/853404481539354392'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/06/weakest-link.html' title='Weakest Link'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-5928339514831774927</id><published>2008-06-22T12:16:00.003-05:00</published><updated>2008-06-22T12:31:34.519-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>My Hopes For Ruby 2.0</title><content type='html'>I must admit I haven't been following Ruby 2.0 too closely lately. But, I since I've been using 1.8 quite a bit lately. I thought I would list the things that are in 1.8, but I hope are gone in 2.0. This is a prayer of good vibes.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Make blocks first class citizens. So, no more &amp; in your methods. Everything should be an object. Blocks are no exception in fact, they have more right than anyone. This will make blocks syntactically cheaper too. No more "lambda". Happiness is cheap syntactic blocks.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Reflection on everything. Yes, this means the stack. It also means keep the source in memory as well as part of classes and blocks. This might could used for a lot of cool things (like interesting ways to traverse code). Don't worry. It doesn't add much memory.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Make blocks accept the same kind of parameters as methods. Right now, you can not have methods take an implicit block (you know with the &amp; in front). Wait a minute. If number one is satisfied, this will be too. Oh goody. Cheap blocks take away complexity. Isn't this reason enough to have them?&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;OK, that's it for now. The above things would make life so much easier. I could lobby for taking away case statements and most keywords, but I think the above would be great to take the language forward without hurting too much.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-5928339514831774927?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/5928339514831774927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=5928339514831774927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5928339514831774927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5928339514831774927'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/06/my-hopes-for-ruby-20.html' title='My Hopes For Ruby 2.0'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-5009642272573375790</id><published>2008-06-14T13:15:00.002-05:00</published><updated>2008-06-14T13:56:16.166-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='misc'/><title type='text'>Five Years</title><content type='html'>I can't believe it. I missed my fifth anniversary for blogging! I started out in 2003 to be a public diary for my technical side. I've enjoyed doing it and plan to do so for many years to come. It's just too much fun to read through all of the posts and remember where I was at during that point of time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-5009642272573375790?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/5009642272573375790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=5009642272573375790' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5009642272573375790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5009642272573375790'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/06/five-years.html' title='Five Years'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-558961052836686648</id><published>2008-06-09T21:41:00.001-05:00</published><updated>2008-06-09T21:44:59.854-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Twitter</title><content type='html'>I've joined the modern age. I'm now on &lt;a href="http://twitter.com/bbuxton"&gt;twitter&lt;/a&gt;. I know, I'm behind the curve. See you there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-558961052836686648?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/558961052836686648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=558961052836686648' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/558961052836686648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/558961052836686648'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/06/twitter.html' title='Twitter'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-4073078432296223405</id><published>2008-05-27T21:35:00.002-05:00</published><updated>2008-05-27T21:39:25.743-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='dynamic languages'/><category scheme='http://www.blogger.com/atom/ns#' term='seaside'/><category scheme='http://www.blogger.com/atom/ns#' term='presentation'/><title type='text'>Yet Another Seaside Talk</title><content type='html'>At the next &lt;a href="http://odynug.kicks-ass.org"&gt;Omaha Dynamic Language User Group&lt;/a&gt;, I will be speaking on Seaside. If you missed my talk at the BarCampKansasCity, you can catch it now. I will be showing how to build web applications with the best web framework out there. Expect lots of simplicity and heretical statements.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-4073078432296223405?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/4073078432296223405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=4073078432296223405' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/4073078432296223405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/4073078432296223405'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/yet-another-seaside-talk.html' title='Yet Another Seaside Talk'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-4356279137372591281</id><published>2008-05-27T10:12:00.002-05:00</published><updated>2008-05-27T18:50:00.421-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><title type='text'>Change of Plans</title><content type='html'>&lt;strike&gt;Due to a change in plans, I will not be attending the Chicago Lisp Workshop.&lt;/strike&gt;&lt;br /&gt;&lt;br /&gt;No, I'll be there. Things looked bleak this morning, but I'm all clear now. Amazing what a day can do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-4356279137372591281?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/4356279137372591281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=4356279137372591281' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/4356279137372591281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/4356279137372591281'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/change-of-plans.html' title='Change of Plans'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-2507150746288644581</id><published>2008-05-22T20:14:00.002-05:00</published><updated>2008-05-22T20:16:41.317-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conference'/><title type='text'>Chicago Lisp Workshop</title><content type='html'>I will be in Chicago on May 31 to participate in this &lt;a href="http://www.chicagolisp.org/wiki/doku.php?id=lispworkshop"&gt;Lisp Workshop&lt;/a&gt;. It should be more fun than one person is allowed to have. A weekend of Lisp sounds nice doesn't it? See you in Chicago.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-2507150746288644581?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/2507150746288644581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=2507150746288644581' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2507150746288644581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2507150746288644581'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/chicago-lisp-workshop.html' title='Chicago Lisp Workshop'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-4296628803345028221</id><published>2008-05-22T20:12:00.000-05:00</published><updated>2008-05-22T20:14:09.566-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Reading other people's code is good</title><content type='html'>Reading other people's code is the needle lost in the hay buried deep in &lt;a href="http://duartes.org/gustavo/blog/post/language-dabbling-considered-wasteful"&gt;this article entitled "Language Dabbling Considered Wasteful"&lt;/a&gt;. Forget the dreadful title that makes my eyes roll back in my head. It's still too close to Dijkstra's famous paper. But, I digress. This is not a pointless rant on over abused trivia.&lt;br /&gt;&lt;br /&gt;If you want to become a better programmer, read code and understand it. There's no way around it. Read code, experiment with it, and figure out if you like it or not. Bad code can teach just as much. It's no fun to read, but it shows how not to do things. The danger with bad code is being picking up incorrect habits. Get into the practice of reading code and not the Javadocs. If you're learning a new language you will see the idioms and be able to apply them. Plus, you will know how to find how things work underneath the covers if you run into a super thorny issue.&lt;br /&gt;&lt;br /&gt;Yeah, give me the source any day. I love reading code and it's how I learn. Once I get past the basics, I start reading and understanding others code. I will say it again, there are no shortcuts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-4296628803345028221?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/4296628803345028221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=4296628803345028221' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/4296628803345028221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/4296628803345028221'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/reading-other-peoples-code-is-good.html' title='Reading other people&apos;s code is good'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-3621716460351936913</id><published>2008-05-18T11:36:00.000-05:00</published><updated>2008-05-18T11:37:57.356-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>And we wonder why we are one of the most hated careers</title><content type='html'>This is a shame: &lt;a href="http://www.unixwiz.net/ndos-shame.html"&gt;No Dashs or Spaces&lt;/a&gt;. We should be helping and not being a road block. I know I've cussed at a few of these sites listed. Sometimes I think we should put ourselves in the shoes of our customer and think, "What would make their life easier?" We should make it as easy as possible for a user to achieve their goals. The computer should disappear and only the problem at hand should be on the user's mind. We still have a long way to go. Let's start being more empathetic. The users are people too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-3621716460351936913?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/3621716460351936913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=3621716460351936913' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/3621716460351936913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/3621716460351936913'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/and-we-wonder-why-we-are-one-of-most.html' title='And we wonder why we are one of the most hated careers'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-8646483155424209785</id><published>2008-05-18T11:28:00.000-05:00</published><updated>2008-05-18T11:29:37.941-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='analysis'/><title type='text'>Situated Web Application Platform</title><content type='html'>&lt;a href="http://wordpress.com/tag/barcampkc/"&gt;Pete Thomas&lt;/a&gt; presented "Situated Web Application Platforms" at &lt;a href="http://barcamp.org/BarCampKC"&gt;BarCampKC&lt;/a&gt;. The talk was wonderful and it made me think about current IT solutions. A talk ensued after his wonderful presentation about Excel, email, agile methodologies, and enterprise development. It was pondered why business users embrace Excel and email and are reluctant to move off of them. The alternatives, SWAPs, are clearly superior, so why stick with cruder applications? I reasoned because Excel and email were good enough. Why would they want to learn a new tool if the current one fulfills their need? They are not computer people and would rather be solving problems than wasting time in front of a computer. Their passion and strength is not in development, but solving business problems. We should embrace that. While this might startle us because we wouldn't stand for it (I know I would not want to merge data from a bunch of Excel spreadsheets into one, but my passion is different).&lt;br /&gt;&lt;br /&gt;So, why fight and try to replace Excel? We need to change our thinking and embrace it. It could help with requirements gathering. It could help us find the missing pieces in our software. We are always on the lookout for solving problems with technology, but in this case, we should be asking our users why they have the need to use Excel. What else could we do for them. It's time for us to stop mindlessly implementing what the customer tells us and figure out what their true goals are and solve those.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-8646483155424209785?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/8646483155424209785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=8646483155424209785' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8646483155424209785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/8646483155424209785'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/situated-web-application-platform.html' title='Situated Web Application Platform'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-5481669712193349323</id><published>2008-05-14T19:02:00.002-05:00</published><updated>2008-05-14T19:04:24.463-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='funny'/><title type='text'>Standards Gone Wild</title><content type='html'>There was a discussion recently on standards where one poster said that they were big on alignment. Here's an exchange:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Hi__ jwen,&lt;br /&gt;&lt;br /&gt;jhdn&gt; Simple solution: set in your coding standards that ALL&lt;br /&gt;jhdn&gt; classnames MUST be a specific length, and also dictate specific&lt;br /&gt;jhdn&gt; lengths for all member variables, method names, etc. etc.&lt;br /&gt;&lt;br /&gt;Hmmm_, I___ thnk that mght caus more prbs, mayb even a___ rvln from&lt;br /&gt;the_ devs. Not_ to__ mntn that it__ lmts your cr8v ablt to__ use_ good&lt;br /&gt;nams and bild a dict* that hlps bild betr apps.&lt;br /&gt;&lt;br /&gt;Grgg&lt;br /&gt;&lt;br /&gt;* I Just couldn't come up with a four letter substitution for&lt;br /&gt;"vocabulary". :)&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;Classic. I laughed coffee through my nose. It hurt, but was well worth it. I'm glad I don't work somewhere they have standard on the size of my variables. I don't think I would be working there much longer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-5481669712193349323?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/5481669712193349323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=5481669712193349323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5481669712193349323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/5481669712193349323'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/standard-gone-wrong.html' title='Standards Gone Wild'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772872.post-2626187079329530086</id><published>2008-05-13T11:59:00.002-05:00</published><updated>2008-05-13T12:06:38.734-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='prototypes'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Javascript: Stop Fighting It</title><content type='html'>I recently came to the realization that I've been fighting Javascript too much. It's because I've been going against the grain with it. It's like trying to force the OO paradigm in a functional language or the opposite. You might say that I've been treating Javascript like an OO language and you would be right. But, I've been forcing my class-based thinking on it and it's been not so nice.&lt;br /&gt;&lt;br /&gt;I've been reacquainting myself with Self and Io again. And it hit me like a rhino slamming into me. I've been doing Javascript all wrong. I should have treating it like the prototype-based language that it is. Sure, it doesn't have the ability to inherit from multiple prototypes like Self, but the way to succeed is with prototypes. Forcing class-based OO is like walking up the rainbow and finding no pot of gold at the end.&lt;br /&gt;&lt;br /&gt;First, let's write the following:&lt;br /&gt;&lt;pre&gt;Object.prototype.clone=function() {&lt;br /&gt;    var creator=function() { this.constructor=arguments.callee };&lt;br /&gt;    creator.prototype=this;&lt;br /&gt;    return new creator();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Object.prototype.mixIn=function(definitions) {&lt;br /&gt;    for (var each in definitions) if (definitions.hasOwnProperty(each)) {&lt;br /&gt;        this[each]=definitions[each];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's just two methods up on the Object prototype. Why clone is not part of the Javascript standard is beyond me. Clone is required in all the other prototype-bases languages I have seen. It is the only way to create new objects. Enough complaining, it was only a few lines of code. All my clone method does is make the object I call it on the prototype of the result. I get a clean object with all of the properties of the receiver inherited. Nice. This is the behavior we want. Next, I added a convenience method to Object to mix-in in other objects. This is helpful to keep my code organized. I can just create a hash object with my functions and properties like before. So far, this is standard stuff. But, here is how I use it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Pounds = new Object();&lt;br /&gt;Pounds.mixIn({&lt;br /&gt;    of: function(value) {&lt;br /&gt;        var result=this.clone();&lt;br /&gt;        result.value=value;&lt;br /&gt;        return result;&lt;br /&gt;    },&lt;br /&gt;    toString: function() {&lt;br /&gt;        return this.value.toString() + " lbs";&lt;br /&gt;    },&lt;br /&gt;    value: 0&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;print(Pounds.of(5)); // =&gt; 5 lbs&lt;br /&gt;print(Pounds); // =&gt; 0 lbs&lt;br /&gt;print(Pounds.isPrototypeOf(Pounds.of(5))); // =&gt; true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice, normally, you define the constructor with the first letter of the name upper cased. I no longer need the constructor, so I upper case on the prototype that will be the example for all the instances that I clone off it. The example above is a measurement class. "Pounds" is my example so I default it with values that the objects that I clone from will have. This is how prototype-based languages work. It feels slightly unusual coming from the class-based background, but I think it makes my Javascript look a lot less alien. I like it. &lt;br /&gt;&lt;br /&gt;Let's look at a more complicated example shall we?&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Animal = new Object();&lt;br /&gt;Animal.mixIn({&lt;br /&gt;    name: "Unknown",&lt;br /&gt;    sound: function() {&lt;br /&gt;        return "?";&lt;br /&gt;    },&lt;br /&gt;    toString: function() {&lt;br /&gt;        return this.name &lt;br /&gt;                + " goes " + this.sound() &lt;br /&gt;                + " and weighs " &lt;br /&gt;                + this.weight.toString();&lt;br /&gt;    },&lt;br /&gt;    weight: Pounds.of(0)&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;Cat = Animal.clone();&lt;br /&gt;Cat.mixIn({&lt;br /&gt;    name: "Unknown Cat",&lt;br /&gt;    sound: function() {&lt;br /&gt;        return "Meow";&lt;br /&gt;    },&lt;br /&gt;    weight: Pounds.of(10)&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;grendel = Cat.clone();&lt;br /&gt;grendel.mixIn({&lt;br /&gt;    name: "Grendel",&lt;br /&gt;    sound: function() {&lt;br /&gt;        return this.constructor.prototype.sound.call(this) + " and Purr";&lt;br /&gt;    },&lt;br /&gt;    weight: Pounds.of(20)&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;gracie = Cat.clone();&lt;br /&gt;gracie.mixIn({&lt;br /&gt;    name: "Gracie",&lt;br /&gt;    sound: function() {&lt;br /&gt;        return "Purr";&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;print(Animal); // =&gt; Unknown goes ? and weighs 0 lbs&lt;br /&gt;print(Cat); // =&gt; Unknown Cat goes Meow and weighs 10 lbs&lt;br /&gt;print(Animal.isPrototypeOf(grendel)); // =&gt; true&lt;br /&gt;print(grendel); // =&gt; Grendel goes Meow and Purr and weighs 20 lbs&lt;br /&gt;print(gracie); // =&gt; Gracie goes Purr and weighs 10 lbs&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;"super" is implemented with "this.constructor.prototype". It seems wordy, but prototype on the object is not built-in to Javascript. Besides, you should use "super" sparingly. To me, this reads better and works better for inheritance. I have dropped all references to classes. This makes meta-programming easier as well (I simply walk up the prototype chain with "this.constructor.prototype" and iterate through the properties.&lt;br /&gt;&lt;br /&gt;The constructor function used as a class always seemed awkward to me. It was inelegant, but the above fits Javascript coding better. The reason is because I'm now using it as a prototype-based language and not forcing class-based OO on it. The above is meant to get started playing around. Prototype-based programming is so cool and I'm still exploring all of the possibilities. There's little documentation, but the little that is well worth the effort to track down. Have fun!&lt;br /&gt;&lt;br /&gt;The example above was tested in SpiderMonkey. A great little REPL for playing with Javascript.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772872-2626187079329530086?l=blog.blainebuxton.net'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/2626187079329530086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5772872&amp;postID=2626187079329530086' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2626187079329530086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772872/posts/default/2626187079329530086'/><link rel='alternate' type='text/html' href='http://blog.blainebuxton.net/2008/05/javascript-stop-fighting-it.html' title='Javascript: Stop Fighting It'/><author><name>Blaine</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04774976808745968787'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry></feed>