Author Topic: Good coding practices  (Read 1078 times)

Offline pixlepix

  • Level 12
  • *
  • Posts: 90
  • Reputation: +0/-0
    • View Profile
Good coding practices
« on: June 10, 2011, 04:40:53 PM »
So, I know all the code syntax, and I have had experience building code. But, my question is what is the best practices for a large product.

Offline Freyr

  • Level 7
  • *
  • Posts: 30
  • Reputation: +1/-0
    • View Profile
Re: Good coding practices
« Reply #1 on: June 10, 2011, 05:40:37 PM »
Well, there are coding standards, of of which is PEAR. See: http://pear.php.net/manual/en/coding-standards.php
The main thing one had to do is try and make the application as fast and solid as possible.

That generally means using methods like mem-caching to store data for faster usage. Others are only reading chunks of data to make a script faster.
There are many, depends on the application you are building I'd say.
// this is a comment

Offline Nox

  • Level 35
  • **
  • Posts: 767
  • Reputation: +12/-2
    • View Profile
Re: Good coding practices
« Reply #2 on: June 11, 2011, 02:19:20 AM »
Coding standards are imho something else - mostly a naming and whitespace conventions (I use these http://nette.org/cs/coding-standard (not underscores, camel/Pascal)), but they're useful too

That being said I agree caching is a good way to go... also lazy/conditioned loading - generally do/load only what's necessary and store it (or store some rarely changing base)

'm not totally sure what you're asking, if the answer can include: framework(s), versioning (git), automated testing (phpunit, selenium...), scrum (scrumdo), automated deployment (capistrano, phpfog deploy...), perhaps some code generation (but careful since it can mean something's bad (copy&paste)), don't fear using 3rd party (not invented here)
« Last Edit: June 11, 2011, 02:21:49 AM by Nox »
Meet us at an IRC irc.freenode.net #bbg as well
https://vimeo.com/36579366 (a must-watch) | Join BOINC - no longer a hype, but you can help never the less

Offline 133794m3r

  • Level 22
  • *
  • Posts: 265
  • Reputation: +2/-0
    • View Profile
Re: Good coding practices
« Reply #3 on: June 11, 2011, 01:27:28 PM »
I use a style based upon the following. http://www.kernel.org/doc/Documentation/CodingStyle I also use git, with a cron job that does commits twice a day, along with my IDE using local history. On top of this, I've sat down and decided what's going to go where. Like what functions go into what source files and where they're going to be located.

You should also, figure out how you're going to call your things, so that you can more easily remember them. And then create little functions to help yourself. My project's not big(yet), according to the cloc utility http://cloc.sourceforge.net/ It's 19,671 lines at the moment excluding scripts which do cron related things. Also, be sure to use a consistent naming scheme for _everything_. Irregardless of the language you're working with, keep it as one style across everything so that you can better understand your own codebase.

Also of that 19,761 lines, according to cloc ~1k of it is Jquery, Jquery ui, and Jquery ui's css. So the rest is all hand written code that I've done. I'm not using any framework, or similar third party library inside of my project(outside of those that I've just said). All of those are of course minified (at the moment). None of my code is minified as it's still being worked on.

Be extremely strict in your coding practices also, so that your code doesn't turn into spaghetti code. Also something that I need to do, but have not yet done, is the following.
Code: [Select]
if(constant==variable){
    //do magic code
}

since it'll lead to less overall bugs inside of your code. Beyond that I don't have anything else to say about it, beyond just commenting your code with enough information.

I don't do any of that pointless "object oriented" crap, so i have no comments there and thus good luck if you're one of those people.
« Last Edit: June 11, 2011, 09:47:15 PM by 133794m3r »

Offline gnoh

  • Game Owner
  • Level 15
  • *
  • Posts: 127
  • Reputation: +2/-0
    • View Profile
Re: Good coding practices
« Reply #4 on: June 11, 2011, 01:59:10 PM »
I like how you failed to format your code insert as per the coding style you supposedly follow :P

Offline Nox

  • Level 35
  • **
  • Posts: 767
  • Reputation: +12/-2
    • View Profile
Re: Good coding practices
« Reply #5 on: June 11, 2011, 02:37:57 PM »
133794m3r:
- how do you generate commit messages if you commit periodically? I think it's much better to perform logically grouped commits (for example "refactored combat classed") than commit whatever files are changed in the moment with no message
- what do you mean by that snippet, that if-statement? (magic?)
ignoring the oop note :)
Meet us at an IRC irc.freenode.net #bbg as well
https://vimeo.com/36579366 (a must-watch) | Join BOINC - no longer a hype, but you can help never the less

