Collapsing Star Pattern?



  • Since work proxies are now blocking TDWTF site's login page -- not the rest of the site, just the login page (something about the redirect after the submit, I imagine) -- I'm now e-mailing myself WTFs home to post.

    Suppose you're given the following classes which are directly related to tables in a database:

    public class Foo {
      long key;
      String fooInfo;
    
      public Foo(long newKey, String newInfo) {
        this.key = newKey;
        this.fooInfo = newInfo;
      }
    
      public long getKey() {
        return this.key;
      }
    }
    
    public class Bar {
      long key;
      String barInfo;
    
      public Bar(long newKey, String newInfo) {
        this.key = newKey;
        this.barInfo = newInfo;
      }
    
      public long getKey() {
        return this.key;
      }
    }
    
    public class Qux {
      long key;
      String quxInfo;
    
      public Qux(long newKey, String newInfo) {
        this.key = newKey;
        this.quxInfo = newInfo;
      }
    
      public long getKey() {
        return this.key;
      }
    }

    Unfortunately, due to clumsy/naive/criminal(?) database design, you have a "relational" table which allows adding additional information about the given types which looks like:

    create table "additional_info" (
      "fooId" number,
      "barId" number,
      "quxId" number,
      "info_text" varchar(4000)
    )
    
    create index "addl_info_foo" on "additional_info" ( "fooId" );
    create index "addl_info_bar" on "additional_info" ( "barId" );
    create index "addl_info_qux" on "additional_info" ( "quxId" );

    Which means you have to create the following class definition (right?):

    public class AdditionalInfo {
      public AdditionalInfo(long fooKey, long barKey, long quxKey, String info) {
        this.fooKey = fooKey;
        this.barKey = barKey;
        this.quxKey = quxKey;
        this.info = info;
      }
    
      public long getFooKey() {
        return this.fooKey;
      }
    
      public long getBarKey() {
        return this.barKey;
      }  
    
      public long getQuxKey() {
        return this.quxKey;
      }
    }

    It is up to the programmer of all this mess to ensure that ONLY ONE key may be set to anything but null to maintain the relationship between the "parent" object (Foo, Bar, or Qux) and the "child" additional information. So, if you add addtional information to a Bar record:

    AdditionalInfo newBarInfo = new AdditionalInfo(null, bar.getKey(), null, "Here's my new information!!!11");

    and then you call the AdditionalInfo DAO to insert the new record into the database.

    This is all terrible enough, and I've known about this implementation for a while now (my boss thinks, rightly, that it is broken and we want to fix it, but ... Inertia.) However, today I discovered a method in AdditionalInfo with a(n) (anti-)"pattern" I've not seen before, that I hereby dub the "Collapsing Star" pattern:

    public long typeID(AdditionalInfo ai) {
        long idVal = 0;
        if ( ( idVal = ai.getFooKey() ) == 0) {
          if ( ( idVal = ai.getBarKey() ) == 0) {
            idVal = ai.getQuxKey();
          }
        }
        return idVal;
      }

    I imagine it could be some C language idiom, but I rather think its more an idiot than idiom.



  • @zelmak said:

    public class Qux

    I found TRTWTF. Who follows Bar with Qux and not Baz? WHAT DID YOU DO WITH BAZ??



  • @zelmak said:

    However, today I discovered a method in AdditionalInfo with a(n) (anti-)"pattern" I've not seen before, that I hereby dub the "Collapsing Star" pattern:

    public long typeID(AdditionalInfo ai) {
        long idVal = 0;
        if ( ( idVal = ai.getFooKey() ) == 0) {
          if ( ( idVal = ai.getBarKey() ) == 0) {
            idVal = ai.getQuxKey();
          }
        }
        return idVal;
      }

    I imagine it could be some C language idiom, but I rather think its more an idiot than idiom.

    For a moment there I looked at that and thought "well, if the keys are GUIDs then that might have some hope of contributing something useful." Then I noticed that they're declared as number in the SQL and long in the C, and all hope was sucked into the black hole.



  • @flabdablet said:

    For a moment there I looked at that and thought "well, if the keys are GUIDs then that might have some hope of contributing something useful."

    Why would that be any more or less useful?



  • @morbiuswilters said:

    Why would that be any more or less useful?

    Because if the table keys were GUIDs created at random, the namespace collapse caused by keys from three different tables being merged into the same result would at least be reversible. Since they're plain numerics and therefore probably generated as sequence numbers, not so much - unless attention has been paid elsewhere to keeping the sequence ranges well separated which, given the general WTF level of the whole schema, struck me as unlikely.



  • @flabdablet said:

    @morbiuswilters said:
    Why would that be any more or less useful?

    Because if the table keys were GUIDs created at random, the namespace collapse caused by keys from three different tables being merged into the same result would at least be reversible. Since they're plain numerics and therefore probably generated as sequence numbers, not so much - unless attention has been paid elsewhere to keeping the sequence ranges well separated which, given the general WTF level of the whole schema, struck me as unlikely.

    Oh, I thought you were talking about the "collapsing star" function checking if the keys were 0 or not. Yeah, you're right, although UUIDs have their own problems in some databases. Really, it's just an awful scheme. EAV is a pretty crappy idiom in a relational database, anyway, and being so lazy as to create a single EAV table for 3 different parent tables.. blegh. I suppose they could at least use a trigger to make sure a row always had exactly one ID set, but that's still hacky as all get-out.



  • @morbiuswilters said:

    Really, it's just an awful scheme.

    I agree with whatever Morbs just said.



  • Any hope of being able to hide the currently public constructor behind three different static constructor methods?

    Also:

    @Not better, just different said:

    public long typeID(AdditionalInfo ai) {
        return ai.getFooKey() + ai.getBarKey() + ai.getQuxKey();
    }

     



  •  Three cheers for homebrew ORM.



  • @Zecc said:

    Any hope of being able to hide the currently public constructor behind three different static constructor methods?

    Also:

    @Not better, just different said:

    public long typeID(AdditionalInfo ai) {
    return ai.getFooKey() + ai.getBarKey() + ai.getQuxKey();
    }

     

    Or simply use static helpers:

    public static AdditionalInfo createFooInfo(long fooKey, String info) {
      return new AdditionalInfo(fooKey, null, null, info);
    }


  • @dhromed said:

     Three cheers for homebrew ORM.

    I really, really, REALLY wish I could publish the entire program or at least the data-access bits. I have given various pieces of it in various posts here. Yes, each one of those is part of the same code base and expected to work together.

    You wouldn't believe how farbled up the data-access layer is.

    If one could call it a layer.

    It's more like how in Minecraft (and, I gather, in real geology/mining) how bits of valuable minerals are clumped together all over the place at various levels of the program.

    Kind of like that.

    But worse.


  • Trolleybus Mechanic

    @zelmak said:

    Since work proxies are now blocking TDWTF site's login page -- not the rest of the site, just the login page (something about the redirect after the submit, I imagine) -- I'm now e-mailing myself WTFs home to post.
     

    Login at home. Export your cookies. Import them at work. LOGGED IN!



  • @morbiuswilters said:

    @zelmak said:
    public class Qux

    I found TRTWTF. Who follows Bar with Qux and not Baz? WHAT DID YOU DO WITH BAZ??

    I don't like having objects in my examples having initial letters being the same.

    Makes it easier for me to spot screw ups. Oh, here comes one now.

    Wait, no, that doesn't work, I'm not in my office.

    Dammit, I can't make fun of co-workers now. :(



  • @Lorne Kates said:

    @zelmak said:

    Since work proxies are now blocking TDWTF site's login page -- not the rest of the site, just the login page (something about the redirect after the submit, I imagine) -- I'm now e-mailing myself WTFs home to post.
     

    Login at home. Export your cookies. Import them at work. LOGGED IN!

    Had not thought of that ... will give it a try. We'll see if the draconian e-mail firewall strips them out of the e-mail.

    Do you have a newsletter I could subscribe to?


  • Trolleybus Mechanic

    @flabdablet said:

    Because if the table keys were GUIDs created at random
     

    OH OH OH OH! Let me guess:

     @sad day said:

    string guid = "";

    FOR i = 1 to 38

        if (i == 0)
        {
          guid = guid + "{";
        }
       
        if (i == 38)
        {
           guid = guid + "}";
        }
       
        if (i==10)
        {
           guid = guid + "-";
        }
       
        if (i==15)
        {
           guid = guid + "-";
        }

        if (i==20)
        {
           guid = guid + "-";
        }
       
        if (i==25)
        {
           guid = guid + "-";
        }
       
        if (i==2)
        {
           r = random(1,16);
           if (r > 9)
           {
             r = random(1,6);
             chars = {"A", "B", "C", "D", "E", "F", "G"};
             guid = guid + chars[r - 1];
           }
           else
           {
             r = random(1,10);
             guid = guid + (r - 1).toString();
           }
        }
       
        if (i==3)
        {
          // Copy and paste i==2 block
        }
       
        // Copy and pase i==3 block for 4,5,6, etc...
    NEXT i

    return guid;



  • @morbiuswilters said:

    WHAT DID YOU DO WITH BAZ??

    If you want to see your precious Baz again, leave the money in a duffle bag outside the park.



  • @flabdablet said:

    @morbiuswilters said:
    Really, it's just an awful scheme.

    I agree with whatever Morbs just said.

    Me too.



  • That would make a great answer to a "how do I create a guid" stack overflow question...


  • Trolleybus Mechanic

    @zelmak said:

    Had not thought of that ... will give it a try. We'll see if the draconian e-mail firewall strips them out of the e-mail.

    Put them on a USB key? Print them out, put print out on wooden table, take picture of printout with smartphone, go to work, open smart phone, and type them in?

    Do you have a newsletter I could subscribe to?
     

    [url="http://syndication.thedailywtf.com/TheDailyWtf"]Yes[/url]



  • @zelmak said:

    @Zecc said:

    Any hope of being able to hide the currently public constructor behind three different static constructor methods?

    Also:

    @Not better, just different said:

    public long typeID(AdditionalInfo ai) {
    return ai.getFooKey() + ai.getBarKey() + ai.getQuxKey();
    }

     

    Or simply use static helpers:

    public static AdditionalInfo createFooInfo(long fooKey, String info) {
      return new AdditionalInfo(fooKey, null, null, info);
    }


  • @Zecc said:

    @zelmak said:
    @Zecc said:

    Any hope of being able to hide the currently public constructor behind three different static constructor methods?

    Also:

    @Not better, just different said:

    public long typeID(AdditionalInfo ai) {
    return ai.getFooKey() + ai.getBarKey() + ai.getQuxKey();
    }

     

    Or simply use static helpers:

    public static AdditionalInfo createFooInfo(long fooKey, String info) {
      return new AdditionalInfo(fooKey, null, null, info);
    }

    I don't have to read your ... oh, screw it ... I screwed up.

    #losing



  • @Lorne Kates said:

    Do you have a newsletter I could subscribe to?
     

    Yes

    Oh, I'll just add that to my Google Re--

    FUCK



  • @Ben L. said:

    Filed under: If you placed 28٫981٫249٫043 rulers end to end٫ they would reach 28٫981٫249٫043 feet in the sky.

    Napoleon?


    Actually, none of my rulers is exactly 1 foot. They all have a little bit extra on each end.



  • @Zecc said:

    @Not better, just different said:

    public long typeID(AdditionalInfo ai) {
    return ai.getFooKey() + ai.getBarKey() + ai.getQuxKey();
    }

    Pfft...

    @Different and better said:

    <html><body style='color:#55cc66; background:#001800; '>

    public long typeID(AdditionalInfo ai) {
    try {
    return (0 / ai.getFooKey()) + ai.getFooKey();
    } catch (ArithmeticException e1) {
    try {
    return (0 / ai.getBarKey()) + ai.getBarKey();
    } catch (ArithmeticException e2) {
    try {
    return (0 / ai.getQuxKey()) + ai.getQuxKey();
    } catch (ArithmeticException e3) {
    throw new RuntimeException(e3);
    }
    }
    }
    }



  • Filed under: Dark color schemes make everything cooler

     

    (Missed an opportunity to put `baz` back.)



  • @zelmak said:

    public long typeID(AdditionalInfo ai) {
    long idVal = 0;
    if ( ( idVal = ai.getFooKey() ) == 0) {
    if ( ( idVal = ai.getBarKey() ) == 0) {
    idVal = ai.getQuxKey();
    }
    }
    return idVal;
    }

    public long typeID(AdditionalInfo ai) {
        long idVal;
        if ((idVal = ai.getFooKey()) == 0 && (idVal = ai.getBarKey()) == 0 && (idVal = ai.getQuxKey()) == 0) {
            throw new IllegalStateException();
        }
        return idVal;
      }

    FTFY / BTST...



  • @mihi said:

    public long typeID(AdditionalInfo ai) {
    long idVal;
    if ((idVal = ai.getFooKey()) == 0 && (idVal = ai.getBarKey()) == 0 && (idVal = ai.getQuxKey()) == 0) {
    throw new IllegalStateException();
    }
    return idVal;
    }

    If anyone ever committed code like this to one of my projects, I'd hit them in the kidneys with a tire iron.


  • Discourse touched me in a no-no place

    @morbiuswilters said:

    If anyone ever committed code like this to one of my projects, I'd hit them in the kidneys with a tire iron.
    I'm not sure that I agree with “kidneys” or “tire iron”, but the spirit of your assertion is laudable.


Log in to reply