Seriously.
We all remember (or have heard of) the GOTO debate. The practice was pretty normal for a long time, but the times have somehow changed in a way that now it is near-prohibited and a sign of bad taste.
Will we see some other common techniques go that way?
In other words, if in near future there emerges a game-changing paper like "GOTO considered harmful" and rocks the programming world what exactly could it "consider harmful"?
Possible technologies / approaches coming to mind:
[suggested in the answers]
P.S. Crazy / dreadful predictions are welcome too (when supported with at least some arguments).
[NOTE: this is not a question of personal hatred but of possible common practice change.]
Patterns
Instead of thinking on how to solve a problem in the most cost-efficient (or most elegant) way, more and more people are working hard on figuring out what pattern to apply in each particular case (I've heard several times already that "programming is all about patterns").
This is not only causing suboptimal decisions but is also significantly decreasing the level of "creative entropy" (similar to what Google's suggest is doing).
"considered harmful" is also a pattern :)
Added 2010-11-12: Cumulative reply to patterns advocates: I am not against patterns as a reflection of a natural human brain's way of learing by generalizing. Patterns are also good when used to compress the human language (programmers' professional jargon, as one my friend noted). I am against this [1].
[1] http://dropsafe.crypticide.com/article/1928Hmm the next great evil? Here is something I see abused all the time:
This will particularly bear out as concurrent programming becomes more prevalent. I have seen abuses of the singleton pattern so bad the author should have just written the application in C. The truth is, there are very few circumstances where a singleton is truly the correct solution. I think I can count on one finger the number of times that it might have been the correct answer--oh wait, I was wrong....
Singleton is kind of like fancy OO-speak for global variable. People, just because it's a named pattern, doesn't mean it's OK to use it everywhere!! :-) - Mike Clark
Manager mgr; void do_stuff() { mgr.do_smth(); } int main() { do_stuff(); } and this is (in above sence) better: void do_stuff(Manager & mgr) { mgr.do_smth(); } int main() { Manager mgr; do_stuff(mgr); }. - mlvljr
The '90s and 2000s will be seen in hindsight as an unenlightened search for "the" programming paradigm. What is becoming clearer every day is that no one paradigm is right for every problem. More importantly, no one paradigm is even right for every subproblem within a small project. To create code that is at the same time DRY, terse and readable, you need to be able to mix and match paradigms at a fine-grained level and pick the right paradigm for the subproblem.
I think we are past the point where we can again have such a simple and yet meaningful insight as "goto considered harmful".
Test-driven development. It is a crutch for half-baked developers.
Why TDD: I think it's a hype. It kinda works for toy examples where you have functional relationship between inputs and outputs. But when it comes to temporal dependencies, such as event-driven systems, it's useless because the functioning of the program is determined by 1) the events that arrive, and 2) the order they arrive in. You can test that each event handler does the thing it's supposed to, but when there's shared global state (unavoidable in any program that makes money for their creators), you CANNOT test that any ordering of events will produce a correct result.
So what to do: use assertions to ensure that the program state is always consistent and valid. I use this methodology even for algorithmic code, and I spend very little time in the debugger -- most of the bugs are discovered by failed asserts. Assertions force you to think about the state of the program AND about assumptions required for the code you write to work. If you assume something, then assert that it is true! This reduces the number of bugs tremendously.
Why is it a crutch for half-baked developers: Heavily-used and complex systems have been written without TDD, and they have very few bugs. Examples: PostgreSQL database, Solaris or NetBSD kernel and base system (one of the best structured and clean code bases I have seen in my life), TeX typesetting system (I'd dare say, bug-free).
goto, where the situation is reversed and the cases where it's the right tool for the job are limited. - Graham Lee
GOTOs succesfully as well. - UncleZeiv
if compiler directives litter code. Yuck. - Robert Harvey
Personally, I think using four digit years are going to be considered bad practice. Just think about it. In less than 8,000 years we're going to face a major crisis due to our dependence on four digit years.
Comments considered Harmful
I see signs of this one popping up in lots of discussions here. People believe that comments are a code smell - that all comments can be replaced by better method and variable names. I can imagine a world where they are considered as distasteful as GOTOs.
Personally, I think this is an extreme position. There are some potential problems with comments - If they get out of date, they do more harm than good. And there are usless comments: i++; // increment i helps no one.
But, used correctly, comments add context to the code, and capture stuff that you just can't do with naming and refactoring. There are plenty of times I have been grateful for a comment that explained WHY something was done a certain way, instead of how it was done.
So I hope this prediction does not come to pass.
Pseudo-OO spaghetti with "dumb" getters / setters everywhere and severely duplicated code.
Rant: see here [1].
[1] http://www.javaworld.com/cgi-bin/mailto/x_java.cgi?pagetosend=/export/home/httpd/javaworld/javaworld/jw-09-2003/jw-0905-toolbox.html&pagename=/javaworld/jw-09-2003/jw-0905-toolbox.html&pageurl=http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html&site=jw_coreInheritance (at least when used heavily).
see here [1] and here [2] for both C# and Java-based rationale.
[1] http://msmvps.com/blogs/jon_skeet/archive/2006/03/04/inheritancetax.aspxI'm going to way out on a limb here and say that too much abstraction will be considered harmful. We'vee been moving to more and more abstraction and I think this will cycle back to less abstraction when it reaches the poitn that nobody bothers to understand anything and really horrible stuff is produced. Note I am not saying all abstraction is bad (I'm not interested in doing database work in machine code!), just that I think the trend is going to a dangerous place where lack of understanding will cause major development problems. Thus we will cycle away from abstraction sort of how in American politics we cycle between political parties.
printf is ok, one has no need to know anything from the levels below it (or better to say inside it -- because the asm-level inner-mechanics is hidden/encapsulated between the high-level routine and its visible behavior (console output)). - mlvljr
Computation generates a lot of heat. The heat that is generated is proportional to the amount of computation performed, and also to the amount of electricity used. In most parts of the world, electricity is generated from non-renewable sources. Removing the heat from the servers also requires significant energy. All of these will consume resources and emit pollution.
Multinational corporations are building large computation facilities everywhere. A lot of investment is made into making computation as efficient as possible. Often, the most crucial factor is neglected: Why compute? Why do we need to answer a question when nobody is going to use the result? If a person asks a vague question, shouldn't the computer verify the person's intention before going any further? Why waste the person's energy by requiring s/he to browse through thousands of results and still not finding the answer s/he wants?
"GOTO considered harmful" is considered harmful.
def consider_harmful(bool harmful) { harmful?consider_harmful():!consider_harmful() } - mlvljr
Aspect Oriented Programming
Guy Steele [1] famously said [2]
... the ability to define your own operator functions [in C++] means that a simple statement such as x = a + b; in an inner loop might involve the sending of e-mail to Afghanistan.
Aspect Oriented Programming takes this to extremes, such that in some languages it is nearly impossible to determine what code has been inserted where inside an otherwise-understandable block of code.
[1] http://en.wikipedia.org/wiki/Guy_L._Steele,_Jr.goto: It's called comefrom. - Macneil
a.add(b) won't send an e-mail to Afghanistan? - FredOverflow
x=a+b or a.add(b) in an AOP world has no way of knowing anything about the actual meaning of those statements. - Ross Patterson
Mutability Considered Harmful
As multiple cores become a norm, mutability will become the new goto. :-)
Direct SQL injection.
SQL that doesn't go through something that sanitizes user-input, or works through something like ActiveRecord.
Actually, this is already getting enough flack I think it's going to die.
OK, I know this is going to be controversial, but:
Developers considered harmful
Seriously. Many advances over the last fifty years or so have involved reducing scope for human error at the part where the requirements get turned into executable code:
So within a couple of decades, software will probably be largely written by tools that comprehend the business analyst's requirements, rather than by squishy error-prone coders. Well, they did say that computers would make some people redundant...
Multiple Inheritance Considered Harmful
I can't imagine a quicker way to get seriously convoluted than multiple inheritance. I'm sure the comments will be along the lines of "sometimes it's really useful", but those are the comments that come when you say "GOTO Considered Harmful" and they are no more compelling today. :-)
The subject of preprocessor abuse [1] is quite hot. It never really cooled down, but various development methodologies such as TDD have spawned some new and interesting 'tools' that continue to kick off an age old argument.
Additionally, I've seen the argument creeping up even more in the development of other languages, such as PHP that are written in C.
Usually, a mile long cryptic macro is rejected as being overly clever, ambiguous, or other terms. When something like a test framework meets that criteria, but is intended to proliferate an entire code base, it could be referred to as harmful.
[1] http://www.google.com.ph/search?q=preprocessor+abuseDon't get me wrong, I love the separation of concerns I get from MVVM, but has anyone noticed the large amount of duplication you get at the ViewModel level? Essentially any property on a domain object that you want to edit has to have at least one (probably more) corresponding properties on the ViewModel objects to allow for binding (with INotifyPropertyChanged and all that).
Frameworks considered harmful.
Of course there are loads of frameworks already and they all are designed to help you do what the framework designed expects you to do in the way they assume is the best... but I think one day people will start to reject this idea in favour of more flexibility and less learning curve.
They say a you call a library but a framework calls you. I think frameworks will go away and be replaced with reusable libraries.
Functional Programming
I predict a backlash against functional programming, mostly because its integration into mainstream languages like C# will allow for its abuse by programmers who don't really understand it.
Non-software transactional memory considered harmful.
Currently, implementations of threading and concurrency (using locks) feels like low-level assembly programming. Software transactional memory [1] is an alternative synchronization mechanism that leads to code that is much easier to write and understand. Several new languages have it (like Fortress and Clojure).
I think this also has a nice parallel to the origins of your question: clear blocks of code to add structure to low-level mechanisms that are too powerful. Saying "Locks considered harmful" not quite a slam dunk case as goto was, but it's the closest I've seen.
Underscore naming, despite that it is the most readable naming convention in programming according to Bjarne Stroustrup. I'll miss it.
Tricks like connect() or die() allowed in many dynamic languages, will be considered bad tone
Assignment as expression while (a = get())
I wish this thing is considered harmful one day: if (0 == i), it's so anti-human and plain stupid despite all justifications (which are as stupid)
connect() / die() trickery? - mlvljr
if (!connect()) then die() which works in languages like JavaScript, PHP, Python. Short boolean evaluation allows to skip the die() part if connect() was successful, plus dynamic languages usually don't care about the return type of die(), which is going to die anyway :) P.S. also in Perl, the UNIX shell, etc - mojuba
Shared ownership
I think it is bad because you loose information that is pertinent to get it, that's it, the owner of the object. Here is a try to an example:
Say you have a class with some members, say a list
class MyClass
{
list<SomeObject> list;
};
now you pass the pointer of one of those object to another class, say something about GUI that is updated to the user. Now, if you have to delete the list, say to recreate the object because they are polymorphic or something, there will be a reference to an object that is no longer valid in the GUI, but, since you have shared ownership, that object will still look valid to the GUI object and be shown to the user, which will probably not detect that the change did not take place correctly.
Now if we look at the other extreme, normal pointer, you don't have that problem since when the list get deleted, the program will crash when trying to show the thing to the user, which is bad if in production, but, in my view, better than having incorrect data.
Now, sometime you might not care, say in the example of a function that do calculation on the reference and return the result: you might care only about the result after the calculation and if someone delete the pointer while doing the calculation it will crash while the shared ownership strategy will work since you wanted the calculation on the old data.
The solution, I think, is to have way to differentiate the usage (encode it in the type if you will) depending on the situation. So, in the case of the GUI, you would maybe want the pointer in the GUI to be updated automatically with the new reference. In the case of the calculation one you would want a sort of copy on delete (well, keep on delete, that's it, shared ownership). Now you could also have both situation with the same SomeObject reference and that would complicate things a little but I think it can be done.
Not (fully) specifying exact code semantics / contract via
(and nobody speaks of useless / excessively lengthy documentation here, of course)
I actually don't think of any, but it might be because none of the stuff listed in other answers or even previous papers really seem "harmful" to me.
A gun looks harmful. A MOMD looks pretty harmful. Their intent is to be. A development process, tool, technique or language do not look harmful. Because their intent has never been to be. They're only artifacts that morons use the wrong way or in wrong situations.
I don't use goto in day-to-day programming and would indeed be breathing down the neck of any coder who would use some in a project I work on to force him to tell how in hell that thing could have been useful there (and in some case, it can), and I will encourage the use of static checkers and linters to oppose to the use of some constructs and patterns, but if a bypass is needed, I'll grant the exception with grace.
However, when an idiot manages to kill himself driving a fast car because he cannot drive, it's not the car which is harmful. It's the moron, and the people who don't did not regulate and enforce the regulations on the conditions of use. Basically, if my company's projects get crippled by "harmful" constructs, it's not the constructs fault: it's mine. They still have their uses in some situations.
Same with people who manage to burn themselves pouring coffee. I won't blame the kettle, the hot water, the coffee, the coffee maker, or mother nature. The only element of failure here I can see is pretty obvious, and we cannot remove him or her either.
In the end I don't see any harmful constructs, tools, patterns, techniques, languages and processes. I see situations, and iterations of these items which tend to improve them.
Dicing stuff for being harmful and contriving your mind into thinking about things in terms of what can be damaging, that's the harmful thing. It's a lack of open-mind thingy.
Any current or past programming paradigm carried to the extreme.
I once worked on a program where the initial programmer refused to use GOTO, didn’t comment his code, didn’t limit his functions / subroutines to one functionality or anything close to one functionality and moreover he created new code by copying old code instead of creating a function to handle the logic. The result of this was 3 million lines of code that was almost impossible to maintain.
I may sound Crazy but c variants lol. Back to BASIC everyone :)
Relational Databases considered harmful
Relational databases are to easy to abuse screw up, not be maintained and drag your software into the grave. Programmers who interface with databases should eschew any notion that having a relational database packaged with or connecting to their software will somehow make it seem more modular.
A bucket of snakes is portable, a handful of snakes is not portable - a handful of snakes may kill. A handful of snakes in the wrong hands in a 10 story building will kill all the occupants of that 10 story building. A relational database is a handful of snakes, waiting. Watching and waiting.
...
Well, I just figured I'd go out a limb with that answer as a crazy/dreadful prediction.
You may not find this to be applicable to your situation, but it's clearly the truth regardless. If you have a 'relational' database but, keep a plethora of multivariable attributes and every field in your tables is indexed and/or a primary key. Then you're only using the database as a stand-in for a big honky text file. Like a handful of snakes, this will wiggle out of your hands and bite you, not a bad analogy if I do say so myself. A RDBMS, like a GOTO is always one step away from being terribly abused. Simpler methods of storing and sorting data just plain old can't be abused - or at the very least mistaken for what they are.
And I never advocated NoSQL, I don't even really know what that means.
...
This may be of interest [1], as a better, snakeless argument against RDBMS for things they're not meant to be used for.
[1] http://ox.no/posts/object-relational-mappings-considered-harmful(new SnakeHandler(this._snake_events)).start_handling() ? - mlvljr
gotowas a majority-backed practice for a long time, so the answer with the FEWEST votes here is most likely to be the correct one. "Relational Databases considered harmful" is leading the pack at the moment. - Inaimathi