Offline Mutant

  • Level 10
  • *
  • Posts: 55
  • Reputation: +5/-0
    • View Profile
    • Kingdoms
Re: Good coding practices
« Reply #6 on: June 11, 2011, 06:03:03 PM »
The main thing one had to do is try and make the application as fast and solid as possible.

That generally means using methods like mem-caching to store data for faster usage. Others are only reading chunks of data to make a script faster.
There are many, depends on the application you are building I'd say.

Strongly disagree with this. Make your code solid, sure (the exact definition of what qualifies as "solid" is debated, but I think having a good automated test suite is pretty critical). But making your code faster is premature optimisation, commonly referred to as the root of all evil. Your code should only be as fast as is necessary.

Unless you're serving upwards of a few hundred requests a second, this is probably nothing too sophisticated. You might need to optimise the odd query here, add an index there, but besides that you don't need anything fancy. And the decision to optimise should be based on where you actually *need* it, not on where you think "hmm, this could be faster if I just add these funky hacks..." The reason for this is the fancy stuff starts to make your code difficult to work with. It's unnecessary complexity.

Offline 133794m3r

  • Level 22
  • *
  • Posts: 265
  • Reputation: +2/-0
    • View Profile
Re: Good coding practices
« Reply #7 on: June 11, 2011, 09:27:06 PM »
I like how you failed to format your code insert as per the coding style you supposedly follow :P


I thought i said it was similar... Oh well, it's close to that. I use it as it is shown. That's what I've done with my code style. I've written up a html document if people want me to upload it. It's my own personal coding style.

@nox

The first thing is for my rsyncs which goes to my git commits folder and syncs it back to my little networked storage drive. The first thing? Well instead of doing something like the following.

Code: [Select]
if($variable===1){
    //do some magic code
}

you'd do the following.

Code: [Select]
if(1===$variable){
    //do some magic
}

That's how you'd do it, and thus since you cannot assign a constant the value of a variable ,it's always going to fail and throw a bug instead of just going along.

Onto the next thing. Here's my shell script(might work with dash, but i always use bash).

Code: [Select]
#!/bin/bash
variable=$(date -u);
project_location="/home/username/project_name";
cd $project_location;
git commit . -m "Bidaily commit on $variable";

The bit about the cron-jobs I'm sure that you can find documentation about it.

I'll also edit my previous one and state that I based it off of it. It's not exactly like it, since I dislike wasting space. And as stated, if someone would honestly want to see the HTML file which I've written up to basically give to others who might be in the future working with me so that they know the coding style, I'll attach it.

