Design by Contract for abstract base class?

Discussion in 'C++' started by kk_oop, Oct 26, 2003.

  1. kk_oop

    kk_oop Guest

    Hi. I'm looking to find a way to apply Design by Contract in my C++
    programs.

    The problem that I'm having deals with pure abstract base classes.
    Since these are often how an object gets exposed to clients via
    polymorphism, it seems critical that an abstract base class can define
    and enforce its contracts. Defining contracts is critical, so LSP can
    be utilized when defining derived implementation classes. However, if
    the pure abstract base class defines a method to enforce its contract,
    it will no longer be pure abstract. This poses a problem, for instance,
    if the abstract class is being used to apply multiple interface
    inheritance. In that case, the abstract class really needs to be pure
    abstract.

    Is there a way for C++ to somehow enable an pure abstract base class to
    enforce its contracts? Seems like an unfixable paradox.

    Any thoughts?

    Thanks,

    Ken
     
    kk_oop, Oct 26, 2003
    #1
    1. Advertising

  2. kk_oop

    David White Guest

    kk_oop<no_spam> @yahoo.com> <"kk_oop<no_spam> wrote in message
    news:bnh5k7$cje$...
    > Hi. I'm looking to find a way to apply Design by Contract in my C++
    > programs.
    >
    > The problem that I'm having deals with pure abstract base classes.
    > Since these are often how an object gets exposed to clients via
    > polymorphism, it seems critical that an abstract base class can define
    > and enforce its contracts. Defining contracts is critical, so LSP can
    > be utilized when defining derived implementation classes. However, if
    > the pure abstract base class defines a method to enforce its contract,
    > it will no longer be pure abstract. This poses a problem, for instance,
    > if the abstract class is being used to apply multiple interface
    > inheritance. In that case, the abstract class really needs to be pure
    > abstract.
    >
    > Is there a way for C++ to somehow enable an pure abstract base class to
    > enforce its contracts? Seems like an unfixable paradox.


    I don't know if I can help because I don't know what you are talking about.
    This is a C++ (and, incidentally, a plain text) newsgroup, but I don't see
    much in your post beyond a whole lot of OO jargon. If you have a C++
    question, and you can ask it in _plain_ language, and without undefined
    abbreviations such as 'LSP', please ask it.

    In the meantime, I'll have a stab at answering this part: "However, if the
    pure abstract base class defines a method to enforce its contract, it will
    no longer be pure abstract."

    // abstract class
    class Base
    {
    public:
    virtual void f() = 0; // pure virtual
    };

    // implementation of pure virtual
    void Base::f()
    {
    }

    // concrete class
    class Derived : public Base
    {
    public:
    void f() {} // override Base::f()
    };

    int main()
    {
    Derived d; // okay
    Base b; // error; Base::f() pure virtual
    }

    The point is that Base is still abstract, or "pure abstract" as you put it,
    even though Base "defines a method" for its only pure virtual function.

    DW
     
    David White, Oct 27, 2003
    #2
    1. Advertising

  3. kk_oop

    jeffc Guest

    "David White" <> wrote in message
    news:vE%mb.87$...
    > kk_oop<no_spam> @yahoo.com> <"kk_oop<no_spam> wrote in message
    > news:bnh5k7$cje$...
    > > Hi. I'm looking to find a way to apply Design by Contract in my C++
    > > programs.
    > >
    > > The problem that I'm having deals with pure abstract base classes.
    > > Since these are often how an object gets exposed to clients via
    > > polymorphism, it seems critical that an abstract base class can define
    > > and enforce its contracts. Defining contracts is critical, so LSP can
    > > be utilized when defining derived implementation classes. However, if
    > > the pure abstract base class defines a method to enforce its contract,
    > > it will no longer be pure abstract. This poses a problem, for instance,
    > > if the abstract class is being used to apply multiple interface
    > > inheritance. In that case, the abstract class really needs to be pure
    > > abstract.
    > >
    > > Is there a way for C++ to somehow enable an pure abstract base class to
    > > enforce its contracts? Seems like an unfixable paradox.

    >
    > I don't know if I can help because I don't know what you are talking

    about.
    > This is a C++ (and, incidentally, a plain text) newsgroup, but I don't see
    > much in your post beyond a whole lot of OO jargon. If you have a C++
    > question, and you can ask it in _plain_ language, and without undefined
    > abbreviations such as 'LSP', please ask it.


    OO jargon is obviously part of C++, since C++ is an OO language. LSP is
    Liskov Substitution Principle, which basically says that inheritance should
    be used when a subclass object can be substituted for a base class object,
    and the code would still work the same.

    > In the meantime, I'll have a stab at answering this part: "However, if the
    > pure abstract base class defines a method to enforce its contract, it will
    > no longer be pure abstract."


    He might be confusing "pure abstract" with "pure virtual", or there might be
    an OO term that would translate in C++ terms to "a base class with a pure
    virtual function that has no function definitions". Or, as you said, he
    might not be aware that abstract classes can have function definitions while
    still not allowing any instances to be created. I'd ask the OP what his
    definition of "abstract class" is, at this point.
     
    jeffc, Oct 27, 2003
    #3
  4. kk_oop

    David White Guest

    jeffc <> wrote in message
    news:...
    >
    > "David White" <> wrote in message
    > news:vE%mb.87$...
    > > I don't know if I can help because I don't know what you are talking

    > about.
    > > This is a C++ (and, incidentally, a plain text) newsgroup, but I don't

    see
    > > much in your post beyond a whole lot of OO jargon. If you have a C++
    > > question, and you can ask it in _plain_ language, and without undefined
    > > abbreviations such as 'LSP', please ask it.

    >
    > OO jargon is obviously part of C++, since C++ is an OO language.


    Yes, but I've never see so much OO jargon in discussions of C++ features.
    What exactly does it mean for an abstract base class to "define and enforce
    its contracts"? Is "multiple interface inheritance" simply multiple
    inheritance? The OP is speaking a language that I don't recall most of the
    C++ experts in this newsgroup ever speaking.

    > LSP is
    > Liskov Substitution Principle, which basically says that inheritance

    should
    > be used when a subclass object can be substituted for a base class object,
    > and the code would still work the same.


    I have a colleague who is usually brilliant at recalling the meanings of the
    most obscure abbreviations used in a range of computing-related areas. If I
    come across one I don't know, I call out, "What does <insert abbrev> mean?"
    and he can nearly always tell me. He and I are also project leaders and OO
    designers and implementers of about 10 years experience. Neither of us knew
    what "LSP" meant. The principle itself seems rather obvious to me and I use
    it all the time, but I don't feel as though I've missed anything important
    in not knowing its name.

    DW
     
    David White, Oct 27, 2003
    #4
  5. kk_oop

    Ken Guest

    "jeffc" <> wrote in message news:<>...

    > He might be confusing "pure abstract" with "pure virtual", or there might be
    > an OO term that would translate in C++ terms to "a base class with a pure
    > virtual function that has no function definitions". Or, as you said, he
    > might not be aware that abstract classes can have function definitions while
    > still not allowing any instances to be created. I'd ask the OP what his
    > definition of "abstract class" is, at this point.


    Hi. What I was trying to refer to is a class that has only pure
    virtual methods and no data. What is the term for that in C++? In
    Java and UML it's an interface.

    Anyway, perhaps that puts my original question in a clearer context?
    My understanding of C++ (based on Scott Meyers' Effective C++) is that
    multiple inheritance should only be done for interface base classes
    (using my definition of interface class above). By adding a contract
    verification method to the interface base class, it should no longer
    be used in multiple inheritance relationships, since it would have
    implementation. But if you don't define these contract verification
    methods in the base class, you'd have to define them in every instance
    of the derived classes. Perhaps not a bad thing. Or perhaps there's
    another way to do this--maybe with ASSERTs?

    If that adds some clarity, are there any suggestions or comments?

    Thanks again,

    Ken
     
    Ken, Oct 28, 2003
    #5
  6. kk_oop

    David White Guest

    Ken <> wrote in message
    news:...
    > "jeffc" <> wrote in message

    news:<>...
    >
    > > He might be confusing "pure abstract" with "pure virtual", or there

    might be
    > > an OO term that would translate in C++ terms to "a base class with a

    pure
    > > virtual function that has no function definitions". Or, as you said, he
    > > might not be aware that abstract classes can have function definitions

    while
    > > still not allowing any instances to be created. I'd ask the OP what his
    > > definition of "abstract class" is, at this point.

    >
    > Hi. What I was trying to refer to is a class that has only pure
    > virtual methods and no data. What is the term for that in C++? In
    > Java and UML it's an interface.


    I don't know, but I doubt it has a different name in C++. I've never paid
    much attention to whether a class that only has pure virtual functions has
    data members or not, because I don't see how that makes a fundamental
    difference to it either way.

    > Anyway, perhaps that puts my original question in a clearer context?
    > My understanding of C++ (based on Scott Meyers' Effective C++) is that
    > multiple inheritance should only be done for interface base classes
    > (using my definition of interface class above).


    I haven't read it, but that sounds a bit odd to me. I've hardly ever used
    multiple inheritance for any purpose. It just seems unwieldy and inelegant
    to me, but if I were to use it I don't see why it should be restricted to
    interface classes.

    > By adding a contract
    > verification method to the interface base class, it should no longer
    > be used in multiple inheritance relationships, since it would have
    > implementation.


    I think it's necessary to fully understand the reason for what "should" no
    longer be done. If there's a compelling reason that multiple inheritance
    should not be used just because you add implementations for pure virtual
    functions, I can't guess what it is. Do what works unless someone can
    identify why it shouldn't be done.

    > But if you don't define these contract verification
    > methods in the base class, you'd have to define them in every instance
    > of the derived classes. Perhaps not a bad thing. Or perhaps there's
    > another way to do this--maybe with ASSERTs?


    Can you give an example of what a contract-verification method does,
    preferably with some real code?

    DW
     
    David White, Oct 28, 2003
    #6
  7. kk_oop

    kenandeva Guest

    David White wrote:

    >>"David White" <> wrote in message
    >>news:vE%mb.87$...
    >>
    >>

    DW:

    For info on contracts and LSP, see: http://ootips.org/lsp.html

    It's got some cross reference links to additional info.

    You can look at LSP almost like a design pattern, in that it's a good
    practice that lots of good OO designers do without giving it a name.
    Barbara Liskov gave it a name and wrote a paper about it, so, just like
    with a design pattern, the name she gave stuck--and it just happens to
    include her own name (as in Liskov Substitutability Principle). Save
    that for the OO version of Trivial Pursuit. :) Though I do find it
    useful to just refer to the concept as LSP, just like calling a
    Singleton a Singleton is easier that describing what it means every time
    you need to bring it up.

    If you want to see her original paper (I wouldn't recommend it--it's
    very dense. The OO tips links are much more readable.), it's called: A
    Behavioral Notion of Subtyping. Doing a Google search reveals many PDF
    versions suitable for framing and giving as gifts this holiday season :).

    My questions have to do with defining the contracts used to verify
    LSP--namely should they just be comments in a method or class abstract,
    or can/should they be actually included in the code via ASSERTs or
    contract verification methods.

    See ya,

    Ken



    >
    >
    >
     
    kenandeva, Oct 28, 2003
    #7
  8. kk_oop

    jeffc Guest

    "David White" <> wrote in message
    news:W9hnb.141$...
    > >
    > > OO jargon is obviously part of C++, since C++ is an OO language.

    >
    > Yes, but I've never see so much OO jargon in discussions of C++ features.


    That was quite a load :)

    > > LSP is
    > > Liskov Substitution Principle, which basically says that inheritance

    > should
    > > be used when a subclass object can be substituted for a base class

    object,
    > > and the code would still work the same.

    >
    > I have a colleague who is usually brilliant at recalling the meanings of

    the
    > most obscure abbreviations used in a range of computing-related areas. If

    I
    > come across one I don't know, I call out, "What does <insert abbrev>

    mean?"
    > and he can nearly always tell me. He and I are also project leaders and OO
    > designers and implementers of about 10 years experience. Neither of us

    knew
    > what "LSP" meant. The principle itself seems rather obvious to me and I

    use
    > it all the time, but I don't feel as though I've missed anything important
    > in not knowing its name.


    Yes, the principle is sometimes called just "substitutability", as in C++
    FAQs. Someone (Liskov?) decided someone needed credit for it. I don't
    think you've missed anything either.
     
    jeffc, Oct 28, 2003
    #8
  9. kk_oop

    jeffc Guest

    "kenandeva<no spam> @yahoo.com>" <"kenandeva<no spam> wrote in message
    news:bnkkci$dq2$...
    >
    > My questions have to do with defining the contracts used to verify
    > LSP--namely should they just be comments in a method or class abstract,
    > or can/should they be actually included in the code via ASSERTs or
    > contract verification methods.


    ASSERTs are pretty much a waste of time, since they only affect debug code
    (I've never been much of a fan of ASSERT). Comments would be good, but they
    can never be enforced (I know, I tried - that was my job for about 6 months
    one time.)
     
    jeffc, Oct 28, 2003
    #9
  10. kk_oop

    jeffc Guest

    "Ken" <> wrote in message
    news:...
    > "jeffc" <> wrote in message

    news:<>...
    >
    > > He might be confusing "pure abstract" with "pure virtual", or there

    might be
    > > an OO term that would translate in C++ terms to "a base class with a

    pure
    > > virtual function that has no function definitions". Or, as you said, he
    > > might not be aware that abstract classes can have function definitions

    while
    > > still not allowing any instances to be created. I'd ask the OP what his
    > > definition of "abstract class" is, at this point.

    >
    > Hi. What I was trying to refer to is a class that has only pure
    > virtual methods and no data. What is the term for that in C++? In
    > Java and UML it's an interface.


    I don't think there is a term for that in C++ because there's nothing to
    enforce it. An abstract class can have data.

    > Anyway, perhaps that puts my original question in a clearer context?
    > My understanding of C++ (based on Scott Meyers' Effective C++) is that
    > multiple inheritance should only be done for interface base classes
    > (using my definition of interface class above).


    Maybe I'm not the best person to ask because I'm not sure I agree with him.
    You might ask on comp.object. Even though you're asking about C++
    specifically, that shouldn't throw them off.
     
    jeffc, Oct 28, 2003
    #10
  11. kk_oop

    jeffc Guest

    "David White" <> wrote in message
    news:Keknb.153$...
    >
    > I haven't read it, but that sounds a bit odd to me. I've hardly ever used
    > multiple inheritance for any purpose. It just seems unwieldy and inelegant
    > to me, but if I were to use it I don't see why it should be restricted to
    > interface classes.


    It can come in handy for "mix-in" classes. You will see many references to
    this on the web, e.g.
    http://archive.devx.com/free/mgznarch/vcdj/1998/augmag98/mixin1.asp
     
    jeffc, Oct 28, 2003
    #11
  12. kk_oop

    jeffc Guest

    "jeffc" <> wrote in message
    news:...
    >
    > "David White" <> wrote in message
    > news:Keknb.153$...
    > >
    > > I haven't read it, but that sounds a bit odd to me. I've hardly ever

    used
    > > multiple inheritance for any purpose. It just seems unwieldy and

    inelegant
    > > to me, but if I were to use it I don't see why it should be restricted

    to
    > > interface classes.

    >
    > It can come in handy for "mix-in" classes. You will see many references

    to
    > this on the web, e.g.
    > http://archive.devx.com/free/mgznarch/vcdj/1998/augmag98/mixin1.asp


    Or more to the point for you
    http://archive.devx.com/free/mgznarch/vcdj/1998/augmag98/mixin2.asp
     
    jeffc, Oct 28, 2003
    #12
  13. jeffc escribió:

    > ASSERTs are pretty much a waste of time, since they only affect debug code
    > (I've never been much of a fan of ASSERT). Comments would be good, butthey


    An assert is a comment that is enforced at debug time.

    Regards.
     
    =?iso-8859-1?Q?Juli=E1n?= Albo, Oct 28, 2003
    #13
  14. kk_oop

    lilburne Guest

    jeffc wrote:
    > "kenandeva<no spam> @yahoo.com>" <"kenandeva<no spam> wrote in message
    > news:bnkkci$dq2$...
    >
    >>My questions have to do with defining the contracts used to verify
    >>LSP--namely should they just be comments in a method or class abstract,
    >>or can/should they be actually included in the code via ASSERTs or
    >>contract verification methods.

    >
    >
    > ASSERTs are pretty much a waste of time, since they only affect debug code
    > (I've never been much of a fan of ASSERT). Comments would be good, but they
    > can never be enforced (I know, I tried - that was my job for about 6 months
    > one time.)
    >


    Someone came for an interview with us once and said they
    were just starting to use exceptions in their code, one of
    the interviewers growled "We don't like fucking exceptions,
    and you won't be fucking well throwing any here".

    I'll attempt to be more diplomatic but it may be hard to
    disguise my disgust.

    When we last looked into exceptions we discovered a 14-18%
    performance degradation due to the code that was being
    inserted to handle stack unwinding. Things may be different
    now, but at the time we found that alone to be an
    unacceptable price to pay.

    We are also deeply suspicious of the use of exceptions to
    enforce class contracts. We simply do not believe, for
    example, that failure to honour a precondition is an
    exceptional condition: it is a BUG.

    Throwing exceptions because function arguments are out of
    range, or invalid seems to be an abomination particularly
    prevalent amongst programmers schooled in java, or at least
    recent CS graduates. The problem with this style of
    programming is that you are forcing customers of your
    runtime system to pay a price for the fact that the caller
    couldn't or wouldn't honour a methods published contract.

    Our code is heavily laced with assertions. Each method will
    assert that its preconditions have been met and that the
    state invariant is valid, some parts of our code run 20x
    slower in debug than release due to such checks. Using
    exceptions for these checks would place that burden into the
    customer releases, that is totally unacceptable, and we
    would not consider code that did not perform such checks was
    of adequate quality.

    If someone passes me a point or vector in 3d space I expect
    it to be properly initialized not to hold some crappy value
    due to a default construction and I don't need to do
    millions of such checks in a customer release. One thing
    that does amuse is that those using exceptions the most,
    tend also to be those that think that inlining a set method
    will speed up their application, or worry over the speed of
    '++i' vs 'i++' when i is an int.

    I'm sure that there are plenty of valid reasons for using
    exceptions, I just don't think those reasons are as
    prevalent as people think, and they haven't been found in
    the applications we write.

    BTW the interviewee got the job.
     
    lilburne, Oct 28, 2003
    #14
  15. kk_oop

    Ken Guest

    lilburne <> wrote in message news:<bnmk4n$1386mb$-berlin.de>...

    > Our code is heavily laced with assertions. Each method will
    > assert that its preconditions have been met and that the
    > state invariant is valid, some parts of our code run 20x
    > slower in debug than release due to such checks. Using
    > exceptions for these checks would place that burden into the
    > customer releases, that is totally unacceptable, and we
    > would not consider code that did not perform such checks was
    > of adequate quality.


    That last sentence threw me off. Too many nots for my little brain
    :). Are you saying that code that performs the checks as exceptions
    is not acceptable?

    I do agree that exceptions are overused to identify "normal" error
    conditions--namely errors which are not due to a bug in the software.
    But if the error is actually a bug, it probably shouldn't be happening
    too often, and when it does--that path of the software shouldn't be
    used until it gets debugged. So I'm thinking that the performance hit
    of an exception might not be a problem here.

    Here's a follow up question: How do you handle contract definition in
    your abstract interface base classes? As I mentioned earlier in the
    thread, this is a concern with respect to enforcing LSP. I'm eager to
    know how folks handle that.

    Thanks so much!

    Ken
     
    Ken, Oct 29, 2003
    #15
  16. lilburne escribió:

    > Take another example: I have a polyline (think of it as a
    > vector of 3d points) which has the constraint that it has at
    > least 2 points, no two adjacent points are coincident, and
    > all the points are valid. Every method that takes a polyline
    > should check that the polyline it is given is valid. Testing
    > a polyline with a 100 points or more starts to become an
    > expensive operation, okay you may cache the result of a test


    Don't use a vector. Make the polyline a class and check for validity
    when constructing and when adding points.

    Regards.
     
    =?iso-8859-1?Q?Juli=E1n?= Albo, Oct 30, 2003
    #16
  17. kk_oop

    lilburne Guest

    Julián Albo wrote:
    > lilburne escribió:
    >
    >
    >>Take another example: I have a polyline (think of it as a
    >>vector of 3d points) which has the constraint that it has at
    >>least 2 points, no two adjacent points are coincident, and
    >>all the points are valid. Every method that takes a polyline
    >>should check that the polyline it is given is valid. Testing
    >>a polyline with a 100 points or more starts to become an
    >>expensive operation, okay you may cache the result of a test

    >
    >
    > Don't use a vector. Make the polyline a class and check for validity
    > when constructing and when adding points.
    >


    Well yes, but talking about some optimized container that we
    built 10 years ago, obscures the issue when people can
    simple think of it as a std::vector which they are already
    familiar with.

    Besides although the points *are* checked when they are
    added to the container, there is nothing that stops someone
    adding or modifying a method to the class that bypasses
    those validity checks.

    Well actually there is ... there are all the methods that on
    taking a polyline call its is_valid() method, and the unit
    tests that check that the is_valid() method asserts when
    called on a polyline that is invalid.
     
    lilburne, Oct 30, 2003
    #17
  18. lilburne escribió:

    > > Don't use a vector. Make the polyline a class and check for validity
    > > when constructing and when adding points.

    >
    > Well yes, but talking about some optimized container that we
    > built 10 years ago, obscures the issue when people can
    > simple think of it as a std::vector which they are already
    > familiar with.
    >
    > Besides although the points *are* checked when they are
    > added to the container, there is nothing that stops someone
    > adding or modifying a method to the class that bypasses
    > those validity checks.


    Make the source ot the polyline class read only ;)

    > Well actually there is ... there are all the methods that on
    > taking a polyline call its is_valid() method, and the unit
    > tests that check that the is_valid() method asserts when
    > called on a polyline that is invalid.


    Or you can automate this by using a polyline_ref class that when
    constucted call is_valid on the polline it refers, and make all
    functions take a polyline_ref as parameter.

    Regards.
     
    =?iso-8859-1?Q?Juli=E1n?= Albo, Oct 30, 2003
    #18
  19. kk_oop

    lilburne Guest

    Julián Albo wrote:

    > lilburne escribió:
    >
    >>Well actually there is ... there are all the methods that on
    >>taking a polyline call its is_valid() method, and the unit
    >>tests that check that the is_valid() method asserts when
    >>called on a polyline that is invalid.

    >
    >
    > Or you can automate this by using a polyline_ref class that when
    > constucted call is_valid on the polline it refers, and make all
    > functions take a polyline_ref as parameter.
    >


    You've got the idea, though there are issues with that
    approach. However you do it, I think you'll agree you don't
    want all these checks being performed in a customer release
    build. That is why you'll use assertions rather than exceptions.
     
    lilburne, Oct 30, 2003
    #19
  20. lilburne escribió:

    > >>Well actually there is ... there are all the methods that on
    > >>taking a polyline call its is_valid() method, and the unit
    > >>tests that check that the is_valid() method asserts when
    > >>called on a polyline that is invalid.

    > >
    > >
    > > Or you can automate this by using a polyline_ref class that when
    > > constucted call is_valid on the polline it refers, and make all
    > > functions take a polyline_ref as parameter.
    > >

    >
    > You've got the idea, though there are issues with that
    > approach. However you do it, I think you'll agree you don't
    > want all these checks being performed in a customer release
    > build. That is why you'll use assertions rather than exceptions.


    The check made in all methods that takes a polyline argument yes, the
    check done in a polyline constructions probably will be in the release
    build and throw exceptions, if the construction is done with data
    obtained from user interaction. That way the debug checks verifies that
    the polyline class is valid and the other grants that no invalid
    polyline object is used. Supossing, naturally, that a polyline
    construction is done much less frequently that his use.

    Regards.
     
    =?iso-8859-1?Q?Juli=E1n?= Albo, Oct 30, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matthias Kaeppler
    Replies:
    1
    Views:
    470
    R.F. Pels
    May 22, 2005
  2. Sameer
    Replies:
    4
    Views:
    632
    Roedy Green
    Aug 31, 2005
  3. Uzytkownik
    Replies:
    3
    Views:
    610
    Uzytkownik
    Apr 3, 2005
  4. Iyer, Prasad C

    Abstract Methods & Abstract Class

    Iyer, Prasad C, Oct 20, 2005, in forum: Python
    Replies:
    0
    Views:
    552
    Iyer, Prasad C
    Oct 20, 2005
  5. Replies:
    4
    Views:
    865
    Rolf Magnus
    May 17, 2006
Loading...

Share This Page