Beautiful Code and Beautiful Software
Monday, October 29, 2007
Programming was fun because I could make cool stuff, but what actually got me obsessed about it was suddenly seeing something interesting in the semantics and syntactics of the very lines of code. Being sensitive to the difference between good and bad code was intensely motivating, and discovering ways to write efficient, self-documenting, and thoughtfully-organized code was something I knew could captivate me forever. This is what I loved (and still love) about my field—the art of programming, the wonderfully complex craft that could take a lifetime to master.
As I added to my Ruby knowledge Java and then Objective-C, I began appreciating software development at a lower level. I grew up in an environment (the Rails community) where there was a lot of hate for those big verbose languages, but upon actually experiencing them for the first time myself, I discovered that I enjoyed them. They were different, but still interesting in differing ways. And hey, there was something satisfying and clarifying about writing dumb code after being born in high-level land—my first for-loop in Java, for example, helped me better appreciate the cleaner, object-oriented practices I knew, but I also saw something appealing in the for-loop itself. It wasn't just elegant language that intrigued me, it was also the basic logic behind the syntax, and the fact of differing syntax. Computer language, and differences in computer languages, were fascinating in and of themselves.
I had the same satisfying feeling when I first learned Assembly in college this term. Assembly was tedious and sometimes quite painful, but the way it made me think about basic programatic functions in such new ways was completely worth the pain. Of course, I also got a geeky pleasure just from being aware of the low-levelness of the code I was writing.
It gets worse! I had a great moment of self-discovery when I read Wolf's Programmers Don't Like to Code early this year. I indeed love the problem solving, elegance-creating, coding-to-learn part of coding, but I realized that I actually like coding for coding's sake, too. At least, that's how I describe my enjoyment of CSS and XHTML. I have an extensive enough grasp of front-end programming that I don't often solve a new problem these days (in fact, problems that take me a while or bugs I haven't seen before can be downright thrilling). Yet, I still enjoy working with the stuff. There's something relaxing about dumping out good-looking code that I understand very well, sort of like how I enjoy doodling the same cartoon cat over and over in my class notes, or how I enjoy playing the same three tunes when I sit at a piano. Even just looking at good CSS—well ok, my CSS, with everything ordered, indented, and cascading correctly—feels good in the same way that I felt bad, almost physically ill, as I waded around in the stylesheets of a certain forum software and found inconsistent indentation, extra line breaks, commented-out junk styles, and styles disabled by deliberately misspelling the property name.
This is what happens when you're so easily inspired, interesting shadows on the walls motivate you to continue living. You have to come back in once in a while and reorganize your levels of sensitivity so that your appreciation for light and sound is appropriately proportional to your appreciation for Off-Off-Broadway.
That is to say, these days I've been thinking a lot about the software part of software development. Specifically, the design of user interfaces in software. At BARcamp this year, I liked how Aza Raskin asked all developers to raise their hands, then all designers, later saying that the hands that went up the first time should have stayed up. All developers should be designers. At least, that's true for all developers lucky enough to work jobs where they have a say in the design of their software.
I'm getting increasingly excited about the importance of design within development, especially as I come to terms with my different passions and reflect over some of my past gigs. In the web app contracting world, design and development are usually separate jobs. In some cases, the design job is minimized in comparison to the rest of the project because clients generally pay for features, not for beautifully thoughtful design. On a project where I played both design and development roles, I recall feeling uncomfortable because I was assigned only two days to complete the visual design. It needed a lot more than two days. It was a complicated application that deserved weeks of rigorous iteration and conversations with the client. Unfortunately, that's not what the client was paying us for. The client was perfectly fine with the version-one mockup that took me a couple hours, and well, we had an app to launch.
I had another wake up call while I was at C4 this year. It appears that many Mac developers, perhaps most of them, are solo indies producing their own products. As such, they really do have to be both designers and developers. Actually, design is often the most significant part, and there seems to be a lot more enthusiasm over user experience and just producing a great product than there is over the code itself. One night during C4, someone inadvertently helped me see this when he described to me the nature of his work: "Coding the basic functionality is the easy part. That just take a couple weeks. What's really hard and time consuming is figuring out the specifics of the UI."
Wow, I thought. Why does that seem so right? Why is that so cool to me?! Oh, right, I'm a designer to begin with. There are dramatic rifts between my enjoyment of development, design, and art because I appreciate each of them in very different ways. I constantly try to integrate development and art, but I really ought to figure out how to mix all three.
After all, my goodness! Do we want beautiful code, or beautiful software? Here's another peek into my life: A side effect of being extremely open minded and absorbent is that I find myself believing all kinds of contradictory ideas, sometimes even opposite ones. It doesn't bother me right now because I'm in exploratory mode, not know-what-I-believe mode, but to retain sanity it is, of course, a must to occasionally sort things through until they make some kind of sense.
Thus, for further consideration I've listed just a fraction of the many things people like about software development, loosely ordered from the most intrinsic rewards to the most extrinsic rewards. I've left out a lot of really wonderful stuff like community, open source values, and challenges because those are harder to fit into this order, but I think you'll get the point. This is an extremely interesting sort order to me because of how psychologists say that intrinsic motivations are stronger and more likely to keep you going. For example, the person who takes karate classes because she feels energized and excited by the sensation of punching and kicking will more likely end up with a black belt than the person who takes the same classes for the health benefits.
Is it the same for programming?
- The sensation of writing code
- The knowledge that one is writing code
- Enjoying computer logic
- Enjoying computer language
- Elegant syntax
- Elegant semantics
- Learning about code
- Problem solving
- Learning about problems
- Achieving usability
- Finishing a product
- Elegant software
- Solving human problems
- Solving business problems
- Satisfying market needs
- Making money
- Having a stable career
Which is the most persistently motivating kind of reward? Most importantly, which kind of motivation produces the best software? I'd love to do some formal research on this topic sometime, but I'm already pretty sure that the answer is "a healthy balance of most of the items on this list," as we certainly want our software to be both usable and maintainable, and sellable, and everything else. I'm also pretty sure that the balance is different for every situation and person. At the moment, however, I envision a wide bell-shaped curve sitting upon a rectangle, and everything turned on its side—the motivations that result in the best software are the ones nearer to the middle of the curve; but really, I think all of the motivations are beneficial in some way, and insofar as the programmer has her priorities straight, the more the better.
The tragedy of our field is that most programmers don't ever get to appreciate the majority of these rewards, particularly the more profound ones. Then again, it works out great because the majority of programming jobs couldn't possibly satisfy someone who cared about all these things. Still, I wonder what the industry would be like if we were all intrinsically, thoroughly passionate about our craft, and nobody was signing up for Computer Science classes just for the "stable career." I wonder what it would do to the world.
I think I should revisit this train of thought every year or so as I become a better software developer. I get the feeling, though, that my fate is already somewhat set in the fact that the more I grow, the more I desire a working situation where I have enough freedom to create beautiful things. It's probably worth noting that both freedom and beauty are vague, subjective ideas, so that could mean anything. All I know is that the compromises to both beauty in code and beauty in software design as necessitated in most programming jobs give me an unwavering feeling of discontent. I wouldn't be surprised if I ended up settling down as a freewheeling solo developer using, you know, web design contracting to support my freewheeling solo lifestyle.
Eventually I'll retire my computers and spend the rest of my days plein air painting on some beautiful farm out in the country. That, or a sensuous city life of alternating between street art missions and serving time. It's fun to imagine where I'll go once I feel done with technology. Hopefully that never happens, because I want to be the cool guru grandma who's still around when her children are giving mandatory programming lessons to their children.