I have it setup to commit every 12hrs(incase I don't) since I normally commit about that often. With something new to make it worthwhile. I've got ~30 or so scripts that I've written to make working with my computer a lot faster and easier. Keybindings, and custom scripts. my life is a lot simpler.

Also I just pull up a terminal ctrl+, then type git commit . -m "refactored combat classed", hit enter. And I'm done.
« Last Edit: June 11, 2011, 09:46:22 PM by 133794m3r »

Offline Nox

  • Level 35
  • **
  • Posts: 767
  • Reputation: +12/-2
    • View Profile
Re: Good coding practices
« Reply #8 on: June 12, 2011, 01:43:22 AM »
Strongly disagree with this. Make your code solid, sure (the exact definition of what qualifies as "solid" is debated, but I think having a good automated test suite is pretty critical). But making your code faster is premature optimisation, commonly referred to as the root of all evil. Your code should only be as fast as is necessary.

Unless you're serving upwards of a few hundred requests a second, this is probably nothing too sophisticated. You might need to optimise the odd query here, add an index there, but besides that you don't need anything fancy. And the decision to optimise should be based on where you actually *need* it, not on where you think "hmm, this could be faster if I just add these funky hacks..." The reason for this is the fancy stuff starts to make your code difficult to work with. It's unnecessary complexity.
The quote about optimization is used out of context and quite overused, see http://programmers.stackexchange.com/search?q=premature+optimization
As long as you use some framework (which imho you should), caching becomes quite easy so there's not really an argument against usage in performance critical areas, which you can profile, but in practice you often know what it is...it's no use optimizing script sending forgotten password but optimizing combat calculations or something that runs on every request surely pays off.

And lazy loading brings close to none additional complexity and decreased readability, yet it's a very good tool.



@133794m3r: ah, okey, that's provided you don't use IDE and are prone to this error, usually it's easy to spot the difference between = and ===

besides it relies on using not-assible expression - thus usually a magic value - in the condition which is highly discouraged and also error-prone (unless they are constants, not literals; still, constants are difficult to test with, replace etc.)

Periodic commiting of a random bulk of files is a very bad git practice imho... how you're gonna do reverting? branching? and readability is none
take a look at this https://github.com/nette/nette/commits/master?page=3 the commits are just clear, easy to undo whatever change...
I use IDE and can do 40-80 commits a day and don't feel it hampers my speed anyhow, it's just a few seconds each time
Meet us at an IRC irc.freenode.net #bbg as well
https://vimeo.com/36579366 (a must-watch) | Join BOINC - no longer a hype, but you can help never the less

Offline 133794m3r

  • Level 22
  • *
  • Posts: 265
  • Reputation: +2/-0
    • View Profile
Re: Good coding practices
« Reply #9 on: June 12, 2011, 02:19:48 AM »

@133794m3r: ah, okey, that's provided you don't use IDE and are prone to this error, usually it's easy to spot the difference between = and ===

besides it relies on using not-assible expression - thus usually a magic value - in the condition which is highly discouraged and also error-prone (unless they are constants, not literals; still, constants are difficult to test with, replace etc.)

Periodic commiting of a random bulk of files is a very bad git practice imho... how you're gonna do reverting? branching? and readability is none
take a look at this https://github.com/nette/nette/commits/master?page=3 the commits are just clear, easy to undo whatever change...
I use IDE and can do 40-80 commits a day and don't feel it hampers my speed anyhow, it's just a few seconds each time

I do it out of security mostly. I don't want to end up fucking up some code and then messing up my code. And I don't get what you mean by 'commitng a random bulk of files'. So you're telling me that you don't commit your changes? You just commit bits and pieces of your code? I always commit all of my changes when I do a commit. If I have worked with 20 files, I commit the changes in all 20 files. I don't know how me tracking all changes to all of my code is going ot make it any worse.

Git is made for committing, branching, merging, and also fairly fast searches for content. I commit twice a day out of habit, since I don't want to trust things. I really really doubt that there is anyone out there just committing one or two working files. If there are, then I will be very surprised.

The constant==variable thing is mostly a "just in case" type of thing. Since it is very easy to see, but you never know. It's one of those 'better safe than sorry things', I keep telling myself I'm going to be doing it. But I continually keep on doing the it the old way. The same way I continue to use while loops instead of a for loop when the performance and readability of the resulting code is about the same. Even though, I know that me using a while loop is more likely to end up in a never ending loop due to some stupid mistake.

I usually make my own/actual commits happen when I've accomplished something(outside of the automatic ones). The last one I committed, was for the first version of tool/page that shows/allows one to edit/create npcs/mobs. 40-80 commits throughout an 8hr period vs 2 big commits that are automatic(in case I forget to commit), and NetBeans Local History doesn't work, is not a huge deal for me. I usually end up with ~700-800 changes in a day(before I did the every 12hrs.) Now I average ~100-500.

Going outside of 'coding mode' to have to commit. Is a real drag, it requires me to stop what I'm doing and remember to run some script, or pull down some menu inside of the NetBeans(if i'm going to use jgit). It's a lot more work than just continuing on my coding excursion. I'm the type of person who usually sits down and gets into the zone for ~4-5hrs and I do nothing but code during that time. Doing constant commits that I have to manually do, I'd end up how I did last time.

I made some really stupid mistake on my code, and wanted to go back to the last known working state. Well according to git, I hadn't remembered to commit in five days. So instead of attempting to work my way out of the mess. I threw away five days of work. Now I'll lose at most 12hrs, if I do something stupid again.

As for readability, I can just look at my commits once I'm ready for that. This is mostly a precaution, as with all things. It's best to take precautions instead of ending up sorry. I want multiple points of failure for my system. Any single point will end up screwing me over. My actual commits are always detailed enough. Usually one-two sentences describing what has changed since hte previous one. Usually a big change.

