• Excelsior (unregistered)

    Frist snowflake of the year ?

  • ThaMe90 (unregistered) in reply to Excelsior
    Excelsior:
    Frist snowflake of the year ?

    It's the snowflake that broke the system. Much like our Dutch railway system....

  • Walky_one (unregistered)

    Now if only we had something like virtual property setters...

    Still kind of WTF to have a virtual method you're not allowed to call, but at least you don't need to do such a hack...

    My approach to these kind of problems is usually to create a special "Edit" interface that has the property as read/write (while the class itself only has read access). Then implicitly implement the interface in the derived class. Anybody knows a better approach?

  • Mike (unregistered)

    ...and you wish that, somehow, you could throttle the invisible person responsible for that invisible code

  • faoileag (unregistered)
    Remy wrote:
    a mysterious, uninformative, and untyped exception
    What's uninformative about "Cannot call set on RecordDateTime for table <insert_table_name>"?
  • faoileag (unregistered) in reply to Walky_one
    Walky_one:
    My approach to these kind of problems is usually to create a special "Edit" interface that has the property as read/write (while the class itself only has read access). Then implicitly implement the interface in the derived class. Anybody knows a better approach?
    My C# is pretty rusted, so this might not work, but I would only provide a "get" in the RecordDateTime property of Record_Base, then explicitly override that property in Record_PartRegister to also provide "set".

    Of course that would require either "_recordDateTime" itself being protected (and protected member variables are usually frowned upon) or a protected setRecordDateTime() method provided by Record_Base.

    Still better than the solution from the article though, since maintenance of the submitted code must be awkward. I mean, who would suspect a hardcoded classname of a child class in its parent class? This is so profoundly wrong that I'm tempted to call it the "worstest" mistake you can make in OOP.

  • QJo (unregistered) in reply to ThaMe90
    ThaMe90:
    Excelsior:
    Frist snowflake of the year ?

    It's the snowflake that broke the system. Much like our Dutch railway system....

    A-ha-ha. You Dutch too? We Brits were told once that the railway delays were caused by "the wrong kind of snow". Instant folklore.

  • QJo (unregistered)

    TRWTF is of course C#.

  • Hasse de great (unregistered)

    Yellow Snow?

  • faoileag (unregistered) in reply to Hasse de great
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"
  • humdum (unregistered) in reply to faoileag

    In C# overriding a property and adding/removing/changing the get/set signature will not work.

  • faoileag (unregistered) in reply to humdum
    humdum:
    In C# overriding a property and adding/removing/changing the get/set signature will not work.
    Oh, ok. Next try:
    set { this.setRecordDateTime(value); }
    

    Record_Base: protected virtual void setRecordDateTime(DateTime value) { throw new NotSupportedException(); }

    Record_PartRegister: protected virtual void setRecordDateTime(DateTime value) { this._recordDateTime = value; }

    Still requires _recordDateTime to be protected, though.

  • Doctor_of_Ineptitude (unregistered)

    This is not an error. This is a sadistic plot to inflect pain and suffering (in this case, specifically to Alex). So, Alex, what did you do to antagonize Satan or his minions?

    Captcha: abico: as best i can owl

  • faoileag (unregistered) in reply to faoileag
    faoileag:
    Next try: ... Still requires _recordDateTime to be protected, though.
    Hah!
    set { _recordDateTime = this.setRecordDateTime(value); }
    

    Record_Base: protected virtual DateTime setRecordDateTime(DateTime value) { throw new NotSupportedException(); return null; // does the C# compiler need this? }

    Record_PartRegister: protected virtual DateTime setRecordDateTime(DateTime value) { return value; }

    Now you don't even need to make _recordDateTime protected.

  • Doctor_of_Ineptitude (unregistered)

    For added fun, is _recordDateTime is declared as private in an intermediate inheritance class between Record_PartRegister and Record_Base?

  • Meep (unregistered) in reply to QJo
    QJo:
    TRWTF is of course C#.

    No, TRWTF is equating classes and tables.

  • faoileag (unregistered) in reply to Meep
    Meep:
    QJo:
    TRWTF is of course C#.

    No, TRWTF is equating classes and tables.

    This looks like being part of a homegrown ORM. Nothing wrong with mentally equating a class with the table it represents then.

  • nmclean (unregistered)
    Walky_one:
    Now if only we had something like virtual property setters...

    Still kind of WTF to have a virtual method you're not allowed to call, but at least you don't need to do such a hack...

    My approach to these kind of problems is usually to create a special "Edit" interface that has the property as read/write (while the class itself only has read access). Then implicitly implement the interface in the derived class. Anybody knows a better approach?

    What's wrong with simply documenting on the base class that attempting to write may throw an exception, and/or providing another overridable bool that informs the user whether writing is allowed? For standard library examples of this see Java's "AbstractCollection.add" (which throws UnsupportedOperationException) or .NET's "Stream.CanWrite".

  • (cs)

    The "right" answer is to avoid situations where you implement code to this pattern. But there are two better answers to this. The first is to simply have the base class throw a NotImplementedException in the set (which is exactly what that exception is for), and the child-class can override the set to stop throwing that.

    The second, and arguably better solution, is to have the child class implement the read-write version as shadows. This is a weird language feature that you almost should never use, because it really does make maintenance confused. But by slapping the shadows modifier on the property allows the child class to replace its parent method, but only when you polymorphically reference the instance as a type of the child class. So

    (Parent)foo.property
    is read only, but
    (Child)foo.property
    is read-write.

    I was honestly rather surprised to stumble across a good case for using Shadows in the slushpile.

  • QJo (unregistered) in reply to faoileag
    faoileag:
    Meep:
    QJo:
    TRWTF is of course C#.

    No, TRWTF is equating classes and tables.

    This looks like being part of a homegrown ORM. Nothing wrong with mentally equating a class with the table it represents then.

    Object-role modelling or object-relational mapping? Which?

  • faoileag (unregistered) in reply to QJo
    QJo:
    faoileag:
    Meep:
    QJo:
    TRWTF is of course C#.

    No, TRWTF is equating classes and tables.

    This looks like being part of a homegrown ORM. Nothing wrong with mentally equating a class with the table it represents then.

    Object-role modelling or object-relational mapping? Which?

    The word "table" is suspiciously absent in the wikipedia article on "Object-role modelling", that should give you a hint.

  • (cs) in reply to faoileag
    faoileag:
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"
    Now all your snowflakes are urine and you can't even find the cat.
  • Jack (unregistered)

    Users can't be expected to understand all this parent, class mumbo-jumbo. It sounds like grade school or something! Anyway, it is far past time for software designers to get their heads out of the cloud and realize that normal people just can't be bothered with this kind of detail. The computer is merely a tool, not an obsession. If the rules get in the way of Getting The Job Done it is the rules that are at fault, not the user.

    We want software that Just Works, dammit!

  • RFox (unregistered) in reply to faoileag

    Watch out where the huskies go

    faoileag:
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"
  • faoileag (unregistered) in reply to mikeTheLiar
    mikeTheLiar:
    faoileag:
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"
    Now all your snowflakes are urine and you can't even find the cat.
    Have you looked in the snow cannon?
  • You're Kiffing, Right? (unregistered) in reply to Jack
    Jack:
    Users can't be expected to understand all this parent, class mumbo-jumbo. It sounds like grade school or something! Anyway, it is far past time for software designers to get their heads out of the cloud and realize that normal people just can't be bothered with this kind of detail. The computer is merely a tool, not an obsession. If the rules get in the way of Getting The Job Done it is the rules that are at fault, not the user.

    We want software that Just Works, dammit!

    Must be a Mac user. And what they hey do users even care about the code for anyway?

  • tim (unregistered) in reply to faoileag
    faoileag:
    Remy wrote:
    a mysterious, uninformative, and untyped exception
    What's uninformative about "Cannot call set on RecordDateTime for table <insert_table_name>"?
    Exactly. I'm not sure how long he spend "trying to diagnose" it, but if it was more than about 1/10 second he's obviously not the sharpest tool in the box.

    This may not be the pinacle of OO design but it sure as hell ain't a WTF

  • The Fury (unregistered) in reply to QJo
    QJo:
    ThaMe90:
    Excelsior:
    Frist snowflake of the year ?

    It's the snowflake that broke the system. Much like our Dutch railway system....

    A-ha-ha. You Dutch too? We Brits were told once that the railway delays were caused by "the wrong kind of snow". Instant folklore.

    How about dew?

    http://www.telegraph.co.uk/culture/tvandradio/8395270/Ten-of-the-most-ridiculous-excuses-for-late-trains.html

  • Walky_one (unregistered) in reply to nmclean

    The basics of object oriented design with polymorphism is:

    The base class defines functionality that is COMMON for all derived classes. Functionality that is NOT COMMON should NOT be in the base class.

    I know the UnsupportedOperationException approach (and sometimes I even agree that it's a workable way): However it's still an approach that violates one of the most central aspects of object oriented design...

  • (cs) in reply to faoileag
    faoileag:
    What's uninformative about "Cannot call set on RecordDateTime for table <insert_table_name>"?

    The Exception is untyped, and is also not an exception type that should ever be raised by application code (all application exceptions should inherit from ApplicationException).

    The chances of this exception running way up the call stack before getting caught are pretty good. Since the exception is throw by a base class, there are lots of reasonable situations where you might have an instance of the base class mixed with instances of child classes (which is why I suggested using Shadows upthread, because then you can't set the property until you cast to the proper type, forcing you to catch cast exception).

    This could be extremely tricky to debug in a real-world application of any complexity.

  • Doodpants (unregistered)

    TRWTF is 8-character tab stops.

  • Walky_one (unregistered) in reply to faoileag

    [quote user="faoileag"][quote user="faoileag"]Next try: ... bla bla bla[/quote] If you define a virtual set method that raises "NotImplemented" exception, you can just use a virtual property setter (as I originally proposed...)

  • Maj najm (unregistered) in reply to faoileag
    faoileag:
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"

    Eat yellow snow, it might be beer!

  • (cs)

    This code is bringing tears into my eyes.

  • (cs)

    This code is bringing tears into my eyes.

  • n9ds (unregistered) in reply to mikeTheLiar
    mikeTheLiar:
    faoileag:
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"
    Now all your snowflakes are urine and you can't even find the cat.

    Well of course not. Any lover of Classic Rock will tell you the snow is yellow from where the Huskies go. No cats involved.

  • Sucatraps (unregistered)

    This has to be the most elegant WTF in at least a year. As we like to say around here: "gets the concept, but completely misses the point" (wrt OO design, and even basic ORM - "Look mommy, we gots classes!")

  • Blah (unregistered) in reply to tim
    tim:
    faoileag:
    Remy wrote:
    a mysterious, uninformative, and untyped exception
    What's uninformative about "Cannot call set on RecordDateTime for table <insert_table_name>"?
    Exactly. I'm not sure how long he spend "trying to diagnose" it, but if it was more than about 1/10 second he's obviously not the sharpest tool in the box.

    This may not be the pinacle of OO design but it sure as hell ain't a WTF

    That depends, I guess. It's possible that this was a new dev who thought they were being clever using the base class instead of just adding the property to the corresponding child class. Then again, it could still be the WTF code of an ass trying to mess with people by adding a pretty generically named property that can potentially be useful to any number of table classes but instead only tells you that it doesn't work. No other information. No just saying "This only works for the following table <Record_PartRegister>." While it would take no time to debug, it would still be time wasted on an unnecessary, planned error.

  • JustSomeDudette (unregistered) in reply to Maj najm
    Maj najm:
    faoileag:
    Hasse de great:
    Yellow Snow?
    "Don't eat yellow snow!"

    Eat yellow snow, it might be beer!

    If your beer is yellow, you're doing it wrong.

  • faoileag (unregistered) in reply to Remy Porter
    Remy Porter:
    The chances of this exception running way up the call stack before getting caught are pretty good. ... This could be extremely tricky to debug in a real-world application of any complexity.
    The approach is pretty straightforward. If the exception is bubbling up to the top of the call stack, you will see the exception message once you set your debugger to it.

    Then you can search for the text, find the place where it is thrown and understand why it is thrown.

    The next step takes some time, but basically now all you've got to do ist find all places where RecordDateTime is assigned a value and the class of the object is not Record_PartRegister.

    Easy as that.

    Now, if the exception does not bubble up but is silently ignored along the call stack, that's when you've got a real problem. But you would also have that problem if instead of the generic base exception an exception with a more descriptive class name is thrown.

    Remy Porter:
    The Exception is untyped, and is also not an exception type that should ever be raised by application code (all application exceptions should inherit from ApplicationException).
    To quote what MSDN has to say about ApplicationException: "It was originally thought that custom exceptions should derive from the ApplicationException class; however in practice this has not been found to add significant value"

    So I don't really see any reason to use a derived class, at least not one derived from ApplicationException. But since for the use case from the article MSDN's entry for Exception recommends to use NotSupportedException, I would use that (and did in the code samples above).

  • faoileag (unregistered) in reply to Walky_one
    Walky_one:
    faoileag:
    Next try: ... bla bla bla
    If you define a virtual set method that raises "NotImplemented" exception, you can just use a virtual property setter (as I originally proposed...)
    As I said, my C# is rusted - that code was a response to humdum's post that you can't have virtual properties.

    Since you can, obviously virtual properties are the way to do it, saves you the virtual value-piping-through method I introduced.

  • clydesdale (unregistered) in reply to Maj najm
    Maj najm:
    Eat yellow snow, it might be beer!

    It might have been beer, more like.

  • F (unregistered) in reply to Nagesh
    Nagesh:
    This code is bringing tears into my eyes.

    One of the other Nageshes already said that.

  • Paul Neumann (unregistered) in reply to faoileag
    faoileag:
    "Don't eat yellow snow!"
    That's just something your mom told you so there was more for her.
  • (cs) in reply to tim
    tim:
    faoileag:
    Remy wrote:
    a mysterious, uninformative, and untyped exception
    What's uninformative about "Cannot call set on RecordDateTime for table <insert_table_name>"?
    Exactly. I'm not sure how long he spend "trying to diagnose" it, but if it was more than about 1/10 second he's obviously not the sharpest tool in the box.

    This may not be the pinacle of OO design but it sure as hell ain't a WTF

    Tim, you're so wrong. This is by far the most WTF'y code I've seen in a long time.
    -- a hardcoded class name -- a setter only legally callable by a specific subclass -- pretending that this class is really a "table" and not just a data object

  • (cs)

    Creative. Very creative.

    ...oh, wait...can't create.

    Okay, not creative. Very not creative.

  • Walky_one (unregistered) in reply to faoileag
    faoileag:
    Walky_one:
    faoileag:
    Next try: ... bla bla bla
    If you define a virtual set method that raises "NotImplemented" exception, you can just use a virtual property setter (as I originally proposed...)
    As I said, my C# is rusted - that code was a response to humdum's post that you can't have virtual properties.

    Since you can, obviously virtual properties are the way to do it, saves you the virtual value-piping-through method I introduced.

    I run into these problems a couple of months ago. The problem with "setters" that raise "NotImplemented" is, that it makes it very hard to use the property (almost by default you need to have a second property "CanSetXY"). And it's AFAIK not possible to introduce the setter only in the derived class (defining an abstract setter in the base class is possible, but not a solution for this problem).

    My solution was to introduce an interface that contains (an equally named) property that contained a read/write property while the class published a read-only property. The interface then was implicitly implemented by the derived class.

    However I still consider it somewhat a "hack" approach (so that's why I asked if somebody knew a better approach)

  • faoileag (unregistered) in reply to Paul Neumann
    Paul Neumann:
    faoileag:
    "Don't eat yellow snow!"
    That's just something your mom told you so there was more for her.
    That's just something that xsnow tells you when you try to set the snow color to yellow.
  • faoileag (unregistered) in reply to Walky_one
    Walky_one:
    I run into these problems a couple of months ago. The problem with "setters" that raise "NotImplemented" is, that it makes it very hard to use the property (almost by default you need to have a second property "CanSetXY").
    Hm, that sounds a bit like you have to deal with some strange code indeed...

    But I would probably choose the ugly but easy way in that case:

    try {
    myRecord.RecordDateTime = DateTime.Now;
    }
    catch {Exception ex) {
    // intentionally left blank
    }

    Then you don't need the "CanSetXY" method... but of course that sort of exception handling is really, really ugly.

  • Walky_one (unregistered) in reply to faoileag
    faoileag:
    Walky_one:
    I run into these problems a couple of months ago. The problem with "setters" that raise "NotImplemented" is, that it makes it very hard to use the property (almost by default you need to have a second property "CanSetXY").
    Hm, that sounds a bit like you have to deal with some strange code indeed...

    But I would probably choose the ugly but easy way in that case:

    try {
    myRecord.RecordDateTime = DateTime.Now;
    }
    catch {Exception ex) {
    // intentionally left blank
    }

    Then you don't need the "CanSetXY" method... but of course that sort of exception handling is really, really ugly.

    Wouldn't work (let's rephrase this: would what the user expected). The point was a generic property display: some properties you could edit. Some you couldn't (and allowing the user to edit and telling them afterwards: "Hey! it didn't work!" is kind of bad style). The "CanEditXY" approach would have worked though... However since the same properties also were used within the code itself, I didn't want to go the "Darn! I used an invalid property there" way

Leave a comment on “Making Off With Your Inheritance”

Log In or post as a guest

Replying to comment #:

« Return to Article