Does Abstraction add Fuzziness?

Does Abstraction add Fuzziness to software?

I observed that Asbtraction though it helps in better communication of ideas will actually add fuzziness to the program understanding when we actually have to write some code that actually works.

(The context of abstractions here is that they are in a domain , as in a financial software or some product etc.. and consider OOP and consider systems in the wild)

The reason why i feel that it adds fuzziness is that it does not immedietly allow me to write some code after understanding the abstractions.Even in a well designed system, I know what objects i should invoke, but it does not exactly tell me what should be done.It will be ok if the abstraction uses a standard design pattern, which usually is not the case.

I have found that for objects which map realworld entities, these abstractions will be easy to understand. But when these abstractions involve process information , the control flow becomes very fuzzy.I cannot figure out the exact control flow of the code from a Java source code . Some people may find this statement pretty stupid , but i think that they have trained their minds to look at things that way, but the fuzziness still remains .

For example, the processing of a transaction might involve creating lots of objects. These objects each perform a specific operation on the given transaction. This code base is was written by many teams and each team has its own way of looking at it.For example some object computes risk of that transaction, for that it needs to be instantiated with other objects whose values we should know before.For other team for the process of printing a report, a type of report might be the basic abstraction in his world.So thats additional mapping. Also once i also came across an asbtraction that was made to make it easy to test code, which is common IMHO.

Now in a large team of say 500 memebers, how do we expect people to get in proper abstractions. Refactoring the code may not be an option because there is a lot of code that runs using these abstractions. Also, the above code is a very stripped down version and for each task we need to be aware of many special cases which usually cannot be abstracted or abstraction may not make much sense or was an overkill.

The problem is only aggravated in a badly designed system as it does not follow known patterns or ways of doing things. The reason why i see bad designs at my work place is not because people are bad, but because there might be a change in the requirement which was assumed would not change, but it did change during the final stages of the testing or the system was extended beyond what it was intended to do.

Please leave your comments, opinions or flames on this issue.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

welcome!

Welcome to the real world of software development, using old boring paradigms and languages and having to deal with legacy code made by many people, skilled or not!

So, domain specific abstractions add fuzziness to the system? Well, just imagine with no abstraction, then! If such a thing is possible that is...

anyway

I know what objects i should invoke, but it does not exactly tell me what should be done.

So, you have a model and its interface and doesn't know what to do next? Perhaps you're missing the relationships between the several objects? Docs might be of some help?

Abstractionless programming?

I want one!

Abstractionless programming

Mentioned previously on LtU, and again in another thread on the same topic.

But

Trees are abstractions. So are GUI metaphors like clicking and dragging, for that matter.

An LtU Koan

A useful distinction worth making:

Good abstractions increase clarity and offer insight into repeating patterns.

Bad abstractions increase complexity and add "fuzziness".

If you don't understand this, get your Zen master to whack you with a bamboo beta abstraction at random intervals.

After a sufficient number of whacks you will be enlightened.

(Please consider this whack number one.)

problem with imperative programming

My opinion is that control flow is really the basis of imperative programming and the more you can hide the better. What do you prefer, declarative programming (a = b)? Or imperative programming (when "a" changes, change "b" also)?

Abstraction doesn't add fuzzy

Abstraction doesn't add fuzzyness it creates conceptual precision at the expense of "reality". Abstractions fit reality with some degree of precision. The laws of physics are conceptually true and yet don't exactly fit any "real" problem! Just ask any engineer. What saves the engineer is a constant "activity". Constantly checking and verifying that one's models correctly match the real situation. In order to use an abstraction it must be carefully chosen and tuned to fit the real world problem. To use an abstraction safely it must be used actively in a way that checks the "fit". It is like a problem in syntactic pattern recognition.

Edit: Or instead of syntactic pattern recognition it is "like" the process of static or dynamic type checking. Something familiar to everyone in the field but not used enough. Taking this arguement to the limit a program becomes a knowledge base and it's execution becomes an activity in an environment.

It's lack of abstraction that adds fuziness.

