• (cs) in reply to Anonymous
    Anonymous:
    Anonymous:
    Even if this was the case with Java, which I've been led to believe it isn't, I would consider good programming practice more important than avoiding the most likely inconsequential performance hit.


    I have tested it, and it is the case. You have been misled. And how is using misleading variable types "good programming practice"?

    Jörg:
    I really want to see evidence of this.  I see no reason that this should be true.  Both require a vtable lookup.


    Finding the method pointer for interface methods in the vtable takes much longer, since it's not in the same place in all classes.


    Sure, why not.

    I tested this scenario and accessing via Map-interface was 3,19% FASTER. Since you omit used JVM we can't compare results. Mine was j2re1.4.2_08.

    (Actually I suspect first access would we slower but hotspot can somehow optimize subsequent accesses).

  • (cs) in reply to aakoch
    aakoch:
    aakoch:
    Alex Papadimoulis:

    String[] unused = new String[1];
    unused[0] = ""; //note this is only used for updates

    GenericObject myRequest = ApprovalRequestInterface.Query(objectQuery, unused);


    That's my favorite part.

    GenericObject myRequest = ApprovalRequestInterface.Query(objectQuery, "");

    True, it less code, but should would be faster!


    or
    GenericObject myRequest = ApprovalRequestInterface.Query(objectQuery, new String{""});
    if String[] is needed...



    These stinkers usally accept Object[] "Because then you can pass around ANYTHING you may want".

    And surely passing two parameter is BAD. They should have GenericObjectRequest which wraps those maps and arrays.

  • (cs)

    "fairly documented"? That's like "slightly alive"...

  • Anonymous (unregistered) in reply to oview
    oview:
    Sure, why not.

    I tested this scenario and accessing via Map-interface was 3,19% FASTER. Since you omit used JVM we can't compare results. Mine was j2re1.4.2_08.

    (Actually I suspect first access would we slower but hotspot can somehow optimize subsequent accesses).


    I use j2re1.4.2_03-b02 and interface calls are way, way slower. Here is the code I used,

    interface I { void f(); }
    class A implements I { public void f() { } }

    class B {
        public static void main(String args[]) {
            A a = new A();
            I i = new A();
            long t1;
           
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) a.f();
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) i.f();
            System.out.println(System.currentTimeMillis() - t1);
           
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) a.f();
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) i.f();
            System.out.println(System.currentTimeMillis() - t1);
        }
    }

    and here are the results: (the first time around it's slower because it hasn't been JITted yet)

    2516
    1359
    5344
    1250
    1359
    5375

    Deduct the empty loop time and you have 1359-1250=109ms for normal calls and 5375-1250=4125ms for interface calls. That's 37.8 times slower!
  • (cs) in reply to Anita Tinkle
    Anonymous:

    [...] wedding cakes (too many layers) [...]

    YMMD. That's a good one.

    Torsten

     

  • Bert (unregistered) in reply to Aaron Griffin
    Anonymous:
    R.Flowers:

    Umm, I just noticed the graphic... 242 items. Is that 242 tables? (Well, that seems to be a screenshot of - heh -'Enterprise Manager'. So is it 242 minus the handful of 'overhead' tables?)

    If so - wow. Two-hundred-plus tables with TLNs*.

     

    *Three Letter Names



    Absolutely.  And it keeps growing.  Every month or so I see an additional 20-ish tables.

    Which means they run out after 262626/20/12=73 years! assuming they use all TLN possible (which does not seem to be the case) and do not increase the rate of new tables

  • (cs) in reply to Bert
    Anonymous:
    Anonymous:
    R.Flowers:

    Umm, I just noticed the graphic... 242 items. Is that 242 tables? (Well, that seems to be a screenshot of - heh -'Enterprise Manager'. So is it 242 minus the handful of 'overhead' tables?)

    If so - wow. Two-hundred-plus tables with TLNs*.

     

    *Three Letter Names



    Absolutely.  And it keeps growing.  Every month or so I see an additional 20-ish tables.

    Which means they run out after 262626/20/12=73 years! assuming they use all TLN possible (which does not seem to be the case) and do not increase the rate of new tables



    It's rather 263737, since the 2nd and 3rd characters can be digits or underscore. (Does SQLServer allow underscore for the first character? IIRC Oracle doesn't)

  • (cs) in reply to ammoQ
    ammoQ:
    Anonymous:
    Which means they run out after 26*26*26/20/12=73 years! assuming they use all TLN possible (which does not seem to be the case) and do not increase the rate of new tables


    It's rather 26*37*37, since the 2nd and 3rd characters can be digits or underscore. (Does SQLServer allow underscore for the first character? IIRC Oracle doesn't)


    Then they wouldn't be TLNs

  • (cs) in reply to Anonymous
    Anonymous:
    That's pointless, since you can use a HashMap any time you need a Map anyway. All that does it make things slower, since calling a method through an interface-type reference has around 10 times as much overhead as calling through a class-type reference.


    Unmitigated hogwash. That used to be the case somwhere around java 1.1.
  • (cs) in reply to R.Flowers
    R.Flowers:
    He probably likes also cryptic three-letter variable names like 'num', 'str' and 'sex'

    I'm not too sure about num and str, but I like sex.


    Funny factoid:

    The hexadecimal  system should properly be called "sexadecimal", because "hexa" is greek, while "decimal" is latin.

    You can thank IBM for depriving the world's programmers of the fun of talking about "sex numbers".
  • (cs) in reply to gremlin
    gremlin:
    ammoQ:
    Anonymous:
    Which means they run out after 26*26*26/20/12=73 years! assuming they use all TLN possible (which does not seem to be the case) and do not increase the rate of new tables


    It's rather 26*37*37, since the 2nd and 3rd characters can be digits or underscore. (Does SQLServer allow underscore for the first character? IIRC Oracle doesn't)


    Then they wouldn't be TLNs



    Good point. What about TLNs containing accents, umlauts etc., like
    select * from ÄÁÀ;
    ?
  • Anthony (unregistered) in reply to JamesCurran
    JamesCurran:

    ammoQ:
    I wonder if there is a (arguably very small) performance penalty for the casting between interface an actual class or not.

    um..No.

    What do you think could possibly be happening is such a cast?

    The most that could be happening is that a pointer is copied from one variable to another.  Otherwise, the only difference between using a class object and an interface object is that the compiler would see a different set of methods & properties.  The generated code would be the same.



    That's not correct, and it depends on the implementation details, but in general it's not just a pointer copy. If an object implements several interfaces, you cannot assume that a pointer to the object is also a pointer to one of the interfaces. The object's vtable's first byte is not going to be an interface's vtable's first byte. You must query the object by the normal methods in order to allow it to give you the proper reference. Luckily in Java and C#, this happens automagically. However, there is a (small) performance penalty when casting between interface an actual class.

  • (cs) in reply to Anonymous
    Anonymous:


    I use j2re1.4.2_03-b02 and interface calls are way, way slower. Here is the code I used,



    Anonymous:

    and here are the results: (the first time around it's slower because it hasn't been JITted yet)

    2516
    1359
    5344
    1250
    1359
    5375

    Deduct the empty loop time and you have 1359-1250=109ms for normal calls and 5375-1250=4125ms for interface calls. That's 37.8 times slower!



    Things are not that clear cut that you seem to think. Consider

        private static void tsA(HashMap a) {
            a.get("a");
        }
       
        private static void tsI(Map a) {
            a.get("a");
        }

       
        public static void main(String[] args) {
           
            HashMap m = new HashMap();
            Map p = new HashMap();
           
            long t1;
            t1 = System.currentTimeMillis();
              
            for(int c=0;c<1000000000;c++);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) tsA(m);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) tsI(p);
            System.out.println(System.currentTimeMillis() - t1);
          
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) tsA(m);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) tsI(p);
            System.out.println(System.currentTimeMillis() - t1);       
        }

    and results

    4096
    38095
    37384
    1863
    37874
    37364

    Only thing right now I can think of is that your original code somehow throws hotspots inlining out of game. Dealing with dynamic compiling IS tricky.
  • (cs) in reply to Anonymous

    Anonymous:
    oview:
    Sure, why not.

    I tested this scenario and accessing via Map-interface was 3,19% FASTER. Since you omit used JVM we can't compare results. Mine was j2re1.4.2_08.

    (Actually I suspect first access would we slower but hotspot can somehow optimize subsequent accesses).


    I use j2re1.4.2_03-b02 and interface calls are way, way slower. Here is the code I used,

    interface I { void f(); }
    class A implements I { public void f() { } }

    class B {
        public static void main(String args[]) {
            A a = new A();
            I i = new A();
            long t1;
           
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) a.f();
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) i.f();
            System.out.println(System.currentTimeMillis() - t1);
           
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++);
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) a.f();
            System.out.println(System.currentTimeMillis() - t1);
            t1 = System.currentTimeMillis();
            for(int c=0;c<1000000000;c++) i.f();
            System.out.println(System.currentTimeMillis() - t1);
        }
    }

    and here are the results: (the first time around it's slower because it hasn't been JITted yet)

    2516
    1359
    5344
    1250
    1359
    5375

    Deduct the empty loop time and you have 1359-1250=109ms for normal calls and 5375-1250=4125ms for interface calls. That's 37.8 times slower!

    I don't see anything like that.  Given a program:

    interface I
    {
     void f();
     int getValue();
    }
    class A implements I
    {
     private int i;
     public void f()
     {
      ++i;
     }
     public int getValue()
     {
      return i;
     }
    }
    class B
    {
     public static void main(String args[])
     {
      long t1;
      A a = new A();
      I i = new A();
      int k = 0;
      for(int j = 0; j < 10; ++j)
      {
       a = new A();
       i = new A();
       k = 0;
       t1 = System.currentTimeMillis();
       for(int c=0;c<1000000000;c++)
       {
        ++k;
       }
       System.out.println("no fn call: " + (System.currentTimeMillis() - t1));
       t1 = System.currentTimeMillis();
       for(int c=0;c<1000000000;c++)
       {
        a.f();
       }
       System.out.println("concrete disp: " + (System.currentTimeMillis() - t1));
       t1 = System.currentTimeMillis();
       for(int c=0;c<1000000000;c++)
       {
        i.f();
       }
       System.out.println("iface disp: " + (System.currentTimeMillis() - t1));
      }
      System.exit(k + a.getValue() + i.getValue());
     }
    }

    (the slight changes are so I can ascertain with some confidence that calls aren't being simply elided, though the opening loop looks like it's being removed anyway)

    I see:

    C:\TEMP>javac B.java
    C:\TEMP>java -cp . B
    no fn call: 0
    concrete disp: 2719
    iface disp: 5110
    no fn call: 0
    concrete disp: 2751
    iface disp: 5423
    no fn call: 0
    concrete disp: 2672
    iface disp: 4704
    no fn call: 0
    concrete disp: 3470
    iface disp: 5892
    no fn call: 0
    concrete disp: 2797
    iface disp: 4829
    no fn call: 0
    concrete disp: 2892
    iface disp: 5876
    no fn call: 0
    concrete disp: 3219
    iface disp: 6002
    no fn call: 0
    concrete disp: 3719
    iface disp: 5876
    no fn call: 0
    concrete disp: 3251
    iface disp: 5345
    no fn call: 0
    concrete disp: 3219
    iface disp: 5455

    with:

    C:\TEMP>java -version
    java version "1.5.0_04"
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
    Java HotSpot(TM) Server VM (build 1.5.0_04-b05, mixed mode)

    The interface is slower, but not so much slower as to be grounds for concern. The general rule--program to interfaces--is still a sound one.  The difference is a few clock cycles.  The greater flexibility afforded by programming to interfaces more than makes up for this.

  • (cs) in reply to DrPizza
    DrPizza:

    The interface is slower, but not so much slower as to be grounds for concern. The general rule--program to interfaces--is still a sound one.  The difference is a few clock cycles.  The greater flexibility afforded by programming to interfaces more than makes up for this.



    Bingo.  It's an 'enterprise' solution, backed by a database.  The performance bottleneck is going to be there, not in the java code using Map instead of HashMap.  Especially as it has 200+ tables.  I fear teh joins.

    However, it gets bonus points for having a table called 'Rug'.  'Rug' makes me laugh.

    Simon
  • Asd (unregistered) in reply to Anonymous
    Anonymous:
    Here is the code I used,

    interface I { void f(); }
    class A implements I { public void f() { } }

    The problem here is that your method does nothing. Yes there is an extra overhead for interface calls but if you actually do something (such as a Map lookup) in your method it quickly becomes insignificant.
  • (cs) in reply to chrismcb
    chrismcb:

    Anonymous:
    Call me nit-picky if you must, but one thing that bugs the shit out of me is when people don't code to interfaces that already exist. For the love of Pete, use Map as your variable type.

    I'm not a java programmer so enlighten me. (I've read all the arguments, and they either don't make sense, or are contradictory)

    I assume that HashMap is a derivative of Map? If Query expects a HashMap, or calls a HashMap only function, how can you give it anything but a HashMap?

    It's not a derivative, Map is an interface and HashMap implements the Map interface. Map is not concrete, but a reference to a Map object can reference anything implementing the Map interface and therefore allows your steel-and-bolts Java Dreadnought to be slightly more flexible by being less implementation-dependant (e.g. if you want to change the type of map used, you only have to change the HashMap initialisation to WhateverYourMapIs, the references to the interface won't have to change)

    Anonymous:
    chrismcb:

    Anonymous:
    Call me nit-picky if you must, but one thing that bugs the shit out of me is when people don't code to interfaces that already exist. For the love of Pete, use Map as your variable type.

    I'm not a java programmer so enlighten me. (I've read all the arguments, and they either don't make sense, or are contradictory)

    I assume that HashMap is a derivative of Map? If Query expects a HashMap, or calls a HashMap only function, how can you give it anything but a HashMap?

     



    It's not so much a Java thing, as a general design principle to reduce class dependencies. The Query shouldn't unless absolutely necessary be programmed against the HashMap implementation in the first place.

    It is, few other languages are as inflexible and as interface-reliant than Java.

    And when you check the code, you see that the lifespan of the map is likely to be about 3 lines of code, I'd have a hard time calling that "class dependencies", using a Map in this case is more of an overengineering issue really.

  • Bailey (unregistered) in reply to dmitriy

    dmitriy:
    From reading these replies, I see that no one else has noticed that the database tables are all owned by "sysadmin." This makes me uneasy, and is potentially a WTF. I assume that by its nature, an enterprise system has many users, with different roles requiring different privileges. One of the things this implies is that there are parts of the database some users should not be able to touch or see. Where is the separation of privileges in the new system?

    To be fair, the owner of the table has absolutely no relevance to the DB users that may or may not have access to said tables.  I would expect to see all the tables owned by sysadmin, or some similar user.

    Of course, some people might decide to implement their security at the application level, rather than the database level.  Or both.

  • (cs) in reply to Bailey
    Bailey:

    To be fair, the owner of the table has absolutely no relevance to the DB users that may or may not have access to said tables.  I would expect to see all the tables owned by sysadmin, or some similar user.

    Of course, some people might decide to implement their security at the application level, rather than the database level.  Or both.



    In Oracle, there is typically a DB user (aka schema) dedicated to the application who owns all the tables, views etc.
    One reason is that the owner of the application (the one to grant rights on that tables) is not necessarily a DBA, so he might not have DBA privileges at all. Another reason is visibility: If there are two apps, both having a table called CUSTOMERS, there is no conflict if one table belongs to the user APP1 and the other one to APP2.
  • Abednigo Boink (unregistered) in reply to Andy

    Glad that nobody's mentioned Clarion yet in this language flame-fest.

    Oops...  [:D]

  • (cs) in reply to Anonymous
    Anonymous:

    and here are the results: (the first time around it's slower because it hasn't been JITted yet)

    2516
    1359
    5344
    1250
    1359
    5375


    giggle

    Try running that with the -server VM switch. Meditate on the results. Read an article in the difficulties of writing microbenchmarks:
    http://www-128.ibm.com/developerworks/java/library/j-jtp02225.html

  • (cs) in reply to masklinn
    masklinn:
    And when you check the code, you see that the lifespan of the map is likely to be about 3 lines of code, I'd have a hard time calling that "class dependencies", using a Map in this case is more of an overengineering issue really.


    It's irrelevant in the code shown, that calls the method. But I strongly suspect (because I have seen it too often in the wild) that the method actually requires HashMap as its parameter type. And that is seriously crappy, because by tying  you to a specific implementation class, it also denies you the use of all the nice conveniences in java.util.Collections (unmodifiableMap(), synchronizedMap(), singletonMap(), the EMPTY_MAP constant...).
  • (cs) in reply to brazzy
    brazzy:
    But I strongly suspect (because I have seen it too often in the wild) that the method actually requires HashMap as its parameter type. And that is seriously crappy, because by tying  you to a specific implementation class, it also denies you the use of all the nice conveniences in java.util.Collections (unmodifiableMap(), synchronizedMap(), singletonMap(), the EMPTY_MAP constant...).

    And I perfectly agree on that.

  • (cs) in reply to Whiskey Tango Foxtrot? Over.

    Well the real WTF stays the same.
    Managers hearing buzzwords....
    Consultants who don't know shit and don't care.
    i've seen it all my life, and I don't expect to see it change ever

  • (cs) in reply to Asd
    Anonymous:
    Anonymous:
    Here is the code I used,

    interface I { void f(); }
    class A implements I { public void f() { } }

    The problem here is that your method does nothing. Yes there is an extra overhead for interface calls but if you actually do something (such as a Map lookup) in your method it quickly becomes insignificant.


    True, but if it did something, anonymous wouldn't have accidentally given evidence that I could use against him ... his experiment shows that an interface call has a performance hit on the order of nanoseconds.  1000000000 requests, 4 seconds slower.

    So, we can lock ourselves into a particular class implementation instead of programming against an interface, in order to save nanoseconds on what is essentially a memory dereference.

    What is that again that they say about premature optimization? Oh, right, can lead to bad design. :)


  • LordHunter317 (unregistered) in reply to squirrel

    Guys, you're all missing the point.

    Anyone who's suggesting that the declaration should be:

    Map map = new HashMap();
    Which is indeed how this whole thing started, is just plain wrong anyway.

    Why?  It gains you nothing.  If the actual type of the variable has to be changed to another implementation of Map, then you have to change the line anyway.

    It gains you nothing else. 

    Now, if this were an argument to a method, there is potential justification for taking the highest-level interface that describes what behaviors you need.  But it isn't.

  • (cs)

    The table structure -MIGHT- have some logic behind it...they might be part of a partition table (although given the gaps in letters that's either highly unlikely or highly unnecessary here).

    For those of you that don't know, a partition table effectively allows you to store another clustered index on a table.  It breaks down a table into N tables and stores data in each one based on a constraint.  In this case, the constraints would be something like left(field, 3)='RUE'.  In certain cases this can -drastically- increase the speed of things.

    MSSQL 2k5 does this without the hundreds or thousands of tables actually showing up, but in MSSQL2k and MSSQL7 you had to create each table and join them together with a view.


    We used this for the "do not call" list for example.  We had 700 or so tables (one for each area code) and then the clustered index in each table was the first 3 digits of their phone number.  Made count/group by statements and joins a lot faster (.1 sec from 2 or 3).

    But as I said, I doubt that's what they're doing here....

  • Pasa (unregistered)

    My opinion is simple: I would quit pretty early, and any team member who stayed just DESERVES to spend his life with enterprise-the-fuck. 

  • (cs) in reply to LordHunter317
    Anonymous:
    Guys, you're all missing the point.

    Anyone who's suggesting that the declaration should be:
    Map map = new
    HashMap();
    Which is indeed how this whole thing started, is just plain wrong anyway.

    Why?  It gains you nothing.  If the actual type of the variable has to be changed to another implementation of Map, then you have to change the line anyway.

    It gains you nothing else. 

    Now, if this were an argument to a method, there is potential justification for taking the highest-level interface that describes what behaviors you need.  But it isn't.


    Sigh.

    You're the one who's missing the point.  You're arguing from strictly a whatever-compiles point of view, and not from an object-oriented point of view.

    The reason all variables, parameters and return types should be of type Map rather than HashMap is that it's a separation of contract (functionality) from implementation.

    The method needs the functionality of a Map.  There is zero probability that the implementation of that Map needs to be a HashMap.  By forcing the parameter to be a HashMap, you remove flexibility and you force an implementation when in fact you only need something that does what the contract of the Map interface specifies.

    This goes for variables too.  It's just good practice.  The variable's type should indicate the object's contract and capabilities, not the implementation of those capabilities.

    The performance arguments I've seen posted are ludicrous.  Ever hear the saying "Premature optimization is the root of all evil"?  (If you haven't, feel free to do a web search for it.)  That's truer in OO than anywhere else.  Overhead is a natural part of OO.  Get over it already.  And no your app will not be noticeably slower because it needs five additional microseconds to make a method call.  (Unless it's, like, a first-person shooter.)  Not even when you have a thousand threads doing it at once.
  • (cs) in reply to Pasa
    Anonymous:

    My opinion is simple: I would quit pretty early, and any team member who stayed just DESERVES to spend his life with enterprise-the-fuck. 


    I see this opinion a lot and it gets me wondering if it's that easy for people to quit one job one day and get another (better of course) the other... I would be very cautious to quit my job instantly even _if_ I found a lot of WTF-ish code and endured general crappy management. I would obviously look for another job, but not quit right away...

    Might be different in different countries, obviously. Perhaps it's that easy in, eg., the US, or the Netherlands, but I don't recognize it from Sweden... Comments?
  • Pasa (unregistered) in reply to impslayer

    impslayer:

    I see this opinion a lot and it gets me wondering if it's that easy for people to quit one job one day and get another (better of course) the other... I would be very cautious to quit my job instantly even _if_ I found a lot of WTF-ish code and endured general crappy management. I would obviously look for another job, but not quit right away...

    You miss a bit of a point.  If everyone there would care about their work, the output, the "good" of the company, etc, the whole team would just hand in their notice, and quite possibly the management reconsidered.  So in the end they could stay and keep improving whatever they had.

    OTOH if developers are content until their check gets bounced, no surprise the world is filled with all those enterprises, enterprise consultants and the results of their collaborated effort.

    And yes, actual quitting comes without a guarantee you can find a job the next day, or a better one within whatever time period.   The guarantee is found the other way: if you stay you will work in crap and be responsile for it too. Then again, if you chose that you deserve it IMO.

     

     

  • (cs) in reply to GoatCheez
    GoatCheez:
    merreborn:
    Anonymous:

    Java attracts the Analysis-Paralysis™ "architects" who spend 99% of their mental efforts writing up designs or building wedding cakes (too many layers) for their apps--only to have them flail on performance and scalability tests when they are released out in the wild to production...


    It's high time that people stop bringing these straw man arguments to language flamewars.  The fact that a given language has several, or many stupid users says nothing about the quality of the language itself.  Their are morons using every language.  The argument that this somehow proves the inferiority of the language is entirely fallacious.


    naw man... it's high time people stop language flamewars. anyone worth their weight knows that all languages have their place somewhere, otherwise the language wouldn't exist. get over it yall.
    I agree, high time everyone moved over to awk.  
  • Ragnaros (unregistered) in reply to icelava

    I hate enterprise "framework solutions." I hate it when some dork believes he can develop a generic system to do anything your heart desires. It's BI! It's CRM! It's a data warehouse! Great, but your code is completely unreadable and takes 20 times longer to execute than if you had just built what you were asked to build and nothing more.

    You know what sucks? Code that looks like this:

    EnterpriseBullshit bs = EnterpriseFramework.BullshitFactory.GetBullshitByString("CreateAccount");
    EnterpriseGenericResult bsResult = bs.Execute();

    Looks great on paper huh? But after lines and lines of this crap building up in your code, nobody even knows where the create account logic is stored anymore because everything is too damn generic!

     

    Stop with the obsession with reuse. Reuse is OK when you write a class library with your data access layer in it or something. But you shouldn't be able to reconfigure your app to brush your ass hair at runtime. It's cheaper to build, easier to maintain, easier to understand and more performant when you build a system that meets the requirements and doesn't exceed them.

  • coder1 (unregistered) in reply to VGR

    VGR:
    Anonymous:
    Guys, you're all missing the point.

    Anyone who's suggesting that the declaration should be:
    Map map = new HashMap();
    Which is indeed how this whole thing started, is just plain wrong anyway.

    Why?  It gains you nothing.  If the actual type of the variable has to be changed to another implementation of Map, then you have to change the line anyway.

    It gains you nothing else. 

    Now, if this were an argument to a method, there is potential justification for taking the highest-level interface that describes what behaviors you need.  But it isn't.


    Sigh.

    You're the one who's missing the point.  You're arguing from strictly a whatever-compiles point of view, and not from an object-oriented point of view.

    The reason all variables, parameters and return types should be of type Map rather than HashMap is that it's a separation of contract (functionality) from implementation.

    The method needs the functionality of a Map.  There is zero probability that the implementation of that Map needs to be a HashMap.  By forcing the parameter to be a HashMap, you remove flexibility and you force an implementation when in fact you only need something that does what the contract of the Map interface specifies.

    This goes for variables too.  It's just good practice.  The variable's type should indicate the object's contract and capabilities, not the implementation of those capabilities.

    The performance arguments I've seen posted are ludicrous.  Ever hear the saying "Premature optimization is the root of all evil"?  (If you haven't, feel free to do a web search for it.)  That's truer in OO than anywhere else.  Overhead is a natural part of OO.  Get over it already.  And no your app will not be noticeably slower because it needs five additional microseconds to make a method call.  (Unless it's, like, a first-person shooter.)  Not even when you have a thousand threads doing it at once.

    You're absolutely right!  Thankyou for succinctly putting this argument to rest (I hope!).  If anyone remains unconvinced, read about Dependecy Injection and become a better OO developer.

  • A chicken passeth by (unregistered) in reply to Ragnaros

    Obsession with the buzzword of the millenium is worse than any mistaken concept of code reuse.

    On the flip side, tho... companies who fall prey to that mistake play good games of buzzword bingo.

    PS: That "Cleveland" captcha has text that's partially blotted out because it colour-matches the background.

  • (cs) in reply to Anonymous
    Anonymous:
    I use j2re1.4.2_03-b02 and interface calls are way, way slower. Here is the code I used [...]

    I used your code and managed to get pretty much the same results on my computer with J2RE 1.5.0_06-b05.  However, like other posters, I think about your code is throwing the VM for a loop.  To be honest, I think it's completely optimizing away the "a.f()" calls, so all you're seeing is the looping cost, which is why it's so low, and actually manages to be lower than the empty loop in the first run.


    I put together a slightly different test, which called overridden, non-overriden, and virtual methods, through both the direct and indirect references.


    Here's my (rather long) code (assuming the forum doesn't eat it):
    class X
    {
        public void x() {}
    };

    abstract class A
    {
        public void f()    {}
        public abstract void g();
        public void h()    {}
    };

    interface I
    {
        void i();
    }

    class B extends A implements I
    {
        public void g() {}
        public void h() {}
        public void i() {}
        public void j() {}
    }

    public class Test
    {
        public static void main(String [] args)
        {
            test();
            test();
        }

        static void test()
        {
            final int N = 1000000000;

            long starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
            }
            long  endtime = System.currentTimeMillis();
            long baseline = endtime - starttime;
            System.out.println(baseline + "\tbaseline");

            X x = new X();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                x.x();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tX as X (x)");


            B b = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                b.f();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as B (f)");


            A a = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                a.f();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as A (f)");


            b = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                b.g();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as B (g)");


            a = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                a.g();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as A (g)");


            b = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                b.h();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as B (h)");


            a = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                a.h();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as A (h)");


            b = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                b.i();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as B (i)");


            I in = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                in.i();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as I (i)");


            b = new B();
            starttime = System.currentTimeMillis();
            for (int i = 0; i < N; i++)
            {
                b.j();
            }
            endtime = System.currentTimeMillis();
            System.out.println(endtime - starttime - baseline + "\tB as B (j)");
        }
    }

    Here is the output:
    C:\Documents and Settings\jörg\Desktop>java Test
    1984    baseline
    4938    X as X (x)
    5376    B as B (f)
    4501    B as A (f)
    4937    B as B (g)
    5407    B as A (g)
    4891    B as B (h)
    4422    B as A (h)
    4516    B as B (i)
    6438    B as I (i)
    4985    B as B (j)
    1469    baseline
    46      X as X (x)
    500     B as B (f)
    515     B as A (f)
    500     B as B (g)
    500     B as A (g)
    906     B as B (h)
    5015    B as A (h)
    734     B as B (i)
    4422    B as I (i)
    781     B as B (j)

    The first run shows that the cost of accessing, whether directly, via an abstract method, overridden virtual, non-overridden virtual, or through an interface is all pretty similar.  The second run shows us that the VM can do whatever it wants and that we can't trust the results of trivial loop-on-an-empty-function benchmarks.  Note how even on the functions inherited from A, the VM isn't consistent with its optimization.
  • Good OO Design Programmer (unregistered) in reply to Anonymous
    Anonymous:

    That's pointless, since you can use a HashMap any time you need a Map anyway. All that does it make things slower, since calling a method through an interface-type reference has around 10 times as much overhead as calling through a class-type reference.

    ...

    If it needs to be used on other types of Maps as well as HashMap, then yes. Otherwise, again you're just making things pointlessly slower.


    This is 100% false. Just an FYI.

    Good OO design dictates that a method should not accept HashMap, but rather Map. And the object type should also be map even if the specific implementation is HashMap.

    So...the thing would look like this:

    Map m = new HashMap()

    public void aMethod(Map m, OtherParams...){}

    There are specific design reasons for this that revolve around the idea that this code might be used else where. There is a reason to have interfaces after all and this is one of hte major reasons.
  • drobnox (unregistered) in reply to brazzy

    Funny factoid:

    The hexadecimal  system should properly be called "sexadecimal", because "hexa" is greek, while "decimal" is latin.

    You can thank IBM for depriving the world's programmers of the fun of talking about "sex numbers".



    "Automobile" is a good example of a hybrid Greek-Latin compound word.

    All-Latin would be "ipsomobile".
    All-Greek would be "autokinetikon".

  • coder1 (unregistered) in reply to Good OO Design Programmer

    Anonymous:
    Anonymous:

    That's pointless, since you can use a HashMap any time you need a Map anyway. All that does it make things slower, since calling a method through an interface-type reference has around 10 times as much overhead as calling through a class-type reference.

    ...

    If it needs to be used on other types of Maps as well as HashMap, then yes. Otherwise, again you're just making things pointlessly slower.


    This is 100% false. Just an FYI.

    Good OO design dictates that a method should not accept HashMap, but rather Map. And the object type should also be map even if the specific implementation is HashMap.

     

    OK, but you mean the reference type should be Map - there's no such thing as an object type Map - it's an interface.  Let's not cloud the issue further.

  • Better OO (unregistered) in reply to Good OO Design Programmer
    Anonymous:
    Anonymous:

    That's pointless, since you can use a HashMap any time you need a Map anyway. All that does it make things slower, since calling a method through an interface-type reference has around 10 times as much overhead as calling through a class-type reference.

    ...

    If it needs to be used on other types of Maps as well as HashMap, then yes. Otherwise, again you're just making things pointlessly slower.


    This is 100% false. Just an FYI.

    Good OO design dictates that a method should not accept HashMap, but rather Map. And the object type should also be map even if the specific implementation is HashMap.

    So...the thing would look like this:

    Map m = new HashMap()

    public void aMethod(Map m, OtherParams...){}

    There are specific design reasons for this that revolve around the idea that this code might be used else where. There is a reason to have interfaces after all and this is one of hte major reasons.


    Honestly, this is kind of silly.  There really is no reason to do

       Map m = new HashMap(); 

    instead of

       HashMap m = new HashMap();

    within the method itself.  If the method wants to use a HashMap internally, by all means, do so, and even reference it as such..  If it returns it or passes it into a method call, then those should most likely be Map references.

    There are reasons to do stuff like this.  While probably not the case for Maps, there are times when a method needs to instantiate a class that is an implementation of an interface, and then call methods on it that aren't part of the interface itself, but are part of that specific class (perhaps to configure it).  Often times factories work like this.  They might return an interface, but inside the factory itself, they need to call specific methods on the class implementing it before they are ready to return it.

    That being said, worrying about peformance of interface calls is really silly.
  • TomCo (unregistered) in reply to jimojimo

    Regarding IBM having that 6-char limit, doesn't that extend all the way back to their FORTRAN compiler (70's)?  Anyone remember that mess?  I think they still ensure their "enterprise" products from the past are still compatible with today's ("Open Soars" initiatives) as well as some possible future that hasn't happened yet. [;)]

  • Aaron Griffin (unregistered) in reply to Jeff
    Anonymous:
    The given code fragment doesn't suggest they didn't.

    There's nothing wrong with the
    HashMap map = new HashMap();

    Now, if their Query() method requires a HashMap and not a Map, then yes that is an issue.


    Actually, it takes an Object which is cast to a HashMap right of the bat.  Who knows....?
  • Some Guy (unregistered) in reply to Ragnaros
    Anonymous:

    I hate enterprise "framework solutions." I hate it when some dork believes he can develop a generic system to do anything your heart desires. It's BI! It's CRM! It's a data warehouse! Great, but your code is completely unreadable and takes 20 times longer to execute than if you had just built what you were asked to build and nothing more.

    You know what sucks? Code that looks like this:

    EnterpriseBullshit bs = EnterpriseFramework.BullshitFactory.GetBullshitByString("CreateAccount");
    EnterpriseGenericResult bsResult = bs.Execute();

    Looks great on paper huh? But after lines and lines of this crap building up in your code, nobody even knows where the create account logic is stored anymore because everything is too damn generic!

     

    Stop with the obsession with reuse. Reuse is OK when you write a class library with your data access layer in it or something. But you shouldn't be able to reconfigure your app to brush your ass hair at runtime. It's cheaper to build, easier to maintain, easier to understand and more performant when you build a system that meets the requirements and doesn't exceed them.

    Amen!

  • Aaron Griffin (unregistered) in reply to Aaron Griffin

    Oh, and for all of you in this Map-HashMap discussion, who cares.  That's just one of the many many WTF-able code fragments that was chosen for posting.  For instance, there's alot of:

    catch(SomeException se) { throw se; }
    catch(AnotherException ae) { throw ae; }
    catch(ThirdException te) { throw te; }
    ... continue ad nauseum for 5-10 lines
    catch(Exception e) { throw e; }

    Here's another good one:

    public ArrayList getCurrentProcessRoles(String[] req) -- req[0] is the userid, req[1] is the request id, and the rest of req[] are the column names to retrieve in addition to the process role

  • Lunkwill (unregistered) in reply to Joost_

    enterprison[tm] ASAP.

  • (cs) in reply to GoatCheez
    GoatCheez:
    naw man... it's high time people stop language flamewars. anyone worth their weight knows that all languages have their place somewhere, otherwise the language wouldn't exist. get over it yall.

    The problem is most language designers do not know the place of their language.

    Java is not that much better than C++ that is should have been created. C++ is not better than smalltalk, so it should not have been created. Is C really better than BCPL better than ALGOL?

    I presume ALGOL was better than Fortran (that isn't hard to do), so it can exist (maybe, since LISP also existed).

    There is nothing wrong with creating your own programming language. In fact it is educational, and perhaps fun (depending on what type of person you are). However there is something wrong with releasing a language without first being sure it is better. (Other than to get peer review from others)

    The only way that Java is better than its peers is marketing. As a programmer I do not consider this useful.

    The JVM is an interesting idea perhaps worth bring out, but it does not need the Java language to exist. Many other languages run on the JVM.

  • (cs) in reply to Ragnaros
    Anonymous:

    Stop with the obsession with reuse. Reuse is OK when you write a class library with your data access layer in it or something. But you shouldn't be able to reconfigure your app to brush your ass hair at runtime. It's cheaper to build, easier to maintain, easier to understand and more performant when you build a system that meets the requirements and doesn't exceed them.


    I agree.  Personally, I INSIST on having a dedicated routine built just for brushing my ass hair.

    (Let the historians note; this is the first time I have ever used the term 'ass hair' in a public forum.)
  • protoscript (unregistered) in reply to Whiskey Tango Foxtrot? Over.

    That one...eleven...onehundredeleven thing just made me spit water onto my desk!

     

    Thank you so much!

  • (cs) in reply to protoscript
    Anonymous:
    That one...eleven...onehundredeleven thing just made me spit water onto my desk!


    Yeah, that was so cool!!!!!11eleventy(i^2)*(e^i*pi)!!
  • (cs) in reply to VGR
    VGR:
    Anonymous:
    Guys, you're all missing the point.

    Anyone who's suggesting that the declaration should be:
    Map map = new
    HashMap();
    Which is indeed how this whole thing started, is just plain wrong anyway.

    Why?  It gains you nothing.  If the actual type of the variable has to be changed to another implementation of Map, then you have to change the line anyway.

    It gains you nothing else. 

    Now, if this were an argument to a method, there is potential justification for taking the highest-level interface that describes what behaviors you need.  But it isn't.


    Sigh.

    You're the one who's missing the point.  You're arguing from strictly a whatever-compiles point of view, and not from an java-style object-oriented point of view.

    The reason all variables, parameters and return types should be of type Map rather than HashMap is that it's a separation of contract (functionality) from implementation.

    The method needs the functionality of a Map.  There is zero probability that the implementation of that Map needs to be a HashMap.  By forcing the parameter to be a HashMap, you remove flexibility and you force an implementation when in fact you only need something that does what the contract of the Map interface specifies.

    This goes for variables too.  It's just good practice.  The variable's type should indicate the object's contract and capabilities, not the implementation of those capabilities.

    The performance arguments I've seen posted are ludicrous.  Ever hear the saying "Premature optimization is the root of all evil"?  (If you haven't, feel free to do a web search for it.)  That's truer in OO than anywhere else.  Overhead is a natural part of OO.  Get over it already.  And no your app will not be noticeably slower because it needs five additional microseconds to make a method call.  (Unless it's, like, a first-person shooter.)  Not even when you have a thousand threads doing it at once.

    I fixed that for you

    Anonymous:
    Anonymous:

    That's pointless, since you can use a HashMap any time you need a Map anyway. All that does it make things slower, since calling a method through an interface-type reference has around 10 times as much overhead as calling through a class-type reference.

    ...

    If it needs to be used on other types of Maps as well as HashMap, then yes. Otherwise, again you're just making things pointlessly slower.


    This is 100% false. Just an FYI.

    Good java-style OO design dictates that a method should not accept HashMap, but rather Map. And the object type should also be map even if the specific implementation is HashMap.

    So...the thing would look like this:

    Map m = new HashMap()

    public void aMethod(Map m, OtherParams...){}

    There are specific design reasons for this that revolve around the idea that this code might be used else where. There is a reason to have interfaces after all and this is one of hte major reasons.

    Fixed that one too.

Leave a comment on “Bitten by the Enterprise Bug”

Log In or post as a guest

Replying to comment #64798:

« Return to Article