Too Low Level and Too High Level Abstraction

Warning! Some information on this page is older than 6 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Fri
15
Jul 2011

Programmers fascinated by object-oriented methodology love the idea of abstraction and generalization, but others - especially those interested in data-oriented design - consider "premature generalization" as a big anti-pattern. I prefer the latter approach, so as I recently learn a little bit of Java, including Servlers and JSP, I feel terrified of how its API looks like. Let me explain...

Today an idea came to my mind that an API can be too abstract (general, universal) at low level or high level. The most abstract low-level API looks like this:

int write(void *buf, int bytes);
int read(void *buf, int bytes);

It's so general and universal that it would fit anywhere, but on the other hand it doesn't provide anything specific. It's just a very narrow pipe we have to pass all our data through. Of course this method is sometimes useful. For example that's the way we transfer data over network. But we do it using some specific protocol so it's reasonable to define a higher-level API with some objects that encapsulate concepts specific to that protocol, just like cURL implements HTTP, FTP and other network protocols on top of network sockets.

Let's compare some details from two APIs. A socket can have additional options that can be set. There are different options for different kinds of sockets and they have different types - some of them are bools, others are ints. But there is only one function to set such options - setsockopt:

int setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen);

Objects in POSIX Threads API also can have additional attributes, but there are specific functions to set them, like in the example below. Which way do you prefer?

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_setstacksize(pthread_attr_t *attr , size_t stacksize);

But excessive abstraction can also go too far the other way. That's what I see in Java API. I mean, these who code a lot in this language certainly can "feel" the sense in this approach, but for me it's almost ridiculous. Not only every part of the Java API has dozens of small classes with not much more than simple getName/setName methods and there is an interface for everything just like people were afraid of using real classes, but lots os stuff is refered by strings. I'd say Java is so high level that it's not only a strongly-typed language, it's stringly-typed language. Lots of classes implementing some interface can be registered in some global registry under its name so an instance can be constructed without ever refering to the real class, like: new SomeSpecificClass().

Probably the most grotesque example I saw today is java.naming package. Including its subpackages, it contains about hunred of classes and interfaces. But there is more than this. It's the whole great body of knowledge called JNDI (Java Naming and Directory Interface) with long tutorials and lots of concepts to understand, like Context, InitialContext, Directory, Service Provider, Lookup, Names, Composite Names, Compound Names, Naming System, Federations and so on... All this just to provide an abstract interface for a tree of any objects referred by name, so that disk files and directories can be accessed same way as data received with LDAP or some global variables defined in an XML file. Do anyone really needs that? The javax.naming.Context interface is not far from what would be the ultimate high level abstraction:

interface SuperAbstractEverything {
  public Object getObject(String namePathIdOrWhatever);
};

Comments | #java #software engineering Share

Comments

[Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2024