PSIG 107 | Xmo'd + mogenerator: Seamless Core Data code generation
Saturday, October 13, 2007
(What is PSIG? | PSIG 107 announcement)
Show and Tell
- Practical Ruby Gems. Tom: "Eh it's a library book."
- Gorman tells us of people coming to the Genius Bar because they've renamed their home folders and thus lost sight of their accounts.
- We plug Silicon Prairie Social and I lament RubyCocoa syntax, mentioning named arguments in Ruby's future.
- Kevin tells me that Python has named arguments already, but pyObjC still uses the underscore syntax because of C conversion complications.
- Paul: Good articles in More Java Gems.
- 20 Greatest Unsolved Problems. Says Bradley: "I don't think the author is that talented as a writer. The chapter on protein folding wasn't nearly as interesting as I thought it would be." We ask if he wrote the author to complain. "I didn't write him. I could kick his butt though."
- The Chinese Language: Fact and Fantasy, Elementarz Polish primer. Bradley pointed out something really cool about the Polish number system that I forget.
- Programming Erlang, The Definitive Antler Reference.
- Wolf's going to the OpenGL Bootcamp. "I'm not going to let you keep feeding me OpenGL lies that I've been too ignorant to counteract."
- Chasing the Rising Sun. "Is it about Japan beating us in technology?" No, it's actually about the song about the house.
- Dan demos the iAlertU MacBook alarm to everyone's delight. "Impressed a guy at Panera with it."
- How to shoot yourself in the foot in any programming language

