• (cs) in reply to Phleabo
    Phleabo:
    Is the real WTF the fact that it took him 20 minutes to do a full text search over the codebase? I can do a string search over 100 GB of text data in 20 minutes, and that's on a network volume. If his codebase is that large, he's got bigger problems.

    Install cygwin. Learn to use grep.

    The real WTF is you tell someone to install cygwin. Windows has a perfectly capable command line regex search tool built in.

  • (cs) in reply to Keko
    Keko:
    I don't want to generate a rant here, but what's wrong with MS developers that they love adding layers and layers of complexity?
    I'm not sure what MS developers have to do with anything, as anyone can write overly complex code.

    Recently someone I worked with wrote an API, then wrote some sample code to use the API. The sample code should have been fairly straight foward and simple and a dozen or two lines. Instead I get this behomoth of a file (ok so it wasn't that big, just huge relative to what it should have been) because this person believed you had to abstract everything and have a data layer and a model layer. So he create his data layer which abstracted away IDictionary. With one exception he had a 1 to 1 relationship between his methods and those in IDictionary (although he didn't surface all of the IDictionary methods) Good thing we used a dictionary concept to abstract away IDictionary.

  • Tiara (unregistered)

    His name isn't Mike XD

  • Doctor (unregistered)

    So, let's see. You've got a largish distributed application with an unusual choice of technologies and, deep enough in the stack, you are able to find the bug in it? Oh, yeah, that's a WTF.

  • (cs) in reply to Tiara
    Tiara:
    His name isn't Mike XD
    No, of course not. We've already established that he's the 100th, not the 490th.
  • (cs) in reply to Phleabo
    Phleabo:
    Is the real WTF the fact that it took him 20 minutes to do a full text search over the codebase? I can do a string search over 100 GB of text data in 20 minutes, and that's on a network volume. If his codebase is that large, he's got bigger problems.

    Nah. Most likely it took less than a minute to search it. The 20 minutes would have been mostly to look at the screen in astonishment as it didn't find what was clearly in there -- and then to build the perfect magic-bullet regexp to match all variations and fiddling with nesting escapes to make sure it'd actually work.

    Install cygwin. Learn to use grep.
    Installing cygwin could easily have taken longer. Learning to use grep takes brainwashing and living for a year in a cave (and letting the Unix beard grow).
  • Phleabo (unregistered) in reply to magetoo
    magetoo:
    Install cygwin. Learn to use grep.
    Learning to use grep takes brainwashing and living for a year in a cave (and letting the Unix beard grow).

    Perhaps, but using Windows tools requires full on brain removal. So you'd still come out ahead.

  • Mariano (unregistered)

    Hmm, don't all these enterprisy frameworks and what not have an analogue of good ol' gnu's gettext?

  • (cs)

    It often takes me 20 minutes to run a search on some code. The reason? It's on a remote server in another office, connected via a crappy VPN.

    As for the real WTF - it's that he is writing VB and SQL code and didn't know you could use COM objects from within SQL Server.

  • (cs) in reply to real_aardvark
    real_aardvark:
    Well, the best model I've seen (and it came about by accident, since the thing was written in English and only I18N-ised because of a misguided salesman) was quite simple.

    (1) All messages started life as, well, messages. "Don't do this!", etc. (2) A hasty re-engineering job placed some form of tag (I forget what, but this being Perl, it probably involved one hell of a lot of line-noise) around "Don't do this!" (3) The translation file relevant to the locale was read in at initialisation, such that "Don't do this!"="Laissez cet objet!". (Or whatever.)

    Where a translation existed, it was interpolated as per normal Perl behaviour. Where it didn't, the user got the original English version.

    What the user didn't get was some feeble-minded three-digit magic code, made up of random sub-strings. Let alone the result of an insane recursive call between a series of sql procedures and call-outs to COM.

    But heck, that just wasn't enterprisey enough, was it?

    Same solution that dkf promoted, then. How do you deal with messages that are essentially the same but contain a variable part, i.e. a field name ("Please enter XXX to complete the request") or a number ("You order for $XXX could not be processed because your account balance is $XX")?

    Also, have fun with the angry foreign customers whose application becomes more English with every release because messages get changed in the code but not in the translation file and thus don't get replaced anymore.

  • (cs) in reply to brazzy
    brazzy:
    How do you deal with messages that are essentially the same but contain a variable part, i.e. a field name ("Please enter XXX to complete the request") or a number ("You order for $XXX could not be processed because your account balance is $XX")?

    Also, have fun with the angry foreign customers whose application becomes more English with every release because messages get changed in the code but not in the translation file and thus don't get replaced anymore.

    Here's how Oracle does it:

    16756, 0, "Aktualizujem...%d" 16757, 0, "Vkladám...%d" 16758, 0, "Vymazávam...%d" 16762, 0, "#%d z %d"

    (extracted from obe60sk.msg). I expect these put through a C 'printf' before the user sees them.

    I find these rather cute: "I am updating...", "I am inserting...", "I am deleting...". "z" means "from" (or in this context "out of").

  • (cs) in reply to Phleabo
    Phleabo:
    magetoo:
    Learning to use grep takes brainwashing and living for a year in a cave (and letting the Unix beard grow).
    Perhaps, but using Windows tools requires full on brain removal. So you'd still come out ahead.
    Point taken.
  • Alan Ralsky (unregistered) in reply to brazzy
    brazzy:
    Same solution that dkf promoted, then. How do you deal with messages that are essentially the same but contain a variable part, i.e. a field name ("Please enter XXX to complete the request") or a number ("You order for $XXX could not be processed because your account balance is $XX")?

    printf, see the following example.

    # Init translations
    $a{"I'm doing %d jobs\n"} = "Jag gör %d arbeten\n";
    
    sub tr_print {
        $tr = shift;
        @rest = @_;
        if (defined $a{$tr}) {
    	printf $a{$tr}, @rest;
        } else {
    	printf $tr, @rest;
        }
    }
    
    tr_print("I'm doing %d jobs\n", "10");
    tr_print("The translation does not exist: %s\n", "WTF");
    
    Also, have fun with the angry foreign customers whose application becomes more English with every release because messages get changed in the code but not in the translation file and thus don't get replaced anymore.

    That's a problem with any translated software, although you do have a point there. It's not perfect, but it's arguably a better way to do things than in TFA. It should be fairly trivial to also enable a debugging mode in the library/class/module/gizmo that handles translation to, for instance, log any messages that aren't translated. See example below.

    sub tr_print {
        $tr = shift;
        @rest = @_;
        if (defined $a{$tr}) {
    	printf $a{$tr}, @rest;
        } else {
            if(DEBUG) {
              log_no_translation($tr);
            }
    	printf $tr, @rest;
        }
    }
    
  • (cs)

    That is exactly why I do NOT like functions, inheritance, classes, and all this shit. When you have to debug it takes ages to unfiddle all this stuff.

  • Teh Optermizar (unregistered) in reply to Cloak
    Cloak:
    That is exactly why I do NOT like functions, inheritance, classes, and all this shit. When you have to debug it takes ages to unfiddle all this stuff.

    I agree! Functions are for chumps with short memories... viva la assembler!

  • (cs) in reply to brazzy
    brazzy:
    Same solution that dkf promoted, then. How do you deal with messages that are essentially the same but contain a variable part, i.e. a field name ("Please enter XXX to complete the request") or a number ("You order for $XXX could not be processed because your account balance is $XX")?

    Also, have fun with the angry foreign customers whose application becomes more English with every release because messages get changed in the code but not in the translation file and thus don't get replaced anymore.

    Actually, they had a (partial) solution for that, as well. When the (partial) solution -- yet more interpolations (hmmm. Would that be why they call them things "variables?") -- required something more than the locale could deal with, or had some other problem, they fell back on the English version and a full, one-on-one, translation. Wasn't required all that often (around 2% or less, I believe). No XXX's at all, which is unfortunate for those customers who are looking forward to an interpolated picture of Sylvia Kristel from the neck down.

    I'm not saying it's the perfect solution. I'm just saying that it's one of many practical solutions. Certainly beats cryptic three-character codes buried in an infinite stack of COM-to-middleware conversion ... I think. Of course, you can always take the OP's original solution instead. If you prefer.

    BTW, we had so much fun with the angry foreign customers that we co-opted them for translation. I believe this is what, in XP terms, is called "Siting The Customer" (one of twelve really brain-dead requirements, none of which make any sense, either together or separately).

    C'mon, ya wanna keep the French up-to-date yourself, or ya wanna havve a free weekend in Paris?

    Think outside the box, man. Or maybe, just maybe, improve QA on your release mechanism. Personally, I'd shoot the cunts.

    Bottom line: it worked. Not perfectly, but not a shambles. You want perfection: either design it from scratch for I18N, or talk to God, and be a little less needy.

    That's all I'm saying.

  • hobart (unregistered) in reply to Kooky
    Kooky:
    Andy:
    If you have any text hard coded anywhere then you are a poor developer, bad person and just don't understand OO.

    Bad:

    print "LOL You are a fool!! You broke the president!!"
    

    Good:

    if( 'ru' == language ) {
      BROKE_PRESIDENT_MESSAGE = "LOL You are a Дурачок!! 
    You broke the Президент!!"
    } else {
      BROKE_PRESIDENT_MESSAGE = "LOL You are a fool!! 
    You broke the president!!"
    }
    print BROKE_PRESIDENT
    

    Note that my variable name was actually understandable.

    Sheesh, if only more people would read "Code Complete," the world would be a happier place. Strike that. If only people would #@$# read.

    Are you suggesting that this sort of code goes in every location where a message needs to be printed out?

    What happens when you need to add a new language and you need to get a translator (almost certainly not a coder) to trawl through potentially hundreds of source files to find the relevant text and add their own language version?

    And won't source files end up getting swamped with hundreds of lines of "if" statements if you start supporting several different languages?

    Also, have you ever tried to edit code with (right to left) Arabic text embedded in the middle?

    The scheme in the article isn't the best implementation, but error codes and language resource files exist for a very good reason.

  • Vaccano (unregistered) in reply to Andy

    Sure you don't want text hard coded, but 3 digit codes? No way. How about a constant that actually means something?

  • Latte (unregistered) in reply to Hit
    Hit:
    Oh, and just let me add, in order to use sp_OACreate in any code, the calling user has to have System Administrator rights. Which means if the web server is compromised, that account has full access to any function on the sql server.

    Brillant!

    Not to worry! There's certainly a second line of defense (and a third...) like all the tables having names like TableVarcharL3113 for orders and so one. The hacker would not be able to figure out how to do anything harmful except for maybe a drop table. And that would only make the developers happy.

  • Confused (unregistered)
    Mike got back and track and started the search for the code that called sp_utl_CheckApproval_SubSA.
    Does the phrase 'got back and track' actually mean something, is it a typo, or is it a mishearing of the phrase 'got back on track'.

    I can't make the sentence make any sense to me.

  • (cs) in reply to rbowes
    rbowes:
    So he moved from "Betrayal of Master" (9th circle of hell) to either "Concern for Material Goods" (4th) or maybe even "Gluttony" (3rd circle).

    Good for him! I'd personally aim for gluttony.

    It must have been a real "Master" who decided that "Betrayal of Master" led to a lower level of hell than anything else.

  • eric bloedow (unregistered)

    reminds me of an article in a game magazine: a company was working on a Baseball game, the program had a complicated mathematical formula for the movement of the baseball, one day someone made a small typo when editing the formula, a "-" instead of a "+"...and this REVERSED the entire curve-ball subroutine! that is, trying to make the ball curve left would make it curve right. an interesting example for how easy it is for bugs to slip into games.

Leave a comment on “O Error, Where Art Thou?”

Log In or post as a guest

Replying to comment #:

« Return to Article