summed it up well on http://www.joelonsoftware.com/articles/fog0000000049.html
- When great thinkers think about problems, they start to see patterns. They look at the problem of people sending each other word-processor files, and then they look at the problem of people sending each other spreadsheets, and they realize that there's a general pattern: sending files. That's one level of abstraction already. Then they go up one more level: people send files, but web browsers also "send" requests for web pages. Those are both sending operations, so our clever thinker invents a new, higher, broader abstraction called messaging, but now it's getting really vague and nobody really knows what they're talking about any more.
- And if you go too far up, abstraction-wise, you run out of oxygen. Sometimes smart thinkers just don't know when to stop, and they create these absurd, all-encompassing, high-level pictures of the universe that are all good and fine, but don't actually mean anything at all.
[Actually, I think Joel is full of it on this one. Can you give a good example (I don't think messaging is one). Most advances against complexity (in *any* field) are made by better and/or more powerful abstractions. Period. I agree that *bad* abstractions can be a problem, but you hardly every make a complex situation better by stripping away abstraction levels (rather than improving the abstractions). See mathematics developed over the last 100 years or so for examples of how and when this works very well.]
I think that his point is that when you add abstraction layers, you risk changing the original problem into a more general and possibly more complex one.
The antidote is to DoTheSimplestThingThatCouldPossiblyWork
grounded by TestDrivenDevelopment
I claim the problem is not in too much abstraction but in PrematureAbstraction
(Perhaps too much abstraction all at once?). All abstraction should be based on practical experience. This applies generally in life, not only in programming.
The difference is in that, you don't lose the hang of things because of the abstraction, but because you're not able to map the abstraction into the world anymore. When the abstraction is born out of experience, you already have the means of mapping it into world properly.
Monads (OnMonads) are a great example of a useful abstraction: it's nigh-impossible to explain people what they are, but relatively easy to teach people to use them. At least if they've grasped a couple of other functional abstractions. :)
When abstraction gets out of control in database design, I remind people that really, "I could do the entire thing with only one table: Give it a numeric primary key and a large text field, and programs can parse and populate the text field with whatever data they need, in appropriate formats."
This usually gets people to realize that having more concretely structured data has its benefits -- like performance and ease of processing.
I have personally seen two very large scale (10M$ plus) projects fail because of this sort of thing. In the rush to apply OO logical design they completely forget about the physical context and then wonder why their project fails to work at anything greater than toy scale. Classic architectural mistake to build a beautifully square peg and then bitch about the (unchangeable) shape of the hole. Another reason why NonCodingArchitectsSuck
Too much normalisation could be an example of Too much abstration?
In workplaces I have only seen people doing normalisation to the 3rd form, yet computer science students used to brag about how to do this to higher levels.
Normal forms aren't really a statement of abstaction: A scheme in first normal form isn't less abstract than one in the 2nd, it merely allows a given fact to be stated more than once in a table. Notably, the higher form does not stand in for the lower form; they both state an identical set of facts. An abstraction on the other hand stands in for the concrete: the abstraction implies a loss of detail.
For example, if you ask me what the best restaurant in a city is, I can only answer you in abstract terms. If you ask me what the best restaurant in Toronto, I can give a concrete answer. On the other hand, you don't gain or lose any information by asking what the best restaurant is in Toronto, Toronto and Toronto vs just asking about the best restaurant in Toronto.
Also, in most cases a schema in 3rd form will also be in 4th and 5th. The higher forms generally only differ from the third in more pathological cases. Somebody doing normalization to 'just' the third form is either writting bugs, or doing the normalization by hand elsewhere (with or without understanding).
I do believe that removing duplication while retaining function IS abstraction. Can you think of a case where that is not true? --BryanEdds
(int x, int y)
return x + y;
(int a, int b)
return a + b;
Removing the duplication here (while retaining function) would not be an abstraction.
You are right in this case. I suppose if you have code that duplicates an existing and adequate abstraction, removing that code won't yield a new abstraction. I was really thinking more along the lines where duplication is removed while retaining functionality that is not already made available by an existing abstraction. --BryanEdds
Refactoring can lead to new abstractions. It is one of the reasons XP works - it won't lead you to optimal abstractions (greedy algorithms rarely are optimal), but the simple methodology of coding then refactoring does ensure immediately useful abstractions. Related: DuplicationRefactoringThreshold
I wanted to add in here that abstraction is the nature of software (and possibly in life) because everything is based on the bit. A simple 'on' or 'off' toggle that everything comes from. When you take any abstraction all the way down, all you have is on or off. If we didn't build up from there we'd still be writing binary. So there's definitely no such thing as too much abstraction (IF the problem warrants it).
The primary cost of abstraction is indirection. In my experience, you should only abstract when the added abstraction clarifies things more than the added indirection confuses them.
It's a great idea to experiment
with grand abstractions because often it leads to new ways of doing things, and the knowledge of what went wrong also teaches you something. However, don't depend on those experiments working right the first time or soon. In other words, keep your day job as a back-up. --top
I'm starting to think that coming up with grand abstractions can be the wrong approach. If you want to find the future, you might be best off looking at the past developments in computer science that haven't yet hit the mainstream. When inventing a new piece of software, my mind repeatedly comes back wondering which parts of Common Lisp's functionality I will need to reinvent to accomplish my goals with the God-awful mainstream language I am stuck with. --BryanEdds
I was thinking more of domain abstractions, but it can apply to the computing domain also.