Xmo'd + mogenerator: Seamless Core Data code generation
Mogenerator refresher (from PSIG 98):
Object relational mappers integrate object-oriented software with relational databases. They allow you to work with objects instead of raw SQL statements. Classes map to tables, and rows map to instances. There are a few different ways to implement this:
- Class first (e.g. Java Beans + XDoclet): Embed relational table and column names into the source to write SQL for you. Wolf believes this is the worst philosophy -- you can reference the data source, but there's not enough information to derive the schema from embedded metadata.
- Schema first (e.g. Active Record, code gen): Link classes from the schema. Unfortunately, DDL (Data Definition Language) is a harsh and primitive landscape incapable of supporting sane metadata and you end up needing hacks. With Active Record, "you must name things the way god intended them to be named -- who is of course DHH." With code gen it means manually hacking mapping files.
- Model first (e.g. EOF, Core Data): Wolf likes this philosophy best -- you start with a declarative base, but you have infinite room for sane metadata and you're not tied to any specific data source. Because it's just data, there's no need to write a parser or interpreter. You can generate both DDL and code from a single source. In dynamic languages, custom classes are optional.
Core Data can generate wrappers for all of your attributes as NSManagedObject classes or as custom subclasses of NSManagedObject. Custom subclasses are great for holding your business logic and helping with type safety. The problem is that it's kind of a tedious task to get Xcode to generate your subclasses and it usually involves a lot of painful merging due to the fact that each file contains both generated and custom code.
You can use the lovely Generation Gap pattern to help with the merging problem: put machine-generated and custom code in separate files and make your custom code subclass the generated code.
This is where mogenerator comes in -- it's a command-line tool that automates everything and makes use of this pattern. mogenerator owns the machine's files which are subclassed off of NSManagedObject, and subclassed files off of that are owned by you and untouched by the machine. When you modify your data model and invoke mogenerator, all your generated code will be updated but your custom code won't change.
Xmo'd
Xmo'd makes your life even easier by integrating mogenerator into Xcode. Wolf achieved this with the use of undocumented, reverse-engineered plugin API. Xmo'd overrides the data model document method to automatically run mogenerator for you. When you save a data model document in Xcode, the Xmo'd override fires off an AppleScript which calls mogenerator. This keeps your generated code continuously synced up with your data model. Xmo'd also adds the menu item "Autocustomize Entity Classes." Currently it works on Xcode 2; Xcode 3 support is coming soon.