I also am always working in the "experimental" branch. Once I know that everything is working(I usually do this every saturday), I merge it with the Unstable branch. And currently it just stays there, later one, after being there for a little while. It'd go up on the Unstable path, and then finally go onto Testing, and then end up in "stable."

Code goes from Experimental->Unstable->Testing->Stable
« Last Edit: June 12, 2011, 02:34:41 AM by 133794m3r »

Offline Nox

  • Level 35
  • **
  • Posts: 767
  • Reputation: +12/-2
    • View Profile
Re: Good coding practices
« Reply #10 on: June 12, 2011, 03:03:36 AM »
I commit all the changes made in a certain logical section. The phrase meant I don't see as a good to send changes in combat, tweaking config values, playing with CSS, changing logger, adding new code for areas - all that bulked in a one big commit with either some generic vague messages or a very long one.
--- what if you want to roll back only all the combat changes? you'd have to do it manually file-by-file...
If it's not possible maybe the code is too coupled or repeated...

With the new GIT integration into Netbeans you don't go outside IDE, you just click and it's done... don't you want to give your brain a few moments to rest? Perhaps the coding would go better if done in a more relax way ... when dived in, you perhaps type more lines but when thinking about it more, perhaps you could have it written in a different way and do the same with less typing and re-usable in future

Take a look at github into their repos, you'll see they do it similarly as I discribed ... trying one more time: https://github.com/doctrine/doctrine2/commits/master

