Announcement

Collapse
No announcement yet.

My findings on PowerBasic OO

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • My findings on PowerBasic OO

    Hi, I've been away from PowerBasic for a while but being interested in OO programming decided to examine how this is implemented in PB10. On first glance it looks very good and certainly fills many boxes. I'm not currently implementing any COM based software, but pleased that the developers included the ability to create non COM based classes along with class inheritance.
    To try out PB's capabilities I knocked up a 3D Vector class (See below) to see how it compares to the likes of C++ and C#. Despite the slight syntactical differences all went fairly smoothly. I have noticed a few things which would be nice if added, and also something which at first thought was missing but I seem to have found a way around. To explain I have included a smaller program below which defines a base class along with a derived class. In this example I wanted to see if I could create C++’s equivalents of private and protected field members. Perhaps I have missed this in the documentation or it’s mentioned elsewhere on the forum, but anyway as I now understand it, instance variables are equivalent to C++’s private fields. This means that external code including derived classes do not have access to these instance variables. But, how about protected fields, are these possible in PB10? Protected fields are very good when using inheritance because any classes derived from a base class with protected fields then have their own set of these protected fields. Without this you would have to define the same fields again in each derived class.
    I have discovered that Global fields defined before the interface section within a class do appear to act as per protected fields! Here is the example:

    HTML Code:
    #Compile Exe
    #Dim All
    
    Class BaseClass
       ' Private:
       Instance InstanceVal As Long
    
       ' Protected:
       Global GlobalVal As Long
    
       ' Public Constructor.
       Class Method Create()
          InstanceVal = 12
          GlobalVal = 10
       End Method
    
       ' Public Destructor.
       Class Method Destroy()
       End Method
    
       'Public: Methods and properties only
       Interface BaseInterface
          Inherit IUnknown
    
          Method GetInstanceVal() As Long
             Method = InstanceVal
          End Method
    
          Method GetGlobalVal() As Long
             Method = GlobalVal
          End Method
    
       End Interface
    End Class
    
    Class DerivedClass
    
       Class Method Create()
          'Not visible in derived class, therefore private!
          'InstanceVal = 13
          'Only visible from base class and derived classes, therefore protected!
          GlobalVal = 20
       End Method
    
       Class Method Destroy()
       End Method
    
       Interface DerivedInterface
          Inherit BaseClass, BaseInterface
       End Interface
    End Class
    
    Function PBMain () As Long
    
       Local hWin As Long
    
       Txt.Window("Text Window - Private Fields", 200, 200, 15, 80) To hWin
    
       Local d As DerivedInterface
       d = Class "DerivedClass"
    
       Txt.Print "d.GetInstanceVal() = " + Str$(d.GetInstanceVal())
       Txt.Print "d.GetGlobalVal() = " + Str$(d.GetGlobalVal())
    
       'd.InstanceVal not visible
       'txt.print "d.InstanceVal = " + str$(d.InstanceVal)
       'd.GlobalVal not visible
       'txt.print "d.GlobalVal = " + str$(d.GlobalVal)
    
       Txt.WaitKey$
    End Function
    In the above code I have commented out the lines that wont compile. It can be seen that if trying to access the InstanceVal instance variable from within the Derived class this is a no go, which confirms that it is indeed private. On the other hand, the GlobalVal variable is accessible from within the derived class. In fact, the derived class gets it’s own version which by default is set to 0. In the example I have assigned it a value of 20 within the derived class’s constructor. However, both of these field values are invisible to the object users as can be seen with the commented out code in Function PBMain. This confirms to me that we do have private and protected capability.

    Now for my 3D Vector class example. This showed me how to construct a PB10 class with properties, using a constructor, along with public and private methods. The class provides the usual methods associated with 3D vectors and highlights how it would be nice if we could overload the operators such as +, -, * etc. Additionally, overloaded constructors and methods would be nice!

    Here is the code which I hope some may find useful:

    Code:
    #Compile Exe
    #Dim All
    
    Class Vector3Class
       ' Private. Instance variables are contiguous in memory!
       Instance X, Y, Z As Single
    
       ' Public - Constructor.
       Class Method Create()
          X = 0.0 : Y = 0.0 : Z = 0.0
       End Method
    
       ' Can't have overloaded constructors!
       'Class Method Create()
       '   X = 1.1 : Y = 1.1 : Z = 1.1
       'End Method
    
       ' Public - Destructor.
       Class Method Destroy()
          ' Nothing to do
       End Method
    
       ' Private.
       Class Method getLength() As Single
          Method = Sqr(X*X + Y*Y + Z*Z)
       End Method
    
       ' Public: Methods and properties only.
       Interface Vector3
          Inherit IUnknown
    
          Property Get X As Single
             Property = X
          End Property
          Property Set X (ByVal xval As Single)
             X = xval
          End Property
    
          Property Get Y As Single
             Property = Y
          End Property
          Property Set Y (ByVal yval As Single)
             Y = yval
          End Property
    
          Property Get Z As Single
             Property = Z
          End Property
          Property Set Z (ByVal zval As Single)
             Z = zval
          End Property
    
          Property Get Length As Single
             Property = me.getLength()
          End Property
    
          Property Get Magnitude As Single
             Property = me.getLength()
          End Property
    
          Method Normalise()
             Local vLen As Single
             vLen = me.length()
             ' Divide each component by the length.
             X = X / vLen : Y = Y / vLen : Z = Z / vLen
          End Method
    
          ' Ideally PB would have overloaded operators.
          ' To check for equality we want to write if Vector1 = Vector2 then...
          ' not if Vector1.Equals(Vector2) then...
          Method Equals(vector As Vector3) As Byte
             If( me.X = vector.X And me.Y = vector.Y And me.Z = vector.Z ) Then
                Method = 1
             Else
                Method = 0
             End If
          End Method
    
          ' Ideally PB would have overloaded operators.
          ' We want to be able to write NewVector = Vector1 + Vector2
          ' instead of NewVector = vector1.Plus(vector2)
          Method Plus(vector As Vector3) As Vector3
             Local sum As Vector3
             sum = Class "Vector3Class"
    
             sum.X = X + vector.X
             sum.Y = Y + vector.Y
             sum.Z = Z + vector.Z
             Method = sum
          End Method
    
          ' Ideally PB would have overloaded operators.
          Method Minus(vector As Vector3) As Vector3
             Local subtract As Vector3
             subtract = Class "Vector3Class"
    
             subtract.X = X - vector.X
             subtract.Y = Y - vector.Y
             subtract.Z = Z - vector.Z
             Method = subtract
          End Method
    
          ' Ideally PB would have overloaded operators.
          ' We want to be able to write NewVector = Vector1 * scalar
          ' not NewVector = Vector1.Times(scalar)
          Method Times(scalar As Single) As Vector3
             Local p As Vector3
             p = Class "Vector3Class"
    
             p.X = X * scalar
             p.Y = Y * scalar
             p.Z = Z * scalar
             Method = p
          End Method
    
          ' Ideally PB would have overloaded operators.
          ' We want to be able to write Value = Vector1 * Vector2
          ' not Value = Vector1.dot(Vector2)
          Method dot(vector As Vector3) As Single
             Method = X * vector.X + Y * vector.Y + Z * vector.Z
          End Method
    
          ' Ideally this would be an overloaded constructor.
          ' That way we could set the vector values on creation, making it more efficient.
          Method Vector3(ByVal xval As Single, ByVal yval As Single, ByVal zval As Single)
             X = xval : Y = yval : Z = zval
          End Method
    
          ' Ideally this would be an overloaded constructor.
          ' Same comment as above.  In this case we are setting the Vector fields from an array.
          Method VectorArray(ByVal pCoords As Single Ptr)
             X = @pCoords[0] : Y = @pCoords[1] : Z = @pCoords[2]
          End Method
    
          ' Returns vector as a pointer to an array.
          ' In C++ we could override the float cast operator
          ' to return the address of the array. But I think
          ' the overloaded operators above would be the most wanted.
          Method toSingleArray() As Single
             Method = VarPtr(X)
          End Method
    
       End Interface
    
    End Class
    
    Function PBMain () As Long
    
       Local hWin As Long
       Dim coords(0 To 2) As Single
    
       Txt.Window("Text Window - Vector3", 200, 200, 20, 80) To hWin
    
       Local u, v, w As Vector3
       u = Class "Vector3Class"
       v = Class "Vector3Class"
       w = Class "Vector3Class"
    
       coords(0) = 1.0 : coords(1) = 2.0 : coords(2) = 3.0
    
       v.VectorArray(VarPtr(coords(0)))
       w.Vector3(-5.0, 2.0, 0.0)
    
       ' Print the three vectors
       Txt.Print "Vector u: X = " + Str$(u.X) + " Y = " + Str$(u.Y) + " Z = " + Str$(u.Z)
       Txt.Print "Vector v: X = " + Str$(v.X) + " Y = " + Str$(v.Y) + " Z = " + Str$(v.Z)
       Txt.Print "Vector w: X = " + Str$(w.X) + " Y = " + Str$(w.Y) + " Z = " + Str$(w.Z)
    
       ' u = v + w
       u = v.Plus(w)
       Txt.Print "Vector u: X = " + Str$(u.X) + " Y = " + Str$(u.Y) + " Z = " + Str$(u.Z)
    
       ' Normalise
       v.Normalise()
       Txt.Print "Vector v: X = " + Str$(v.X) + " Y = " + Str$(v.Y) + " Z = " + Str$(v.Z)
       Txt.Print "v.length() = " + Str$(v.length())
    
       ' dotP = u * w
       ' single val = u.dot(w)
       Local dotP As Single
       dotP = u.dot(w)
       Txt.Print "u.dot(w) = " + Str$(dotP)
    
       Local VecByScalar As Vector3
       VecByScalar = Class "Vector3Class"
       VecByScalar.VectorArray(VarPtr(coords(0)))
    
       Txt.Print "Vector : X = " + Str$(VecByScalar.X) + " Y = " + Str$(VecByScalar.Y) + " Z = " + Str$(VecByScalar.Z)
    
       ' NewVector = Vector * scalar
       VecByScalar = VecByScalar.Times(10.0)
       Txt.Print "Vector * scalar : X = " + Str$(VecByScalar.X) + " Y = " + Str$(VecByScalar.Y) + " Z = " + Str$(VecByScalar.Z)
    
       ' Get vector as an array.
       Dim vecarray(0 To 2) As Single At v.toSingleArray()
       Txt.Print "X = " + Str$(vecarray(0)) + " Y = " + Str$(vecarray(1)) + " Z = " + Str$(vecarray(2))
    
       v.VectorArray(VarPtr(coords(0)))
       Txt.Print "Vector v: X = " + Str$(v.X) + " Y = " + Str$(v.Y) + " Z = " + Str$(v.Z)
       w.Vector3(-2.0, -1.0, -3.0)
       Txt.Print "Vector w: X = " + Str$(w.X) + " Y = " + Str$(w.Y) + " Z = " + Str$(w.Z)
    
       ' u = v - w
       u = v.Minus(w)
       Txt.Print "Vector v - w: X = " + Str$(u.X) + " Y = " + Str$(u.Y) + " Z = " + Str$(u.Z)
    
       Txt.WaitKey$
    
    End Function
    Thanks for reading!
    Last edited by Raymond Couzens; 10 Jan 2012, 08:15 AM. Reason: Tidying up my examples!

  • #2
    Implementation Inheritance Not So Good

    There is something of a controversy in the OOP software world Raymond concerning 'Implementation Inheritance' and its merits. In the first phase of OOP thinking during the 1980s when C++ was being developed it was thought that inheritance was an unequivocal good, and during that period deeply nested inheritance chains were developed. By the 1990s some of the problems with this were becomming apparent, and that is why Microsoft did not incorporate implementation inheritance into COM. To put the issue most simply, the very smallest change within any base class brought the entire ediface crumbling down, and Microsoft's goal was the creation of dynamic runtime systems where object/components could e 'hot swapped' at runtime and still keep functioning. To achieve this components had to be oblivious and completely sealed off from any knowledge of the internal structure (knowledge of private data members) of any sub-objects they were using.

    If you do a search of 'implementation inheritance bad' you'll find a lot of links. Here's just one...



    ...and here's some quotes from another...



    Coupling

    A more crucial problem with implementation inheritance is coupling—the undesirable reliance of one part of a program on another part. Global variables provide the classic example of why strong coupling causes trouble. If you change the type of the global variable, for example, all functions that use the variable (i.e., are coupled to the variable) might be affected, so all this code must be examined, modified, and retested. Moreover, all functions that use the variable are coupled to each other through the variable. That is, one function might incorrectly affect another function's behavior if a variable's value is changed at an awkward time. This problem is particularly hideous in multithreaded programs.

    As a designer, you should strive to minimize coupling relationships. You can't eliminate coupling altogether because a method call from an object of one class to an object of another is a form of loose coupling. You can't have a program without some coupling. Nonetheless, you can minimize coupling considerably by slavishly following OO (object-oriented) precepts (the most important is that the implementation of an object should be completely hidden from the objects that use it). For example, an object's instance variables (member fields that aren't constants), should always be private. Period. No exceptions. Ever. I mean it. (You can occasionally use protected methods effectively, but protected instance variables are an abomination.) You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public (though access functions that return full-blown objects rather than a basic-type value are reasonable in situations where the returned object's class is a key abstraction in the design).

    I'm not being pedantic here. I've found a direct correlation in my own work between the strictness of my OO approach, quick code development, and easy code maintenance. Whenever I violate a central OO principle like implementation hiding, I end up rewriting that code (usually because the code is impossible to debug). I don't have time to rewrite programs, so I follow the rules. My concern is entirely practical—I have no interest in purity for the sake of purity.

    The fragile base-class problem

    Now, let's apply the concept of coupling to inheritance. In an implementation-inheritance system that uses extends, the derived classes are very tightly coupled to the base classes, and this close connection is undesirable. Designers have applied the moniker "the fragile base-class problem" to describe this behavior. Base classes are considered fragile because you can modify a base class in a seemingly safe way, but this new behavior, when inherited by the derived classes, might cause the derived classes to malfunction. You can't tell whether a base-class change is safe simply by examining the base class's methods in isolation; you must look at (and test) all derived classes as well. Moreover, you must check all code that uses both base-class and derived-class objects too, since this code might also be broken by the new behavior. A simple change to a key base class can render an entire program inoperable.
    For these reasons I find your judgement on PowerBASIC very favorable in light of the fact that PowerBASIC's implementation of inheritance isn't exactly like that of C++. I think many have judged it unfairly due to this when in point of fact PowerBASIC's implementation is quite advanced and is in accord with current thinking on the topic.
    Fred
    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

    Comment


    • #3
      All PB classes are COM classes.
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        Global is Global in scope

        Global is of global scope and not limited to the class


        Code:
        #COMPILE EXE
        #DIM ALL
        
        
        
        CLASS BaseClass
           ' Private:
           INSTANCE InstanceVal AS LONG
        
           ' Protected:
           GLOBAL GlobalVal AS LONG
        
           ' Public Constructor.
           CLASS METHOD CREATE()
              InstanceVal = 12
              GlobalVal = 10
           END METHOD
        
           ' Public Destructor.
           CLASS METHOD DESTROY()
           END METHOD
        
           'Public: Methods and properties only
           INTERFACE BaseInterface
              INHERIT IUNKNOWN
        
              METHOD GetInstanceVal() AS LONG
                 METHOD = InstanceVal
              END METHOD
        
              METHOD GetGlobalVal() AS LONG
                 METHOD = GlobalVal
              END METHOD
        
           END INTERFACE
        END CLASS
        
        CLASS DerivedClass
        
           CLASS METHOD CREATE()
              'Not visible in derived class, therefore private!
              'InstanceVal = 13
              'Only visible from base class and derived classes, therefore protected!
              GlobalVal = 20
           END METHOD
        
           CLASS METHOD DESTROY()
           END METHOD
        
           INTERFACE DerivedInterface
              INHERIT BaseClass, BaseInterface
           END INTERFACE
        END CLASS
        
        FUNCTION PBMAIN () AS LONG
        
           LOCAL hWin AS LONG
        
           TXT.WINDOW("Text Window - Private Fields", 200, 200, 15, 80) TO hWin
        
           LOCAL d AS DerivedInterface
           d = CLASS "DerivedClass"
        
           TXT.PRINT "d.GetInstanceVal() = " + STR$(d.GetInstanceVal())
           TXT.PRINT "d.GetGlobalVal() = " + STR$(d.GetGlobalVal())
        
        
        [COLOR="Red"][B]   GlobalVal = 99 ' ****************************
        
           TXT.PRINT "d.GetInstanceVal() = " + STR$(d.GetInstanceVal())
           TXT.PRINT "d.GetGlobalVal() = " + STR$(d.GetGlobalVal())
           TXT.PRINT "globalval = " STR$(globalVal)
        [/B][/COLOR]
        
           'd.InstanceVal not visible
           'txt.print "d.InstanceVal = " + str$(d.InstanceVal)
           'd.GlobalVal not visible
           'txt.print "d.GlobalVal = " + str$(d.GlobalVal)
        
           TXT.WAITKEY$
        END FUNCTION

        Comment


        • #5
          Thanks for checking that Brian. I hadn't tried Raymond's code, but had thought of doing so a few times today, as my initial thought when Raymond stated that the 'protected' variable was visible in the derived class, was that it would be visible everywhere else too!
          Fred
          "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

          Comment


          • #6
            Originally posted by José Roca View Post
            All PB classes are COM classes.
            Hi José, yes you are correct, what I meant to say is that we can create classes with inheritance which according to the help file is not part of the COM specification:

            IMPLEMENTATION INHERITANCE is the process whereby a CLASS derives all of the functionality of an interface implemented elsewhere. That is, the derived class now has all the methods and properties of this new, extended version of a Base Class! This form of inheritance is offered by PowerBASIC, even though it is not required by the COM Specification.

            Comment


            • #7
              Thanks Fred for your detailed response it is very useful.

              Also, thanks Brian for checking out the Global scope. I had thought/hoped that it's global scope would have been confined to methods of the containing class or inherited classes as per protected members. This is by no means the end of the world, but I was thinking that that in the situation of having legacy code which you don't want to break, inheriting a class or classes and overriding them to suit new requirements seems to me to be a good methodology. In this situation, you may not like having to redeclare fields used in the base classes.

              Comment


              • #8
                Originally posted by Raymond Couzens View Post
                Hi José, yes you are correct, what I meant to say is that we can create classes with inheritance which according to the help file is not part of the COM specification:
                ...
                This form of inheritance is offered by PowerBASIC, even though it is not required by the COM Specification.
                There is a subtle difference between "not part of" and "not required by".

                Comment


                • #9
                  Originally posted by Stuart McLachlan View Post
                  There is a subtle difference between "not part of" and "not required by".
                  Yes indeed, but I think might point is made.

                  Comment


                  • #10
                    Originally posted by Raymond Couzens View Post
                    Thanks Fred for your detailed response it is very useful.

                    Also, thanks Brian for checking out the Global scope. I had thought/hoped that it's global scope would have been confined to methods of the containing class or inherited classes as per protected members. This is by no means the end of the world, but I was thinking that that in the situation of having legacy code which you don't want to break, inheriting a class or classes and overriding them to suit new requirements seems to me to be a good methodology. In this situation, you may not like having to redeclare fields used in the base classes.
                    Good discussion. Note that inheriting a class would imply breaking all your existing code though. i.e. if class A inherits from class B. No code written in the past that expects a class B could use a class A. i.e. class A inherits from B but is not then also referrable as a class B. You could inherit A from B and write new code, but even the new code couldn't use A and B classes without hand coded tests to pick between them.

                    You could implement the same interface(s) from class B in class A and then they could be interchangable but you wouldn't be able to inherit (at least in the interface(s) in discussion).

                    If you have an OO background, PB objects can seem a bit odd at first.

                    Edit: Sounds like you realize this, but re-declaring fields doesn't allow you to use fields from a base class either even if they have the same names.
                    Last edited by Larry Charlton; 12 Jan 2012, 12:27 PM.
                    LarryC
                    Website
                    Sometimes life's a dream, sometimes it's a scream

                    Comment


                    • #11
                      Originally posted by Larry Charlton View Post
                      Good discussion. Note that inheriting a class would imply breaking all your existing code though. i.e. if class A inherits from class B. No code written in the past that expects a class B could use a class A. i.e. class A inherits from B but is not then also referrable as a class B. You could inherit A from B and write new code, but even the new code couldn't use A and B classes without hand coded tests to pick between them.

                      You could implement the same interface(s) from class B in class A and then they could be interchangable but you wouldn't be able to inherit (at least in the interface(s) in discussion).

                      If you have an OO background, PB objects can seem a bit odd at first.

                      Edit: Sounds like you realize this, but re-declaring fields doesn't allow you to use fields from a base class either even if they have the same names.
                      Hi Larry,

                      I take your point but I was thinking more on the lines of legacy code not needing to use the new derived class, the legacy code would be left working as it always did, unbroken by any new changes. New code would be taking advantage of exisiting tried and tested code but with new requirements added. This is where Protected fields would also be useful. I think one methodology would be to write base classes and have them thoroughly tested, then never to alter them. If new requirements come along then to derive newer classes from the base classes. This would of course require thorough documentation. This may not be ideal or even work in an organisation, but is just my way of thinking that OO could be used.

                      Comment


                      • #12
                        Originally posted by Raymond Couzens View Post
                        I think one methodology would be to write base classes and have them thoroughly tested, then never to alter them. If new requirements come along then to derive newer classes from the base classes.
                        There is nothing wrong with creating new properties/methods in a class as long as your ensure that they do not affect the functionality of any existing property/method..

                        I can't agree with Fred's earlier quote: "You can't tell whether a base-class change is safe simply by examining the base class's methods in isolation; you must look at (and test) all derived classes as well." unless the base-class is poorly implemented in the first place. If it is properly encapsulated, it doesn't matter how it is used in a derived class.

                        Comment


                        • #13
                          I actually agree with Fred and the article he quotes.

                          For many years now I've avoided the use of base classes and their inheritance to form new classes. In complex systems the maintence of such classes can become a nightmare.

                          As more derived classes are created, there is more and more pressure to tweek the base classes in ways that may not be appropriate for all uses of those base classes. So for our systems I've mandated that the "normal" inheritance of base classes is forbidden. Instead we take the following approach, using composite and non-composite classes.

                          Non-composite classes contain everything they need in order to perform their job, without referencing a base class.

                          Composite classes don't inherit base classes in the normal sense, but contain instances of the base classes. This adds a bit of extra code, but provides a good disconnect between the classes. It works well with PB.

                          We use EZGUI and have developed classes that encapsulate the EZGUI functionality, such as form and control creation, and message processing.

                          For example, the composite SplitterBar class contains a form for enclosing the entire control, two forms for the left/top and right/bottom panels, and a shape control for the splitter bar. These forms and controls are instances of a generic panel and a generic shape class.

                          Other examples of composite classes are the Menu class that provides the functionality of a menu bar in the form of a treeview, and the ButtonBar class that allows related sets of Buttons to be defined and processed.

                          The resulting code is structured much like VB, in that message handling happens deep in the bowels of the non-composite classes, and user code is executed in user-level procedures such as Click and KeyPress.

                          R

                          Comment


                          • #14
                            Designers have applied the moniker "the fragile base-class problem" to describe this behavior. Base classes are considered fragile because you can modify a base class in a seemingly safe way, but this new behavior, when inherited by the derived classes, might cause the derived classes to malfunction.
                            Another 'moniker' you'll fnd in the literature concerning this issue is 'white-box-reuse'. You can't really treat these deeply inherited base classes as 'black boxes'; they are somewhat 'opaque', as 'protected' members are accessable from inheriting classes. Hense they're not 'black boxes' but rather 'white boxes'.

                            From...



                            OOP programming also requires that quite a bit of time and effort be spent wrestling with scoping rules and other essentially clerical issues. For example, among the OOP scoping commands are: Protected, Friend, and Shared. You even find combination scoping, using two scope declarations at the same time, such as Protected Friend, ReadOnly Public, and WriteOnly Friend. This kind of inflation, and the resulting ambiguity, should be a clue that theory is triumphing over practicality. Encapsulation--sealing off successful code from further modification--is a valuable component of OOP. (OOP’s polymorphism and inheritance features are often so damaging, bug-inducing, and unnecessarily complex that it’s generally sensible to avoid them whenever possible.) However, creating “black-box” code is hardly exclusive to OOP. Most computer languages permit you to compile code libraries that contain unmodifiable, finished procedures. Where OOP differs is that it encourages encapsulation not just in libraries where code is being reused, but also promotes hiding source code within a currently active programming project. In other words--don’t let one programmer see another programmer’s source code.

                            OOP encourages writing code that behaves differently in different contexts (polymorphism). Instead of creating two procedures, one named ChocolateShake and one named VanillaShake, you instead create one procedure named Shake that can be either chocolate or vanilla, depending on the data you feed to the procedure. While this sounds promising, in practice it’s confusing. Code can become harder to read because you’ve removed the descriptive parts of the name--chocolate and vanilla--from the procedure’s name. You’ve created a more general-purpose procedure out of two, more specific, more understandable, procedures. OOP also encourages code reuse via inheritance: expecting the programmer to modify invisible (encapsulated) code. The contribution of inheritance to code unreadability, slow program execution, and bugs in general has--even among some OOP apologists--been widely acknowledged.
                            Fred
                            "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                            Comment


                            • #15
                              I won't discount that there are challenges facing OO programmers. But statements such as:

                              "There’s no evidence that the OOP approach is efficient for most programming jobs."


                              aren't simply facts because someone stated them. I believe Scott Meyers might completely take issue with that as it appears the be the central theme he lives to debunk.


                              I could just as easily restate what appears to be the wikipedia definition of fragile base classes for procedural programming.


                              "Procedural programming has largely failed because of the use of global variables."


                              Saying doesn't make it any truer, but also doesn't mean it's completely without merit either. I think a bit more acurate restatement of fragile base class could be: Architecture and design are difficult. Even with cautious approaches, initial tries at solving problems in new ways may ultimately reach a dead end and require a good deal of re-work. Finding new ways to assist in minimizing the amount of re-work and increasing the adaptability for any programming endeavor could be considered worthwhile.


                              I personally find articles showing ways to accomplish things far better than articles saying things are bad or impossible.
                              Last edited by Larry Charlton; 13 Jan 2012, 04:59 AM.
                              LarryC
                              Website
                              Sometimes life's a dream, sometimes it's a scream

                              Comment


                              • #16
                                It helps to remember that OOP is just one of many concepts created over the past 50 years that were intended to make programming a perfect science. Of course, that never happened. In general, programs are just as buggy and difficult to maintain as they ever were - except now they're bloated and need massive hardware.

                                Having worked on many different platforms, using many different languages, I've found that you work with what you've got. And in pushing languages to the limit I've come up with some simples rules for overcoming the tyranny of programming dogma.

                                The first rule is: there are no rules when it comes to what language features are used and how you use them.

                                The second rule is: don't get tricky when simple will do it.

                                The third rule is: be paranoid about maintaining whatever programming standards you have deemed are appropriate to the way you think and work.

                                R
                                Last edited by Rod Gobby; 13 Jan 2012, 10:30 AM.

                                Comment


                                • #17
                                  I certainly second the Second Rule of Rod, which could also be abreviated to a KISS.

                                  Regarding the dreaded fragile base class issue, it hasn't yet brought Java programming to its knees, though I note (but have never used) a Java language feature to prohibit inheritance, which might help one's successors-in-code at least to think twice before extending the object beyond its design envelope.

                                  My first ten years coding preceded my first OOP experiences. Many things seem to work out easier for me using classes, though "every head is a world". I have also seen some very bad OOP code where the coder has not really understood the nature of the object and has created a mountain of code to fill the chasm between the ideal object and the one which he has realised.

                                  Comment


                                  • #18
                                    Don't forget that sometimes OOP is your only option. If you need to manipulate a Word document good luck with procedural code. And if you are dealing with a file format that was not designed with OOP in mind, good luck shoehorning it.

                                    My paintbrush is not "better" than my hammer.

                                    -- Eric
                                    "Not my circus, not my monkeys."

                                    Comment


                                    • #19
                                      Don't forget that sometimes OOP is your only option. If you need to manipulate a Word document good luck with procedural code.
                                      Semantics....

                                      Object Oriented Programming is a programming technique.

                                      Component Object Model defines an interface.

                                      You can use a COM interface with procedural code: Jose Roca has posted a bunch of code right here which queries the function pointers and calls the various properties and methods of the interfaces by address.... all using procedural code.

                                      The PB compiler now offers native syntax to utilize or create COM interfaces... which it implements via Object Oriented Programming syntax.

                                      In your specific example - interfacing with Microsoft Word - the API is offered only with COM interface; but you can chose to implement that interface with either procedural code or via OOP.

                                      Also relating to your MS-Word example: if you look at Jose's procedural code for handling a COM interface, yes, you will need good luck because it sure ain't anywhere near as understandable as is using OOP techniques.



                                      MCM
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        Originally posted by Michael Mattias View Post
                                        Object Oriented Programming is a programming technique.

                                        Component Object Model defines an interface.

                                        You can use a COM interface with procedural code
                                        PB Win 8 is great for this, for example.

                                        Comment

                                        Working...
                                        X