PSIG 106 | NSToolbar
Monday, August 6, 2007
(What is PSIG? | PSIG 106 announcement)
Items of Interest
- My Startup Life: What a (Very) Young CEO Learned on His Journey Through Silicon Valley -- We're informed the teen author manages to make himself sound like a 40-year-old what with the dry writing and needless mention of shoehorns :)
- Getting Things Done: The Art of Stress-Free Productivity -- I claim I am henceforth living David Allen's principles. We'll see how it goes!
- Sickert: the painter and his circle -- The story of Walter Sickert, an English Impressionist painter with some newly revealed connections to Jack the Ripper
- Nothing Sacred -- Autobiography of comedian Lewis Black
- Collapse: How Societies Choose to Fail or Succeed -- By the same guy who wrote Guns, Germs, and Steel
- iFuntastic -- Make yer own iPhone ringtones
- Paul on the Xserve, Mini, iMac: "But aren't we so pregnant for a bunch of upgrades?"
- Steve entertains us with crazy stories from his awesome IT job at O'Hare. He also gets me curious about wxPython and the way you can use XML to define GUI with XRC. Most intriguing -- he predicts that the problem of computer viruses will grow hugely in the future, saying that crackers are most certainly in info-collection mode at the moment.
- The meeting ends with the sharing of nasty-food/bug/pyromanic stories!
NSToolbar
Great presentation by Dave and El Wolfo involving a cowboy hat, a gaucho hat, methods named "spanishize" that define anything starting with "El " as Spanish, and oh -- we got to see some live debugging ;). Summary:
Currently, Interface Builder doesn't help you create toolbars, so you either have to do it in code or use Belkadan's GenericToolbar palette.
Doing it in code: After allocating your toolbar, initialize it with a unique identifier (initWithIdentifier) so that Cocoa can automatically remember user customizations to the toolbar. You'll also have to set setAutosavesConfiguration: and setAllowsUserCustomization: to YES. Once you've created and set the delegate, tell your window to setToolbar:toolbar.
There are four basic methods you need to manage your toolbar:
- -toolbarDefaultItemIdentifiers: Specify default toolbar items. Remember to avoid name collision with Apple's standard items
- -toolbarAllowedItemIdentifiers: Choose which of Apple's standard items to allow. By default none of them are allowed
- -toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar: Returns toolbar items as specified by the identifier
- -validateToolbarItem: Called on every toolbar item. The target and action must be set and responsive for this to work
GenericToolbar is the non-code alternative: It has a nice drag/drop interface for adding and removing items as well as hooking up items to your controllers. It doesn't work very well with bindings, so it's better to do those in code.

Thanks to Gruber for the great wwdc photo upon which this is based
C4[1] this weekend!
Ok, I think this is the most excited I've ever been about a tech event. I can't wait for the sessions and I'm hugely looking forward to meeting everybody. I'm actually going to be manning the registration booth so I'll at least get to greet everyone :)
Hay -- anybody out there have an idea for Iron Coder that could use my help? I'm pretty psyched about the announced "API" because it would seem I could easily make use of my art/design/webcode-fu, but I'm not coming up with any ideas...