But the process you describe at the end is interesting, I like that ('m using this one http://nvie.com/posts/a-successful-git-branching-model/ ... and plan to check the stability per entity, not in bulk...haven't been writing tests but 'm gonna do that now and then continue by using TDD)

You can do infinite loop with for too
« Last Edit: June 12, 2011, 03:10:49 AM by Nox »
Meet us at an IRC irc.freenode.net #bbg as well
https://vimeo.com/36579366 (a must-watch) | Join BOINC - no longer a hype, but you can help never the less

Offline Zeggy

  • Global Moderator
  • Level 35
  • *****
  • Posts: 1,187
  • Reputation: +13/-4
    • View Profile
Re: Good coding practices
« Reply #11 on: June 12, 2011, 05:31:43 AM »
If you're going to auto-commit every x hours, you might as well use a backup tool and not git, since you are not using git the way it should be used. You're just creating copies of your working code.

Quote
You just commit bits and pieces of your code? I always commit all of my changes when I do a commit. If I have worked with 20 files, I commit the changes in all 20 files.
Yes, you separate your commits into distinct bits of which files you've changed for a particular feature. That's what the staging area is for. Otherwise you might as well use svn.


Quote
I made some really stupid mistake on my code, and wanted to go back to the last known working state. Well according to git, I hadn't remembered to commit in five days. So instead of attempting to work my way out of the mess. I threw away five days of work. Now I'll lose at most 12hrs, if I do something stupid again.
You should be making commits all the time. Forgetting to commit in 5 days is bad practice, version control should be well integrated into your coding process. You don't always need to commit only after a big feature is done. Make commits all the time, even for small stuff.
« Last Edit: June 12, 2011, 05:34:20 AM by Zeggy »

Offline Chris

  • Game Owner
  • Level 35
  • *
  • Posts: 2,217
  • Reputation: +28/-1
    • View Profile
Re: Good coding practices
« Reply #12 on: June 12, 2011, 02:34:27 PM »
Don't get crazy over "good coding practices". I have been coding for more than 20 years and everytime they talk about proper coding style I hear someting completely new. So, it means, that the ultimate best practice that was invented before turned out to not be the best one in reality :D The odds that the current best practice will turn out to be not so good are extremely high :)

But from all the practices that I have heard about over the years, these are the ones that sticked to me:
- there is almost never a reason to use goto :)
- linear coding style is inferior to procedural coding style (but linear style is sooo ancient that I would be hugely surprised if you know what I'm talking about :D)
- encapsulation is good
- knowing OOP might be useful, even if you almost never use it (I mean here a "real" OOP, not creating classes and objects and pretending that's OOP)
- waterfall methodology is inferior to agile methodology in 98% of cases
- extreme programming's pair programming technique is surprisingly efficient
- crunch time is for noobs and never works
- deadlines ALWAYS reduce the overall development time at least 3 times
- never, ever, make a release before going to bed, do it at the morning and monitor for bug reports; do it regardless of how much testing you did (that's mine invention :D)
- majority of programmers and designers sux, are insanely inefficient, slow and will never finish any project; if you are doing things like majority do you are in a big trouble (that's again mine :D)
- perfection is for losers
- underdesigning is bad
- overdesigning is bad
- do not forget about the user, he/she is the reason you are doing all this (your creative desires come second)
- but do not forget about yourself too, doing things you like might result in better performance and final quality (but if you are a coder it means you enjoy the very process of coding regardless of what it is, so it is not so important)


Offline 133794m3r

  • Level 22
  • *
  • Posts: 265
  • Reputation: +2/-0
    • View Profile
Re: Good coding practices
« Reply #13 on: June 12, 2011, 03:36:18 PM »
I commit all the changes made in a certain logical section. The phrase meant I don't see as a good to send changes in combat, tweaking config values, playing with CSS, changing logger, adding new code for areas - all that bulked in a one big commit with either some generic vague messages or a very long one.
--- what if you want to roll back only all the combat changes? you'd have to do it manually file-by-file...
If it's not possible maybe the code is too coupled or repeated...

With the new GIT integration into Netbeans you don't go outside IDE, you just click and it's done... don't you want to give your brain a few moments to rest? Perhaps the coding would go better if done in a more relax way ... when dived in, you perhaps type more lines but when thinking about it more, perhaps you could have it written in a different way and do the same with less typing and re-usable in future

Take a look at github into their repos, you'll see they do it similarly as I discribed ... trying one more time: https://github.com/doctrine/doctrine2/commits/master

But the process you describe at the end is interesting, I like that ('m using this one http://nvie.com/posts/a-successful-git-branching-model/ ... and plan to check the stability per entity, not in bulk...haven't been writing tests but 'm gonna do that now and then continue by using TDD)

You can do infinite loop with for too
I already know that a lot of people do tons of constant commits. But constantly committing every few moments makes little to no sense to me. I do commits when something changes that's worth noting. If I add some function, that's not worth a commit. If I actually write a set of functions that are worth my time I commit.

I commit when I do one thing. I don't constantly working on a few dozen things at once. The twenty files is mostly out of a generalization. For example, I separate my files into logical groupings of functions. So I don't juts have a single functions.php I have authentication, ajax, sanitization, database, .... So those twenty files might just be me adding things that I need to do.
If you're going to auto-commit every x hours, you might as well use a backup tool and not git, since you are not using git the way it should be used. You're just creating copies of your working code.

Quote
You just commit bits and pieces of your code? I always commit all of my changes when I do a commit. If I have worked with 20 files, I commit the changes in all 20 files.
Yes, you separate your commits into distinct bits of which files you've changed for a particular feature. That's what the staging area is for. Otherwise you might as well use svn.


Quote
I made some really stupid mistake on my code, and wanted to go back to the last known working state. Well according to git, I hadn't remembered to commit in five days. So instead of attempting to work my way out of the mess. I threw away five days of work. Now I'll lose at most 12hrs, if I do something stupid again.
You should be making commits all the time. Forgetting to commit in 5 days is bad practice, version control should be well integrated into your coding process. You don't always need to commit only after a big feature is done. Make commits all the time, even for small stuff.
Doing an infinite loop in a for is much harder though. for($i=0;$i<$something;++$i) is much much less likely to result in an infinite loop than while($i<$something) Since I'm doing my incrementing/decrementing inside of the initial thing. And thus that's already there. The likely hood of the infinite loop happening is much much much less.

The commits that I do, are always things I find worthwhile. And git is git, it's there to be used as a thing to go back through the history of the codebase. That's what I use git for. So that I can look back at my code, and find little things, find out when a bug was first introduced and other such things. Constantly doing commits every couple of minutes, sounds just as bad as doing automatic commits every hour. I use git because a) it's fast as crazy. b) it's fast as crazy. c) it's cryptographically secure. d) it is extremely extensible and fast as hell. e) I can distribute everything with everyone at all times.

Also netbeans commiting is insanely slow. It's ungodly slow, the entire IDE is slow. The only reason I still use it is for a) local history and b) because it supports PHPDOC documentation inside of my apis. Along with it's code completition, I'm stuck with it. If it was faster, it'd be a lot easier to do a commit within itself. But since it is not, I cannot. If there was a good IDE for PHP/JS/HTML/CSS for linux that wasn't java based, and also included the features that netbeans did. I'd be on it instantly, but there's not. It's just kind of well there. I'm the type of person who hates waiting for anything with any of my tools. Waiting for them to do things, and also having to sit there whilst it's trying to do it's thing is annoying beyond belief.

I see no reason to ever use svn since that'd require me to have a server setup for it, whereas git is fast and does what I want it to do. Constantly commiting is not something I ever see myself doing. SCM is there to help me from screwing up too majorly. All of you can probably sit down and constantly do little tiny commits with things that are identical for every single change. Like "add function x to file y for feature z." and constantly do that. But it's never going to be in my workflow. I do commits when there's something worth committing. If I've not done something that was important enough to commit, I don't use it.

The every 12hr commits is setup at 6am and 6pm. Since I'm never actively coding during both of those times, I always know that something was saved. The localhistory is in netbeans is something that I found to be extremely valuable. Since it does something similar with how it works. I may be using git wrong, according to you two but it works. That's the key thing here, that it works.


A working system, is much more important than some 'best practices' that a lot of you apparently like to use. I do my commits with a single line, then a paragraph explaining them in more detail below that first summary. The commits are detailed enough so that I can get them. And what are you talking about creating copies of my working code? I'm commiting changes. It's not a copy at all, it's a diff of what's changed. A backup tool will backup everything that's changed in a huge file rather than a simple diff.

As to Nox, I never do separate things at once. For example, yesterday, I was working on NPCs, that's all I did. I commit every time I change what I'm doing. Since when I change what I'm doing, I'm changing my workflow. And every change of a workflow is a commit.

At the end of the day, git works for me as it is. I can easily revert changes, I can track functions across its history. And that's all that matters. If it's not 'best practices' according to someone else, that doesn't matter. Because they're not the person who's using it. If we were going by a majority ideal here, then I should be writing my code with classes, objects and other frivolous things. I also should be using camelCase for everything. Since that's what the majority of people are doing. What the majority wants to do, and what's best for every person is not always the same thing. And that's how it is here.
« Last Edit: June 12, 2011, 03:42:06 PM by 133794m3r »

Offline Mutant

  • Level 10
  • *
  • Posts: 55
  • Reputation: +5/-0
    • View Profile
    • Kingdoms
Re: Good coding practices
« Reply #14 on: June 12, 2011, 08:56:05 PM »
The quote about optimization is used out of context and quite overused, see http://programmers.stackexchange.com/search?q=premature+optimization
As long as you use some framework (which imho you should), caching becomes quite easy so there's not really an argument against usage in performance critical areas, which you can profile, but in practice you often know what it is...it's no use optimizing script sending forgotten password but optimizing combat calculations or something that runs on every request surely pays off.

And lazy loading brings close to none additional complexity and decreased readability, yet it's a very good tool.

Sure, saying "premature optimisation is the root of all evil" is a simplification, but it's one that's appropriate for those at the intermediate stage (or earlier) of their programming career. The original said:

Quote
The main thing one had to do is try and make the application as fast and solid as possible.

That (ignoring the 'solid' part) is just plain wrong in a general context. Speed of execution should not be your first priority. That's not to say you should ignore it, but readability (or, moreover, understandability) of your code should trump it wherever possible. Non-invasive strategies such as caching should, of course, be used where they need to be. And you should obviously optimise your code where you can do so in a way that doesn't add unnecessary complexity, or when something genuinely isn't fast enough (as opposed to just "fast" - there's a critical difference).

Far too many coders sacrifice understandable code for speed when they simply don't need to. They then end up with a mountain of technical debt they have no hope of being able to pay off. This is why it's bad to optimise prematurely and/or unnecessarily.

(I won't even mention the fact that it's also better to defer optimisation as long as possible, so that you have a better understanding of how best to optimise something. Or the obvious fact that if you optimise something that doesn't need to be, you're simply wasting time).

Edit: The full quote is:

Quote
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.

That, and many of the discussions you linked to on SO make my point much more elegantly than I have.
« Last Edit: June 12, 2011, 08:59:34 PM by Mutant »

 


SimplePortal 2.3.3 © 2008-2010, SimplePortal