http://asawicki.info/ Graphics programming, game programming, C++, games, Windows, Internet and more... |
|
22:23
Fri
15
Jul 2011
Too Low Level and Too High Level Abstraction
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 (5) | Tags: java software engineering
|
Tomasz Dħbrowski 2011-07-15 22:51:50 | template <typename T> virtual T UltimateAbstraction(...) = 0; ;) |
|
Xion 2011-07-16 01:57:29 | You seem to be confusing two different meanings of abstraction. In the "low level" version, it is a simple lack of focus on details - your read/write functions simply don't care what they have to operate on. In the "high level" case, the abstraction is an attempt to *escape* away from details while being fully aware of them. I dont think those two concepts are very comparable. On related note: you are picking a low-hanging fruit in terms of endorsing your data-oriented approach. "Everyone" knows enterprise is hideous abomination of a system which should be at most poked with a veery long stick. |
|
Reg 2011-07-16 10:54:31 | Xion: To me these two concepts have very much in common. Both "low level abstraction" and "high level abstraction" is an API designed to be so general and universal that it suits everywhere, but doesn't provide anything specific and so doesn't add any value except another layer of indirection - a very unconvenient and "narrow" one. |
|
Xion 2011-07-16 11:40:55 | In case of "abstraction" (BTW: I grow wary of (over)using this term as it seems to be losing clear meaning), the generality is usually considered the added value. This can be recognized by the "no matter" phrase: "No mather what X you have, you can do Y equally well". That X is something underneath the abstraction layer, and Y is some logic using the layer directly. In case of the "low level abstraction", below you aren't having much of anything short of bare metal, optical fiber, electromagnetic waves, etc. I find it peculiar that you consider shielding from that as "excessive abstraction" because the thin layer doesn't have anything to offer besides uniform interface. What else would you expect to have there? And could it not be implemented on either side of the abstraction boundary? (Slight correction for the previous comment: I obviously meant that enterprise _Java_ is hideous abomination - but I guess it was easy to figure out ;)) |
|
Kos 2011-07-18 17:11:30 | While learning Java EE, I was once told that Java EE 6 generally made quite a big step towards simplicity and un-abominationness. Little story: I've had a run with Java Persistence API, which is basically a standardised interface for ORM solutions for Java. Using JPA allows to easily replace the ORM implementation (such as Hibernate, EclipseLink, etc), as well as - ofc - the very database backend, without (significant) changes to the code. JPA's even almost comfortable to use. Sounds cool. And then I was told than in Java EE applications a good practice is to always introduce a design pattern called Data Access Objects, basically another level of indirection on top of JPA, just in case you'd want to change JPA _itself_ to something else. Mm. Wasn't the movie Inception perhaps inspired by Java? Just asking... |
| [Stat] [Admin] [STAT NO AD] [pub] [Mirror] | Copyright © 2004-2012 Adam Sawicki |