PSIG 105 | Dissasembling on OS X
Thursday, August 2, 2007
(What is PSIG? | PSIG 105 announcement)
Items of Interest
- AJAX Design Patterns
- Mind Performance Hacks
- The Four-Minute Mile
- Million and one nights
- Endless universe
- Pangea Software's Ultimate Game Programming Guide for Mac OS X
- Mac OS X Internals
- Four members showed up with iPhones. There was a large amount of quality iPhone discussion during which I seem to have zoned out. hehe
- We took a brief critical look at Leopard, particularly at how wrong the dock looks when it's on the side, and how the icons unfortunately bounce with their shadows attached.
- WWDC 2007: It seems that this year's was essentially a repeat of last year's.
- HOPL III: "We're still so primitive."
Dissasembling on OS X
Why disassemble?
- To work around bugs
- To learn more about areas where the docs are out-of-date, incomplete, or intentionally missing
- To find ways to interoperate with other software, such as when implementing file format compatibility/interchange or breaking into proprietary tool-chains
Static tools: Hex editors
- OS X ships with three utilities for hex dumping: hexdump, od, and xxd
- HexEdit is one of the oldest mac open source apps, originally created for system 7
- HexFiend is a newer open source Cocoa hex editor with more features
Static tools: General level
- file tells you what kind of file something is, including all the architecture versions
- strings looks in binaries to see if anything's human-readable. Use with standard input, or it'll only look into the version of the file with the same architecture as your system
Static tools: Code
- Otool understands the Mach-O binary format and can tell you an app's dependencies. Apps linking to private frameworks involve Apple's undocumented stuff. Wolf: "It used to be that all the cool stuff was in the private frameworks. The last of the cool stuff pretty much went public by 10.4. So the hunt isn't there anymore."
- otx does enhancements on Otool's output. It intermixes the raw outcodes into the disassembly in case you want to inject your own instructions. You can follow along and see what strings are being referenced. The tool also detects and works around some obfuscation techniques.
- classdump is another tool for dumping Mach-O code. Trivia: AppKit appears to contain a class called NSEvilHacks.
- MagicHat, a recently open-sourced tool, is like classdump except with a hyper-linked interface. You can specify which frameworks you care about. Wolf uses key-value coding to pull out undocumented methods.
- Interface Builder can open up nibs and let you see names in the targets and actions. Make a copy of the app first because IB may leave some stuff in even if you don't save
Runtime Tools
"What's cool about software is you can put your hand up them like a puppet."
- gdb debugger for obj-c.
- BSInspectors, an Xcode plugin that lets you inspect objects
- F-Script scripting for cocoa. F-Script Anywhere allows you to dynamically inject it into any Cocoa app. You can also dynamically look stuff up in the pop-up completer menu. The Object Browser shows you what methods are supported for the selected object. "Select view" button will inspect anything you click on and allow you to directly call the methods.
The rest of the evening was spent doing evil things to the iPhone. Also! I watched in awe as Dave/Wolf worked some fabulous Quartz Composer action into a little Cocoa toy app that I'd been working on ;D


