There's more than one way to burn in hell on earth



  • I'm wandering knee-deep in legacy Perl code, the original authors of which apparently had never heard you can have named constants. Well, they actually heard about it somewhere, and there are even a few measly attempts at having them occasionally that ultimately go nowhere.

    But most of the code looks like this:

    <font face="courier new,courier">    if ($foo->{status} == 2) ...
    </font>
    There is also

    <font face="courier new,courier">    if ($foo->{status} eq "2")
    </font>
    But it would be a real shame if it was all so easy to refactor. Enter this monstrosity:

    <font face="courier new,courier">    if ($foo->{status} < 4)
    </font>
    Yep, they think of statuses as some stages through which $foo goes, one by one, sequentially and chronologically. But my immediate task which made me open this can of worms, is add a new status in the middle. I'm not even mad...

    Consider the following beauties:

    <font face="courier new,courier">    if (($foo->{status} >= 4) && ($foo->{status} <= 5)) # occasionally, there is an explanation in a comment of what a status 4 or 5 is, but the intent is still a guessing game.
    </font>
    ...or even

    <font face="courier new,courier">    if (($foo->{status} > 4) && ($foo->{status} < 6)) # WAT?!
    </font>
    The fun does not stop there, and we have

    <font face="courier new,courier">    if ($foo->{status} =~ /[234]/)
    </font>
    ...as if the life wasn't already bad enough.

    This makes ~200 source files (CGI scripts with entry points) + ~30 library modules. Not that the original authors are actually familiar with what modularity is, but whatever. And it's all full of these magic numbers.

    Which still makes me think, if I add this new status I need to add, should I go through the hoops of checking every damn occurrence again to see if it fits there or not.

    Also, some refined hatred goes to Perl itself which up to 5.10 didn't  have an operator to check if a given list contains a particular value. There is now this "smart match" operator, which is, for one thing, too smart, and which changes its behaviour even in minor versions (hello, 5.10.0 -> 5.10.1).

    Surely, if there's more than one way to do something, in a large project there will be an instance of EVERY possible way to do it, including some ways you didn't want to know but were forced to find out.



  • @shimon said:

    Also, some refined hatred goes to Perl itself which up to 5.10 didn't  have an operator to check if a given list contains a particular value.
     

    It is a function, not an operator, but otherwise what's wrong with grep?

    print "found 2\n" if grep { $_ == 2 } (1, 2, 3, 4);  # prints
    print "found 9\n" if grep { $_ == 9 } (1, 2, 3, 4);  # doesn't print


  • A lot of our ancient perl would convert the status into a hash and use that. Like my %bar =( $foo{status} => 1 ); if ($bar{2}) ... Works like ~~ with more code.

    I've been refactoring as I go along to make the code more readable. There's a pattern that uses complex for loops and nested if statements of around 10-15 lines that I generally replace with 1-2 lines using grep and map.



  •  

    It is a function, not an operator, but otherwise what's wrong with grep?

     I'm aware of grep, but it's a bit too much boilerplate for me. Also, I suspect a builtin would be written in C and perform slightly better, which could be noticeable if you need to use it a lot.

    Maybe I'm too spoiled by Python which has the in operator. IMO Python has overthrown Perl as a language for data and text processing long time ago.



  • @shimon said:

    Also, some refined hatred goes to Perl itself which up to 5.10 didn't  have an operator to check if a given list contains a particular value. There is now this "smart match" operator, which is, for one thing, too smart, and which changes its behaviour even in minor versions (hello, 5.10.0 -> 5.10.1).
     

    Well, it's not an operator but there's an elem function in Data::Munge.


  • Trolleybus Mechanic

    @shimon said:


    Yep, they think of statuses as some stages through which $foo goes, one by one, sequentially and chronologically. But my immediate task which made me open this can of worms, is add a new status in the middle.
     

    Ah, so you haven't looked at the DB layer yet, where you'll find {status} is actually the primary key in tblStatuses. So you now have to search for all the other tables that rely on that Status. You'd think a look at what Foreign Keys point to tblStatuses.status would work-- but then you find half the database doesn't use foreign keys.  After all, they just make life difficult for the programmers, and if they do their job right, there never will be invalid data in a "foreign" key anyways.



  • @Lorne Kates said:

    @shimon said:


    Yep, they think of statuses as some stages through which $foo goes, one by one, sequentially and chronologically. But my immediate task which made me open this can of worms, is add a new status in the middle.
     

    Ah, so you haven't looked at the DB layer yet, where you'll find {status} is actually the primary key in tblStatuses. So you now have to search for all the other tables that rely on that Status. You'd think a look at what Foreign Keys point to tblStatuses.status would work-- but then you find half the database doesn't use foreign keys.  After all, they just make life difficult for the programmers, and if they do their job right, there never will be invalid data in a "foreign" key anyways.

    And just when you think you found all the foreign keys and references, it still blows up in your face because of stored procedures using dynamic SQL.



  • @Lorne Kates said:

    Ah, so you haven't looked at the DB layer yet, where you'll find {status} is actually the primary key in tblStatuses. So you now have to search for all the other tables that rely on that Status.
     

    Well, not as such. I happen to know what those statuses are, as I practice masochism with this abomination for a year. It so happens that I've come to despise all these pathetic attempts to abstract SQL away and implement everything in the application layer that I'm actually a fan of triggers and stored procedures (I can't think of a better way to handle integrity with 111 tables). Alas, this is all MySQL with MyISAM. They don't even use foreign keys.

    But no, status is not a key of any kind. I bet I myself slapped an index on it to speed up a few queries and that was it.

    However, if it comes that I need to change a value of some status, then yes, here comes the fun with the database. But I'll do my best to avoid it.

    Good thing these schmucks didn't manage entity statuses with increment/decrement, just plain assignment. I suspect they did want to do status++ or status--, but their large intestine had threatened to crawl out and wrap itself tightly around their neck for the greater good of mankind if they did.



  • I don't see the problem. A computer is just a very large finite-state machine, correct?

    Just imagine if the states were named constants. You could have A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, ... then if you needed to add a state between C and D, call it G and renumber so that inequalities still work correctly: A = 1, B = 2, C = 3, G = 4, D = 5, E = 6, F = 7...


  • Trolleybus Mechanic

    @shimon said:

    However, if it comes that I need to change a value of some status, then yes, here comes the fun with the database. But I'll do my best to avoid it.
     

    I'm surprised they did that, rather than the usual.

    if foo->status == 1 then response.write("First Status")

    else if foo->status == 2 then response.write("Second Status")

    ...

    and so forth. Except, of course, for the constant mispellings and abbreviations, so you can't even search for "First Status" without also searching for "First    Status", "Frist Status", "1st Status" and "First Sts"


  • BINNED

    @shimon said:

    Surely, if there's more than one way to do something, in a large project there will be an instance of EVERY possible way to do it, including some ways you didn't want to know but were forced to find out.

    Stolen for signature.



  • @PedanticCurmudgeon said:

    @shimon said:

    Surely, if there's more than one way to do something, in a large project there will be an instance of EVERY possible way to do it, including some ways you didn't want to know but were forced to find out.

    Stolen for signature.

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways.  The bad programmers are the ones whose code gets posted on TDWTF.

     



  • @shimon said:

    Yep, they think of statuses as some stages through which $foo goes, one by one, sequentially and chronologically. But my immediate task which made me open this can of worms, is add a new status in the middle. I'm not even mad...



    Simple! Just make the new status 4.5. This method has infinite extensibility!



  • This is why you always write your basic programs with line numbers divisible by 10. You always need to put an extra line in somewhere and renumbering breaks the computed GOTOs.


  • Discourse touched me in a no-no place

    @Qwerty said:

    This is why you always write your basic programs with line numbers divisible by 10. You always need to put an extra line in somewhere and renumbering breaks the computed GOTOs.
    It's not a real computed goto until you've done it in a language that isn't supposed to have them.



  • @jpa said:

    Simple! Just make the new status 4.5. This method has infinite extensibility!
     

    Yep. Given that in the DB, status is an int, it's going to be infinitely fun.


  • Discourse touched me in a no-no place

    @shimon said:

    @jpa said:
    Simple! Just make the new status 4.5. This method has infinite extensibility!
    Yep. Given that in the DB, status is an int, it's going to be infinitely fun.
    Hmm. Better redefine the column to be a VARCHAR(50) to allow for future expansion.



  • By the way, this is how the sickheads that wrote the software interpret security, just to give an insight: when logging in, they use a Javascript library to make a SHA-1 of your salted password and then send it over the wire.

    Of course, this adds no security whatsoever: whoever is able to intercept a cleartext password is also able to intercept a hash. And as a bonus, the users that we care about so much have problems with making WebKit browsers remember their passwords, 'cuz they fetch the contents of the field after the encryption.

    As a bonus for the attacker, on the flip side, they don't need to bother with decrypting passwords: it suffices for them to disable this javascript porno on the login page and pretend the passwords are stored as clear text — which they actually are.

    Of course, when this issue has been raised, it was assigned the lowest priority. Verbally, of course, by the boss saying, "I don't have the time for your technogibberish, don't you fucking fuck with me when you have got other work to do."


  • BINNED

    @inori said:

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways. The bad programmers are the ones whose code gets posted on TDWTF.

    Thank you, Captain Obvious.



  • @PedanticCurmudgeon said:

    @inori said:

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways. The bad programmers are the ones whose code gets posted on TDWTF.

    Thank you, Captain Obvious.
    Thank you, Captain Thank you, Captain Obvious..


  • Discourse touched me in a no-no place

    @Ben L. said:

    @PedanticCurmudgeon said:
    @inori said:

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways. The bad programmers are the ones whose code gets posted on TDWTF.

    Thank you, Captain Obvious.
    Thank you, Captain Thank you, Captain Obvious..
    Thank you, Captain Thank you, Captain Thank you, Captain Obvious...



  • @dkf said:

    @Ben L. said:
    @PedanticCurmudgeon said:
    @inori said:

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways. The bad programmers are the ones whose code gets posted on TDWTF.

    Thank you, Captain Obvious.
    Thank you, Captain Thank you, Captain Obvious..
    Thank you, Captain Thank you, Captain Thank you, Captain Obvious...

    Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Segmentation fault



  • @Maciejasjmj said:

    @dkf said:
    @Ben L. said:
    @PedanticCurmudgeon said:
    @inori said:

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways. The bad programmers are the ones whose code gets posted on TDWTF.

    Thank you, Captain Obvious.
    Thank you, Captain Thank you, Captain Obvious..
    Thank you, Captain Thank you, Captain Thank you, Captain Obvious...

    Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Segmentation fault

    http://en.wikipedia.org/wiki/User%3ACaptain_Segfault

     



  • @El_Heffe said:

    @Maciejasjmj said:

    @dkf said:
    @Ben L. said:
    @PedanticCurmudgeon said:
    @inori said:

    This is computer science - there's more than one way to do everything.  However, most of those ways are wrong.

    The good programmers are the ones who have learned to distinguish right ways of doing things from wrong ways. The bad programmers are the ones whose code gets posted on TDWTF.

    Thank you, Captain Obvious.
    Thank you, Captain Thank you, Captain Obvious..
    Thank you, Captain Thank you, Captain Thank you, Captain Obvious...

    Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Thank you, Captain Segmentation fault

    http://en.wikipedia.org/wiki/User%3ACaptain_Segfault

     

    Added to my "that would make a good band name" list


Log in to reply