I find it helpful to revisit Steve McConnell's list of classic development process mistakes, and the accompanying case study, at least once every year. Stop me if you've heard this one before:
"Look, Mike," Tomas said. "I can hand off my code today and call it 'feature complete', but I've probably got three weeks of cleanup work to do once I hand it off." Mike asked what Tomas meant by "cleanup." "I haven't gotten the company logo to show up on every page, and I haven't gotten the agent's name and phone number to print on the bottom of every page. It's little stuff like that. All of the important stuff works fine. I'm 99-percent done."
As that old software proverb goes, the first ninety percent of the task takes ninety percent of the time, and the last ten percent takes the other ninety percent.
The Classic Mistakes case study is unnerving to read; it's like those staged re-enactments you see on America's Most Wanted. It's an exaggerated but strangely accurate summary of every pathological software project I've ever participated in, which is to say almost all of them.
This is the phenomenon McConnell likens to Gilligan's Island. Every week there's some new, crazy scheme to escape the island, but at the end of the episode, the castaways always end up stuck on the island for yet another week.
If you don't immediately see the parallels with software development, allow me to reacquaint you with the long, dismal history of software project failure. Classic mistakes are classic because they're so seductive. You have to actively recognize when you're falling into one of these traps. As Steve once said in an interview:
Actually succeeding in a software project depends a whole lot less on not doing a few things wrong but on doing almost everything right.
Which is why you should have every single one of the 36 classic mistakes outlined in McConnell's Rapid Development committed to memory by now:
| People Mistakes | Process Mistakes | Product Mistakes | Technology Mistakes |
|
|
|
|
I've increasingly come to believe the only difference between experienced and inexperienced software developers is that the experienced ones realize when they're making mistakes. The same rule applies to software projects and project managers. If you're not actively scanning through the list of Classic Software Development Mistakes as you run your software project, you have no idea how likely it is you're making one of these mistakes right now.
Making mistakes is inevitable, but repeating the same ones over and over doesn't have to be. You should endeavor to make all-new, spectacular, never-seen-before mistakes. To that end, Steve McConnell highlighted a few new classic mistakes in his blog that he's about to add to the canon, 10 years later:
Steve is also looking for our feedback. He published a Classic Mistakes Survey and invited everyone to participate. If you have any kind of software project experience under your belt, please do.
It's true, the odds are against you. But it's a good idea to periodically remind yourself that maybe, just maybe-- if you can avoid making the same classic mistakes as so many other software projects before you-- you might actually manage to escape from the island one of these days.
I respectfully question your definition of "success."
The definition of success is a legitimate concern, as multiple commenters have pointed out. I've struggled with this before:
http://www.codinghorror.com/blog/archives/000576.html
Jeff Atwood on June 19, 2007 2:54 AMI read "research-oriented development" as "we're not really sure how it works or how we can make it work, but I'm sure we'll figure it out as we go along."
Put that way, it sure sounds like a classic case of running face-first into the fantasy/reality impedance problem.
Gilligan's Island? Maybe, but it's more Twilight Zone - it's entirely possible you've contributed to a flaming wreck so awful that you wish you could sneak into the source repository and erase your initials and any trace of your existence from, but it somehow manages to make money in spite of itself and the users are happy. It's also possible that you've coded up a gem that makes nobody but you happy. Which is the success? Which is the failure?
Without an accurate taxonomy for such fundamentals it's little surprise that software engineering has advanced little since "The Mythical Man-Month" in spite of brilliant minds tackling it.
I'm dealing with 28 out of 36 mistakes listed - what are my chances of successfully finishing this project :) ?
Goran on June 19, 2007 3:47 AMIn a lot of ways, I think "Rapid Development" has stood the test of time rather better than Code Complete. The stuff about mistakes and risks is simply brilliant.
Mike Woodhouse on June 19, 2007 4:37 AMThe biggest problem I've always seen is doing too much at once. I find that projects work best when you try to do a few limited things and do them well. You can always add features later, but do what is absolutely essential and release now, early, and often.
The big difference between a beginning developer and an experienced one is that an experienced one will think about how their code may change in the future. They already thinking what types of changes and modifications that will be added, and write the code to make doing those modifications easy. Beginning developers tend to write their code as if it will never change.
One of the biggest ironies I've discovered in programming is that my best code is when I've lost all my work and I am forced to rewrite it. The rewrite is always cleaner, smoother, and faster than my original work. There are times when one should look at your code, and simply decide it's time to put the effort in not simply patching it, but rewriting it. If you are finding that each new change is causing more bugs than you are fixing, it's time to think about rewriting.
David W. on June 19, 2007 4:46 AMIf you look at it, it seems to me all of the categories ultimately are sub-categories of the People Mistakes category. For example, "research-oriented development" is a direct side effect of what might be called CV (Curriculum Vitae) Syndrome - the desire of developers to work on the "latest and greatest" stuff so they can keep their resumes up to date with the latest or most in demand buzzwords. This seems to be particularly a problem in the Microsoft space.
You can be pretty certain that many web developers are working in a little "AJAX" into their webapps, even when the approach is not indicated (like a small department level, light load intranet app with basic data entry), just so they can get experience with the technology and put it on their resume.
Paul Reynolds on June 19, 2007 6:00 AMDavid hit it right on the head when he suggested that you
do what is absolutely essential and release now, early, and often.
That is a guiding principle for a lot of (successful) software projects - in both the open source and commercial space. Granted, in order to adhere to that advice you'll need avoid making about half the mistakes on McConnell's list.
Steven Harman on June 19, 2007 6:42 AMand yet, i've seen and been a part of more then a few projects which suffer from several of those "classic mistakes" and yet they still succeed brilliantly. go figure...
I've worked in a few large consulting companies in my time.
The problem is management has no incentive to care if a project succeeds or fails. Since they don't have the ability to deliver, they concentrate on 'managing up' and rely on having moved on before the inevitable failure. At these large consulting companies progress is measured by brown-nosing, not results, and the more incompetent and snake-like your nature, the higher you'll rise.
What baffles me is why companies carry on paying them. Unless it's people at those companies (and especially in government departments) who hope to get on the gravy train themselves.
Richard C on June 19, 2007 6:58 AMOne of the worst problems I deal with (and which tends to hit a few of the items on the list) is the idea (from managers) that we can develop a project completely internally, without input from the potential customer(s), surprise them with it, and then, somehow, get them to buy it at a price that covers the development costs, overhead, and some amount of profit. Usually, at best, the product becomes an internal tool that's useful for improving our ability to satisfy the needs of the customer; at worst, though, we end up with budget issues and no cooperation (either internally or from the customer) which leads to an incomplete project that eventually gets cut (after increased time and spending to somehow fix the problem).
I'm also continually amazed at how little input people are willing to give on the user interface of a program in the design phase of a project, and yet they'll still have twenty "little things" they want adjusted in the interface when you finally get a feature complete build in front of them (and then be amazed that what they think of as a minor interface adjustment turns out to be a completely new feature that requires changes to the underlying code). Then there's the idea that we can somehow fix someone else's closed-box software, or give a reasonable estimate of the value of the source code for that software vs. developing a replacement in-house (which we may have to do anyway after purchasing the source for the previous software).
Vizeroth on June 19, 2007 7:08 AMIt's weird. I have worked on projects and I am currently working on a project where many of these mistakes are made. In my current position I've tried to talk to people about it. The other developers nod their heads in agreement but do nothing. Management just doesn't listen at all. We have no clear product concept. Not a single page of documentation, and we're going "live" in a week from now. Yeah we have something but 24 hours after a big meal we can all produce something that smells better than what I'm staring at.
Being aware of these mistakes and the problems they cause is one thing. But it's all really pointless when one is powerless to do anything about it. In the end I give up like the other developers around me. I bury my head in front of the compiler, and hope that I can find a new job before last night's processed dinner hits the fan.
Andrew on June 19, 2007 7:09 AMI've worked in a few large consulting companies in my time.
The problem is management has no incentive to care if a project succeeds or fails. Since they don't have the ability to deliver, they concentrate on 'managing up' and rely on having moved on before the inevitable failure. At these large consulting companies progress is measured by brown-nosing, not results, and the more incompetent and snake-like your nature, the higher you'll rise.
What baffles me is why companies carry on paying them. Unless it's people at those companies (and especially in government departments) who hope to get on the gravy train themselves.
Richard C on June 19, 2007 7:29 AMThis is a very timely posting. A few days ago I posted an update to my classics mistake list on my blog, 10x Software Engineering. Over the 10 years since Rapid Development was first published, we've identified a few more mistakes, and we've also refined the descriptions of a few others.
http://forums.construx.com/blogs/stevemcc/archive/2007/06/15/Classic-Mistakes-Updated.aspx
My company and I are conducting a survey to assess just how classic these mistakes are, i.e., to assess the frequency and severity of occurence. We're looking for volunteers to fill out the survey.
https://vovici.com/wsb.dll/s/10431g2996e
Thanks.
Steve McConnell on June 19, 2007 7:43 AMThe big difference between a beginning developer and an experienced one is that an experienced one will think about how their code may change in the future. They already thinking what types of changes and modifications that will be added, and write the code to make doing those modifications easy. Beginning developers tend to write their code as if it will never change.
I agree with your picture of the beginner, but I'd add another step: The beginner writes code that works now, but is hard to change tomorrow. The experienced developer writes code that works now, can adapt to a few changes tomorrow, but fails a week later, due to too much code that was writte to provide more flexibility.
The expert writes code that works today and refactors it tomorrow and every time he needs to add something, always aiming for the simple and clean solution.
Its easy to find projects that are overloaded with so much unnecessary flexibility that it is impossible to maintain them.
Jrn Zaefferer on June 19, 2007 7:58 AMGreat stuff. Took the survey yesterday. Everyone should, too.
Recently, my management team made no less than 50% of the classic mistakes and a few of the new ones. And guess who got a promotion? Hint: not the developers.
Hopefully, we'll someday reduce the classic mistakes list to an ancient relic of software engineering history.
Cubano on June 19, 2007 8:11 AMI just completed a large scale enterprise software development project for a client. It took over a year. We were on time and under budget with a final bug count that was in the low teens. And I'm talking minor stuff here. The client is absolutely ecstatic and singing our praises all over the place.
The secret? Just two decent programmers. I'm convinced that two good guys can produce a working system when an entire team cannot. The average computer programmer is a real dud and can bring an entire team to its knees. The only way to protect yourself is to use a small team of carefully chosen individuals. As soon as the team gets larger than two people, the probability of bringing in someone who negatively impacts the project goes up dramatically.
I've seen it time and again. If you want to be successful in the software business, think "small".
Matt on June 19, 2007 8:12 AMI think this is good. Basically the bottom line is, pay attention to every detail, large and small. Developers like to just get the big things out of the way and ignore the small details. Eventually the small details pile up into more big details, so it's easier just to get the small details done at the same time you are doing the so called big details.
Steve on June 19, 2007 8:14 AMI was horrified to read this post. Why? One word: Conviction.
I should know better.
Where does the line form to turn in your Qualified Software Professional membership card? I don't think I deserve to carry one anymore.
http://eddiesguy.blogspot.com/2007/06/creating-my-own-personal-hell.html
Mike Hofer on June 19, 2007 9:39 AMI have no idea what is meant by most of these 'mistakes', or why they are so dangerous. I'm on a successful project, live for 2+ years, and we have many (at least as I understand them) of these mistakes. Care to define these?
Skeptic on June 19, 2007 9:51 AMIf, as you claim, your project has "many of these mistakes," I respectfully question your definition of "success.
* On time
* On or under budget
* Users/Customers are happy
* Nobody feels like they had to kill themselves to do it
* The developers feel good about the product they have produced
Those are MY criteria for success, even though we made several of these so-called mistakes during the dev cycles. There are times when it's a near thing of course, and times when it's an utter failure but there have been plenty of success stories to. Enough to make me love my job.
IMO these lists are mis-named. Instead of "classic mistakes" they should be called "classic warning signs". If you see these in your project, watch what your doing or your going to crash and burn but it's by no means a given that you've failed.
I've increasingly come to believe the only difference between
experienced and inexperienced software developers is that
the experienced ones realize when they're making mistakes.
I think that's a fair statement. And what happens when the experienced developers say something about the mistakes? They are troublemakers, not team players, sabotaging the project. Steve McConnell's list is suddenly "academic" and doesn't take into account the "sense of urgency" around the project. Less-experienced programmers are promoted to lead to punish the out-of-step senior people. As the death march proceeds the experienced developers leave the project (or the company). The inexperienced gain some experience -- all of it bad.
Even experienced programmers with ten or more years in the business may never have worked on a successful software project in their career. Most programmers don't know what a well-run project looks like, so every proposed solution seems equally valid.
RE: Skeptic's comments. You sound like a high level manager. lol Yes, many projects go live and work for years despite repeating the classic mistakes. I've been on plenty of them.
However, these mistakes are dangerous because they each have a price tag, in dollars, people, or project success, associated with them. What's the price of undermined motivation? Or confusing estimates with targets? How much wasted effort/overtime will go towards fixing bugs because of unclear requirements? How much money are you (or your clients) spending on rework? These things matter especially in cases where you have a fixed budget or contract. Cost overruns can be very dangerous, wouldn't you say?
Cubano on June 19, 2007 10:53 AMInteresting post and comments. I have been in the pro s/w biz for 17 years and still write code daily (C# by day, IronPython by night). I have been on at least 30 projects over this time frame. Some successful, meaning they made it into production and some not so successful (i.e. never made it to production). That would be my criteria for success.
Not one of these projects was on time or on budget and I can almost name (getting old) which project(s) mapped to which mistake(s) – all 36 and them some. Software development to professional developers seems somewhat straight forward, but to anyone outside this domain, it is a complete mystery, voodoo, or magic.
Even amongst software developer’s we can’t agree on the right approach to designing software. For every requirement there may be 101 ways to design it and for each design there maybe 101 ways to implement it. Toss in the variability around tools/languages and people and is it any wonder that things go wrong?
I used to be an Agile, XP, etc., SEI CMM, ISO 9003, etc. type of guy in various orgs and in the end, I would deem success is that you got your project/product into production by any means possible. I have yet to see one approach better than any other. In fact, I have had more success in just outright gluing a solution together made up of parts/components/source searched on Google. Sad isn’t it? And I am a big fan of industrializing software development!
As John Walker, inventor of AutoCAD in 1982, said, “Absolutely the only way I know to succeed with an innovative product is to throw something together quickly, push it out the door, persuade some lunatic early-adopters to start using it, and then rapidly evolve it on a quick turnaround cycle based on market acceptance and driven by a wish list from actual users.”
In a lot of respects, I believe that still holds true today, some 25 years later. What does this say about our profession?
Skeptic,
If, as you claim, your project has "many of these mistakes," I respectfully question your definition of "success."
Mike Hofer on June 19, 2007 11:10 AMI think the number 1 is always communication. If the communication breaks down, the project is doomed. If you have good communication between each of the people of the team, then you can deal with the other 36 problems.
Tim Underwood on June 19, 2007 11:11 AMThe only issue with your comparison is the pic you posted! Who would NOT want to be Gilligan stuck on that island with Mary Ann and Ginger (in swimsuits to boot)????
Ok, so maybe I missed the point...
Dave on June 19, 2007 11:33 AMCan someone explain to me why Research oriented development is bad? Does it mean that researching new technologies while developing is bad or does it mean that developing your product as a "research product" is bad?
What did I miss?
Sushant Bhatia on June 19, 2007 12:51 PMResearch is a great thing - it just means don't go pinning the success of your project down to assuming you can invent some great new technique within a [small] period.
For an example, take a look at the vista timeline.. Initially it was crammed full of great new technologies and gradually kept slipping cos they weren't working and then they pretty much all got stripped out of the release and everyone laughed :)
chrisb on June 19, 2007 1:09 PMThis is the phenomenon McConnell likens to Gilligan's Island.
The only difference is that unlike Gilligan who's stuck in a tropical paradise with the likes of Mary Ann and Ginger, the developer is stuck in a flourescent lighted cubicle with other sweaty engineers.
Haacked on June 19, 2007 1:15 PMWell,
I loved this article - it's so true...
Like with most things though, it's easier to point out the flaws with the development process - and playing God over idealistic approaches can also get a bit too ideological as well.
As a developer, I feel I have to be a frickin theologian sometimes to join the cult of "good software development". My quote comes from Frank Zappa - Joe's garage:
"After all, all I ever wanted to do was to play my guitar like rin-tin-din-tin-dinny-dee-duh-deedle-deedle-dee..."
;o)
Steve on June 20, 2007 2:12 AMI define success as a project that has met the customers needs and provided a positive net value economically to the company.
I don't put much stock in budgets or deadlines. When the original estimate was done for the project, it was fairly accurate to what eventually happened, but the project sponsors, in order to get the project approved, cut the time and money in half. Naturally, this resulted in lots of stress, and extensions, and so on, but in reality, this was really just so much theater. Not for those of us slaving on the software, and trying to be heroes, and feeling there was no communication, and all the rest, but for the managers, this was how they felt they weren't wasting their money. It allowed them to maintain (or at least the feeling of) control.
Ultimately, I think the project was successful just because there was a real business need for the software.
Skeptic on June 20, 2007 6:44 AMThe really sad part is that even if we get it figured out and finally get off the island, we just hop on another cruise and get stuck on a whole new island. Wait, maybe RoR is the solution.
Joe Brinkman on June 20, 2007 7:49 AMI have problems with a project at present.
Thank fully it is not commercial, this makes a mighty difference.
Progress can be placed on Hold until the design is corrected.
Hi Jeff!
I gave a speech last night about the classic mistakes (it was the first speech of my life!) and when I came back home I opened my RSS reader and I saw your post on the same topic. What a coincidence! Classic mistakes still happen in our lives and they still have a huge impact on the projects' schedule and on the overall quality of our products.
I am very glad that Steve decided to re-evaluate them. It was just about time! Meanwhile, I decided to start a series of posts in my blog on the subject and I will be glad if you take a look on it and give some comments.
Best wishes,
Mike
Jeff, have you really become so PC that you delete benign comments about Ginger and Mary Ann?
If your answer is that they were "irrelevant", I could argue that many comments could be labeled as such.
"I've increasingly come to believe the only difference between experienced and inexperienced software developers is that the experienced ones realize when they're making mistakes."
I am reminded of the old saw, "Engineering experience is proportional to the dollar value of all equipment destroyed."
Karl Meissner on June 20, 2007 12:29 PMHumans learn by trial and error, over time comes experience by armoring against these conditions (and lots of overtime). However its just the nature of our industry, many times its charting new ideas and new systems that are advancements, its not always pretty.
In fact if you ever wake up in a project that doesn't have some of these problems, you are dead or dead man walking and you have just lost your mind.
I don't want heroic programmers and innovators, I want careful, conservative spoon fed slackers.
Paul Allen and the Woz were Batman. And when they left Gilligan's Island the show was over.
ryan on June 21, 2007 2:03 AMAs I make money from fixing broken projects, I suppose I should be glad that people don't take enough notice of McConnell.
There are other amusing books which are good for specific things (eg Brooks' MMM / Silver Bullet, or "Deathmarch"), but McConnell is broader and more practical.
The root cause of most project problems I've had to fix has been stupidity. Sometimes it comes from hubris; sometimes it's naivety; other times corruption. Most failed projects have failure written into them from the start.
I'm a game-player, so I don't do projects which are bound to fail.
I'd much rather wait until failure, then either shut the thing down or save it depending on the nature of the failure.
Last summer I read the "The Mythical Man-Month" by Frederick Brooks Jr. (first published in 1975). I am amazed at how true his book is today was it was when he first wrote it.
Today I still see all those problem, (and those 36 points described above). I think the number one and number two problems of failed projects are
1) communication (or lack there of)
and
2) honesty. Both talking to management and honesty from management.
dave n
dave n on June 21, 2007 7:12 AMI think the saying may have been mistyped. "the first ninety percent of the task takes ninety percent of the time, and the last ten percent takes the other ninety percent" It is saying that the whole project is 180%. It should read "the first ninety percent of the task takes 10 percent of the time, and the last ten percent takes the other 90 percent".
It just sounds funny if a person has not heard the saying.
"It just sounds funny if a person has not heard the saying."
Umm, it's supposed to sound funny. It conveys that idea that the totality of the project (100%) was miscalculated from the start.
Steve Garvey on June 22, 2007 4:53 AMThe quote, as I remember it from McConnell's Code Complete is:
"The first ninety percent of the project takes the first ninety percent of the time. The remaining ten percent of the project takes the other ninety percent of the time".
Yes, it is intended that the "times" don't add to 100%.
As a point of interest to myself, why did McConnell remove the qoutes in the latest edition of Code Complete? I found that I would go back to the book looking for a quote I remembered and then rediscover some section of the text that was appropriate to my problem at hand or that I needed a refresher in. Without the quotes, I find I don't return to the book as often.
Steve updates his list of classic mistakes for 2008
Jeff Atwood on May 14, 2008 6:06 AMRetards
ash on November 4, 2008 8:23 AMI'm getting cynical about some of those points.
Does it make me an "Uncontrolled problem employees" when I roll my eyes and laugh every time management commits "Push me, pull me negotiation", defines "Overly optimistic schedules", "Shortchanges upstream activities" and other sins?
Probably. I'll try not to laugh next time. :D
One thing I did not expect to learn about when I finished Uni and started my career: human psychology!
Stu Thompson on February 6, 2010 10:08 PMPaul: 'For example, "research-oriented development" is a direct side effect of what might be called CV (Curriculum Vitae) Syndrome - the desire of developers to work on the "latest and greatest" stuff so they can keep their resumes up to date with the latest or most in demand buzzwords.'
That's a little heavy on the cynicism. I seriously doubt that many developers have their resume in mind when they decide how to solve a problem, especially considering that any potential future employer is going to care more about the project requirements and success, not what technologies it used.
You want developers who love to be on the bleeding edge. They are motivated and interested, two things that are very hard to find in the industry. You just have to keep them in check, and relegate the experimentation to less critical projects.
Jrn: "The expert writes code that works today and refactors it tomorrow and every time he needs to add something, always aiming for the simple and clean solution."
* Incompetent developers code without a plan (no flexibility).
* Mediocre developers code with an arbitrary, contextually-irrelevant plan (confusing, unusable flexibility).
* Expert developers are aware of their context, can see realistic future points of failure and areas of change, and plan accordingly (actual flexibility). In some (rare) instances, "accordingly" may even mean "not at all".
* Charlatans insist that they have a one-size-fits-all plan, and redefine "success" based on the context. They offer the same long-term productivity as incompetents, but come with the additional overhead of dysfunctional relationships and other management headaches.
To Skeptic and Sushant Bhatia, read the links at the top of the page. They explain what these things mean.
http://www.stevemcconnell.com/rdenum.htm
http://www.stevemcconnell.com/rdmistak.htm
Are we learning from these mistakes? It seems to me that the list is expanding, not contracting.
Switch to antoher career if you want to get off the island.
I loved the Robot episode (of Gilligan's).
Jon Raynor on February 6, 2010 10:08 PM
You know what the biggest problem in coding is these days, that far surpasses any of these?
The fact by US law, a CEO - and therefore indirectly, all management under that CEO - must always act in the best financial interest of the stock holders, unless forbidden by the stockholders from doing so. Should the CEO favor long-term or short-term profit? That question ends up answered by another: Will today's stock holders be stock holders in a few more quarters?
Sadly, the mistakes of the past are so tempting because more often than not, they get crap on the shelf, albeit in a shoddy condition. In a market where companies routinely plaster their products with disclaimers, warnings, and license agreements making it clear that you shouldn't ever rely that the product even function, let alone function well, how the hell is anyone ever supposed to expect quality?
The modern IT consumer ends up raving happy just to get a product that works out of the box, works properly, and continues to work. That is to say, the customer is so used to getting shafted by the industry that shoddy goods are the norm and something that ought to be merely acceptable is regarded as excellence.
The opposite happens from time to time, however... customers who've totally been had with an overpriced IT bauble will rant and rave about some new feature they claim to love to hide the shame of purchasing a product that, while it has that excellent new feature, completely fails to deliver up to expected standards in its other base functionality.
Programmers whine and bitch like children about crap like the last 10% of the job being 90% of the effort, but face facts: you people ship stuff with bugs anyways, so its complete bullshit to count that last 10% as part of the development time; its more like, part of the "We sold you broken shit and now we have to fix it after the fact" service call.
Take a look at how many days, months, years go into bringing something to market from conception of the idea in a field like medicine. It doesn't exactly take too much time to go from "chemical in a test tube" to "bound agent in an unlicensed pill", but take a look at the quality control efforts, product testing, approvals procedures, the massive time, effort, and expense involved in seeing if its worth it at all, it its going to work right, learning all the kinks and oddities of the product.
Outside of NASA and the medical field, where else has this sort of attention ever been paid to software development? Because THATS how its done RIGHT, when its done RIGHT. The rest of you whiners are just selling broken junk, and you know it.
Jason Kennerly on February 6, 2010 10:08 PMThe comments to this entry are closed.
|
|
Traffic Stats |