The problem lies in the tools. For example, you can not tell from a Java program what it does, because you look at the little details (i.e. the program's classes), without having an abstraction of it to look at: the classes are presented in a disconnected way.

Let's take a web server, for example: the source code is a bunch of classes that you actually have to run to see what it happens. But if you looked at the following:

    for each received HTTP request 
        find destination servlet
        if destination found then
            invoke relevant servlet
        else
            return error message HTML page
        end if
    end for

...it would be easier for you to understand what actually happens.

The problem is smaller with functional languages, because the more toplevel you go, the more abstracted the program goes. In a functional program, you can usually look at one or two levels deep from the main loop to understand how the program works.

Functional language advocacy.

I find your statement about FP languages and abstraction inordinately silly.

As a counter-exaple, I'd like to show you my baby -- this program I wrote to highlight the powers of expressivity in FP languages.

Bear with me, it is written in Python, though it is still 100% functional.

print ''.join('%(pre)s%(num)s %(bot)s on the wall, %(nul)s %(bot)s,\n%(tak)s\n' % (lambda c,b:
{'pre':['','%s %s on the wall.\n\n' % (c,b)][abs(cmp(c,'Ninety-nine'))],
 'num':c, 'nul':c.lower(), 'bot':b,
 'tak':['Go to the store and buy some more... Ninety-nine %s.' % b,'Take one down, pass it
around,'][abs(cmp(x,0))]
})((lambda x,o: [(['Twenty','Thirty','Forty','Fifty',
'Sixty','Seventy','Eighty','Ninety'][x/10-2]+'-'+o.lower()).replace('-no more',''),
o][int(x<20)])(x, ['No more','One','Two',
'Three','Four','Five','Six','Seven','Eight',
'Nine','Ten','Eleven','Twelve','Thirteen','Fourteen',
'Fifteen','Sixteen','Seventeen','Eighteen','Nineteen'][[x,x%10][int(x>=20)]]),'bottle%s of beer' %
['','s'][abs(cmp(x,1))])
for x in xrange(99,-1,-1))

Nicely top-down, don't you find? (I played nice and avoided recursion as Python isn't tail-recursive properly.)

uh-oh!

I wrote to highlight the powers of expressivity in FP languages.

ah, i see! a show off...

Bear with me, it is written in Python, though it is still 100% functional.

you mean it's just one big function call, and not even nicely formatted as in scheme code.

Nicely top-down, don't you find?

no. here's why: bad, obfuscated code can be written in any language. even haskell or scheme.

your code just proves the main point of this thread: bad or no abstractions just makes things harder. Your code just lacks the most basic of abstraction techniques: giving names to distinct things and then referring to them by their names, thus hiding their inherent complexity.

Just because your code is one big function call doesn't mean it's functional code. You can do the same with C or any other. Indeed, it's most likely you find, in haskell, something along these lines:

main = doSomething
doSomething = doThis >>= doThat
etc

It is purely 100% functional.

It uses no state, doesn't do destructive updates, has anonymous functions and proper scoping, and doesn't waste stack space.

It is completely and utterly functional in any sense of the word.

(And no, you can't do the equivalent in C without writing your own VM first.)

You are confused with the meaning of "functional" -- briefly said, "functional" is roughly equivalent to "stateless".

Which, by itself, doesn't make code easier to understand or to write, and it certainly isn't linked in any way with "expressiveness" or "abstraction". (Lambda calculus is a perfectly valid FP language.)

functional or not

it still looks like crap. still, i see the point you're trying to make: that no matter the language or paradigm, there's always a way around it so that we can make it look silly. you just deliberately obfuscated your code by amassing you code together in one big call, with stupid anonymous functions for no other reason than to say: "See, functional programming looks like crap!"

well, as i said, no matter the language or paradigm: without sensible abstractions ( names at a minimum ) and with deliberate goal for obfuscation, yeah, it'll look like crap, no doubt. you could prove your point just as well against imperative, OO, or procedural programming.

And no, you can't do the equivalent in C without writing your own VM first.

of course i can. except for anonymous functions, i can do this:

#include <stdio.h>

int main()
{
   int sum_squares( int a )
   {
     int square_a()
     {
       return a*a;
     }
     return square_a() + square_a();
   }
   printf( "stupid => %d\n", sum_squares( 33 ) );
}

it's completely functional, no state whatsoever involved and order of execution isn't important, except for the limitation of not having anonymous functions, so you have to predeclare them. and no need for a VM, either... ;)

You are confused with the meaning of "functional"

yes, i know what it means. i was just annoyed that it was the first time i'd seen obfuscated functional code. i mean, generally people look forward for functional programming as a means of improving their abstraction skillset, not degrading it...

Is this supposed to be C?

Is this supposed to be C?

why, yes. it's C. and yes, it

why, yes. it's C. and yes, it compiles and runs fine.

You are using a non-standard

You are using a non-standard C extension (GCC's nested functions, I guess?).

gotcha!

ok, just took a look on one of my classics: K&R's The C programming language. yes, you're right: it definetely is an extension and the language specification explicitely says it's not a block-structured language. My fault! i guess that's what happens when you forget your origins...

anyway: the example still stands, only it can't count on external scope to deal with variables ( should be parameters ). the one limitation still stands: C doens't have anonymous functions, so you gotta predeclare them. Externally, that is.

#include 

int square( int a )
{
     return a*a;
}

int sum_squares( int a )
{
     return square( a ) + square( a ); 
}

int main()
{
     printf( "stupid => %d\n", sum_squares( 33 ) );
}

still functional...

Where is the abstraction in t

Where is the abstraction in that?

Can you still call that funct

Can you still call that functional with the internal "for x in xrange"? That doesn't appear to be the lexical scoping you mentioned. Where, syntactically, is x bound? What value has it?

Why not?

AFAIK, x is bound in the surrounding block:
x = 0
[ x for x in xrange(10) ]
x ==> 9
I consider this a bug in Python, by the way.

xrange() is roughly equivalent to doing the following: (Ignoring stack allocation issues.)

def r(a,b,c): 
  if a != b:
    yield a
    for x in r(a+c,b,c): 
      yield x

As far as I can tell, there's no equivalent way of re-writing the 'for' loop, but conceptually (ignoring the tail-recursion issue and the broken 'lambda' statement) you could model it in the following way:

def loop(i,f):
  try:
    f(i.next())
    loop(i,f)
  except StopIteration:
    pass

key in last paragraph

The problem doesn't look like abstraction but rather its lack. You don't have an abstraction for the control flow of the program and so are lost in a forest of object without a map when you try to write or alter code. Sorry but that is a hard problem to solve particularly as many feel that those kind of thicketts are unaviodable/desireable as it leads to job security. Even real evangelicals with very clean object code fall into this trap believing the whole system beyond individual comprehension. My best advice is to come up with some metaphor that you can visualise which doesn't have anything to do with the operations going on. Then go back and forth between the two for perspective. Or if you think you can swing it its time to build some actual abstractions that model your employers need better than pure java does and start using it to improve the code base.

Abstraction

Abstraction is an amorphous concept. I think it can help the discussion if you define what each of you means by abstraction.

Specifically: There's a big diference bewteen concrete software artefacts, called "abstractions", that exhibit well defined interfaces, and provide encapsulation, and abstraction as general design goal.

Everyone's been implying this

Everyone's been implying this, but I might as well point it out explicitly. A good abstraction reduces the complexity of reasoning about a program, or makes reasoning possible where it wasn't readily obvious how to do so in the first place. If the abstraction doesn't accomplish that, then what is the point of it?

In computer science everythin

In computer science everything is an abstraction but there are different types of abstractions. Some are abstractions of real things which naturally take the form (metaphorically) the real object. Such objects ought to be intuitive and easy to work with.

But often the objects of a computer program are more purely mathematical or technical. These may not have a nice intuitive form that we recognize from experience. In fact theoretical objects can be manipuleted mathematically into a large number of forms. If we have a number of these objects and there is not a consistent choice of form then they won't fit together. For instance the same automata can have many different serial and parallel decompositions.

Temporary hiding of extraneous information.

Abstractions are designed to hide information that is not relevant to the task at hand.

For example:

Objects can change implementation but keep the same interface.

Monads slice concerns each into their own separate layer.



For a given task, abstractions hide the accidental complexity and expose the essential complexity. Domain specific languages are the perfect example. A DSL for music or cryptography should have no notion of how the computer boots, or whether the monitor uses analog VGA or Digital Video Interface. Even though the computer, and thus the program, depends on those details, they are not important for making music or designing or breaking encryption.


--Shae Erisson - ScannedInAvian.com

Summing it up

Thanks for the tremendous information on this topic.

Neil thanks for especially pointing me to those threads. I learnt a lot there.

I was mostly hinting at OO abstractions that make it difficult to show process information.Sometimes i feel that i cannot come up with an object oriented abstraction for a process. But sometimes a functional view tends to solve the problem very easily.

To sum it up, this is what i conclude/learnt from this thread:

1) Abstractions are important and they help in understanding. If they don't then they are wrong abstractions.
2) Abstractions do not necessarily only mean Objects. They can also be functions and infact functions are very good abstractions.
3) New ways of avoiding abstractions ( as was done in subtext) are only hiding the abstractions/names.