Positronic VibrationsMaking the ugly elegant one day at a time
|
My Stuff Front Page Presentations Projects Music Favorite Quotes Respect Vincent Foley-Bourgon Sam Griffith LeRoy Mattingly Colin Putney Matt Secoske Sam Tesla Andres Valloud Admiration Leo Brodie Avi Bryant Alan Cooper Steve Dekorte Stephane Ducasse Doug Engelbart Eric Evans Brian Foote Martin Fowler Paul Graham Dan Ingalls Alan Kay John McCarthy Steve McConnell Peter Norvig Niall Ross Randall Smith Gerald Jay Sussman David Ungar Rebecca Wirfs-Brock ...And So Many More... My Amps Squeak JavaScript Scheme Java Corman Lisp Ruby Dolphin Smalltalk Cincom Smalltalk Self Archives 05/01/2003 - 06/01/2003 06/01/2003 - 07/01/2003 07/01/2003 - 08/01/2003 08/01/2003 - 09/01/2003 09/01/2003 - 10/01/2003 10/01/2003 - 11/01/2003 11/01/2003 - 12/01/2003 12/01/2003 - 01/01/2004 01/01/2004 - 02/01/2004 02/01/2004 - 03/01/2004 03/01/2004 - 04/01/2004 04/01/2004 - 05/01/2004 05/01/2004 - 06/01/2004 06/01/2004 - 07/01/2004 07/01/2004 - 08/01/2004 08/01/2004 - 09/01/2004 09/01/2004 - 10/01/2004 10/01/2004 - 11/01/2004 11/01/2004 - 12/01/2004 12/01/2004 - 01/01/2005 01/01/2005 - 02/01/2005 02/01/2005 - 03/01/2005 03/01/2005 - 04/01/2005 04/01/2005 - 05/01/2005 05/01/2005 - 06/01/2005 06/01/2005 - 07/01/2005 07/01/2005 - 08/01/2005 08/01/2005 - 09/01/2005 09/01/2005 - 10/01/2005 10/01/2005 - 11/01/2005 11/01/2005 - 12/01/2005 12/01/2005 - 01/01/2006 01/01/2006 - 02/01/2006 02/01/2006 - 03/01/2006 03/01/2006 - 04/01/2006 04/01/2006 - 05/01/2006 05/01/2006 - 06/01/2006 06/01/2006 - 07/01/2006 07/01/2006 - 08/01/2006 08/01/2006 - 09/01/2006 09/01/2006 - 10/01/2006 10/01/2006 - 11/01/2006 11/01/2006 - 12/01/2006 12/01/2006 - 01/01/2007 01/01/2007 - 02/01/2007 02/01/2007 - 03/01/2007 03/01/2007 - 04/01/2007 04/01/2007 - 05/01/2007 05/01/2007 - 06/01/2007 06/01/2007 - 07/01/2007 07/01/2007 - 08/01/2007 08/01/2007 - 09/01/2007 09/01/2007 - 10/01/2007 10/01/2007 - 11/01/2007 11/01/2007 - 12/01/2007 12/01/2007 - 01/01/2008 01/01/2008 - 02/01/2008 02/01/2008 - 03/01/2008 03/01/2008 - 04/01/2008 04/01/2008 - 05/01/2008 05/01/2008 - 06/01/2008 06/01/2008 - 07/01/2008 07/01/2008 - 08/01/2008 08/01/2008 - 09/01/2008 10/01/2008 - 11/01/2008 01/01/2009 - 02/01/2009 09/01/2009 - 10/01/2009 10/01/2009 - 11/01/2009 Feed ![]()
|
Saturday, October 17, 2009Devilishly Clever
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: Tail Call Optimization Decorator. 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.
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: def reg_fact(x): 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. 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. Labels: design, functional programming, Python Saturday, October 10, 2009Freezing Objects in Python
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:
class ValueObject(object): Do you have to ask? Yes, I made a test. Here they are: import unittest Labels: programming, Python CommentsMonday, October 05, 2009method_missing in Python
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:
class PossibleMissingAttribute(object): 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: import unittest You've seen my implementation. Here's another one that I found on the net: method_missing in Python class MethodMissing(object): 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. 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!). Labels: programming, Python CommentsTuesday, September 29, 2009Prototypes in Python
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:
class Prototype(object): The implementation is suprisingly simple: three methods! 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. 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! 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. 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. How do I know all of this works? Here's my tests: import unittest 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. Labels: prototypes, Python Comments
Sunday, September 13, 2009Constraints in Python
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.
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. 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. Labels: Python Comments
Saturday, September 12, 2009The Dead Year
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!
Labels: misc Comments
Sunday, January 04, 2009Domain Change
Update your bookmarks from blainebuxton.com to blainebuxton.net. The new blog address is: blog.blainebuxton.net. 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!
Labels: misc CommentsSaturday, October 11, 2008Forced Pairing
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.
"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. Comments
Sunday, August 24, 2008Mentoring
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.
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. 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. 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? 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. 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. Labels: inspiration Comments
Bar Camps
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 presentations page.
Labels: bar camp Comments
Wednesday, August 06, 2008Update on Javascript
I've been meaning to write an update to my post on Javascript prototypes. Let me just show the updated code and then I'll explain what's changed.
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. 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. 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. 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. Labels: javvascript, programming Comments
Sunday, July 13, 2008Functional Programming Has Warped Me
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:
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:
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):
This turns our first method into this:
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:
Gives this output:
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:
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:
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>>streamContents: does. 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. Labels: design, functional programming, squeak Comments
Monday, June 30, 2008Too Complex?
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: Explanation of Ruby's Unary operator. 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.
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. Comments
Sunday, June 29, 2008Weakest Link
"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
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. 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. With that being said, are they places in your current design that could use a few more fuses? Labels: design CommentsSunday, June 22, 2008My Hopes For Ruby 2.0
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.
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. Labels: ruby Comments |
My Weekly Top 20 Artists |
Comments
This post reminds me of the all-too-true quote by Brian Kernighan:
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
By
kesmit, at 9:51 PM
Hey! I wrote an entry about a clever coding too.
http://squeak.preeminent.org/blog/?p=325
- Steve
By
fastfingers, at 10:07 PM