Monday, November 24, 2008

OOP - Basics of Object Orientation

OOP's, Its always too late to discuss about OOP. Its not mandatory that for any good design we follow OO. Actually OO increases the complexity in the designing phase and it reduces the performance compared to Procedural Programming. Having said that why do we follow OO. Its all for one word:
A good design is very simple like the nature. Its without any instuctions. Take Tree for example, we need not need any instructions, we see the nature and learn. We learn how to eat fruit or how to climb without any instuctions. So, in the process of representing the nature we started using OOP.

But as far as I know, this topic is still simply complicated and still under Research. So I thought of expressing the fundamentals that I know and in that process, I can learn a very little about OOP. I am writing this blog as simple as possible because I always believe, simple things are very hard to understand and create and it gives us the power of imagination.

The first question is, "What is an Object?".
Object has 3 things:

  • Identity
  • State
  • Behaviour

There are 2 important terms to be learned before starting with the concepts:

  • Invariable: The one that is known, that can be reused, abstract, which won't change
  • Variable: Which changes

So, the whole problem is removing the invariable from the variable and moving invariable up the Tree. This produces Shallow tree and which is more prefered than a Deep Tree.

For example:
WindowManager:

  • CreateWindow
  • EditWindow
  • SaveWindow
  • CloseWindow

Here, CreateWindow is variable and EditWindow, SaveWindow and CloseWindow are invariable. Because CreateWindow can be called many times, but the EditWindow, SaveWindow and CloseWindow can be called on a particular instance of Window.

For OOP there 4 mandatory concepts:

  • Abstraction and Encapsulation
  • Implementing Encapsulation using Inheritance or Composability.

Abstraction:

Abstraction is taking the Invariable part out of the Variable. A natural example may be Fruit. Apple exists and once eaten cannot be reused. But Fruit is something that cannot be eaten and that exists only in some form.

Encapsulation:

Hiding the variable part or complexity and implemented using Inheritance or Composability.

Composability:

Composability is very dynamic. Its Composing/Delegating/Ordering. Like someone asks you for time. You see a watch/clock/mobile and then tell time. Here you are encapsulating the implementation, i.e, you are not inbuilt with time functionality. But, you are delegating it to a watch/clock/mobile and telling time. Since there is delegation, its costlier. Most of the times, Composability comes along with Inheritance.

Inheritance:

Inheritance is static. It is Derivation. Let us take the same watch. You see the watch and look into the time. But for a watch mechanic, the encapsulation is different, he looks into the internal parts of the watch. He sees the implementation.

Implementing Encapsulation using Inheritance/Composability may seem confusing. So, let us take another example, say a Data Structure implementation.

Stack:

Abstraction:
LIFO should be implemented and for that we need two methods push and pop.

Encapsulation:
Providing push and pop hiding the implementation.

Implementing stack using Inheritance:
Extend LinkedList and then provide push and pop and implement them using LinkedList methods.

Implementing stack using Composability:
Provide push and pop and then call/use some other methods for implementing the same.

Composability is more global. Hence the reusability is more. Let us take an example:

Sale: log()

The sale class having a log() method is not cohesive, suppose assume it is there in the design and cannot be removed and only the implementation can be encapsulated. A better way is to call and external API for the log() implementation.

AbstractLog:log() <- SalesLog:log()

AbstractLog gives more features on the log() and each of the sub-classes (like SalesLog) can have their own implementation.

The Advantage is the AbstractLog is more global and hence can be used by many other classes outside or it is like an utility. But the abstraction comes via Inheritance. So sometimes Composability comes along with Inheritance.

A good programming need not follow OOP. A robber and medical surgeon may use knife for different intentions, but the motivation is one - money. In the same way, The Intentions may be different for using OO, but the Motivation should be "REUSE".

