• jrobbio (unregistered)

    That is generic squared!

  • Otterdam (cs)

    This is a generic comment that can be posted on any TDWTF article.

  • gabba (cs)

    Needs more generification. Where's the Body11?

    Oh. "Removed for sanity". So I guess it is generic enough. Never mind.

  • Yep (unregistered)

    Easy, just make all the fields booleans and rework your forms to fit the TRUE/FALSE/FILE_NOT_FOUND scheme.

  • Kuli (unregistered)

    I wonder why he just checked for, e.g., "From". He should have checked this way:

    if("From".equals(usedField[i].getText()) || "fRom".equals(usedField[i].getText()) || "frOm".equals(usedField[i].getText()) || "froM".equals(usedField[i].getText()) || "FRom".equals(usedField[i].getText()) || "FrOm".equals(usedField[i].getText()) || "FroM".equals(usedField[i].getText()) || "fROm".equals(usedField[i].getText()) || "fRoM".equals(usedField[i].getText()) || "frOM".equals(usedField[i].getText()) || "FROm".equals(usedField[i].getText()) || "FRoM".equals(usedField[i].getText()) || "FrOM".equals(usedField[i].getText()) || "fROM".equals(usedField[i].getText()) || "FROM".equals(usedField[i].getText()) || "from".equals(usedField[i].getText())){ ...

  • Rushyo (unregistered)

    Urgh. Can you imagine what the rest of the 'generic' code at the company is like?

  • A B (unregistered)
    Comment held for moderation.
  • Peej (unregistered)

    Surely the problem is that it wasn't generic enough though?

  • brazzy (cs) in reply to Peej
    Peej:
    Surely the problem is that it wasn't generic enough though?
    Definitely. There is no program that can't be improved upon by making it more generic (usually involves tripling the code size and quintupling the time required to make any changes that were not foreseen by the genericiser).
  • Just Some Guy (unregistered)

    I'm with the boss on this one. I hate special exceptions because they inevitably break whenever you change whatever it is that they're modifying.

    One of our legacy applications had logic like

    if (zipcode == $foo) { do special stuff; }
    . When I converted that to a web application, I insisted (successfully) that a new boolean column be added to our customer database and rewrote that as
    if (user.isspecial) { do special stuff; }
    I'm sure a few people thought I was a jerk until we added three similar customers later that year and everything automatically worked for them.

    And what's wrong with building in internationalization? I've yet to see a language or coding framework that doesn't support phrase libraries. Again, everyone probably thought J.K.'s boss was a jerk until they sold a copy to a customer in Quebec.

    I think TRWTF is that J.K. and his coworkers wanted to hardcode everything. That seems perfectly reasonable the first few times you write something, but get burned by changing requirements a few times and "generic" starts looking pretty good.

  • Johnny Anklebiter (unregistered)

    It's bad code. But why wasn't it working?

  • I walked the dinosaur (unregistered)

    Hey, at least he is using .equals()....

  • Kevin (unregistered) in reply to gabba

    How in the hell is this ever anything nearing a good idea?! You can make this page generic by having it pull a translation from a field in an included php file, and have the mail-to address set in the same file! Well, that is assuming this is php...

  • dkf (cs) in reply to I walked the dinosaur
    I walked the dinosaur:
    Hey, at least he is using .equals()....
    But that's slow! It'd be much faster if they used String.intern() before returning from that getText() method, since then they'd be able to do all those comparisons with == directly.
  • Beldar the Phantom Troll (unregistered) in reply to Just Some Guy
    Just Some Guy:
    I'm with the boss on this one. I hate special exceptions because they inevitably break whenever you change whatever it is that they're modifying.

    One of our legacy applications had logic like

    if (zipcode == $foo) { do special stuff; }
    . When I converted that to a web application, I insisted (successfully) that a new boolean column be added to our customer database and rewrote that as
    if (user.isspecial) { do special stuff; }
    I'm sure a few people thought I was a jerk until we added three similar customers later that year and everything automatically worked for them.

    And what's wrong with building in internationalization? I've yet to see a language or coding framework that doesn't support phrase libraries. Again, everyone probably thought J.K.'s boss was a jerk until they sold a copy to a customer in Quebec.

    I think TRWTF is that J.K. and his coworkers wanted to hardcode everything. That seems perfectly reasonable the first few times you write something, but get burned by changing requirements a few times and "generic" starts looking pretty good.

    TopCod3r, is that you?

  • DeLos (cs) in reply to Johnny Anklebiter
    Johnny Anklebiter:
    It's bad code. But why wasn't it working?

    I am assuming because the code was unable to handle the additional fields on the new form.

  • Someone You Know (cs)
    Jake Vinson:
    Working on an application that will only ever be used by the local government in Podunk, MA?

    Podunk is in Michigan. Podunk, MA is actually called "Florida".

  • Just Some Guy (unregistered) in reply to Beldar the Phantom Troll
    Beldar the Phantom Troll:
    TopCod3r, is that you?

    Nope. I'm just too lazy to to back and change everything later just because I believed the boss when he swore that we would never need a certain feature. In my experience, that turns out to be incorrect about 95% of the time.

    Boss: Can you make it do $something? Me: Not anymore. You told me that $something was impossible in our industry and not to waste time setting up the database tables to handle it. Boss: Well, that changed. So can you do it? Me: pounds head on desk

  • brazzy (cs) in reply to Just Some Guy
    Just Some Guy:
    I think TRWTF is that J.K. and his coworkers wanted to hardcode everything. That seems perfectly reasonable the first few times you write something, but get burned by changing requirements a few times and "generic" starts looking pretty good.
    That in turn seems perfectly reasonable until you've gone "generic" a few times and realized that the extra work you put into it was wasted because it was an isolated special case after all, or got burned by changing requirements that you "generic" solution didn't cover, but DID make far more difficult to implement than with a simple, straightforward solution.

    Yeah, requirements will change. But often not they way you expect them to. And the overall most flexible solution that can accomodate ANY change in a short time is usually a simple, straightforward one that does not involve config files or code generation.

  • RIF (unregistered) in reply to Kuli
    Kuli:
    I wonder why he just checked for, e.g., "From". He should have checked this way:

    if("From".equals(usedField[i].getText()) || "fRom".equals(usedField[i].getText()) || "frOm".equals(usedField[i].getText()) || "froM".equals(usedField[i].getText()) || "FRom".equals(usedField[i].getText()) || "FrOm".equals(usedField[i].getText()) || "FroM".equals(usedField[i].getText()) || "fROm".equals(usedField[i].getText()) || "fRoM".equals(usedField[i].getText()) || "frOM".equals(usedField[i].getText()) || "FROm".equals(usedField[i].getText()) || "FRoM".equals(usedField[i].getText()) || "FrOM".equals(usedField[i].getText()) || "fROM".equals(usedField[i].getText()) || "FROM".equals(usedField[i].getText()) || "from".equals(usedField[i].getText())){ ...

    "It had been built to convert any HTML form with a properly named From, To, and Subject line into an email."

    RIF ;-)

  • akatherder (cs) in reply to Just Some Guy
    Just Some Guy:
    Again, everyone probably thought J.K.'s boss was a jerk until they sold a copy to a customer in Quebec.
    public function Canadify($phrase){
       $phrase.=", eh?";
    
       return $phrase;
    }
    
  • RIF (unregistered) in reply to DeLos
    DeLos:
    Johnny Anklebiter:
    It's bad code. But why wasn't it working?

    I am assuming because the code was unable to handle the additional fields on the new form.

    Assumption is the mother of all f*ckups.

    Needs more generic.

  • Just Some Guy (unregistered) in reply to brazzy
    brazzy:
    That in turn seems perfectly reasonable until you've gone "generic" a few times and realized that the extra work you put into it was wasted because it was an isolated special case after all, or got burned by changing requirements that you "generic" solution didn't cover, but DID make far more difficult to implement than with a simple, straightforward solution.

    Well, there's an art to making it "generic enough". I think a baseline starting point is not hardcoding high-level information directly into the application, as per my example. Instead of writing

    if username == 'jdoe'
    you should figure out what's different about that user's needs and make it work for all users that might have those needs. You see such things a lot in web apps that've grown past their original specifications, and the authors have to go back and replace instances of
    if userid == 0
    with
    if user.isadmin()
    and such.

    brazzy:
    Yeah, requirements will change. But often not they way you expect them to. And the overall most flexible solution that can accomodate ANY change in a short time is usually a simple, straightforward one that does not involve config files or code generation.

    Well, right. That's where experience comes into play. After a while you get an instinct for which assumptions are safe and which are certain to come back to bite you.

  • danixdefcon5 (cs) in reply to Just Some Guy
    Just Some Guy:
    Beldar the Phantom Troll:
    TopCod3r, is that you?

    Nope. I'm just too lazy to to back and change everything later just because I believed the boss when he swore that we would never need a certain feature. In my experience, that turns out to be incorrect about 95% of the time.

    Boss: Can you make it do $something? Me: Not anymore. You told me that $something was impossible in our industry and not to waste time setting up the database tables to handle it. Boss: Well, that changed. So can you do it? Me: pounds head on desk

    Why do I feel that deja vu feeling?? Oh yes:

    Me: Hey, this "status" field they're sending in, aren't we supposed to do something with it? Boss: Nah, everything we get will have the same status. Me: But I remember reading in the requirements that we did have to use that field! Boss: Nope. Don't use it.

    *** two weeks later, in an urgent meeting ***

    Boss: Well, some requirements changed, and the app now has to do X instead of Y. Oh, and by the way, you were right! We do need to do something with that status field! Me: BANG BANG BANG

  • vaecus (unregistered) in reply to Kevin
    Kevin:
    Well, that is assuming this is php...
    Which it obviously isn't.
  • Paul (unregistered) in reply to Just Some Guy
    Just Some Guy:
    Well, there's an art to making it "generic enough". I think a baseline starting point is not hardcoding high-level information directly into the application, as per my example.

    But that's not what J.K's boss wanted. He wanted far beyond that.

    I mean, there's absolutely no need for the private names of a form's fields to be genericified. The visible labels can be changed without needing the actual field name to be changed. (which is the whole WTF in this case).

    As far as generification goes, the best advice I've heard is - the first time you need to do something, just do what you need to do. The second time, cut & paste from the first time. The third time, start generificying it.

    It's a lot harder to generificate something than it is to just do what you actually need to do (as well as being harder to maintain), and 9 times out of 10 you could well guess wrong what needs generificatifying, so wait until you actually need a generificatifiatiatiated version before you make one.

  • Matt (unregistered) in reply to brazzy
    brazzy:
    Peej:
    Surely the problem is that it wasn't generic enough though?
    Definitely. There is no program that can't be improved upon by making it more generic (usually involves tripling the code size and quintupling the time required to make any changes that were not foreseen by the genericiser).

    Isn't the point of making code generic that you don't have to make changes to it in order to do something else??

    :D

  • lbp (unregistered) in reply to Just Some Guy
    Just Some Guy:
    brazzy:
    That in turn seems perfectly reasonable until you've gone "generic" a few times and realized that the extra work you put into it was wasted because it was an isolated special case after all, or got burned by changing requirements that you "generic" solution didn't cover, but DID make far more difficult to implement than with a simple, straightforward solution.

    Well, there's an art to making it "generic enough". I think a baseline starting point is not hardcoding high-level information directly into the application, as per my example. Instead of writing

    if username == 'jdoe'
    you should figure out what's different about that user's needs and make it work for all users that might have those needs. You see such things a lot in web apps that've grown past their original specifications, and the authors have to go back and replace instances of
    if userid == 0
    with
    if user.isadmin()
    and such.

    I once read something which summed that situation up as (I think) - a type, struggling to express itself.

    Where it becomes even more important, and I can't believe I've been unfortunate enough to see code that does this, in a modern, not embedded, environment:

    // repeat this, and slight variations of it, without comment, all over the code base if (a.someEnum || a.someOtherEnum || a.someOtherEnum || a.yetAnotherEnum) { // do something special }

    Surely after typing that twice, anybody who understands what a function is would consider making it one?

    Sorry if this doesn't make much sense, my eyes are still bleeding after having recently dealt with the worst codebase I've ever seen.

  • Tom JP (unregistered)

    TRWTF is using the word "generic" to describe non-generic code. Try using "generalized" for these cases.

  • lbp (unregistered) in reply to danixdefcon5
    *** two weeks later, in an urgent meeting ***

    Boss: Well, some requirements changed, and the app now has to do X instead of Y. Oh, and by the way, you were right! We do need to do something with that status field! Me: BANG BANG BANG

    Boss: Oh, and apparently that field would have had different values in a few important cases over the last few weeks, so we'd best reprocess

    For me it was an important lesson in assert your assumptions in production code, and storing as much raw data as you can manage.

  • JD (unregistered)

    It always annoys me when co-workers put together some really great component but with specific hooks in it that will prevent it from being used in a generic manner. Personally, I always aim to make components as generic as possible. The platform I'm working on at the moment is so generic that I can customise both the look and the behaviour of it with just a few lines of human-readable text. I call it a "programming language" and I can do just about anything I want with it after editing the configuration (I call the config files "source code" to make them sound important).

  • Zach Bora (unregistered) in reply to Just Some Guy
    Just Some Guy:
    Beldar the Phantom Troll:
    TopCod3r, is that you?

    Nope. I'm just too lazy to to back and change everything later just because I believed the boss when he swore that we would never need a certain feature. In my experience, that turns out to be incorrect about 95% of the time.

    Boss: Can you make it do $something? Me: Not anymore. You told me that $something was impossible in our industry and not to waste time setting up the database tables to handle it. Boss: Well, that changed. So can you do it? Me: pounds head on desk

    I modified the invoicing module on one of our sites 2 years ago that would handle partial billing, but only if management approved it. They had a lot of problems over there and management didn't want to makes things worse by allowing partial invoices. Turn out I did that modification for nothing because that site got closed 1 year later.

  • cellocgw (unregistered) in reply to Someone You Know
    Someone You Know:
    Jake Vinson:
    Working on an application that will only ever be used by the local government in Podunk, MA?

    Podunk is in Michigan. Podunk, MA is actually called "Florida".

    Hey, I'm the Mayor of Podunk, MA, you insensitive clod!

  • Kuli (unregistered) in reply to RIF
    RIF:
    "It had been built to convert any HTML form with a properly named From, To, and Subject line into an email."

    RIF ;-)

    But what if the naming standards change some time? Then this wouldn't be generic enough.

    He'd better set up a database table with the current name of a field and some Java code that handles it. Then he could check it for every field and execute the Java code with Janino at runtime. Then he would've no problems if there's a new "body183" field some time.

    -Kuli

  • Charles400 (cs)

    I once had a generic boss.

  • Martin (unregistered)

    It is obvious what the original coder wanted.

    He wanted to only include all form fields that started with "Body" in the memo variable. All other fields, like the submit button, should be excluded.

    He also correctly used "Constant".equals(Variable) instead of the usual novice error of Variable.equals("Constant") to prevent null pointers.

    So his thinking is clear, if a little "ungeneric".

    All he needs to do to correct this code is to use four nested else-ifs, instead of serial ifs, with the final one being

       } else if (usedField[i].getText()!=null && usedField[i].getText().startsWith("Body")){
          memo += usedField[i].getValue();
       }

    Nice and generic. [As long as you maintain the form field naming convention]

  • Raedwald (cs)

    I'm seeing several ads for solid oak furniture. Is this some meta joke about taking-a-picture-of-it-on-a-table?

  • Messy Wiper (unregistered) in reply to dkf
    Comment held for moderation.
  • Someone You Know (cs) in reply to cellocgw
    cellocgw:
    Someone You Know:
    Jake Vinson:
    Working on an application that will only ever be used by the local government in Podunk, MA?

    Podunk is in Michigan. Podunk, MA is actually called "Florida".

    Hey, I'm the Mayor of Podunk, MA, you insensitive clod!

    East Brookfield has no mayor. East Brookfield needs no mayor.

  • adsfg (unregistered) in reply to danixdefcon5
    danixdefcon5:
    Just Some Guy:
    Beldar the Phantom Troll:
    TopCod3r, is that you?

    Nope. I'm just too lazy to to back and change everything later just because I believed the boss when he swore that we would never need a certain feature. In my experience, that turns out to be incorrect about 95% of the time.

    Boss: Can you make it do $something? Me: Not anymore. You told me that $something was impossible in our industry and not to waste time setting up the database tables to handle it. Boss: Well, that changed. So can you do it? Me: pounds head on desk

    Why do I feel that deja vu feeling?? Oh yes:

    Me: Hey, this "status" field they're sending in, aren't we supposed to do something with it? Boss: Nah, everything we get will have the same status. Me: But I remember reading in the requirements that we did have to use that field! Boss: Nope. Don't use it.

    *** two weeks later, in an urgent meeting ***

    Boss: Well, some requirements changed, and the app now has to do X instead of Y. Oh, and by the way, you were right! We do need to do something with that status field! Me: BANG BANG BANG

    Those were gunshots, right?

  • Messy Wiper (unregistered) in reply to adsfg

    [quote user="adsfg"][quote user="danixdefcon5"][quote user="Just Some Guy"][quote user="Beldar the Phantom Troll"]TopCod3r, is that you?[/quote] Me: BANG BANG BANG[/quote]Those were gunshots, right?[/quote]

    No... those are farts escaping the exit of the cavity that is my asshole.

  • Franz Kafka (unregistered) in reply to Just Some Guy
    Just Some Guy:
    I think TRWTF is that J.K. and his coworkers wanted to hardcode everything. That seems perfectly reasonable the first few times you write something, but get burned by changing requirements a few times and "generic" starts looking pretty good.

    There's a middle ground between hardcoding every last thing and making everything completely generic; when I write an app, I do hardcode a lot of stuff (it's all semantic, so the user.isAdmin test is coded sensibly, for instance), then generalize as necessary. All data should be looked up, but no reason for making everything generic - YAGNI

  • Mobile guru (unregistered) in reply to Martin
    Martin:
    He also correctly used "Constant".equals(Variable) instead of the usual novice error of Variable.equals("Constant") to prevent null pointers.
    WTF?! This doesn't prevent null pointers, instead it HIDES real error. This is the same thing as enclosing all code in try/catch and ignoring exception, thinking you "prevented" them!

    Null pointers prevented by proper design and right tools.

  • JamesQMurphy (unregistered) in reply to Franz Kafka
    Comment held for moderation.
  • Outlaw Programmer (cs) in reply to Mobile guru
    Mobile guru:
    Martin:
    He also correctly used "Constant".equals(Variable) instead of the usual novice error of Variable.equals("Constant") to prevent null pointers.
    WTF?! This doesn't prevent null pointers, instead it HIDES real error. This is the same thing as enclosing all code in try/catch and ignoring exception, thinking you "prevented" them!

    Null pointers prevented by proper design and right tools.

    Uhhh what? Most of the time doing something like that just prevents you from checking if the pointer is null in the first place. Example:

    public boolean isAwesome(String s)
    {
      if(s == null)
        return false;
    
      return s.equals("Awesome");
    }

    Becomes:

    public boolean isAwesome(String s)
    {
      return "Awesome".equals(s);
    }

    Most of the time you're not "hiding" anything.

  • K (unregistered)

    Reminds me of a few bugs I had to fix a while ago. A number of different pages in a web application all had to show a particular piece of information. The html was generated by inserting a bunch of values into a template. For some part of the html it was unclear if it was supposed to come from the template or the inserted values, which was the reason why a bug had shown up that caused this piece to show up twice in the generated html. I thought that was going to be an easy fix. However later another bug popped up where sometimes this piece of the html was completely absent.

    The templates themselves were java code. And running a grep over the code base I found 10 different copies of that code which were inconsistent in whether they included that piece of the html in the template or not. The different values that could be inserted into the template were inconsistent as well. The different copies of the code had other differences as well. Some of them used different ways to get to the same piece of information to insert. They also had other bugs, which I don't exactly recall what were. Anyway no two of those 10 copies of the code were identical, even though they were all supposed to do exactly the same thing.

    I did what I considered the right thing to do. First found out if there were any good reason for any of the differences, which there turned out not to be. So I wrote one method to render the html and replaced all 10 instances with a call of that method.

    So I thought this bug was finally resolved. Turned out I was wrong. A few weeks later another bug of the same kind showed up. I was puzzled. I knew there was no such bug in the method I had written, and all 10 copies of the code had been replaced with a call to that method. So how could there still be a bug?

    Turned out there was actually originally 11 copies of the code across the code base. But I had missed one of them. How come grep could actually miss this? It turned out, that the 11th instance happened to have a bug none of the others had, and that bug was in the line I had greped for, which is why I didn't find it.

    At that point I did a few more grep commands across the code base searching for various parts of the code to ensure there were no more versions lying around. I also carefully looked through the flow charts for the interaction and verified that there were only 11 pages in the flow that needed this piece of information.

    Then I explained the project lead why there still was one of those bugs left and that we had to remove the last buggy copy and replace it with a call of the method that did things right. His response was, that we were too close to the deadline for such changes, so we just had to fix the bug in the remaining instance of the code instead.

  • Gabelstaplerfahrer (cs)

    I used to work for a boss who also expected me to wave the MWoG (Magic Wand of Generic) every time I needed to write something very customer specific.

    But our contact form wasn't so customer specific, it was pretty generic: it only asked you to fill in every little piece of personal information we could think of, and all fields were required. And it had to work in four languages, and it had to fill multiple databases when needed. And those databases weren't interchangeable.

    No wonder then, that as soon as the form was implemented on our websites, not a single form has ever been submitted since. Even after putting the form on a diet, nobody seems to like it :)

    To see it in action, take a look at http://www.lablines.com/page/common/register_and_correct_become_an_early_bird.aspx?lang=en

  • Franz_Kafka (cs) in reply to K
    K:
    Then I explained the project lead why there still was one of those bugs left and that we had to remove the last buggy copy and replace it with a call of the method that did things right. His response was, that we were too close to the deadline for such changes, so we just had to fix the bug in the remaining instance of the code instead.

    That makes sense from a risk mitigation standpoint - don't change large chunks of code right before release. Did he schedule a bugfix to do the proper thing after release?

  • Walleye (cs) in reply to Someone You Know
    Someone You Know:
    Jake Vinson:
    Working on an application that will only ever be used by the local government in Podunk, MA?

    Podunk is in Michigan. Podunk, MA is actually called "Florida".

    A quick search of MapPoint shows that there are TWO Podunks in Michigan. And one each in Connecticut, New York, Vermont, and Ohio.

  • 5|i(3_x (unregistered)

    It's possible to over-engineer solutions just as much as it is to under-engineer them.

    This, on the other hand, seems to be a case of plain ol' poor-engineering. Having a generic form to email processor is not a bad idea but this is a bad implementation.

    I've heard a pretty good guideline for knowing when to start genericizing:

    1st time a customer wants something done, just do it. 2nd time a customer wants something done, maybe just do it. 3rd time, automate/abstract/etc it.

Leave a comment on “The Magic Wand of Generic”

Log In or post as a guest

Replying to comment #:

« Return to Article