- Loves To Code
- Gets Things Done
- Continuously Refactors Code
- Uses Design Patterns
- Writes Tests
- Leverages Existing Code
- Focuses on Usability
- Writes Maintainable Code
- Can Code in any Language
- Knows Basic Computer Science
2008-04-08
Top 10 Traits of a Rockstar Software Engineer
2008-03-29
How to create "interesting, cool, and relevant software"
The only workable system for generating interesting, cool, and relevant software is well-known. Find a bunch of really smart programmers and point them at a large problem space for which there are actual users, and for which new solutions are unconstrained by old designs.—Mencius Moldbug, What's Wrong with CS ResearchNote the desired outcome: Interesting, cool, and relevant software. Do not become mired in empty debate over the phrase "smart programmers." Instead, ponder the other three preconditions: a large problem space, actual users and most especially no constraints by old designs.
Alan Kay is purported to have said, "A fresh perspective is worth 80 IQ points." You cannot have a fresh perspective when you are encumbered by backwards compatibility.
Meta-level thinking
I have been trying to figure out what characterizes some of the best programmers I know, or know about...
When people try to become better programmers there are generally a few different kinds of advices you can get. The ones that seem prevalent right now is (among others):
- Learn - and understand - Lisp
- More generally, learn a new language that is sufficiently different from your current knowledge
- Work with domain specific languages
- Understand metaprogramming
- Read up on the available data structures (Knuth anyone)?
- Implement a compiler and runtime system for a language
2008-03-25
Dates vs. Quality
What's the best way to avoid problems?
- Work at a small company (or in a small group) so you can set your own dates. Large organizations tend to be top down and impose schedules without any idea of what is actually happening.
- When you start out, set the date based on what you hope to accomplish. Or, set the date first, then pick a feature set you can implement in the time available. Or, iterate back and forth. But, whatever you do, don't set them independently of each other. I know this isn't news to anybody reading this blog, but it still seems to get ignored a lot.
- Be willing to cut anything -- anything -- if you have to make your date. Even features that are almost done. You can always ship them later. If you have an immovable force and an irresistible object, the dev team explodes.
- Be willing to change the date if you can't get the quality you want (my wife and I slipped our wedding date because we weren't going to have the quality we wanted on the original date we picked).
- Stay calm. No matter what, you will be dealing with the issue at the end.
They say, on the Internet, nobody knows you're a dog. Similarly, nobody has any idea what you were going to ship or (hopefully) when you were going to ship. They only know what you actually do ship. And, if you don't ship in the first place, it's pretty hard to ship updates.
2008-03-13
Eliza Programmer Dead
Joseph Weizenbaum, who invented the famous "virtual psychiatrist" computer program Eliza, died from cancer on March 5 in Groben, Germany at age 85.
> How does that make you feel?
Weizenbaum was a pioneer in computer science and professor at the MIT Artificial Intelligence Lab, where he created Eliza in 1966.
> Tell me more…
Eliza was a simple question & answer program in the form of today's online chat software. Eliza parodied a Rogerian psycho-therapist, mostly by rephrasing the user/patient's statements as questions and posing them back to the patient. This eliminated the need for a large real-world database.
> I'm not sure I understand you fully.
Eliza foreshadowed the potential of artificial intelligence, but Weizenbaum was stunned to discover how many people became engrossed in conversations with Eliza, even revealing intimate personal details. Over time, Weizenbaum grew skeptical about technology's ability to improve the human condition.
> Can't you be more positive?
In his 1976 book, Computer Power and Human Reason: From Judgment to Calculation, Weizenbaum criticized systems that substituted automated decision-making for the human mind. He also believed there were "transcendent qualities in the human experience that could not be duplicated in interactions with machines" such as "the wordless glance that a father and mother share over the bed of their sleeping child." (source)
> What does that suggest to you?
As Theodore Piszak wrote, Weizenbaum's book was "Superb…The work of a man who is struggling with the utmost seriousness to save our humanity from the reductionist onslaught of one of the most prestigious, active, and richly funded technologies of our time."
2008-03-10
10 ways to improve your code
- Write the tests before writing the code.
- Use static analysis tools.
- Practice "good citizenship" by paying attention to how well your objects interact with the outside world. "Never let them exist in an invalid state."
- Avoid indulging in speculative software development. "The goal should be to build the simplest thing we need right now."
- Simplify essential complexity and kill accidental complexity.
- Challenge programming conventions, such as writing long, unreadable test names, and blindly following the JavaBean specification to the detriment of your code.
- Embrace single level of abstraction principle (SLAP). From Kent Beck's book Smalltalk Best Practices and Patterns: every public method should be as short as possible, and should consist of steps, each one of which is a private method. "Don't make abstraction leaps in your code."
- Leverage existing platforms with languages targeted at specific problems and applications.
- Learn every nuance of the languages you're using.
- Change your perspective and consider "antiobjects." An antiobject is a kind of object that appears to do the opposite of what we think it should do. The object metaphor sometimes impedes the solution "by making us try to create objects that are too inspired by the real world."
It's the libraries, stupid!
Let's be clear. It is not the language, but the libraries that matter. Every time I hear developers talk about a new language and say it is by far the best one, I just shake my head. A new language is not going to be usable in today's world unless all of the libraries are in place. As the complexity of our software increases, so do demands on libraries. Microsoft learned it the hard way with years of set backs when it rolled out .Net. Had it simply embraced and optimized Java, it could have been years ahead instead.
Apple choose a different path. For the last decade Apple has been wowing the crowds and investors with its flawless and lightening quick execution. Every new Apple announcement, we keep thinking that they won't top it. But every time, Jobs and his crew pulls another trick out of the hat. Clearly, Apple is a well-oiled machine that has perfected the art of execution. But beyond that, Apple's secret sauce has been its software. While others have been inventing new languages and frameworks, Apple kept perfecting and building up its code.
Since the early days, Apple embraced a language called Objective-C - an object-oriented flavor of the popular procedural language. When Jobs returned to Apple, one of the early smart decisions was to ditch the old operating system in favor of Unix. This moved allowed Apple to instantly tap into serious programmers while retaining a beautiful and simple UI. When Java came along, Apple was unmoved, because it was just too slow. In general, over the years Apple has ignored new languages and just stuck with its platform. Smart, disciplined and mature...
2008-03-08
Interface "Wow" Factor
That’s what it really all comes down to: user perception. Jeff Atwood harps on about this constantly, but just because it’s oft-repeated doesn’t make it less true. It doesn’t matter what your application can do, just what your users think it can do. It’s all an elaborate illusion anyway, we just have to realize how complete that illusion really is. If a user looks at your application and thinks, “Wow! I don’t know what it is, but it looks powerful,” then you have succeeded as a developer. Your application could do nothing more than print “Hello, World!” an infinite number of times; so long as it is impressive looking, it will be a success (think iPhoto 1.0). Likewise, your application may desalinate water and hold the key to world peace, but if it looks wimpy, users will never give it a chance.
2008-03-04
Software Engineering Goals
- Modifiability
- Understandability
- Reliability
- Efficiency
Application Development in the "Cloud"
...Although it is difficult to come up with a precise and comprehensive definition of cloud computing, at the heart of it is the idea that applications run somewhere on the “cloud” (whether an internal corporate network or the public Internet) – we don’t know or care where. But as end users, that’s not big news: We’ve been using web applications for years without any concern as to where the applications actually run.
The big news is for application developers and IT operations. Done right, cloud computing allows them to develop, deploy and run applications that can easily grow capacity (scalability), work fast (performance), and never — or at least rarely — fail (reliability), all without any concern as to the nature and location of the underlying infrastructure.
Taken to the next step, this implies that cloud computing infrastructures, and specifically their middleware and application platforms, should ideally have these characteristics:
- Self-healing: In case of failure, there will be a hot backup instance of the application ready to take over without disruption (known as failover)...
- SLA-driven: The system is dynamically managed by service-level agreements that define policies such as how quickly responses to requests need to be delivered...
- Multi-tenancy: The system is built in a way that allows several customers to share infrastructure, without the customers being aware of it and without compromising the privacy and security of each customer’s data.
- Service-oriented: The system allows composing applications out of discrete services that are loosely coupled (independent of each other)...
- Linearly Scalable: Perhaps the biggest challenge. The system will be predictable and efficient in growing the application. If one server can process 1,000 transactions per second, two servers should be able to process 2,000 transactions per second, and so forth.
- Data, Data, Data: The key to many of these aspects is management of the data: its distribution, partitioning, security and synchronization...
What Stanford Learned Building Facebook Apps
Dr. BJ Fogg and Dave McClure taught a class last semester at Stanford on Building Facebook Applications. In 10 weeks, the 80 students had created 50+ applications and in total had over 20 Million installs - with 5 having more than 1 million users.
At today's Graphing Social Patterns conference, BJ and his two teacher assistants shared 10 tips they learned from the experience. Here they are:
- It's never too late to create a winning app
- Simplicity & clarity are key to app success
- Aim for speed & flexibility in launch and iterations
- Community cooperation leads to success (in other words, the most successful students shared the most)
- Individual opinion about apps are worthless, you need to get out there and see what happens
- Copying success is a cheap / fast way to succeed
- Metrics do matter, but today's tools are too weak
- You CAN learn to create a winning app
- Success comes from the CHAOS / CONTROL Cycle
- Mass Interpersonal Persuasion is finally here
2008-03-02
Google's Engineering Philosophy
12 principles that guide programming at Google:
- All developers work out of a ~single source depot; shared infrastructure!
- A developer can fix bugs anywhere in the source tree.
- Building a product takes 3 commands ("get, config, make")
- Uniform coding style guidelines across company
- Code reviews mandatory for all checkins
- Pervasive unit testing, written by developers
- Unit tests run continuously, email sent on failure
- Powerful tools, shared company-wide
- Rapid project cycles; developers change projects often; 20% time
- Peer-driven review process; flat management structure
- Transparency into projects, code, process, ideas, etc.
- Dozens of offices around world => hire best people regardless of location
The March of Progress
1980: C
printf("%10.2f", x);
1988: C++
cout << setw(10) << setprecision(2) << showpoint << x;
1996: Java
java.text.NumberFormat formatter = java.text.NumberFormat.getNumberInstance();
formatter.setMinimumFractionDigits(2);
formatter.setMaximumFractionDigits(2);
String s = formatter.format(x);
for (int i = s.length(); i < 10; i++) {
System.out.print(' ');
System.out.print(s);
}
2004: Java
System.out.printf("%10.2f", x);
Why Programming Languages?
...we first need to look at the reasons that programming languages exist.
- So that people can efficiently talk to the computer.
- So that people can read how other people talk to the computer.
That’s it. There are no more reasons.
2008-03-01
About 3-2-1 Launch by Hashrocket
...my new startup company named Hashrocket. (We are named after the ubiquitous key/value => operator in Ruby.) One of our two principal offerings is called 3-2-1 Launch...
We ... came to the conclusion that a span of 3 days is just enough time to get a new project off the ground - enough to nail down some distinguishing functionality, without sacrificing quality and good looks. Of course, it's not applicable to all projects -- our team of developers is 4-6 people (mostly working in pairs) which limits the amount of complexity we can tackle in one 3-day iteration (which we've taken to calling "orbits").
Here's a quick list of factors that empower us be ultra-productive in 3 days:
- Expertise in Ruby, Rails and BDD (using RSpec)
- Heavy automation of common tasks (pretty much anything repeatable is automated, including our initial application bootstrap which includes basic functionality such as authentication)
- Smart use of web services such as Amazon's EC2 and S3
- Reliance on Rails-based web 2.0 tools such as Basecamp, Highrise, Lighthouse, and Beanstalk
The 3 scheduled days (always Mon-Wed) refers strictly to implementation work, specifically the first iteration, ending with a public release of the software. Prior to the 3 days, our contract specifies a time period of 3 weeks during which we agree on detailed specification ... and high-fidelity mockups. What we're looking to achieve is a high level of confidence that we'll be able to launch in 3 days, and that necessarily involves locking down requirements prior to implementation. We've talked about an abort mechanism if anybody on the team thinks we're not going to achieve a successful launch (unveiling) on Thursday. If an abort were to occur, we'd postpone the launch for the next available date (probably the following week) at no additional charge to the client.
2008-02-29
UsWare vs. ThemWare
Ted Dennison left this astute comment in response to Do Not Listen to Your Users:
Generally when I go talk to users, it is to educate myself enough to become a user like them. Then I can see what needs doing, what needs streamlining, reorganizing, rearranging, etc.This brought to mind Eric Sink's claim that there are three categories of software:
- MeWare
The developer creates software. The developer uses it. Nobody else does.- ThemWare
The developer creates software. Other people use it. The developer does not.- UsWare
The developer creates software. Other people use it. The developer uses it too.ThemWare is how most software gets developed, with predictably disastrous results:
If I am building software that I don't use and don't know how to use for people I don't understand or even like, how good is my software going to be?I probably see every feature in terms of how difficult it will be to implement, rather than how valuable it will be for my users. I probably find myself wanting to label or document the features using my jargon instead of theirs. I probably create features that are tedious or unintuitive for my users. I can't imagine why the user interface I designed doesn't make sense to them.
I've found that much of the best software is the best because the programmers are the users, too. It is UsWare.
It behooves software developers to understand users, to walk a mile in their shoes. If we can bridge the gap between users and ourselves-- even if only a little-- we start slowly converting our mediocre ThemWare into vastly superior UsWare. To really care about the software you're writing, you have to become a user, at least in spirit.
Consuming the software you're creating is colloquially known as dogfooding in programming circles. Unless you're (un)lucky enough to be writing software intended for other software developers, dogfooding can be a challenge. But it's worth it. Dogfooding keeps software developers honest. Why work against your users by producing ThemWare when you could work alongside them to build UsWare?
2008-02-27
Continuous Integration
"Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly."
The Fallacy of 100% Code Coverage
So, let's start at the foundational level: 100% code coverage is a fallacious goal. Unit testing is designed to provide two principal benefits: 1) validate the operation of code; 2) create sensors that can detect when code operation has changed, thereby identifying unanticipated effects of code changes. There is no point in writing tests that do not fulfill one of the two goals. Consequently, a getter or setter [i.e. "properties" in the .NET world] should not be the target of a unit test:
public void setHeight( float newHeight ) { height = newHeight; }This code cannot go wrong (unless you believe that your language's assignment operator doesn't work consistently ;-). Likewise, there is no benefit in a test as a sensor here. The operation of this code cannot change. Hence, any time spent writing a unit test for this routine is wasted.
Excellent Explanation of Dependency Injection (Inversion of Control)
...Here is clearest explanation I've found--slightly edited for brevity (from the very good Spring in Action, 2nd. Ed. by Craig Walls):
"Any nontrivial application is made up of two or more classes that collaborate with each other to perform some business logic. Traditionally, each object is responsible for obtaining its own references to the objects it collaborates with (its dependencies). When applying DI, the objects are given their dependencies at creation time by some external entity that coordinates each object in the system. In other words, dependencies are injected into objects."
I find that very clear.
Dependency Injection was originally called Inversion of Control (IoC) because the normal control sequence would be the object finds the objects it depends on by itself and then calls them. Here, this is reversed: The dependencies are handed to the object when it's created. This also illustrates the Hollywood Principle at work: Don't call around for your dependencies, we'll give them to you when we need you.
If you don't use DI, you're probably wondering why it's a big deal. It delivers a key advantage: loose coupling. Objects can be added and tested independently of other objects, because they don't depend on anything other than what you pass them. When using traditional dependencies, to test an object you have to create an environment where all of its dependencies exist and are reachable before you can test it. With DI, it's possible to test the object in isolation passing it mock objects for the ones you don't want or need to create. Likewise, adding a class to a project is facilitated because the class is self-contained, so this avoids the "big hairball" that large projects often evolve into...
Build One To Throw Away, You Will Anyhow
Such [i.e. the title: "Build one to throw away, you will anyhow"] was one of the many pieces of advice of Fred Brooks in The Mythical Man-Month and while others of Brooks aphorisms have stood the test of time, completely scrapping a codebase is today seen more as an aberration than a painful but necessary part of the process.
Andrew Binstock, who's been developing a modern typesetting language (a TeX for the new millennium), has decided to do just that with his 20K LoC, multiple man-year codebase. His recognition that "the more I code, the more I see that I am adding top floors to a leaning tower. Eventually I'll topple it" may seem startling coming from a vocal advocate of unit-testing, especially to younger developers who probably have had pretty-good success developing Web-based applications.
Andrew pinpoints the critical issue:
It's extremely difficult to figure out where your architecture is deficient if you have never done the kind of project you're currently undertaking.Nowadays, most of us do our professional programming in pretty well-worn niches -- Web-based database-driven this, Smart-client semi-connected that, etc. Because of that, we (or our team) tend to make pretty good architectural choices. So good, in fact, that nowadays you don't hear nearly as much concern about application architecture as used to be the case. So good, in fact, that lots of people think you can refactor your way out of the wrong architecture; Andrew's decision is surely painful, but I think it's vastly less painful than architectural refactoring...
Just a quick follow-up... Here's the direct link to Andrew Binstock's blog posting: Restarting the Platypus and the Lessons Learned. Based on a remarkably clear-sighted forensic autopsy of his own project (surely not an easy thing to do!) Binstock enumerates a number of valuable lessons - in addition to the one noted above. E.g. "When it comes to modularity for input and output processing, plug-ins are an excellent design model," and "Unit testing delivers extra value when you're writing difficult code."
Yes, very much worth reading. And absorbing.