12 comments:

  1. Very well written.. good illustrations... i can see ur concepts are crystal clear! Good work! Keep sharing your knwoledge...

    ReplyDelete
  2. You have done a very good job...The concepts are being explained more interactively...with live examples.

    ReplyDelete
  3. Interesting article. OOPS explained in a very simple way.

    ReplyDelete
  4. OK, I finally got a chance to go through your article completely. It was nice with some good examples. I liked the "knife" one...

    But, I'm not a believer of the main motivation you mentioned for OOP, which was "reusability." May it's just me and few others. IMO, except for the very basic data structures and some other utility functions, there's nothing that can be reused. Out of 10,000 classes I might have written, only a very few in number were ever reused across projects. Yes, I agree it's one of the motivations but to me, the most important motivation for using OOP is "testability."

    In particular, "Unit testing." It's the fundamental and yet how many of us can stand up and say my class or module is thoroughly unit testable?. We've a gazillion dependencies. Accessing file systems, querying databases, talking to that other component by going on the wire. These things are hard to test because of their dependencies and this is where I think my motivation of OOP, Mr.Morph (polymorphism) comes into picture.

    Without polymorphism, you cannot do Unit testing that easily. And in procedural programming, I don't know how you would do that without "interfaces." And if it ain't tested, it's probably broken.

    So, what I'm saying here? Yes, this is what. Reusability is a solved problem and it's overrated. It existed even before OOP. And OOP components are not that easily usable.

    My two cents,
    Srikanth

    ReplyDelete
  5. Correction in my last sentence, what I meant was "OOP components are not that easily reusable. Of course, they are usable otherwise why would we even write them :-)

    Srikanth

    ReplyDelete
  6. Hey Srikanth,

    I can say "REUSE" is the correct word. For instance, take Collection framework. It is higly reused.

    If the design is good, Unit testing the framework gives the cofidence and here the framework is "REUSED".

    ReplyDelete
  7. I agree with you on Collections framework. It's definitely reusable. But what I don't agree is with this sentence:


    Having said that why do we follow OO. Its all for one word: reuse


    As I told you, it may be just me who thinks this. But if you're building application level stuff, then reusability goes out of picture very soon; almost. You don't find many components reusable even if you make them so. And reusability is something you can have without using OOP also. Take pthread library or take any C library. They are all done with plain C structures. And they are all done using procedural programming and they are all reusable, just like the object oriented Java Collections framework.

    In my opinion, polymorphism and inheritance are the grand daddy of all OOP features. Polymorphism with careful inheritance gives us the ability to replace one component with another: plugability. This helps testing a component in isolation. This feature of OOP is something you can't find in other programming methodologies. And even if you try to mimic them, it's very difficult.

    What do you say? :-)

    Srikanth

    ReplyDelete
  8. One thing adding to your comment is we develop applications not for Unit testing, but for solving some Problem.

    Now, OOP is much useful and reusable at Design level. For e.g: It is very good when we design frameworks, where many people reuse it and the complications can be reduced in using the API.

    For application programmers who are not designers, they can use OOP for some entity Objects rather than for some transient objects.

    But still the option is open, if they want to use it to reduce the complexity and reduce the performance Or make it complicated and check for more performance and less maintaince.

    And for your comments on "Its all for one word: reuse". It should be "Its highly used for one word: reuse".

    ReplyDelete
  9. hey man ... well thought.. here u'll find some good vid resources ..
    infoq.com
    parleys.com

    - ashwin

    ReplyDelete
  10. @Srikanth - I agree with you that reuse in the sense of "reusing components between projects" is not that common. However, reuse within a project is very common...and we have polymorphism and encapsulation to think.

    Any time you have two classes implementing an interface, you have reuse. Clients of that interface could previously only use that first class, but when you create the second one, clients can now be reused with this other object to modify behavior somewhat. Encapsulation makes it possible to write self-contained, composable behavior, and polymorphism lets us reuse logic with many different objects.

    ReplyDelete
  11. @Pat - Although your arguments didn't entirely convince me, it was the most convincing I've heard so far.

    Still, I wouldn't like to call switching implementations as reusability. IMO, the name is a little misleading. If polymorphism is a little confusing word, I would like it if it's called "pluggability" instead of reusability. In other words those two classes are substitutable, not reusable.

    Good discussion, thanks!

    ReplyDelete
  12. Some of the info from CMU:

    abstraction: 1. A process of eliminating, hiding, or ignoring characteristics or aspects of a concept unrelated to a given purpose. 2. A concept or system construct that has been subjected to a process of abstraction.

    composition: An act or result of combining simpler objects into more complex ones. For example, simpler data types can be combined into more complex ones. Composition also refers to the act or result of determining the net effect produced by combining functions; for example a composite function can be determined by applying each given function to the results of the previous function in some order in a cascade.

    ReplyDelete