views:

535

answers:

7

What is the worst (due to either prevalence or severity) example of abstraction inversion that you see in programming today?

For those of you who are not familiar with the concept, abstraction inversion is implementing low-level constructs on top of high-level constructs. More precisely, assume you have constructs A and B. B is implemented on top of A, but A is not exposed anywhere. Therefore, if you really need the lower level construct A, you end up implementing A on top of B, when B is implemented in terms of A in the first place. See http://en.wikipedia.org/wiki/Abstraction_inversion.

+1  A: 

I'm not sure if this is answering your question, but I've seen this (and I've been guilty of it) where a nice high-level language like Lisp gets used as if it were Fortran or even Assembly language, because that's the level the programmer was at.

IMHO, it's one of the ironies of computation that no matter how high-level a language is, if it's universal, it can be used at the lowest level. Sophistication is no guarantee of sophistication.

Mike Dunlavey
Not really. High level languages are often designed so that you can program a a lower level if there's no good way to express what you want at a high level. This is more like just not using an abstraction, rather than inverting it.
dsimcha
+1  A: 

This seems like a pretty dead topic. I'll answer my own question just to start some discussion. I'd say the worst abstraction inversion I've seen is using OOP-style abstract classes/interfaces to replicate function pointers. For example:

interface foo {
    int bar();
}

class myClass1 implements foo {
    // No member variables.

    int bar() {
        // Implementation
    }

    // No other methods.
}

class myClass2 implements foo {
    // No member variables.

    int bar() {
        // Implementation
    }

    // No other methods.
}

A class is supposed to be a powerful abstraction for when you need to encapsulate both state and behavior. A function pointer is something relatively simple that is used to contain behavior only. Virtual functions are implemented using arrays of function pointers, but many OO languages don't expose function pointers or anything directly equivalent. You therefore end up using interfaces and classes to implement functionality equivalent to function pointers, and these classes and interfaces are themselves implemented in terms of function pointers. This leads to both unnecessary complexity and decreased performance.

dsimcha
I hate to see an interesting question go dead too. As you can tell from my other answer(s), I think there's way too much idea-worship in this field (like your use of the word "powerful") in place of simple accounting of pros and cons.
Mike Dunlavey
C#, F#, Delphi, C++, Python, Ruby, OCaml, Perl, Javascript, Scala, Lisp+Clos, D, and a boatload of other OOP languages support lambdas and first-class functions. Java is really the only "big" language left to add support for function pointers.
Juliet
A: 

Another answer, or question, if you don't mind. Does the word "abstraction" actually have a definition? Are abstractions actually good, or bad, or neutral? I mean, I understand the number 2 is abstract because it stands for what is common about 2 shoes, 2 eyes, 2 cycles, etc. An interface IStack can be abstract because it applies to things that act like stacks. But if subroutine A calls subroutine B does that mean it is more abstract? Why are we so enamored of this word?

EDT: I'm only asking because I've seen people turn up their noses at "concrete" issues, thinking the forest is more important than the trees.

Mike Dunlavey
A: 

I'm not sure if this really qualifies, but it seems related. When SQL Server 2005 came out with the CLR capabilities, I heard a bunch of developers saying things like "well, now we can fire off Web service calls directly from our stored procedures!" I also saw several tutorials on doing this. Those are some conflicting levels of abstraction.

David Grant
+1  A: 

The use of client-side procedural collections libraries to process SQL result sets.

Steven Huwig
A: 

What is the worst (due to either prevalence or severity) example of abstraction inversion that you see in programming today?

I don't know if this counts, but I usually get irked when I see classes named after their implementation instead of what they're for. Its really a kind of Hungarian notation, observe:

  • CustomerFactory
  • DecisionTreeVisitor
  • AbstractWindowDecorator
  • JsonDataAdapter
  • TabbedDocumentImpl
  • ConcreteListHandler

"Factory", "Visitor", "Decorator", "Adapter", "Impl", "Concrete" -- who cares how its implemented, what's it used for?

Juliet
Factory, Adapter and Handler are all perfectly legitimate uses for something in my opinion: a factory makes stuff, an adapter adapts stuff and a handler handles stuff. Impl, Concrete and (debatably) visitor are just silly notation though.
Ed Woodcock
+2  A: 

Probably the worst example of abstraction abuse I've ever seen was this fluent C#, which wrapped basic flow control elements (if, whiles, sequenced expressions) in a fluent interface.

So your perfectly idiomatic, clean code:

var selectedTextBox = (TextBox)sender,
if (IsAdmin)
{
    selectedTextBox.Enabled = true;
    selectedTextBox.Text = superSecretPassword;
}
else
{ 
    selectedTextBox.Clear();
}

Becomes this mess:

Cast<TextBox>(sender).
    WithIf(IsAdmin,
        With(selectedTextBox => selectedTextBox.Enabled = true).
        With(selectedTextBox => selectedTextBox.Text = superSecretPassword),
        With(selectedTextBox => selectedTextBox.Clear());

Because everything's better with lambdas!

Juliet