Tuesday, January 09, 2007
How To Make Sure Your Fans Don't Find You
"Riders of Apocalypse". Why the name change? Oh well, who cares? One of my favorite bands are back and I got two new albums by them this year. I should be happy and I am! I just would have liked to been listening to one of them now for 3 years....I got a lot of time to make up!
Great Post On Smalltalk and Parsers
tangent: No Virginia, Smalltalk does not have operator overloading. It simply allows method names using non-alphanumeric characters. These are always infix and all have the same fixed precedence. How can it be so simple? It’s called minimalism, and it’s not for everyone. Like Mies van der Rohe vs. Rococo.
He makes more and it's a great read. I almost got diet pepsi all over my new Mac while reading it. I tend to stand on the same fence that thinks functional and object-oriented programming compliment each other well. I'll even go as far and say they need each other. I ran across this blog because of my recent interest in Self and Factor. Fun stuff!
Monday, January 08, 2007
Don't You Want To Own a Lisp?
Sunday, January 07, 2007
The First Week With Mac
I love the quickness of putting it to sleep! Wow! Booting it up from scratch is slow, but I've only had to do that once so far. I just put it to sleep. Nice.
I'm enjoying Dashboard and I've already gone a little nuts with it. I think I have something like 8 widgets. I have a weather one, two quotes of the day, inspiration for the day, word of the day, unix command lookup, ruby documentation, and a thesaurus.
Switching between applications is nice. It took me a little time to get into the multiple windows per application way of thought. In Windows, everything is a window with no grouping by application. Mac groups windows by applications and makes it super easy to switch between.
The only problem I've had is re-learning key mappings for Eclipse and Squeak. They are generally the same, but it's the apple key versus alt key on Windows. The keyboard is a laid out a little differently too, but I'm not complaining. It's just taking a little to get used to.
I'm loving Self. It makes the whole reason for getting the Mac worthwhile. I've been going through the tutorials and I've only scratched the surface. But, language-wise I'm so impressed with Self. They take their simplicity seriously!
On more thing, I can now read postscript files directly! Yippee! They get converted automatically to PDF and that is wonderful. I can see I'm going to go super crazy with academic papers. Mac will be my pipe for my crack.
My Mac didn't come with an AirPort card and the battery lasts 1 minutes. I'm missing my wireless and I got to have battery power. All in all, I'm having fun with it. Right now, I'll be staying in both Windows and Mac. But, there's a lot of cool things on the Mac that I still need to explore like XCode. I'll keep you posted!
Theme Song For The Year
One Way
Most computer designers, for some reason, delight in providing many ways of doing something. If there are fifteen ways to do something, they think it gives you freedom. The fact is that most users don't use the majority of the commands on their word processors. There are a few that everyone uses. And even though they've read the manual and know it might be a little more efficient to use a special technique, they don't bother. They use the same ones every time.
I've seen this time and time again. I know I've even fallen for the "flexibility" fallacy where I should have been simple. The above can apply to not only user interfaces, but APIs and languages. It made me immediately think of Ruby.
Ruby falls prey to the "flexibility" vulture and it's even touted as one of its greatest strengths by some (Reason #7). You have two ways to define blocks ({}, do), various ways of constructing arrays (new Array, %w), and other things to make various programmers from other languages feel comfortable. I think Ruby itself needs to become more opinionated.
There's a lot of great things about Ruby that I'm proud that are finally getting into mainstream minds like dynamic typing, closures, and meta-programming. It's cool seeing all of the excitement. But, I think if Ruby wants to go further, it needs to trim some of the fat. Now, this fat might have made programmers from other languages more comfortable, but we need to lose it. I would like to see Ruby more lightweight, easier to parse (it's a nightmare), and of course more opinionated. But, I worry that with all of the activity that bad habits will continue. I'm worried about the future of Ruby because all of the forking and lack of a clear direction.
With all of the battles that Ruby has won, I would hate to see it fail because of sins to gain more acceptance. It's won that, now, let's make Ruby the best it can be.
Wednesday, January 03, 2007
More On Nulls
Empty Collections instead of null.
The easiest way to prevent null pointer exceptions when using collections is to use empty ones. The Java collections library in fact includes empty versions of all the collection interfaces. Use them. It takes a little more typing, but it prevents one more check. And usually, most collection code can be written to be size agnostic.
Use meaningful defaults.
This one is really simple. Instead of being lazy, think about good defaults for your objects or at least ones that will be easy to spot when debugging. One of the problems that I have with nulls is that when I have to debug code, they tell me nothing about the intention. A default can give some sort of clue. If defaults can not be used, then...
Throw an exception.
But, if you must insist on using nulls, then please don't use them for incorrect usages of your API. In other words, if I pass you bad parameter, don't return null because your API can't handle it. Signal an exception and tell me what the problem is. Sadly, the Java collection API falls into this trap. The implementation of Map returns a null if it doesn't find the key and null is ambiguous in this case because it can be the key was not found or that null was stored as the value. I think an exception for the first case would prevent that. It would also make it easier to spot an incorrect usage of the API with a good message to tell me what to correct. Good designs are easy to debug and require little to no detective work. Be nice to your users.
Use small objects.
Wrap primitives into something more meaningful. You can then use the interface for both the implementation of real values and another one for true Undefined scenarios. Small objects are easy to debug because they can give much more meaningful information and you don't have to deal with all knowing objects that are 300+ lines of code. Small objects make dealing with nulls easier because...
Null object Pattern.
This pattern described in "Pattern Languages 3" by Bobby Wolfe. Go read it now if you haven't. Basically, implement a different implementation of your interface that either deals with the undefined case more gracefully. Now, by that, I mean, either throw an exception detailing why the request could not be completed, ignore the request, or forward it on to someone else. There could even be more options, but the first two are the most commonly used which of course, brings me to...
Deaf object pattern.
This is the Null object pattern where the implementation of the interface ignores all exceptions. This is used throughout Dolphin Smalltalk to great effect. This is a dangerous pattern, but when used right can make life easier. Dolphin uses it as a placeholder for objects that are not fully instantiated yet and requests would not make sense. It does this external resources where the object is instantiated, but they have not yet allocated the proper resources yet to make it fully functional. It helps them avoid timing issues. Again, I would caution the overzealous use of this pattern because it can mask bugs which brings me to...
Undefined object pattern.
Yet another popular variant of the Null object pattern, this version throws an exception with a meaningful message (be creative, but put something better than "undefined object<>
In closing, the one point I want to make is relying less on null requires thought in your design. Too many times, I see use of nulls as absence of caring for the users of your code. Nulls are just lazy and you can replace most of the them in your code using the above arsenal. Plus, the techniques above can make your code more readable, easier to debug, and more fun to extend.
Amen
I’ve also been reading a lot of the relevant academic literature published since the 1970s; for instance, the Lambda Papers and the myriad works of Henry Baker have been particularly inspiring. I continue to be struck by the harsh reality of the often-asserted, but seldom-accepted, truth that most of the great work in software was indeed done very early on, with virtually no further fundamental progress having been made during the past couple of decades.
I'm in the same boat. I'm just so much in awe of early computer science. I've been reading David Parnas's old papers and they are inspiring. It's amazing how much of the old papers we are reinventing. It's fun and mind blowing reading, but depressing that we haven't push the envelopes further. I think it's time to stop being sad and just do it.
Here's my call to arms. Let's take it further and stop whining! Who's with me?! CHARGE! The next generation of computer science starts NOW!
Superfluous Parentheses
of course, I can’t help but admire what the Smalltalkers have built with Squeak. (I suppose once you’ve reached the Source, being a polyglot becomes second nature.)
and...
The Lisp machines seem to have been the apex of Lisp, a brilliant achievement still unequalled (except by the Smalltalkers, as always). These wonderous machines have been followed by two decades of standstill, or even retrograde, progress.
It's funny, but I chose Scheme as well for slightly different reasons. I like the simplicity and elegance of Scheme which barely edges out Common Lisp. And the debugger is really great. It's also weird when he mentioned Forth and Factor. I just downloaded the Factor implementation recently. Weird. Forth is something that I like the elegance and enjoyed Brodie's book immensely. But, haven't played around enough with stack-based languages yet to know whether I like them or not. So much cool stuff!
Anyway, it's a great read. One of these days, I need to do one of these for why I choose Smalltalk. I think the above article was frank about Lisp and we need to be the same about Smalltalk.
I noticed he had a few books that he was planning on reading and are still on my reading list. I wonder if a virtual book club might be in order?
Monday, January 01, 2007
More Having Headaches Over Null
Sunday, December 31, 2006
Dipping My Foot In The Mac Waters
Friday, December 15, 2006
L'Atomium
You are missed, Dawn
Power lines,
Steel webs confine,
Violating the brownish sky.
Hard grey smothers,
Earth, like cancer.
Cracks revealing,
Ground below.
Broken and bleeding,
every seed, every stone.
One of my favorite albums of all time, Fear of God's "Within The Veil" began with the above quote and you knew it wasn't going to be a cheery album. It's been ten years since Dawn passed and this has to be the darkest week in metal. We lost three great musicians all of which released albums that I cherish and love. So, today I raise my glass and listen to my metal brothers and sisters that are no longer with us. You all are missed dearly.
Are We Worrying About The Wrong Things?
I agree whole-heartily with him. After awhile, I get tired of the same old language wars (pick your tools, know them well, and kick booty). We all need to know our tools better.
The core of the article is the message: Get better at your craft and mentor others on what you learn. It's up to us to make our community better. The time of being smug is over. We're in the same boat, let's help each other out.
I love Smalltalk, but I'm not afraid to use other tools. And I really don't mind Java that much (most of my rants come looking at poorly written Java). Good design is good design no matter what language. Yet, I see under-abundance of talk on design. I'm still shocked at meeting people who have never read Rebecca Wirfs-Brock's excellent "Object Oriented Design" or "Structure and Interpretation of Computer Programming". Both excellent books on design that transcend language. If you don't have them, buy them now and get "Code Complete" as well.
Anyway, the article is awesome and is a good wake-up call to us to look at the bigger picture.
Wednesday, December 13, 2006
Thought And Readable Code
No tool solves every problem. Put down the damned hammer and pick up a screw-driver once in a while.I agree with the above sentiment. I love a lot of different languages for various reasons. I often say that everyday I get closer to becoming a functional programmer because that style keeps rearing its head in my code. But, like anything it needs to be tempered.
It's all about balance and simplicity. I think the functional guidelines of trying to make most objects stateless and composition to the smallest and simplest are wonderful. The code you write reads well and if you try to restrict the places where you change, then it's easier to find bugs when problems arise.
The point is don't go overboard with your ideology. The end goal should always be readable code. Readable code changes information in few places. Readable code is easier to maintain. Readable code performs well. Readable code cares about the programmer that has to pick up the pieces once you're on to something else. Readable code is small. And finally, readable code is simple.
But, readable code takes thought. Design takes thought. Most of the zealotry that I witness is from people who want to remove thought. They think great code comes from restriction. It does not. It comes from freedom to have choice. Sure, you can make a bad choice, but sometimes the bad choice might be the good choice in certain situations. But, the choice requires thought. Any hard and fast rules should be looked upon with suspension. In the wise words of George Clinton:
Think! It Ain't Illegal Yet!
Oh, and if someone still wants to make religion and dogma out of anything technical (like the functional and XP evangelists), tell them to:
Go Wiggle
I'm going to think about making better code and designs.
Shallow are words from those who starve...
...For a dream not their own to slash and scar.
Chuck you are missed, bud. Thank you for enlightening us with such great music before your untimely death. Let the metal flow!
Friday, December 08, 2006
Thinking And Sharing Ain't It Cool?!
Then, it occurred to me. I should just make my collection of objects it's own domain specific object that I can then send the proper messages to. Thus, instead of a Collection object, you have an AccountCollection object that wraps around an ordinary collection. And this is where I can stick the "active" method. It's not static and reads so much better.
But, what about being able to combine predicates, transformers, and closures? I didn't discuss that in the original post. My post was inspired by a problem at work where I needed to combine different predicates on in-memory objects. So, it would be nice to have a "where" method that selects a subset of my new AccountCollection. I could even make the "where" functionality available in an abstract collection so that future domain specific collections could enjoy its benefits. But, to combine predicates, it's still ugly with all of the static utility method calls. Yuck. OK, what if I write my own abstract predicates, closures, and transformers that can chain themselves? For instance, you could have "and" and "or" methods to predicate; "then" for closures; and "as" method for transformers. Underneath the covers, could simply call all of the static utility methods. I get readability back (getUser().getAccounts().active() and getUser().getAccounts().where(Account.BY.olderThan(DAYS_90).and(Account.BY.active())).
I like this approach better and it keeps the knowledge shared. You could put the most frequent queries in the the domain specific collection, but still leave it open for future extension of less used queries or transformations.
Yet, again, this approves the more you move functionality down and spread responsibilities around, the easier your code becomes to read. Thanks to Jeff for making me thinking of where my solution was ugly.
Case Statements...They're Still Used?! Say it Ain't So!
Of course, I'm surprised the minds at Sun let such mistakes go by. Both auto-boxing and enumerations allow null pointer exceptions that most coders will not catch because typically you don't expect them (because of the expansion of the real code). I think this is going to catch a lot of unsuspecting developers. Java has trained our eyes and minds to where potential null pointer exceptions could lie. Ouch. The rules have now changed.
Again, nulls rears its ugly head to smash down all of that compile type checking non-sense. It all compiles, but will it run? How much do you want to pay for safety that's not guaranteed? I'd rather not fight monsters with blankeys, but with a real sword (unit tests).
Getcha Pull
Thursday, December 07, 2006
Agile Religion
I thought Patton's definition of "software success" (taken from the blog post) was interesting:
'We knew we?d delivered successfully not when the ?EAR file as uploaded to the server,? but when we saw end users successfully working with the software on a daily basis.'
Depends on the scope of a project I suppose, but for me, I would add to that sentence "and in 5 years' time".
That draws in concerns such as flexibility of design, level and quality of documentation, ability to accomodate increasing volumes, anticipation of change, etc.
A lot of these things are anathema to the Agile dogmatist mindset (you ain't gonna need it!), and, dare I say it, the typical consultancy mindset (I've used my glorious methodology, now the maintenance guys can take over and I'll move on to the next gig - but first I'll blog about how great I feel about it.)
Given the investment in money, people and time for software of any real significance, just having something that is good enough today is, not, well, good enough.
The point that 'Agile' is now an overused cliche is well made. As is the use of 'Waterfall' to paint any project that doesn't call themselves 'Agile'. They're just labels that lazy people use to pigeonhole - kind of like music genres!
All I can add is, "AMEN BROTHER!" I totally agree.
Sunday, December 03, 2006
Apparently, I like bad music
Metal
Jakarta Commons: Collections
Collection activeAccounts=CollectionUtils.select(someAccounts, new Predicate() {
public boolean evaluate(Object object) {
return ((Account)each).isActive();
}
});Wouldn't this be nicer:Collection activeAccounts=CollectionUtils.select(someAccounts, Account.BY_ACTIVE);One, it's lot less typing and reads much better in your logic. I've put the Predicate on the Account class. I really liked doing it this way and made my code read much more cleanly. Also, by having the Predicates defined on the objects that they were operating on, it made it easier to find which Predicates had already been defined. Everyone wins right? Well, no, I started using the same technique for Closures and Transformers too. My objects started to get crowded because I look putting my public static declarations at the top. Now, what to do?
Well, I was speaking to Matt Secoske one morning, we naturally started to discuss my dilemma of growing predicates and he had a simple answer: Put them in inner classes. At first, I scoffed at the idea, but after thinking about it, I came up with the following code:
public class Account {
public static final Predicates BY=new Predicates();
//Class stuff...
//Put this at the bottom of the class
static class Predicates {
public Predicate active() {
return new Predicate() {
public boolean evaluate(Object each) {
return ((Account)each).status.isActive();
}
};
}
}
}I have no idea why I didn't like the idea at first. But now, my client code looks like this:Collection activeAccounts=CollectionUtils.select(someAccounts, Account.BY.active());The client reads the same, but now, I've gotten the implementation of the predicates out of the way. Everyone wins. I also put my transformers in their inner class named AS and one for closures called EACH. The important thing is that I keep meaningful information at the top and my client code reads well. Another thing to note is that now I can hide more information and expose less. You would be amazed at how much data is exposed in predicates. Yet, another nice side effect.
You will also notice that in the resulting code that I used a status instance variable to figure out if it was active so that I didn't have to duplicate the protocol of the status object through the Account object. My code has been getting simpler and it's been shocking me.
The point should always be to make the clients that use your objects life easier and more readable.
Wednesday, November 29, 2006
To Closure or Not
Both of the extreme cases seem comical. One takes the position of nothing but objects and the other nothing but blocks. It seems that pure object-oriented programming is at odds with functional programming. But, it's not. They need each other. I think Smalltalk and Ruby strike a good balance in this area. Blocks are used as lightweight objects (ala syntactically cheap) where a full object definition would be cumbersome. But, having nothing but blocks would also be problematic. For bigger things, we use full objects. It's the balance of having both that allows us to choose the one that allows us to more succinctly express our solution.
I don't know why people argue these things. There are problems that are better expressed in objects and others in closures (blocks). Why do I have to choose one over the other? I want both! There's also a lot that object-oriented programmers can learn from functional programmers and visa-versa. In fact, I'm always shocked how much functional programming is in pure object-oriented languages like Smalltalk and Ruby.
I'm going to go message something.
Tuesday, November 28, 2006
Notes From One of Alan Kay's Talks
"interactive LISP -- a metainvention, the Maxwell's Equations of programming. Today is the 40th aniversary of the first interactive implementation by a 16-year-old Peter Deutsch. It was the first time a programming language became an operating system."
WOW! Really, that's all I can say. Peter does correct the above quote. But, I'll leave that to you to discover. Makes me wish I would have asked more questions when I met Peter at Camp Smalltalk. Darn it!
Prefactoring Hate
Friday, November 24, 2006
After A Rough Day, This Made Me Laugh.
Thursday, November 23, 2006
About Time
Commands are not Text-based
Unlike traditional command-line interface commands, Windows PowerShell cmdlets are designed to deal with objects - structured information that is more than just a string of characters appearing on the screen. Command output always carries along extra information that you can use if you need it. We will discuss this topic in depth in this document.
If you have used text-processing tools to process command-line data in the past, you will find that they behave differently if you try to use them in Windows PowerShell. In most cases, you do not need text-processing tools to extract specific information. You can access portions of the data directly by using standard Windows PowerShell object manipulation commands.
This was taken from the documentation for Microsoft's PowerShell. All I can say is: FINALLY! Tools like grep have their place, but man, working with objects is so much nicer. I just started to look into this, but I'm liking it thus far. I've been waiting forever for a command line environment that dealt with objects instead of dumb old text.
Wednesday, November 22, 2006
Compile Time Reflection
Class someClass=MyObject.class
But, I wish it went further. If you're going to make me go through the pain of verifying everything at compile-time, then make my life easier for example:
try {
Method method=MyObject.class.getDeclaredMethod("doSomethingCool", AnotherObject.class, String.class);
} catch(NoSuchMethodException problem) {
//handle reflection exception that could have been caught at compile-time
} catch(SecurityException problem) {
//handle reflection exception that could have been caught at compile-time
}Right now, if I mis-typed "doSomethingCool" then it wouldn't get caught until run-time.Now, we don't want to make the baby Gosling cry, do we? How about this:
Method method=MyObject.class.doSomethingCool(AnotherObject,String);
For one, it's more succint and no need for any try/catch blocks because the compiler did all of the work. Another nice side effect is that you can check regular visibility constraints (if I call the above in MyObject and doSomethingCool is private, then all is good. Otherwise, don't allow it if outside of MyObject). Now, I don't have to set the setAccessible() method on Method and no security check. Now, of course, you can also use this for fields as well. In fact, it's simpler.
Now, I ask since they gave us ".class", why didn't they finish the job? Java reflection has always seemed half way there to me.
Just don't get me started on JavaBeans (where are the collections?).
Beauty. Remember that word.
In 1958, John McCarthy was thinking about a symbolic differentiation program in a programming language that was later to become Lisp. He was concerned about the “erasure problem”: no-longer-needed list structure needs to be recycled for future use. In subsequent languages, such problems were handled either by the structure of the program being restricted to trees (stack allocation of data and its trivially automatic deallocation through stack popping) or by explicit allocation and deallocation (malloc/free). His comment on erasure / explicit deallocation:
The recursive definition of differentiation made no provision
for erasure of abandoned list structure. No solution
was apparent at the time, but the idea of complicating
the elegant definition of differentiation with explicit
erasure was unattractive.-John McCarthy
It’s worth a pause to notice the style of research described. McCarthy and his colleagues were trying to design a programming language. Part of their methodology was to write the program they thought should be able to do the job and not the program that a compiler or execution system would require to make the program run well. In fact, the beauty of the program was foremost in their minds, not correctness down to the last detail. Beauty. Remember that word.
Eventually the first Lisp implementers decided to ignore the bug—the fault of not explicitly erasing abandoned list cells, causing the error of unreachable cells accumulating in memory, leading to a failure to locate a free cell when one is expected—until the failure occurred and to repair it then. This avoided the problem of entangling a common set of functionality (keeping available all the memory that should be) with a pure and clear program (symbolic differentiation). The failure the fault eventually caused was repaired, along with a lot of other similar errors in a process named at the time and still called garbage collection.
What are you waiting for read the whole thing. It's awesome and will make you think about how we can write better software. The garbage collection story put a smile on my face. "Beauty. Remember that word." I couldn't have said it better. We should always strive for beauty in our designs.
I Am Object
"I should calculate the total when given a new line item"
"...that is not my responsibility..."
I act like I am the object. It's so natural to me that I don't even think about it. Now, this is very common when designing with other Smalltalkers as well. Are we the only ones that do this? And if so why? Is it because we are behavior-ists (ala Wirfs-Brock) and not data-ists? I don't know, but I think it's funny and it's what makes being a Smalltalker a joy.
Fate Is Weird
Well, I am pleased to announce that I will be returning (once again) to the land of messages and freedom. I can't wait to start. I will be working with some scary smart folks and doing outrageously cool feats of programming acrobatics. And it can only be done in Smalltalk. How lovely.
The railroad was awesome in retrospect and I had a blast. It was short-lived and I wish I could have stayed longer because I was just getting some steam on my project. Oh well, this new opportunity was just too good to pass up. The railroad has some cool aspects that I never thought about and the shipping industry is an interesting domain.
ROCK! Pass the messages and hold the data. I'm back to writing elegant code unhampered by a stuffy old compiler!
Tuesday, November 21, 2006
Why Lisp Has The Parentheses
Null: The Runtime Error Generator
if (something != null) {
something.doWhatYouWereBornToDo()
}You know what I mean. It's inevitable in legacy java applications. Now, I generally only do null checks on my inputs and avoid null conditions at all cost. But, the other day it got me thinking:
Null gets around all static type checking at compile time.
It's not a real type. It can be ANYTHING. At compile time, it slips under the radar because it only exists at runtime. So, what is my typing system doing for me? I find NullPointerExceptions tend do great damage on lazy (bad, whatever you want to call it) code. And let's face it, we've all had those days where we weren't exactly on the ball. NullPointerExceptions are sitting there to wake us up.
I really don't mind static typing. But, let's not kid ourselves. Allowing nulls throws out the safety of the compiler catching our dumb mistakes because most of mine are of the null variety (the dumb ones that is).
Of course, we could just reference everything by their interface and do the Null Object pattern and be smart about messages to ignore and which ones to worry about. But, it's a lot of typing without much gain.
Now, you might be saying to me, "But, Blaine, you imbecile! Don't you have nulls in Smalltalk, Ruby, and Lisp?" Yes, we do and it's called nil. But, we don't pretend to catch all of our dumb mistakes up front. And our nil is an ordinary object which we can add messages to. Nil, our null, is a little bit more powerful. Does it still sting when we make a programming mistake? You bet it does.
Enough on that, just don't get me started on primitive arrays in java. They are even sneakier and there's a plethora of stuff that the compiler doesn't catch.
Till next rant, keep your objects small and your messages plenty. AMEN!
Sunday, November 05, 2006
Worst Web Site Ever?
Wednesday, November 01, 2006
Happy Belated Halloween
How cool is that? So, you might guess what I might have done. I was thinking carving either Alice Cooper or this:
And of course, my wife, Michelle had to quickly take a snapshot of me in all of my techy glory.
Now, I must ask the question, am I knight now or what? I even used Squeak to edit the pictures.
By the way, I used Melissa Winger's "Powered By Smalltalk" logo. Thanks! It was a blast to carve!
Tuesday, October 31, 2006
Ruby and Continuations
Monday, October 30, 2006
I didn't say it, honestly!
Smalltalk
All your concepts belong to us.
Lisp
(no ‘they all belong to (us))
MOHAHAHAHA! Ok, I'll stop the diabolical laughter now.
Saturday, October 28, 2006
Welcome To World, Duncan Manning
Rebol in Omaha
Here's the location specifics:
Creighton University
2500 California Plaza
Omaha, NE 68178
Parking
Additional Information:
Enter the west end of the Old Gym.
Go up the elevator to the fourth floor.
You're there.
Restrooms are on the 2nd floor, unfortunately.
Vending machines are on the 1st floor, around the wall to the right of the elevator.
Anyone asks, you are attending the Omaha Dynamic Users Group meeting on the fourth floor of the Old Gym or ODUG.
PropertyDescriptor in JavaBeans
OK, it's time for an example. Spring is all of the rage (and rightfully so) and injects by the exposed writer methods in an object. But, wouldn't be nice not to expose them, but give Spring priviledged access to these fields and basically disallow ordinary access. What if I could have a custom PropertyDescriptor for just those fields. Well....
Right now, I could have a private writer and have a custom PropertyDecsriptor to grant access to it. But, what if I didn't want to add unnecessary noise to my class? Besides, it seems like a lot of trouble. Let's dream for a bit shall we?
What if instead of having getReaderMethod() and getWriterMethod(), we had getPropertyAccessor()? What would this new method return? How about this:
public interface PropertyAccessor {
Object get(Object receiver);
void set(Object receiver, Object newValue);
}And this would be the default implementation:
public class MethodPropertyAccessor implements PropertyAccessor {
private Method reader;
private Method writer;
public MethodPropertyAccessor(Method reader, Method writer) {
this.reader=reader;
this.writer=writer;
}
public Object get(Object receiver) {
try {
return reader.invoke(object, null);
} catch(...PlethoraOfReflectionExceptions) {
throw new RuntimeException(reflectionException);
}
}
public void set(Object receiver, Object newValue) {
try {
writer.invoke(object, new Object[] {newValue});
} catch(...PlethoraOfReflectionExceptions...) {
throw new RuntimeException(reflectionException);
}
}
}More of the knowledge in how to get/set properties in the object are known to the PropertyAccessor. We could then provide our own PropertyAccessors like we could have one built by giving it the Field itself. Like this:
public class DirectAccessPropertyAccessor implements PropertyAccessor {
private Field property;
public DirectAccessPropertyAccessor(Field property) {
this.property=property;
this.property.setAccessible(true);
}
public Object get(Object receiver) {
try {
return property.get(receiver);
} catch(...PlethoraOfReflectionExceptions...) {
throw new RuntimeException(reflectionException);
}
}
public void set(Object receiver, Object newValue) {
try {
property.set(receiver, newValue);
} catch(...PlethoraOfReflectionExceptions...) {
throw new RuntimeException(reflectionException);
}
}
}Users of the PropertyAccessor would not have to know how the field is accessed (whether via methods or direct access or by going through other objects). By hard-wiring to always use methods, the JavaBeans framework has exposed too much of its internal implementation to the outside world. If they would have hidden more, it would have been more flexible. Of course, the examples need more fleshing out to handle things like primitives (but, you're not using those anymore are you since you have autoboxing, right?).
I wanted to show this as a simple example of why encapsulation is good. I've made the code more flexbile, simpler, and easier to test even. The PropertyAccessor is simply a facade around the business of accessing a field. Pretty simple stuff.
Just think if you had this with so many java frameworks that use JavaBeans. Wouldn't it be nice?
Monday, October 23, 2006
RubyConf 2006
The Gospel Of Closures
Saturday, October 14, 2006
Tour Updates
Next up, I'll be attending this year's Ruby Conference in Denver October 20-22. I can't wait. It's going to be so much fun! New people to meet and exchange ideas with.
Wednesday, October 11, 2006
Eclipse Mylar
Basically, it keeps the context of what you're working on. You create tasks and it pays attention to what you're editing. The cool thing is when you start switching tasks. It switches out the editors to exactly where you were and it creates a custom working set with only the files you were working on (you can also show everything and it greys out the least interesting items). I'm impressed and it works great with Eclipse 3.2. Finally, I have Squeak projects for Java and a whole lot more.
Now, I need to get Bugzilla installed...
Strings suck
Saturday, October 07, 2006
What Makes Ruby Roll
Kevlin Henney said...
Someone will have rewritten it by then. Yes, will succeed where Smalltalk failed because it's not bound up in the smalltalk environment (you can open up Ruby files in Notepad). Also, do not underestimate how important a 'normal' if statement is. The biggest problem with Smalltalk is Smalltalkers.
The first part of the quote is right. Smalltalk is too much change for most developers to accept. You have a new syntax to learn, a new environment to learn, and a completely different way of thinking. It's too much for a lot of developers. It's human nature. An image-less Smalltalk would have a nicer entry point since developers love their editors (you spend a lot of time there and well, when you learn one well, you don't want to leave it). The last part of the quote really hurt. I see myself as a lot of things. I see myself as rubyist, a smalltalker, a java programmer, and a bunch more. But, I can see where the arrogance of certain Smalltalkers can detract from the true message. It makes me sad. Smalltalk is a cool language to program in and I love talking about it. But, I know it has warts like anything else. I hope no one ever sees me as an arrogant Smalltalker. I want them to see me as passionate and thoughtful.
Dave Thomas said...
As long as the people who have big checks are running on the CLR and JVM Ruby will have to crossover to those platforms to succeed. Business and economics were the downfall of Smalltalk, not natural selection. The "arrogance of the smalltalk communities sealed the lid".
Another quote right on the money, but stings me in the heart. It's true. Marketing killed Smalltalk and the arrogance that their product was better. The sad fact was yes, Smalltalk was better than C++ and Java, but having a better product doesn't win. Java had a lower cost of entry (familiar syntax, could use any text editor, and a familiar work flow) and it was good enough. Maybe if Smalltalk had been marketed correctly, maybe the story would be different. And one more thing, yeah, the arrogance of some Smalltalkers didn't help our cause.
It's always interesting to see how the rest of the developer commounities see us. I feel like we get lumped in with the grumpy Lispers. We both have great languages with communities that can be intimidating. I hope that never happens with Ruby because right now their community is inviting.
Wednesday, October 04, 2006
Seaside Presentation
Sunday, October 01, 2006
Six Weird Things/Habits/Facts About Me
- I own lots of music (enough to fill an 80 gig MP3 if they made one), but I do not own a stereo. I prefer to listen to music on headphones.
- Territorial. I do not like anyone to be in my space when I'm not around. And I do not like it when neighbors park in front of my house.
- I loathe cigarette smoke even though I'm an ex-smoker.
- I love high fiber cereal. The higher the better.
- I carry Equal and a pen wherever I go. I'm freakishly prepared for anything.
- Encyclopedic knowledge of heavy metal that stems from being a rabid fan (I love a lot of other genres, but metal is my favorite). I can name not only the song, but the artist, album, side (remember records?), year, producer, and my first impression when I first heard it.
Seaside and Smalltalk in Omaha
Here's the location specifics:
Creighton University
2500 California Plaza
Omaha, NE 68178
Parking
Additional Information:
Enter the west end of the Old Gym.
Go up the elevator to the fourth floor.
You're there.
Restrooms are on the 2nd floor, unfortunately.
Vending machines are on the 1st floor, around the wall to the right of the elevator.
Anyone asks, you are attending the Omaha Dynamic Users Group meeting on the fourth floor of the Old Gym or ODUG.
Thursday, September 28, 2006
XP Youth
Truth is, pair programming is one of the only effective ways that a lot of us have ever witnessed keeping average developers from pissing away 95% of their productivity engaging in non-work such as reading and writing blogs, instant messaging, personal email, shopping online and otherwise wasting time on bullshit.
So, we need the XP youth to keep us inline? If I'm not doing my job, I should be fired. Period. End of story. We all can't be above average, but we all need mental breaks (I doubt most developers spend 95% of their time shopping online).
Pair programming has pluses and minuses. It takes a certain personality to be good at it. I've had very few good pairs in my career. Nothing can match the creativity of two minds locked in a common crusade. It's great. BUT, I have found it takes a person that can take constructive critism of their ideas, is vocal, loves programming, and the most important: listens. Your average developer if he's browsing the net for 95% of his time probably doens't "love" what he/she is doing. I found while pairing can give the illusion of productivity, it's easy for one part of pair to be asleep at the wheel to speak. If you don't love what you do, you will find ways to avoid doing it no matter what hurdles managers throw at you.
I love pairing with passionate yet humble programmers (the greatest minds I have met have been this way). But, I hate pairing with ego maniacs. I love short bursts where we colloborate intensely and then go program solo for a short while. Get back together and show each other what we did. Rinse, repeat. I find it keeps the creativity spark alive (because you can experiment without the sucritiny of another to verify if the idea is good) and the interaction rich. It allows the feeling of working together, as well as ownership of a piece of it.
Pairing should be something that is not mandatory. It should be up to the programmers. Anything forced is going to cause people to find ways around your dogmatic rules. It's human nature. XP should be agreed upon, not enforced.
Confession Time
"A wise man changes his mind, a fool never" - Spanish Proverb
Well, at least it makes me feel better right? Well, I have a confession to make. In the past, I have argued for the use of accessors on instance variables. I liked accessors because they looked the same in the code as a method call and the flexibility. But, several months ago, I tried writing code without accessors. I was shocked by what I found about myself. First, it was hard after programming with accessors for so long and it didn't feel natural. But, I got over that in the first month or so. Second, I noticed that I broke encapsulation of my objects less. In fact, if I felt the need to access an instance variable outside of my class, I questioned myself thoroughly and generally tried to find another way.
I thought I was writing good code, but I was making little sins that added up. Forcing myself to use accessors only when necessary caused my objects to be more self-contained. I started writing smaller objects. My code got way better. So good in fact, that I find myself on the other side of the accessors debate.
Yes, I now frown upon the use of accessors by default. It leads to data structures (not objects) and controllers (not objects). The funny thing is the road to breaking encapsulation is one paved with small sins along the way. Besides, with today's tools, it's easy to switch the accessors if needed.
Oh well, I had to get that off my chest.
Wednesday, September 27, 2006
Too Many Toys?
There's one thing that hasn't changed. Good design and thought. Frameworks are only amplifiers in this regard much like languages. They can make our life easier if we apply them to good sound design principles. But, I think that's what is missing in our field. Go to any Border's and Barnes and Noble bookstore. Hell, go to any coder's shop and what you will find are rows and rows of books on the latest "cool" frameworks and languages. It's all vocational. You might find a little section on design if that. And it's not like we don't have great books on design. Hell, I can list several and still have more to recommend! These are the books that will stay on my shelf long after the latest framework fad or language has gone to the legacy island of old technology. It amazes me how many developers are up on the latest technology, but have never read a book on design (or maybe just one).
It shocks me. Knowledge is our most treasured asset. I strive to understand the core concepts and to go beyond. I'm always trying to learn from anything I can find (even non-software books) if it can give me a glimmer of understanding more about our field. Sometimes, I think though, we get so caught up in the flavor of the month, that we neglect the knowledge that will survive after the fads are dead.
Do we have too many toys? We're spending all of our time playing with them and not learning the core concepts that's behind them. I think that's sad. I love solving hard problems, but I want to spend my learning the problem domain. I want to learn the business of my users so I can solve their problems in elegant ways. The world of business is one of the most fun beasts to tame. I don't get excited anymore about applying the latest technology to a problem, but by solving it period. The tools needed are in your head. The frameworks only amplify what is at the core. When push comes to shove, it's still takes thought to do a good design.
So, here's my solution: read one non-vocational technical book per year. Understand it. Become it. Or at least be able to argue why you hate it. I read more books about design that any other every year. It's time well spent and it only makes you a stronger developer. Rock on, brothers!
Wednesday, September 13, 2006
Design Patterns of 1972
Now, let's roll up our sleeves and take our industry further!
Sunday, September 10, 2006
I miss Zappa
PINE: I guess your long hair makes you a girl.
ZAPPA: I guess your wooden leg makes you a table.
Made me laugh. Time to fire up "Grand Wazoo".
Thursday, September 07, 2006
Working On The Railroad
Time And Money Library
Monday, September 04, 2006
Updated: Comment Unit Tests For Ruby
Here's a simple example:
### >>> 3 + 4
### >>= 7
You can even use variables:
### >>> a='i'
### >>> b=' love '
### >>> c='michelle'
### >>> a + b + c
### >>= 'i love michelle'
And if they are part of the same comment, it will keep the variable bindings active, so you can do this:
### >>> a + ', robot will never die'
### >>= 'i, robot will never die'
And finally, if comparing two objects bores you, then you can create your own equality check like this (notice the >>>?):
### >>> a = 5
### >>> b = 4 + 1
### >>? a == b
Enjoy and Ruby on!
Saturday, September 02, 2006
Functional Programming Considered Harmful? Nonsense!
The moral of the story: don't bother improving yourself, unless you have the freedom to improve your environment accordingly. That's rather depressing. Can anyone put a better spin on this and cheer me up?
After reading this article, I was reminded of an argument to remove objects and blocks from Smalltalk. Basically, the argument of closures versus objects is futile. They both have their place and strengths in design. But, without closures, you can use simple objects as a substitute.
Luke's article argues how hard it is to instill functional programminging in languages like C# and Java. I think while it is hard to use pure functional style in these languages, it's matter of changing the way you think about it. I find since I don't have blocks/closures in Java, I use more of a stream approach (think pipe/filter pattern). It's a little trickier in the iterator objects, but the users of the code have to write less and their code is easier. I used this technique to good effect in my Reflective Testing Framework. As for side-effect free programming, I think it's a good goal to try to attain. We have a thing called encapsulation which can localize the effects of change. It's all in the way we think about it.
So, the next time, you see a road block because Java or C# doesn't have some feature from one of your favorite dynamic or functional languages. Think about the goal of the feature and ways you can attain it. Sure, code is more succint in Ruby, Python, Haskell, Scheme, and a host of other languages, but for those of us in the trenches, we might not be able to use them. We're stuck with Java/C#/C++. Be creative and remember to always keep your code easy to understand.
Wednesday, August 30, 2006
Ruby Quiz #6: Too Simple?
require 'test/unit'
require 'test/unit/ui/console/testrunner'
module Enumerable
def in?(candidate)
any? {|any| any.in? candidate}
end
end
class Fixnum
def in?(candidate)
equal? candidate
end
end
class Range
def in?(candidate)
include? candidate
end
end
class BuildRegexp
GUARD = /^[0123456789]+$/
def initialize(candidates)
@candidates = candidates
end
def =~(candidate)
GUARD =~ candidate && (@candidates.in? candidate.to_i)
end
end
class Regexp
def self.build(*candidates)
BuildRegexp.new(candidates)
end
end
class BuildTest < Test::Unit::TestCase
def test_lucky()
lucky = Regexp.build(3,7)
assert('7' =~ lucky)
assert(!('13' =~ lucky))
assert('3' =~ lucky)
end
def test_month()
month = Regexp.build(1..12)
assert(!('0' =~ month))
assert('1' =~ month)
assert('12' =~ month)
end
def test_day()
day = Regexp.build(1..31)
assert('6' =~ day)
assert('16' =~ day)
assert(!('Tues' =~ day))
end
def test_year()
year = Regexp.build(98,99,2000..2005)
assert(!('04' =~ year))
assert('2004' =~ year)
assert('98' =~ year)
end
def test_num()
num = Regexp.build(0..1_000_000)
assert(!('-1' =~ num))
end
end
Test::Unit::UI::Console::TestRunner.new(BuildTest.suite()).start()
Of course, we excitedly looked up the answer in the book and were shocked. Their final answer was longer and harder to understand. Our code uses less of the regular expression class. In fact, we only used it as a guard to make sure we could convert the input to a number. We also made heavy use of polymorphism and duck typing(in?, =~). As you can see the code is very short.
The quiz was to build a Regexp to handle any list or range of numbers. The tests are taken exactly from the book and of course, we wrote them first. Well, actually, we wrote them at each stage. At one point, we were using Regexp extensively until we hit the last test. And that is when the change in requirements caused all of the code you see above.
How fun! We looked at each other and wondered, "Was our solution too simple?" We then laughed and said, "Nah." We were both proud for our simple and readable solution.
Tuesday, August 29, 2006
What Do You Value?
| Objective To Maximize | Minimize Memory | Most Readable Output | Most Readable Code | Least Code | Minimize Programming Time |
| Minimum Memory | 1 | 4 | 4 | 2 | 5 |
| Output Readability | 5 | 1 | 1 | 5 | 3 |
| Program Readability | 3 | 2 | 2 | 3 | 4 |
| Least Code | 2 | 5 | 3 | 1 | 3 |
| Minimum Programming Time | 4 | 3 | 5 | 4 | 1 |
Basically, it shows we achieve what we value. But, it also shows that the worst performer on the other metrics was "Minimize Programming Time" and the best overall is "Most Readable Code". I think we should always strive for readable code, but this study shows that the side effects are nice too.
I think sometimes XP shops can get too caught up in miniminizing programming time and thus, lose sight of the quality we should value most. We just need to be mindful and keep our code readable!
Behaving Poorly At Work
Monday, August 28, 2006
Matt's Ruby Log Splitter
class SplitFile
def self.open(suffix, mode, &when_to_split)
self.new(suffix, mode, when_to_split)
end
def write_all(enumerable)
enumerable.each {|line| write(line) }
end
def write(line)
open_next() if should_split?(line) || @file.nil?
@file.write(line)
end
def close()
@file.close() unless @file.nil?
@file = nil
end
private
def initialize(suffix, mode, when_to_split)
@suffix = suffix
@mode = mode
@when_to_split = when_to_split
@file_count = -1
end
def open_next()
close()
file_name = next_file_name()
puts "Writing file #{file_name}"
@file = File.open(file_name, @mode)
end
def next_file_name()
@file_count += 1
"#{@file_count}_#{@suffix}"
end
def should_split?(line)
@when_to_split.call(line)
end
end
FILE_SUFFIX = ARGV[0] ? ARGV[0] : "split.log"
MAX_LINES = ARGV[1] ? ARGV[1].to_i : 500000
lines = 0
split=SplitFile.open(FILE_SUFFIX, 'w') do |line|
lines += 1
result = lines >= MAX_LINES
lines = 0 if result
result
end
begin
split.write_all($stdin)
ensure
split.close
end
Sunday, August 27, 2006
Python and XML in Omaha
We do have a new location this month. Here's the details:
Creighton University
2500 California Plaza
Omaha, NE 68178
Parking
Additional Information:
Enter the west end of the Old Gym.
Go up the elevator to the fourth floor.
You're there.
Restrooms are on the 2nd floor, unfortunately.
Vending machines are on the 1st floor, around the wall to the right of the elevator.
Anyone asks, you are attending the Omaha Dynamic Users Group meeting on the fourth floor of the Old Gym or ODUG.
Think Good Thoughts
Think Good Thoughts.
Words become actions,
Actions become habits,
Habits become character,
Character becomes destiny.
I love it!
Wednesday, August 23, 2006
Oh No! Let's Not Hurt Our Brains!
To not do something because you are afraid of the average programmer is ludicrious. They never will become more than average if we don't push them. I'm sure object-oriented programming was scary at first for a lot of developers, but they learned. To not do a feature because it might confuse the "not-so-bright" developers is assuming too much. I'm reminded of a quote by Paul Graham:
"If you think you're designing something for idiots, odds are you're not designing something good, even for idiots."
If you don't know the power of closures, please go read "Structure and Interpretation of Computer Programs" right now! Don't worry...It's not only for smart people.
Saturday, August 19, 2006
Pepsi through the nose hurts...
Goodbye, Smalltalk
I'm looking to the future with excitement. RubyConf is going to be interesting to see how their community works. My experiences with the Ruby community have been positive, but it's been by all email. It will be cool to meet a lot of people in person. Of course, it will be cool to give a demo of Squeak or Dolphin to anyone that wants one.
The sad new is that I will probably not attend any of the Smalltalk conferences any time in the near future. Everyone will be missed! But, I will be out there trying to show Smalltalk to anyone curious (at RubyConf and beyond).
I will always love Smalltalk...
Generics not so bad
I've also noticed that Hibernate forces you in the same ways. Everytime I do something complicated in Hibernate, I have found it's a pain. And everytime there was an easier and more elegant approach that would not only appease Hibernate, but make my design better.
Funk Card Ready, Mothership Taking Off
Sunday, August 13, 2006
Amen Brother!
Diet Pepsi Jazz: Strawberries & Cream
Saturday, August 12, 2006
Gross Code
Jerry Goldsmith
Critical Communities
Well, I'd like to be brutally honest right now. Cursing and calling people "stupid" does not make a community. It discourages existing members and pushes potential new members away. I think being introspective and honest in your community is a must. I see this in spades in both the Ruby and Java communities. If you look long enough at the Ruby blogs, you will notice that we are all aware of the problems. Same goes for the Java community as well. But, what makes me love the Ruby community is the "roll up your sleeves and help" mentality. If you don't like something, work to make it better. I find this extremely positive. Now, I know this is in the Java community as well, but it's more pronounced in the Ruby community.
I find that the Bile Blog gives the Java community a black eye and it's one of the reasons why people are flocking to the Ruby community. It's more positive and not yet mired in endless negativity. I would be shocked if there was ever a Bile Blog for Ruby.
I like being apart of both communities. They both have things I love. But, I love the overwhelming positivity of Ruby. I think a lot of that comes from Matz.
Sunday, August 06, 2006
Interesting Quote
"I always knew one day Smalltalk would replace Java. I just didn’t know it would be called Ruby."
-- Kent Beck
I got it from ozmmdotorg blog.
Shallow Knowledge
IF a person has a pink monkey
THEN take a refrigerator
It comes from the excellent book, "Expert Systems: Principles and Programming" by Giarratano and Riley. They use it as an example to make their point about shallow knowledge structure. It made me laugh because it's so silly, yet made their point perfectly clear. I love the book and it's one where you can pick it up and start reading at any point. A great book to read if you're interested in expert rule systems. Plus, they have funny examples that make you think.
Sepultura and Talladega Nights
Saturday, August 05, 2006
My Wife: The quick pick me upper
So, what does she do? She gave me an empty journal with a mocked up cover of the book I want to write eventually. She knows my ambitions and the cover was gorgeous. It had a lot of funny quotes from various people about my book (of course, they were fake). But, it's exactly what I needed to lift my spirits.
She always knows exactly what to say to me to cheer me up. This gift touched me beyond words. It is the journal I will keep for my ideas on "Balance". She is the person that picks me up when I fall and tells me to push forward. This week has been a failure week and my new journal will be where I write my new successes.
I love my wife. She is the best. I wish everyone had a Michelle in their lives.
I'm reminded of two quotes that keep me going:
"Winners are losers who got up and gave it one more try."-Dennis DeYoung
"Good thoughts bear good fruit. Bullshit thoughts rot your meat."-George Clinton
More About Examples
Blaine,
I don't read your blog as often as I'd like, but whenever I do it gets me thinking.
I cut my teeth on the first edition of "Java in a Nutshell" and agree many of the code examples are horrible. For some unfathomable reason, most Java books make little or no attempt to teach OO concepts, choosing instead to focus on syntax and the API.
The problem with correcting code is that your corrections are open for correction :) In fixing the "baby sins" you've created, IMHO, a more egregious one. public methods with filname parameters is generally a Bad Idea as it allows a careless coder to corrupt any file of his choosing.
Well, but, I was trying to show a simple example. Wait a minute. I'm in the very quicksand that I complained about. Ouch. You are so right. I would generally have file access behind some kind of broker and then had the operations split out. Darn it! Maybe I should keep my mouth shut because it's hard to come up with succint yet correct examples.
You've also created some minor baby sins (embryo sins?) yourself. I believe redundancy does not necessarily lead to clarity. The repetitive "InCents" while well intended, gets downright annoying. I only need to be told once that we're dealing in cents. When you switch to another unit measure, let me know, otherwise it should be safe to assume nothing has changed. Make cents, er, sense? By renaming the method to addCentsToPurse, it pretty clear that cents is the order of the day.
Well, I usually have an object to represent money. Wait a minute. I'm down my rat hole again. DARN IT! You are exactly right. The "InCents" does get annoying. I usually put them in when I'm dealing with legacy code that deals in primitive. I don't like dealing with primitive types at all. Again, it's hard to come up with good examples. I should have done the right thing. I wrote the counter example in haste and committed sins in my rush.
Your constant and variable names are a little too "techie." I've lately come to understand that if code can be read by a non-coder, coders will be able to read it all the faster. seek(TOTAL_AMOUNT) is less technically accurate than seek(RECORD_POSITION) but it more clearly indicates what we expect to find at that location.
Another great suggestion and one that I fight with constantly. I do try to come up with good variable names, but I do fall into the techie trap a lot. Thank you for giving me more ammo to fight this battle in my head.
So, here's my version (hoping the format looks ok):
private static final String PURSE = "blah";
private static final String READ_AND_WRITE = "rw";
private static final int TOTAL_AMOUNT = 100;
public void addCentsToPurse(int cents) throws IOException {
RandomAccessFile purse = new RandomAccessFile(PURSE, READ_AND_WRITE);
try {
purse.seek(TOTAL_AMOUNT);
int centsInPurse = purse.readInt();
int total = centsInPurse + cents;
purse.seek(TOTAL_AMOUNT);
purse.writeInt(total);
} finally {
purse.close();
}
}
As a final note, I'm always tempted to combine multiple lines, as in:
purse.writeInt(centsInPurse + cents);
While this is a trivial example, it does help with debugging to use a new variable and multiple lines.
Jeff
WOW. Excellent code. I love these kinds of comments. It should a lot of faults in my code and I learned a lot. Great stuff. And we got a better example out of it to boot. Thanks, Jeff...You ROCK! I will work harder to make my code the best it can be and encourage everyone else to do the same thing.
My Boys!
Friday, August 04, 2006
Running
Wednesday, August 02, 2006
Lisp In Omaha
The next meeting looks to be equally great: Python and XML by Mike Hostetler. See you all there!