Welcome visitors--as of today (Apr 29, 2008) it's been many years since I participated in Ward's Wiki. I offer the below as a purely historical curiosity. It's not necessarily representative of my views today--in fact, some of it's pretty embarrassing to me now.
I have a new website and blog: http://www.jamesshore.com
Formerly known as JimLittle
. These days, I'm doing business as Titanium I.T. LLC ("Making IT Profitable"), helping companies improve the profitability of their software development efforts. Although I started out as a programmer, focused entirely on technical issues, now I'm more interested in how software fits into the big picture--the difference between writing code and creating software that improves lives. In the context of business, "profitability" is a nice, pithy way to say this.
I haven't lost interest in technical issues... in fact, I think the foundation of software development is programming. Writing code. Design, requirements, testing; these are all inputs to the final end result of making software that has an impact. Writing code poorly leads to poor results. Writing it well leads to good results... but writing it "well" means more than making it work. I believe programmers, business experts, and the rest of the development team all need to work together, intimately, in order to make truly great software.
Here are some pages I've written along these lines.
I'm particularly proud of GoodDesign
--I've seen many attempts to define "good design" in the past, and they all get caught up in subjective discussions of "truth and beauty." I like to think my approach brings a new spin to the discussion.
The above was written March 2004. The following is pretty old, but not so old that I want to rewrite it today.
If you're just looking for interesting pages that I've written, I consider each of these six pages my best of its category. I started these pages, and often didn't sign my work, but not everything unsigned is from me.
For more of my writing, take a look at the "New Stuff" section (next) and the "About Me" section that follows.
If you'd rather learn about me by seeing what I like, scroll about halfway down the page, where you'll find favorite links and quotes by other authors.
If you'd like to leave me a message, scroll down to the very bottom of the page. I don't check it regularly, but I like getting it. Or send me an email if you want me to read it now. You'll see a link to my email at the very top of this page.
I've also added a picture of myself. Vanity is an important cause, so I'm glad to be able to contribute. That's at the very very very bottom. Consider yourself warned.
Short warning about my sense of humor: When they were handing out the funny, I applied for "clever and witty" but all they had left was "goofy." I do the best I can with what I've been given.
If you're not at all interested in me, try RandomPages
. It tends to be better reading anyway.
If you're like me and think "short and sweet" is preferable to "long and drawn out," pretend this is the end of the page. Thanks.
At the risk of seeming egotistical, here's something I wrote on OoEmpiricalEvidence
. I really like it. (And besides, that's what this home page is about. Me me me me me. Scroll down... way down... if you want stuff by other people.)
- Every so often, I have a customer ask me to show that I'm improving productivity. In one case, it was because the company wanted productivity to improve over time; in another, it was because they were considering paying for another programmer to be added to the project.
- Whenever this happens, I'm put into a quandary. I don't know how to objectively measure productivity in the programming world. I can define it - "productivity = features / effort" - and I can measure effort - but I can't measure features. And that stumps me every time.
- I'm aware of the function point metric, but last time I looked at it, it wasn't entirely measuring features. It included stuff like "number of database tables" and "number of forms." A sufficiently clever team might spend more time per function point and come up with fewer forms and database tables, while still satisfying the base requirement. They would be penalized, because they would seem less productive. BehavioralEffectOfMetrics (blatant plug) says that you'll get what you measure. If you measure productivity using function points, then you'll get lots of forms and database tables, and that will lead to crappy software.
- This is a very basic problem. If we can't objectively measure productivity in software projects, then we have no way to say whether or not OO is better than procedural. We can't say whether or not anything is better than anything. We have nothing but anecdotal evidence and personal experience. If that's all we have, fine, I can use that with some success. But it's very hard to defend to a business person, and a hell of a way to run a profession.
- -- JimLittle
Here's something else I wrote recently that I think is way cool... except that it implies that refactoring is a stand-alone activity, rather than being an active part of development. Oh, well. It's still a fun analogy.
- Here�s an analogy that illustrates the difference between refactoring and rewriting.
- Imagine that you�re a young boy, sitting in your room, playing with a Rubik's cube. It�s all jumbled up, and you want to solve it before dinner. Your mom is going to call you to dinner in fifteen minutes.
- Okay, the analogy here is that the boy is the programming team, the Rubik's cube is the application, and dinnertime is the ship date. The cube is jumbled up, but it�s still in one piece: the application works, but it doesn�t have everything neatly lined up.
- So you want to solve the Rubik�s cube. What do you do?
- Well, when I was kid, I took a screwdriver to it. I levered out each of the little squares - sproing! - and then fit them all back together in the correct order. The problem was that sometimes the pieces went flying across the room. Sometimes I couldn't find them all before dinnertime, and my cube ended up with pieces missing.
- I had a friend who was a little more determined. You might even say plodding. He would turn the Rubik's cube back and forth, back and forth. He would think a lot before making each turn, so he wasn�t usually done before dinner either. But every turn he made got the cube a little bit closer to being solved. When he got called to dinner, the cube wasn�t always done, but it was always in one piece, and it was always better off than when he started.
- Rewriting software is like taking apart a Rubik's cube. It�s tempting and easy, but you run the risk of losing a piece. Refactoring is like solving the cube. It's kind of boring, and it requires you to think a lot, but turn by turn, the application gets better. You never lose a piece.
- Some people are whizzes with a Rubik's cube. They can solve it faster than I can take it apart and put it back together again, and they never lose a piece. If we practice refactoring a lot, we'll be able to do the same thing.
I've been thinking about my DefinitionOfProjectSuccess
recently. I have a very strict definition:
- The project DeliversValue? to the person or organization paying for it.
- The project doesn't degrade the QualityOfLife of the people involved in producing it.
A response to a post on the XP mailing list about the need for up-front design with some transactions and multithreading:
- Having done "hard" retrofits several times, I strongly disagree. I've retrofitted code with "hard" features three times now: security, transactions, and internationalization. Each time I was modifying good code that had zero prior design for the feature in question. In each case, the retrofit was easy.
- About four years ago, I retrofitted transaction security into a client-server application I had led. By "transaction security," I mean that every business operation was verified by the server when it occurred and backed up by a pretty user interface. The code was very good, but not stellar. It took a team of three programmers about four days to add that code. Most of it was fairly mindless modification: we added security status objects that we passed around and added security checking to every server-side entry point. (There were quite a few.)
- A year or so after that, I retrofitted business transactions into a web-based application I was leading. This project had been developed with XP and had outstanding code. It was a little more complex than it needed to be, but I was still new to XP. This retrofit, which was more significant than the security retrofit, took much less time because the code was better. It took one pair about a day, maybe two. We extended an existing database connection object, already used by most business objects, renamed it to "Transaction," and added commit and rollback features. Then we modified existing centralized database and exception-handling logic to use it.
- About half a year later, I retrofitted the same web-based application with internationalized input and output. At the time, that web application was one of the few on the net (that I'm aware of) that handled international input successfully. The code had been getting steadily better over time, thanks to XP practices, and at this point was absolutely fantastic. The change took one pair about four hours of coding, if that. (There was a lot more time spent researching Unicode and internationalization issues.) It required a five-line change to the centralized user input processing and another ten-line change to the centralized output template picker.
- We did not design in advance for any of these problems. It might seem like it (why have a centralized user input processing method, otherwise?), but in fact we were just following good XP design principles: simplicity and reduction of duplication. At one point, we had the same two lines of user input handling duplicated in three or four places. We refactored that into a centralized method. Months later, when we had dozens of pages, we came back and reused that method to support international input. No grand design, just damn good code.
- The common wisdom is that some things are so hard they require up-front design. I've pushed this theory, and it hasn't pushed back. I'm not so sure it's true. I think they require good code, but up-front design isn't the only way to get that. And in my experience, it's not the most effective way to get it, either.
A random statement I made recently that I like. I know this is going to come back and bite me, but I have to post it anyway. (Vanity, thou art a cruel master!)
- If you can't be selectively dogmatic, you can't do XP.
I'm writing an article about ContinualDesign?
. Here's a thought that occurred to me as I wrote. It's a silly metaphor, but a fun comment.
- Why is it that continual design doesn't back you into a corner like up-front design does? With the lack of planning, you'd think you'd be more likely to end up in a corner, not less. The reason: continual design is focused on simplicity. In continual design, there are no walls... just the floor you're painting. Hence, no corners to be backed into.
I just wrote quite a bit on ObjectOrientedForDummies
, which inspired and then fed off of GoodDesign
. It's 4:30 am. Right now, I'm thinking this is great stuff. I fear what I'll think in the morning. (Or rather, when I wake up, which probably won't actually be morning anymore.)
I just saw "The Bar is Higher Now" on MichaelFeathers
' blog (http://www.artima.com/weblogs/viewpost.jsp?thread=42486
- I love it. I think that DontRepeatYourself and CouplingAndCohesion are basic principles of GoodDesign. DontRepeatYourself is easy to understand and apply. CouplingAndCohesion isn't. I've been looking for a simple rule to use to help people understand these rules, and I think Michael's hit on one for decoupling: Can you take any arbitrary class and write a unit test for it, alone, in a few minutes? Brilliant. Now, what about cohesion?
A thought on LawOfDemeter
- I have to admit, I've always been a bit unclear on the Law of Demeter. I understand what it is and why it exists, but the formal definition never made total sense to me. And when I try to explain it to others, I get bogged down. Still, I've been looking for a simple guideline, like the PragmaticProgrammers?' DontRepeatYourself, that does for coupling what DontRepeatYourself does for duplication. (Actually, I mentioned this in the blurb just above.)
- I think I may have found one. It's not quite as encompassing as LawOfDemeter, but it's a lot simpler, and might have the kinds of emergent properties I love about DontRepeatYourself. Here it is:
- Don't implement "set" methods.
- You can pass parameters into an object when you construct it, and you can pass messages that include parameters, but except in the constructor, you can't write any method that does nothing but take a parameter and store it in an instance variable.
- Wacky idea, I know. I'm going to experiment with it for a few years and let you know how it works out. :)
I'm a programmer who's very interested in high quality software and effective methodologies. I'm a sporadic contributor to Wiki - I have bursts in which I'll contribute a lot, but then I'll go away for a while. Right now, most of my energy is focused on NunitAsp
. I've also been recruited for the C# port and maintenance of fit (FrameworkForIntegratedTest
I like creating small pages that focus on a single concept, then seeing the pages grow as people add their thoughts. I experiment with writing as compactly and clearly as possible. I also experiment with concepts: I'll start a page as a way of trying out an idea, as well as a way of seeing what other people think. Sometimes I'll write provocatively in order to seed discussion:
My current favorite contribution has been the "ProcessPrinciples?
" set of pages, which I mostly created in August and September of 2001. In these, I'm experimenting with the beginnings of a process pattern language. Eventually, I'd like to collect enough process patterns and forces to write a book about creating processes customized to an individual project and work environment. Here's the pages:
pages that I authored:
I once heard Ward Cunningham talk about the idea of complexity as debt, and I thought it was a great metaphor. I wrote several pages about that idea:
I own a small consulting business and once had grand ideas for it. I've since learned better, but the pages I wrote during that time are still around:
I've done a fair amount of ExtremeProgramming
. I started using it in April 2000, and written some pages about it:
I love stories. They're fun to read, fun to write, and a great way to learn. Some of the pages I created are for stories:
Finally, I have a few pages which focus purely on the nuts and bolts of programming:
That's all the pages that I can think of right now. If you've gotten this far, you probably need to go do whatever it is that you've been putting off. :) But if you've had a chance to read some of these pages, I'd love to hear your comments, good and bad. Knowing that people are listening is what keeps me writing. There's a place for comments at the bottom of the page.
About others, mostly:
Thus ends the self-aggrandizing part of my home page. The rest is stuff by other people.
Here's some other links that I like or want handy:
Some quotes I like:
- I learned to write UnitTests while I was still a Java fanatic. I wrote some tests; they caught some bugs. I wrote more, they caught more. By the time I had enough tests to be confident that I had NearZeroBugs??, I didn't feel like I needed the static typing anymore. I shouted, "Aha!" and went to try out Smalltalk. -- AdamSpitz, StaticTypeSafety
- Computer Science graduates tend to be loud advocates of anything formal, regardless of their own (lack of) experience in usefully applying such tools. -- AnonymousDonor, StaticTypeSafety
- Since foresight doesn't work, don't rely on it. Go for early hindsight. -- BenKovitz, OnlyForesightMatters
- Somebody said (and I think it's on Wiki somewhere), "People hate change." The first reaction is, "Yeah, well, everyone knows that!" To which the proper reply is, "No, you don't understand, people really really hate change." -- AnonymousDonor, TheyWillNotListen
- Estimates are about "how much work does it take". Delivery (velocity) is about "when will we get it". This is why I find estimating clock/calendar time to be sketchy. -- J. B. Rainsberger, XP mailing list
For sushi lovers:
- The first dish we tried was raw octopus. It was very, very raw. It had been chopped up into little strips, and doused with sesame oil, but each of the individual pieces was still squirming and writhing vigorously. One of our Koreans hosts demonstrated how to eat it. Grab a piece quick and put it into the hot sauce (a self-saucing food - it wriggles itself full of sauce) and then eat it quick before it stops moving.
- I decided to start with the smallest, most straightforward piece I could find. I fastened my silver chopsticks on the tip of a small tentacle.. Big surprise. The dismembered tentacle's suction cups grabbed the plate and wouldn't let go. I pulled, and the plate lifted. I poked it for a while, and it finally bonded to one of the chopsticks. I quickly dunked it into the red-hot sauce (no apparent effect on the still animate tentacle) and pried it off the chopstick with my teeth. It didn't fight too much once it was inside my mouth. Later I discovered from someone in Seoul that every year several people choke to death when the tentacles fasten themselves on the inside of their throats. I never realized enjoying local cuisine could be so risky.
An interesting stat: Slashdot's normal peak load is 25 pages/second, using 6 servers. That's more processor power than I expected for a popular site like Slashdot. (On the other hand, it's a DB-intensive site.) Prior to the WTC bombing, their hit record was 1.6M pages in a day, and their average was 1.4M ppd.
On Tuesday, the day of the WTC attack, they peaked at 70 pps, and served nearly 3 million pages. They continually monitored performance and tweaked the code to deal with the load. Average page serving time slowed by 2 seconds per page after performance tweaks.
(extracted from http://slashdot.org/article.pl?sid=01/09/13/154222&mode=nocomment
From the stating-the-obvious department:
- It's easier to add features to an architecture than to remove them. If you have a misguided feature that a bunch of classes are using, taking it out requires that you modify all kinds of existing code... correctly! On the other hand, if you have a new feature that would make life easier, adding it doesn't require that you retrofit any old code.
- This is why architectures and designs with don't do much are better than ones that do a lot. It's counter-intuitive, but true: the more your design anticipates future needs, the less prepared it is to deal with future requirements.
(This is a basic XP principle so I'm being very redundant here. But this particular twist on DoTheSimplestThingThatCouldPossiblyWork
just occurred to me. I'm going to search Wiki when I have time and see if it deserves its own page.)
A success story about completely refactoring an old, crufty application in three weeks. Apparently no tests were used or added.
Random thoughts not yet worthy of their own page:
- The programmers' bookshelf should contain few specific language and tool how-to books and many books on general principles and practices.
- Constructors should never do any significant work. Although having an object be fully baked after construction is nice, it leads to coupling issues that can make testing extremely difficult. As the code evolves, the coupling can lead to code that is fragile and resistant to change. Instead, use LazyInitialization in those cases where significant work is necessary.
- When using LazyInitialization, avoid side effects. I've twice seen a case where LazyInitialization was used to log into a remote system (once was in my own code!) and both times it resulted in confusing and brittle code.
Research on the effects of eye-contact in group discussions:
- "The effect of eye gaze has literally fascinated people throughout the ages," says Dr. Vertegaal, whose paper, Explaining Effects of Eye Gaze on Mediated Group Conversations: Amount or Synchronization? was presented this week at the Association for Computing Machinery (ACM) Conference on Computer Supported Cooperative Work.
This is an entertaining story, in a way that only the very wacky true stories can be. It's about a couple of guys who snuck into Apple to create the "graphing calculator" application that was shipped with every PowerMacintosh
I wonder if history is repeating itself? To very little fanfare, MacOsx version 10.4 "Tiger" will again include a free ultra-nifty graphic calculator. -- IanOsgood
Leave me a comment here.
I like hearing from other people.
Is this the same Jim Little? http://www.cs.ubc.ca/~little/
Nope, not me. Here's me (on the right):
Jim got a haircut since the last time I saw him. (-- Alistair)
I like the Rubik's cube story. Have you seen NoseJobRefactoring? -- MatthewAstley
Sorry girls, Jim is no longer available. Congratulations on the recent wedding, Jim! -- RobMyers
Jim, I appreciate the comment about making FireFox
work with UserNames
- I tested and tweaked the info a little and put it on the UserName
page. Thanks again! -- LayneThomas
Jim I have motioned a delete of ManagementlessO
rganization and therefore its related CompensationG
ame, and CompensationG
ameTheoryAnalysis. Perhaps EgalitarianCompensation
is a more suitable home for some of the material. If I am wrong please explain. thx