Countless times over the years I have seen areas where Academia is decades ahead of us so-called industry experts. What is "new", "shiny", and posted all over the place online today is built of theory produced 20+ years ago. In practice, we have gotten our tasks done without some of this knowledge, but theoretically, we have, over time in our ignorance, cost our employers millions of dollars in hours dedicated to bug-fixing and features that could not meet deadlines. It is a hard pill to swallow. The silver lining is that we can recognize this and work to grow, to learn that missed theory, rather than fall into the trap of complacency.
Today's fad is functional programming. In the coming years, we will relearn the weaknesses of functional programming, why OOP was the next stage of evolution. Hopefully we will have learned not to fall into extremist camps again (the notion of a "functional vs OOP" conflict still strikes me as hilarious misunderstanding).
If I were to put a finger on it, I would say that the reason OOP arose was that there was general recognition of the need for a rich type system. I got a hint of this in the first couple parts of SICP. Haskell incorporates a kind of type system that is, itself, pretty interesting. CLOS/Moose makes C++ and Java feel antiquated.
In my experience, a lot of us who learned OOP via C++, Pascal, Java, Ada, and the like generally missed the point: type systems. We tend to treat classes like collections of the language primitives as opposed to combinations of data structures. Specifically, we make do with primitive data types and neglect to constrain them as a type. And "everything must be an object" is an extremist mantra with little value; given that your process image must have an entry point, purely a code-flow issue, was there really a point to the illusion of wrapping the entrypoint main() function in a class (I am looking at you, Java)?
Here is an OOP type example I see in the wild: an ID that is a string of four characters, a dash, and three digits tends to be stored as a string. This is incorrect; that string is not like other strings, and this is a blind faith that somebody is not going to incorrectly use that string. Wrap that in a type that specifically checks that the ID fits that pattern. It is easy to fall into this kind of mistake in the database management world, too, where an ORM pulls in a VARCHAR2 and does not translate values of this type into an appropriate type in the system, perhaps a type with a restricted domain.
Another example: I have learned to always question if my method really needs to accept an "int". This is a smell. Could my value be negative? What is the real min/max range of the value? Could the value have a magic value, such as "Number Not Given" (or NULL)?
Functional programming helps us with code flow. OOP helps us carefully classify the data.
Far be it for me to defend Java (I hate the damn thing), but: main is just a function in a class. The class is the entry point, as specified in the command line; main is just what the OS looks for, by convention. You could have a "main" in each class, but only the one in the specified class will be the entry point.
I remember a long time ago I was watching an online forum on riddles. One of the 'riddles' was how many cigarettes (read as: finite regular cylinders) can you arrange such that each one is touching each other one. I watched the thread go for three days as various theorists claim a maximum number according to mathematical theorem A or B or C. It started out with a max number of 3 and took three days of impassioned debate to work up to 6, with theories floating in and out of favour - and each one claiming to be 'the absolute ceiling limit'.
I then took a matchbox down the pub and asked the same task of my drunk friends (telling them to ignore the bulbous heads/square cross-section). Within five minutes, all of them, even the utterly non-scientific ones, had found a solution for six. Most of them found it within 1-2 minutes. Drunk, untrained, undiscplined folks that actually physically played with the items beat out impassioned, educated enthusiasts.
It highlighted the issue for me that theory is all well and good, but it's not useful in a vacuum. Theory and practice need each other to be efficient.
Similarly I went back to visit my old university. I saw a guy there 12 years into his PhD... and still clueless about the practicalities of what he was recording. He'd spent his whole career in the theory of it and had no idea of the realities of recording his subject, something that 3-6 months in industry would have given him in spades.
So no, it's not as clear cut as 'theory done cleanly in practice would win', as the real world is grubbier and has more edge cases. Theory and practice need each other for efficiency. Thinking of it another way - you don't need to test your backups... in theory... :)
Incidentally, on the cigarette question, I've seen a solution for 7, but I don't know of any higher. The guy who showed the solution for 7 was also the first one to say 'this is a solution, but there may be a higher ceiling out there'.
For infinitely long cigarettes, it is at most 24: http://library.msri.org/books/Book52/files/07bezd.pdf
Is eight attainable? http://portal.acm.org/citation.cfm?id=1450373
It's a good question, but then, it is also a perfect example of why playing around with the real object is sometimes better than applying a theoretical analysis. The question was about cigarettes, and cigarettes do bend / deform. That means that any analysis will need to take this characteristic into account. The problem is, we don't necessarily know all of the factors that need to be modelled to do a correct analysis, which is why empirical testing is still an important technique for problem solving.
I've lost count of the number of times a theorist has told me that result -foo- shouldn't be possible during application :)