My Stuff
Email
Twitter
Front Page
Presentations
Projects
Music
Favorite Quotes
Dynamic Language User's Group

Love
Michelle Buxton

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

Feed

Add this feed to a running copy of BottomFeeder

Saturday, October 11, 2008

Forced 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.

Labels: ,


Comments
  • Pairing assumes that two people working on the problem is the best way to proceed. Often even if the two like their pair partner it's not the best use of their skills nor time.

    The blind assumption that agile pairing will result in success, or more success, that the individuals working alone is a very big assumption and often false.

    Many people do their best thinking alone. Maybe they are inspired or get an idea within a team framework but the execution for them is best done alone. Working with someone to refine their initial work is often the best time to introduce another pair of eyes or even a whole group of many eyes.

    Often the extra eyes are needed for assistence with aspects of design, or with debugging or refinement. Often the extra eyes get in the way and prevent progress.

    Maximizing the genius of the people on your team can be a valuable asset. Applying the blind hammer of blunt instruments like the agile methods can be highly counter productive.

    As a professional programmer, systems analyst and designer, and producer of products it's important to know when to seek out others for assistence. To force it upon the process and team members is highly unwise.

    Working together with other professionals on many projects I always attempt to maximize the best of working alone and working together with the rest of the team. The key is knowing what is best for your productivity and for the team's productivity in producing the results that are aimed for.

    There is an "I" in "team" after all and it's known as the intelligence of the individual.

    By Blogger peter, at 9:09 PM   

  • Couldn't have said it better myself.

    By Blogger Blaine, at 9:14 PM   

  • Hi, Blaine! I know you've had reservations about this. Pairing with difficult people is, well, difficult. It is tempting to opt out.

    But what better place to work out the give and take of teamwork than in the smallest possible team: the pair? Anybody can work with a friend. But to work with a person who I don't naturally get along with is a chance to grow in virtue. I would not lightly pass up that opportunity.

    If two people cannot or will not work together, it seems to me one or both of them shouldn't be on the team who's standard is all production code written by pairs. Pairing is not forced, anymore than showing up for work on time is forced, because joining a team is voluntary.

    By Blogger Alan Wostenberg, at 2:26 PM   

  • I think both points are good. Human nature is certainly something to be tuned into. "Virtue" as Alan put it is also a worthwhile investment.

    I see so much value that comes from pairing that I tend to move in that direction, but I also prefer many times to work alone, allowing ideas to form, etc...

    Team make-up is probably key. At the end of the day, I suppose the wisest of us will employ that which delivers the most value to the company. That would require that each of us be open to either approach, and probably some combination of the two.

    If a pairing assignment offers little to no value, and nature forbid, negative value, then some action to correct the situation must occur.

    I think we can trust each other more than we do, so I will agree mostly with Blaine and Peter, but not entirely.

    Not pairing at all discourages engagement in the pairing activity a great deal. I find that a bit unsafe.

    Long story short, no absolutes, they just don't work.

    By Blogger Doug Stewart, at 11:35 AM   

Sunday, August 24, 2008

Mentoring

 
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:


Comments
  • Blaine,

    Great post. One fact that immediately came to mind was that Minneapolis' Minnebar '08 was held at the U of M Union: http://is.gd/1TEk

    By Blogger Share Tactics, at 9:54 AM   

  • Blaine,

    I think this is a great idea. I wonder though how many CS students are excited about learning, considering the amount of education they just completed or are currently undertaking. Part of it may be that they need a break or feel it is just too much burden on their schedule.

    Some have lots of extra energy in them (Samuel comes to mind). I'm sure after a couple sessions of fun, they'll be turned on.

    By Blogger Doug Stewart, at 4:33 PM   

  • Wow on Minnebar. I need to make that one year. Awesome.

    On CS Students, I think a lot are excited and just need some guidance. I know I seeked out mentors (I had a couple of professors that gave me advice). But, to have someone in the real world, would have been glorious. I would like to return the favor.

    By Blogger Blaine, at 8:08 PM   

  • Agreed, dude. Agreed. A mentoring model is a cool idea. It's too bad that most companies don't get this idea. It's more "and into the fire you go with your 39k" sort of deal. Very tough to learn - properly - in those environments.

    By Blogger Jeff, at 2:16 PM   

  • Interesting point about the U of M Union. Perhaps we could hold user group meetings at the UNO union if we got a faculty member involved?

    By Blogger Matt, at 10:33 AM   

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:


