Arkansas Inheritance?



  • Sanitized for your pleasure: 

    public class AbstractWorker {

    public AbstractWorker ( Properties props, MoreSpecificWorker worker ) {
    this.properties = props;
    this.worker = worker;
    }

    }

    public class SpecificWorker extends AbstractWorker {

    public SpecificWorker ( Properties props, MoreSpecificWorker worker ) {
    super(props, worker);
    }

    }

    public class MoreSpecificWorker extends SpecificWorker {

    public MoreSpecificWorker ( Properties props, MoreSpecificWorker worker ) {
    super(props, worker);
    }

    }

    I don't think there are words to express my dismay when I realized that this structure exists ...



  • Let me guess:  Every method in AbstractWorker calls this.worker.[MethodName]?

     



  • Hmmm, inheritance or composition...I know, let's use both at the same time! Two design patterns must be twice as good as one!



  • Well, in this very form, the structure makes no sense, of course. It would make sense, though, if SpecificWorker and MoreSpecificWorker had more methods than just the constructor that would actually make those classes more specific.



  • I'm my own grandfather!

    I'm my own father!

    I'm my own self!

    I'm my own son!

    I'm my own grandson!

    ...

    //snipped for length

    ...

    Out of memory exception: I am the alpha and the omega, the beginning and the end. I am that I am.



  • Please tell me that AbstractWorker is marked abstract. Please.

    Honestly, I don't believe I've ever seen a piece of code that so perfectly encapsulates OOP principles, while completely botching them at the same time. It's like the author knew OOP, but had an aneurysm just before he actually wrote crapped out this gem.



  • @zelmak said:

    public class MoreSpecificWorker extends SpecificWorker {

    public MoreSpecificWorker ( Properties props, MoreSpecificWorker worker ) {
    super(props, worker);
    }

    }

    So how does one come about the first instance, when each instance requires another one?

    I expected you'd have written this:

    public class MoreSpecificWorker extends SpecificWorker {
    

    public MoreSpecificWorker ( Properties props ) {
    super(props, this);
    }

    }



  • Please don't tell me it was coded like that because the requirements said it had to be like that...



  • @Bulb said:

    @zelmak said:

    public class MoreSpecificWorker extends SpecificWorker {
    

    public MoreSpecificWorker ( Properties props, MoreSpecificWorker worker ) {
    super(props, worker);
    }

    }

    So how does one come about the first instance, when each instance requires another one?

    I expected you'd have written this:

    public class MoreSpecificWorker extends SpecificWorker {
    

    public MoreSpecificWorker ( Properties props ) {
    super(props, this);
    }

    }

     

    And then cross your fingers and pray that the superclass constructor doesn't modify its second parameter at all.



  • How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?



  • @smxlong said:

    How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?

    Spontaneous generation.



  • @smxlong said:

    How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?
     

    Possibly there's another constructor that we're not seeing here — maybe one that passes this as a parameter, as Bulb suggested. Though I'm curious what the JVM garbage collector would do with an object that has itself as a member variable. It's possible you might have to explicitly set the "worker" member variable to null before this thing would be garbage collected.

    You could also pass null as the constructor parameter, though I'm not clear on what purpose the whole thing would serve in that case. Then again, I'm not clear on what purpose the whole thing serves to begin with.



  • @Someone You Know said:

    @smxlong said:

    How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?
     

    Possibly there's another constructor that we're not seeing here — maybe one that passes this as a parameter, as Bulb suggested. Though I'm curious what the JVM garbage collector would do with an object that
    has itself as a member variable. It's possible you might have to
    explicitly set the "worker" member variable to null before this thing
    would be garbage collected.

    You could also pass null as the constructor parameter, though I'm not clear on what purpose the whole thing would serve in that case. Then again, I'm not clear on what purpose the whole thing serves to begin with.

    Can't the garbage collector get around circular references, or at least self-references?



  • [quote user="Renan "C#" Sousa"]@Someone You Know said:

    @smxlong said:

    How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?
     

    Possibly there's another constructor that we're not seeing here — maybe one that passes this as a parameter, as Bulb suggested. Though I'm curious what the JVM garbage collector would do with an object that has itself as a member variable. It's possible you might have to explicitly set the "worker" member variable to null before this thing would be garbage collected.

    You could also pass null as the constructor parameter, though I'm not clear on what purpose the whole thing would serve in that case. Then again, I'm not clear on what purpose the whole thing serves to begin with.

    Can't the garbage collector get around circular references, or at least self-references?[/quote] 

    Actually, now that I think about it, you're right. It would only really be a problem if the garbage collector were using reference counting, which the Sun Oracle JVM's garbage collector does not. I think it uses some kind of system where it determines whether an object is "reachable", via a chain of references, from some Kevin-Bacon-like object(s) it considers to always be reachable.



  • @Someone You Know said:

    [quote user="Renan "C#" Sousa"]@Someone You Know said:

    @smxlong said:

    How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?
     

    Possibly there's another constructor that we're not seeing here — maybe one that passes this as a parameter, as Bulb suggested. Though I'm curious what the JVM garbage collector would do with an object that has itself as a member variable. It's possible you might have to explicitly set the "worker" member variable to null before this thing would be garbage collected.

    You could also pass null as the constructor parameter, though I'm not clear on what purpose the whole thing would serve in that case. Then again, I'm not clear on what purpose the whole thing serves to begin with.

    Can't the garbage collector get around circular references, or at least self-references?

     

    Actually, now that I think about it, you're right. It would only really be a problem if the garbage collector were using reference counting, which the Sun Oracle JVM's garbage collector does not. I think it uses some kind of system where it determines whether an object is "reachable", via a chain of references, from some Kevin-Bacon-like object(s) it considers to always be reachable.

    [/quote]

    Generally, those Kevin-Bacon-like objects are classes and static members, plus anything in any stack (plus a few others):

    http://www.yourkit.com/docs/75/help/performance_problems/memory_leaks/gc_roots.jsp

     



  • @smxlong said:

    How can this code even be used? The constructor of MoreSpecificWorker takes an instance of a MoreSpecificWorker. How would that instance get constructed, since you already need to have an instance in order to create an instance?

    I don't see any obvious reason why you couldn't get the first ever MoreSpecificWorker just by passing in null.

    (Whether this is a horrendously bad idea or not rather depends on the rest of the code. At least, it seems unlikely to make things any worse.)



  • Wow 4-1/2 stars... and I just posted this on Friday and ran off to get ready for a business trip ... which is why I'm answering questions now... 

    @frits said:


    Let me guess:  Every method in AbstractWorker calls this.worker.[MethodName]?

    No, but there are a few.

    @The_Assimilator said:


    Please tell me that AbstractWorker is marked abstract. Please.

    Surprisingly, yes, it is marked as abstract.

    @ais523 said:


    I don't see any obvious reason why you couldn't get the first ever MoreSpecificWorker just by passing in null.

    Sadly, the 'null'-ized parameter paradigm is used a LOT. But why create a constructor on AnObject with AnObject as an argument ... when it is NOT a copy-constructor?

    I believe the problem was that the implementors didn't realize that constructors are not inherited, but created them to match up and down the chain nonetheless.

    However, the mess in the original post stems, I believe, from the fact that "SpecificWorker" got to be too large to manage (about 46K text lines.) So the programmers extended it to "MoreSpecificWorker" to make room until it too grew too large to handle (about 55K text lines). So someone started making parallel workers for the new functions as necessary.

    But the WTFery is actually more widespread than I led you to believe to keep the example simple. There are actually (at least) four classes which extend AbstractWorker ... each of which has constructors requiring each of the other descendent classes as arguments. And then, each has a reference to its 'boss' -- a worker manager, per se.

    So, you have

    public ConcreteWorker1(Properties props, 
    ConcreteWorker1 worker1,
    ConcreteWorker2 worker2,
    ConcreteWorker3 worker3,
    ConcreteWorker4 worker4,
    WorkerManager boss)
    Repeat for ConcreteWorker2, etc. And WorkerManager also inherits from AbstractWorker.

    Edit: I forgot to mention, AbstractWorker has internal references to each of the passed in arguments ... not as if it is simply spinning off those workers, but actually maintaining connection with them and such. An array

    AbstractWorker common[4]
    ... which was then dereferenced by its subsequent users by such arcanity as
    (CommonWorker1) common[WORKER1_INDEX]


  • @zelmak said:

    AbstractWorker has internal references to each of the passed in arguments
     

    That in itself might make sense

    @zelmak said:

    AbstractWorker common[4]
    ... which was then dereferenced by its subsequent users by such arcanity as
    (CommonWorker1) common[WORKER1_INDEX]

    Aaargggghhhh...



  • That is pretty mind-blowing.  Are the original coders still around?  Are they proud of their work?



  • @zelmak said:

    But the WTFery is actually more widespread than I led you to believe to keep the example simple. There are actually (at least) four classes which extend AbstractWorker ... each of which has constructors requiring each of the other descendent classes as arguments. And then, each has a reference to its 'boss' -- a worker manager, per se.

    So, you have

    public ConcreteWorker1(Properties props, 
    ConcreteWorker1 worker1,
    ConcreteWorker2 worker2,
    ConcreteWorker3 worker3,
    ConcreteWorker4 worker4,
    WorkerManager boss)

    Repeat for ConcreteWorker2, etc. And WorkerManager also inherits from AbstractWorker.

     

    Holy fuck.

    Nuke the site from orbit. It's the only way to be sure.


Log in to reply