BARcamp Chicago 2007
Thursday, July 26, 2007
I had a lovely time at BARCamp. Like last year, it was a mind-expanding experience and encouraging on several fronts. This year we had more people, more energy, much cooler weather, a nicer venue (with clean bathroom!), and insanely large amounts of free food in addition to the obligatory free beer. For me, the best part was actually seeing familiar faces and getting to catch up with great geeks like Peter Chan, David Dalka, Peter Harkins, Justin Kruger, and of course the amazing Jason Rexillius. It especially rocked to finally meet my fellow DevChix, Jen Stander and Sarah Gray. I talked to a lot of interesting new people as well, like Rich the sound guy, Ben Collins-Sussman-SVN, Joi Podgorny, Conrad Albrecht-Buehler, and Atul, Aza, & Jono from Humanized.
Here are highlights from some of the presentations I attended:
Mass Customization: Next Generation of Software is Hardware -- Ziad Hussain
The dream is that ordinary people should be able to manufacture their own gizmos. We ought to have a Kinko's of fabrication -- a service that would allow users to design an item to be produced in full plastics and circuitry right away. Currently, some very interesting work is being done in producing cheap rapid-prototyping machines like RepRap and Fab@home. Geared to home users who can't afford commercial systems, these machines aim to democratize innovation.
Why most businesses fail, most businesspeople are miserable, and why you'll be different -- Sean Johnson
People seem to think that success requires either (1) working systematically for 50 years to get to the point where they can live the good life on a pile of money, or (2) hitting the jackpot on a business idea that rakes in the good-life piles of money right away. But what is the good life? Your dreams probably cost a lot less than you think. And in some cases, they are dreams you could be living right now.
Sean described ways to break free from standard business models in order to start happier, smarter companies. He discussed our tendency to put too much care on the validation of our peers as well as "VC money, a few hundred diggs, a write up on TechCrunch, etc." He encouraged us to, instead, design useful products that will help everyday people -- products that make money at every single sale.
Dynamic Mashups with RSS -- Aaron Williams
Kirix Strata is a data browser based on the Gecko engine, currently for Windows and soon to run on Ubuntu as well. Strata's aim is to make it easy to uncouple data from its context and render it usable. With a few clicks, Aaron demonstrated Strata's ability to import static HTML tables and RSS feeds into database form. He then showed us some database management features that remind me of Access and Excel. I was most intrigued by the Relationship Manager -- a GUI database editor which allows you to do wonderful things like visually join tables together.
Building Geo-Distributed Web Applications -- Jason Rexilius
Geo-distribution is a single app running simultaneously in multiple locations around the world. It could involve server clusters, network routing, multiple data centers/providers, or multiple carriers. Says Jason: Premature optimization is bad; ignoring your objectives is also bad. He gave us some interesting technical ideas on building web apps, encouraging us to think outside the database and leverage the right tools for the job.
Lisp -- John Quigley
John truly loves Lisp. I'm pretty sure his trembly, tender speech was the most passionate I've ever seen anyone get about any language. Lisp, he says, forgoes the syntax so you can get to the heart of the matter. It's a highly dynamic language that grows to meet your needs -- a programmable programming language for doing the impossible. Throughout John's presentation, he tried to help us see that Lisp was not some crazy language with a hideous syntax, but rather a gorgeous language with a very logical syntax.
The most interesting part was his explanation of the XML format and how it relates to Lisp. XML's tree design allows it to be both code and data, resulting in a very simple, flexible, and extensible tool -- the same is true of Lisp. An in-depth exploration of this idea can be found here.
For learning Lisp, John recommends Structure and Interpretation of Computer Programs, and two other books depending on your approach: Those wishing to take the practical path should read Practical Common Lisp (also available for free online). Those taking the academic path should read Paul Graham's ANSI Common Lisp.
DIY Beer - Tristan Sloughter
With beer in hand, Tristan gave us a beautiful talk on homebrewing.
Ingredients:
- Malts -- Barley that's been malted, sugar. Provides body, color, and some flavors (chocolate, coffee, smokey, etc)
- Hops -- A flower which provides bitterness (oils, measured in IBUs), hoppy flavor, and aromas like citrus and fruit
- Yeast -- A fungus which creates ethanol by eating glucose from the malt; provides subtle flavor/texture
- Other -- Irish Moss, insingglass, gypsum for clear color, Belgian candi, lactose, fruit, honey, coffee, spices, wormwood, pizza
Types:
- Ale -- Top fermenting. Temp 65-75, belgian ales up to 86. Most common & easiest.
- Lager -- Bottom fermenting. Temp 45-55. Harder to make and refrigeration. Mellow, crisp flavor.
- Lambic -- Uses wild yeast. You leave your fermenter open and let any yeast (such as from a barn) fly in. Dry, vinous, cidery, sour aftertaste (the taste of bad beer). You can actually buy "wild yeast" to make your Lambic.
Equipment -- You need a 4 gallon pot and a kit from, say, Northern Brewer. It's an initial $100 investment for the kit and another $25-40 for ingredients, but in the end you're only paying 50 cents a glass instead of $1.25 for beer of same quality.
The process of brewing beer is essentially boiling the malt, adding hops at some point (depending on how bitter the beer should be), plugging it with an airlock and waiting for 3-7 days. I was amused by the formula for measuring IBU:
(gallons of brew * 1.34) / (oz. of hops * Alpha Acid * (time of boil) / 2)
"Happy brew hacking," Tristan concluded. "It's just like programming -- have fun with it, try different things, get drunk."
Enterprise Searching -- Dieselpoint
A guy from Dieselpoint gave a nose-bleedingly intense and detailed talk on different methods of searching for data and why enterprise searching is such a complex problem. There were some major gems in his speech, though they were a bit hard to understand -- I wished the talk had been more simplified and BARcampy rather than Fortune-500-board-meetingy so that we could have all internalized it better. I was impressed by the huge role linguistics play in searching and the many creative ideas for improving search engine performance.
Groovy -- James Williams
Groovy is an agile, dynamic language for the JVM that can fully integrate with Java. It looks similar to scripting languages like Ruby and Python in the way they've pruned away a lot of the Java syntax. For example, printing Hello World is as simple as: println "Hello, World!" Groovy includes some extra features such as closures, dynamic collections, and builders, which allow you to build data types with a tree-based syntax. The point of Groovy is not really to replace Java but to give you an alternative to more quickly code prototypes, UI, one-off apps, and extensions.
Getting involved in FOSS -- Freddy Martinez
I was completely impressed by fellow underage kid Freddy and his impassioned talk on getting into open source. He made several points I can totally confirm, such as the importance of users groups and mentors. His mentor actually got him started in the community by saying: "I'm doing documentation work. Wanna help edit?"
How to protect your open source project from poisonous people -- Ben Collins-Sussman
In any community, attention and focus are your scarcest resources. You must protect them from people who distract, emotionally drain, or cause needless infighting. It's not just trolls who are problematic -- perfectionists can also derail forward progress. It's important to do something about those who complain without helping, insult the status quo, are unable to pick up on the mood or common goals of the project. Ask questions like: Is the person draining attention and focus? Is this dispute worth it? Is the person paralyzing the project? Is the dispute likely to finish soon?
Don't: feed the energy beast or get emotional. Do: initially give people the benefit of the doubt and look for the facts under the emotions. Know when to ignore or forcibly boot someone. Most importantly, address the behavior, and not the person.
Build your community on politeness, respect, trust, and humility. The community founders establish the culture, and in turn, the culture should become self-selecting. Pick a direction and limit your scope. When you're limited, it's easier to measure your progress, easier to get people to join, and easier to screen away people who shouldn't join. Example: SVN's scope was solely to create a compelling replacement for CVS.
Have well-defined processes as far as backporting bugs, accepting and reviewing patches, and admitting new committers. Document important design decisions, bug fixes, mistakes, and code changes. Have healthy code collaboration policies -- send commit emails and encourage email review. Do big changes on branches for easier review. Increase your project's bus-factor on components by spreading the knowledge and not allowing names in files.
Humanized: Tales from developing Enso -- Atul Varma, Aza Raskin, & Jono DiCarlo
The guys from Humanized really have an good grasp on interface design, and their talk was one of the most inspiring I've ever heard. There's actually a lot more to their Enso products than the unfortunate labeling of "Quicksilver for Windows."
One of their major concerns is the problem of modal interfaces. Modes are in their essence confusing because every time a mode changes, a user's habituated actions are no longer relevant and she has to break her train of thought to add yet another set of actions to her memory. Says Humanized, almost everything that frustrates users about interfaces is due to a mode. That's why good interfaces have as few modes as possible.
In Enso, users hold down a key to get into the universal quasi-mode. It involves visual feedback, but also kinetic feedback, which is more effective -- your brain remembers you're in that mode because your finger's down on that key.
Another thing Humanized believes in is building from scratch. They say the toolkit straightjacket, while providing consistency, kills innovation. You can't be better without being different. You can't different without taking the time to make your own stuff.
On design: People think the GUI is just picking a good shade of blue, so it's pushed back to the end. In reality, all programmers should act as interface designers right from the start. As soon as you design a program, you're designing an interface. To the user, the interface is the product.
On the curse of being a geek: No matter how good you get with computers, you still have to design your programs for normal people.