Comments
  • Had an interesting presentation. I wish I could have stuck around to hear more about seaside, I've never messed around with Smalltalk.

    By Blogger Paris Holley, at 8:53 AM   

  • Well, next time I'm in Des Moines pull me to the side and I'll show all you want to know about Smalltalk. I'll be back in October for the Ruby User's Group.

    By Blogger Blaine, at 8:09 PM   

Wednesday, August 06, 2008

Update 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.

Base = new Object();
Base.clone = function() {
var creator = function() {
this.constructor = arguments.callee
};
creator.prototype = this;
var result = new creator();
if (result.initialize)
result.initialize.apply(result, arguments);
return result;
}

Base.mixIn = function(properties) {
for ( var each in properties)
if (properties.hasOwnProperty(each))
this[each] = properties[each];
return this;
}

ZipCode = Base.clone().mixIn( {
initialize : function(standard, extension) {
this.standard = standard;
this.extension = extension;
},
toString : function() {
return this.standard + "-" + this.extension;
}
});

print(ZipCode.clone('56777', '4567'));

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: ,


Comments

Sunday, July 13, 2008

Functional 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:

commitEvery: aNumber during: aBlock
| count |
count := 1.
[self session beginUnitOfWork.
aBlock value:
[count := count + 1.
count > aNumber
ifTrue:
[self session commitUnitOfWork.
self session beginUnitOfWork.
count := 1]]].
self session commitUnitOfWork

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:

populate
| db |
db := self new.
[db
commitEvery: 1000
during:
[:afterAdd |
ITunesSAXHandler readUsing:
(ITunesTracksHandler onEachTrackDo:
[:each |
db addTrack: each.
afterAdd value])]]
ensure: [db disconnect]

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):

duringDoEvery: aNumber onBegin: beginBlock onEnd: endBlock
| count result |
count := 1.
beginBlock value.
result := self value:
[ count := count + 1.
count > aNumber ifTrue:
[ endBlock value.
beginBlock value.
count := 1 ] ].
endBlock value.
^result

This turns our first method into this:

commitEvery: aNumber during: aBlock
^aBlock
duringDoEvery: 1000
onBegin: [ self session beginUnitOfWork ]
onEnd: [ self session commitUnitOfWork ]

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:

[:afterAdd |
| count |
count := 0.
10 timesRepeat:
[Transcript show: (count := count + 1) printString; cr.
afterAdd value]]
duringDoEvery: 5
onBegin: [Transcript show: 'begin'; cr]
onEnd: [Transcript show: 'end'; cr]

Gives this output:

begin
1
2
3
4
5
end
begin
6
7
8
9
10
end
begin
end

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:

duringDoEvery: aNumber onBegin: beginBlock onEnd: endBlock
| count result hasBegun |
count := 1.
hasBegun := false.
result := self value:
[ :eachBlock |
count := count + 1.
hasBegun ifFalse:
[ beginBlock value.
hasBegun := true ].
eachBlock value.
count > aNumber ifTrue:
[ endBlock value.
hasBegun := false.
count := 1 ] ].
hasBegun ifTrue: [ endBlock value ].
^ result

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:

[:onEachAdd |
| count |
count := 0.
10 timesRepeat:
[onEachAdd value:
[Transcript show: (count := count + 1) printString; cr]]]
duringDoEvery: 5
onBegin: [Transcript show: 'begin'; cr]
onEnd: [Transcript show: 'end'; cr]

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: , ,


Comments
  • The post reminded me the message #do:separatedBy:. The problem looks analog to its behavior, but I my smalltalk is a bit rusty right now..

    By Blogger tenuki, at 11:04 PM   

  • It is similar. But, do:separatedBy: iterates through the collection and then calls the separatedBy after each one except the last. Here I wanted to call the separatedBy: after x members in the collection and make sure it called in the end as well.

    By Blogger Blaine, at 7:36 AM   

Monday, June 30, 2008

Too 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.

Labels: ,


Comments
  • I like the phrasing in the Scheme Standard:

    Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.

    Sadly, R6RS seems to have lost sight of this to a degree.

    By Blogger Jeremy, at 10:04 PM   

  • In all fairness, although there’s a lot of explanation for how to do unusual things, the simple things really are simple to accomplish, like using blocks with methods.

    So although I like the Scheme quote, someone defending Ruby might quote Alan Kay:

    Simple things should be simple, complex things should be possible.

    :-)

    By Blogger Reginald Braithwaite, at 8:16 PM   

  • I agree that most things in Ruby are simple. It's just frustrating for me when I'm trying to solve a problem and my head is completely into it and then WHAM! I'm caught off guard with a compiler issue or prevented by something else. It's the cognitive friction that I would like to remove from Ruby. I think the core ingredients are there, but I think Ruby should go through a feature removal. The first things for me to go would the ampersand followed closely by all of the built-in global variables.

    I would like to see Ruby go the path less traveled and not the one Java took.

    By Blogger Blaine, at 8:51 PM   

  • By Blogger Reginald Braithwaite, at 8:55 PM   

Sunday, June 29, 2008

Weakest 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:


Comments

Sunday, June 22, 2008

My 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.

  1. Make blocks first class citizens. So, no more & 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.

  2. 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.

  3. 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 & 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?


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:


Comments

Saturday, June 14, 2008

Five Years

 
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.

Labels:


Comments

Monday, June 09, 2008

Twitter

 
I've joined the modern age. I'm now on twitter. I know, I'm behind the curve. See you there!

Labels:


Comments

Tuesday, May 27, 2008

Yet Another Seaside Talk

 
At the next Omaha Dynamic Language User Group, 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.

Labels: , , ,


Comments

Change of Plans

 
Due to a change in plans, I will not be attending the Chicago Lisp Workshop.

No, I'll be there. Things looked bleak this morning, but I'm all clear now. Amazing what a day can do.

Labels:


Comments

Thursday, May 22, 2008

Chicago Lisp Workshop

 
I will be in Chicago on May 31 to participate in this Lisp Workshop. 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.

Labels:


Comments

Reading other people's code is good

 
Reading other people's code is the needle lost in the hay buried deep in this article entitled "Language Dabbling Considered Wasteful". 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.

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.

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.

Labels:


Comments
  • Hi Blaine,

    I'd say it's not buried too deep in the post though: it's the only bolded sentence in the whole thing, and reinforced in the update.

    Where it did get buried was the pseudo-discussion following the post, where people who didn't read past the first paragraph and/or cannot understand written English completely missed the point of the post and attacked various straw men of their own creation. One who particularly pissed me off was a guy saying I was arguing against for single-language programming, despite SEVERAL instances where I push multiple languages. Argh.

    It's good to see someone picked on the read code part.

    And I used to cover a lot of Iron Maiden songs a few years back ;) hehe. Hallowed Be Thy Name is my favorite.

    cheers,
    gustavo

    By Blogger Gustavo, at 12:28 PM   

Sunday, May 18, 2008

And we wonder why we are one of the most hated careers

 
This is a shame: No Dashs or Spaces. 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.

Labels: ,


Comments
  • On the flip side, I don't have a high opinion of "warning this hot beverage is hot!" labels on coffee cups either, but then again where did that come from...

    Same thing with warning labels such as "watch out a baby can drown here!" in 5 gallon buckets of e.g.: laundry soap, complete with a drawing and everything.

    Now I just can't help wondering if some customer didn't sue somebody for something just as ridiculous and now everybody basically says "no dashes nor hyphens", and omit the part about "so that we don't get frivolously sued"...

    Andres.

    By Blogger Andres, at 3:10 PM   

Situated Web Application Platform

 
Pete Thomas presented "Situated Web Application Platforms" at BarCampKC. 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).

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.

Labels:


Comments

Wednesday, May 14, 2008

Standards Gone Wild

 
There was a discussion recently on standards where one poster said that they were big on alignment. Here's an exchange:
Hi__ jwen,

jhdn> Simple solution: set in your coding standards that ALL
jhdn> classnames MUST be a specific length, and also dictate specific
jhdn> lengths for all member variables, method names, etc. etc.

Hmmm_, I___ thnk that mght caus more prbs, mayb even a___ rvln from
the_ devs. Not_ to__ mntn that it__ lmts your cr8v ablt to__ use_ good
nams and bild a dict* that hlps bild betr apps.

Grgg

* I Just couldn't come up with a four letter substitution for
"vocabulary". :)

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.

Labels:


Comments

Tuesday, May 13, 2008

Javascript: Stop Fighting It

 
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.

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.

First, let's write the following:
Object.prototype.clone=function() {
var creator=function() { this.constructor=arguments.callee };
creator.prototype=this;
return new creator();
}

Object.prototype.mixIn=function(definitions) {
for (var each in definitions) if (definitions.hasOwnProperty(each)) {
this[each]=definitions[each];
}
}

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:

Pounds = new Object();
Pounds.mixIn({
of: function(value) {
var result=this.clone();
result.value=value;
return result;
},
toString: function() {
return this.value.toString() + " lbs";
},
value: 0
});

print(Pounds.of(5)); // => 5 lbs
print(Pounds); // => 0 lbs
print(Pounds.isPrototypeOf(Pounds.of(5))); // => true

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.

Let's look at a more complicated example shall we?

Animal = new Object();
Animal.mixIn({
name: "Unknown",
sound: function() {
return "?";
},
toString: function() {
return this.name
+ " goes " + this.sound()
+ " and weighs "
+ this.weight.toString();
},
weight: Pounds.of(0)
});

Cat = Animal.clone();
Cat.mixIn({
name: "Unknown Cat",
sound: function() {
return "Meow";
},
weight: Pounds.of(10)
});

grendel = Cat.clone();
grendel.mixIn({
name: "Grendel",
sound: function() {
return this.constructor.prototype.sound.call(this) + " and Purr";
},
weight: Pounds.of(20)
});

gracie = Cat.clone();
gracie.mixIn({
name: "Gracie",
sound: function() {
return "Purr";
}
});

print(Animal); // => Unknown goes ? and weighs 0 lbs
print(Cat); // => Unknown Cat goes Meow and weighs 10 lbs
print(Animal.isPrototypeOf(grendel)); // => true
print(grendel); // => Grendel goes Meow and Purr and weighs 20 lbs
print(gracie); // => Gracie goes Purr and weighs 10 lbs

"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.

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!

The example above was tested in SpiderMonkey. A great little REPL for playing with Javascript.

Labels: , ,


Comments
  • Never, ever touch Object.prototype, please. Thousands of lines of Javascript which treat objects like associative arrays will break in horrible, horrible ways.

    By Blogger Jesse, at 11:59 AM   

  • Agreed w/ jesse. Adding things to Object.prototype is a big no-no.

    By Blogger Tom, at 2:48 PM   

  • Crap. You are both right. I've been on the server-side for so long (I use Javascript mainly as a scripting tool, that I forgot about this. Anyway, it's quickly fixed with this:

    Base=new Object();
    Base.clone=function...

    Thank you for bringing that up.

    By Blogger Blaine, at 6:45 AM   

Two years after XP

 
I feel like I can finally write about my XP experiences. I was once a member of the largest XP teams in the country for three years. The XP practices were the main reason for me joining the team. I had been experimenting with agile at my prior work places with great success, but no one wanted to jump in. I found this team and they were up to their necks in it. I loved the thought of it. The people were passionate, caring, and intelligent. What could go wrong?

Nothing went wrong. But, I'm a bit of a skeptic now when some company touts agile to me now. I'm a bit shell-shocked. How could this possibly happen? I'll just list them. Don't worry it's only a few.

  • Everyone owns the code

  • In theory, this sounds wonderful. It really does and I think it works on a small team of 3-4 dedicated developers. It doesn't scale beyond that. The 3-4 developers must be dedicated to keeping the code clean too. If someone fails to clean up ugly code, then it quickly turns into glue. It turns against you if everyone thinks that everyone else will do the cleanup. There are plenty of negatives to personal code ownership, but the point is to have at least two people as masters of each section. Multiple eyes should see any code commit. But, someone or a pair should own it.
  • Mandatory pairing

  • Pairing sounds so good on paper, but it completely takes away the human element. Programmers are introverts by and large. Pairing can wear out some people quickly. I found forced pairing tiresome because not all folks get along. There were some people that I would enjoy pairing with and I learned a lot from. I would always want to pair with them, but other folks it was a constant struggle. I think pairing should be an optional activity that developers should naturally want to do when brain storming or checking in code. I find that code reviews with a pair of eyes who have never seen the code that I am checking is always a good thing. This should be done often. If you think about it, what I am describing is collaboration. Pairing to me as a term basically means one side can turn off. Collaboration is where both sides are equally engaged.

You will notice I didn't list test-driven development above. If anything, XP got that one right. I write tests for everything and stand behind them. I don't see how anyone can stand behind their work without them. I even write tests for my research code. I'm still 100% agile, but I think each practice needs to be tailored to your team. Don't blindly follow the book. If something hurts, don't keep picking at it. You might lose the limb and your project.

This is only the beginning. I plan to write more the subject.

Labels: ,


Comments
  • Pair programming is great, but all pairs are not created equal. I used to pair with someone and we were extremely effective together, but when we were finished I would be exhausted. Somehow our interaction required a lot of energy even though we were not at odds with each other. After a few of these sessions I was reluctant to do it anymore. Funny thing.

    By Blogger Carl Gundel, at 3:41 PM   



Web hosting by ICDSoft

Metalheads Against Racism
This page is powered by Blogger. Isn't yours?


My Weekly Top 20 Artists