• Mike D. (unregistered) in reply to wtf
    wtf:
    Fred:
    Refactoring best case: the code still does exactly what it did before, but it's now possible to improve and extend it without breaking stuff.

    Refactoring worst case: you introduce new bugs because you took it upon yourself to change something that is invisible to everybody who pays your salary, and your unit tests reveal that your method calls are no longer returning according to spec, so you revert to the previous kludgy hacked-together junk and try again another time.

    No refactoring case: you leave it alone and work on something that your bosses, their bosses, and/or the customer actually sees. Some subset of them likes your work, perceives you as more productive than the other code monkeys, and you're on the road to either getting a raise, a promotion, or taken seriously next time you get into an argument with the other monkeys.

    FTFY.
    (FTFY)^2
  • Pete (unregistered) in reply to Morrell
    Morrell:
    oh dear god

    my answer is Maybe

    Maybe as in Nothing or Just True ?

  • delenit (unregistered) in reply to venio
    venio:
    similis:
    Here are the minimum states needed for a universal boolean: boolean { <value> true </value>, <value> false </value>, <value> fileNotfound </value>, <value> NULL </value>, <value> fish </value>, <value> -1 </value>, <value> 0 </value>, <value> 1 </value>, <value> f </value>, <value> t </value>, <value> F </value>, <value> T </value>, <value> True </value>, <value> False </value>, <value> TRUE </value>, <value> FALSE </value>, <value> y </value>, <value> n </value>, <value> Y </value>, <value> N </value>, <value> yes </value>, <value> no </value>, <value> Yes </value>, <value> No </value>, <value> YES </value>, <value> NO </value>, <value> maybe </value>, <value> Maybe </value>, <value> MAYBE </value> }
    ftfy
    FTFTFY -- needs XML to be moar 'enterprisey'.
  • wtf (unregistered) in reply to Mike D.
    Mike D.:
    wtf:
    Fred:
    Refactoring best case: the code still does exactly what it did before, but it's now possible to improve and extend it without breaking stuff.

    Refactoring worst case: you introduce new bugs because you took it upon yourself to change something that is invisible to everybody who pays your salary, and your unit tests reveal that your method calls are no longer returning according to spec, so you revert to the previous kludgy hacked-together junk and try again another time.

    No refactoring case: you leave it alone and work on something that your bosses, their bosses, and/or the customer actually sees. Some subset of them likes your work, perceives you as more productive than the other code monkeys, and you're on the road to either getting a raise, a promotion, or taken seriously next time you get into an argument with the other monkeys, while the code gets more and more dire as you stack crap on top of crap, and eventually you get to see your hopelessly muddled code featured on thedailywtf.com. Profit! (or not...)

    FTFY.
    (FTFY)^2
    ((FTFY)^2)!
  • Ouch! (unregistered) in reply to Pete
    Pete:
    Morrell:
    oh dear god

    my answer is Maybe

    Maybe as in Nothing or Just True ?

    Just undefined >> skipValidationAnyway
  • George (unregistered)

    I love it. Take me behind the shed and bury me if I ever produce something like it.

  • wtf (unregistered) in reply to Ouch!
    Ouch!:
    Pete:
    Morrell:
    oh dear god

    my answer is Maybe

    Maybe as in Nothing or Just True ?

    Just undefined >> skipValidationAnyway

    WTF are you doing with that bit shift operator?

  • by (unregistered) in reply to golddog
    golddog:
    Now just imagine the fun E.H. has with such quandaries line-after-line and day-after-day.
    Does E.H. refactor this code when he comes across it, or leave it and bitch?

    That's acutally one of the things I find fun about my job; taking some crap code and refactoring it into something good. makes me feel I've made our little world slightly better.

    Who are you, Hitler?

  • (cs) in reply to Someone who can't be bothered to login from work
    Someone who can't be bothered to login from work:
    At a basic level you could just have NAND and NOR, because they're functionally complete.

    Well to be pedantic, you only need one of them, as either of them can be constructed from the other, kind of like you only need one instruction to have a turing complete language ('subtract and branch if negative' as I recall). Not that using only NAND operations or 'subtract and branch if negative' is advisable for any real work... :-)

    Yazeran.

    Plan: To go to Mars one day with a hammer.

  • Andrew Richard (unregistered) in reply to delenit
    delenit:
    venio:
    similis:
    Here are the minimum states needed for a universal boolean: boolean { <value> true </value>, <value> false </value>, <value> fileNotfound </value>, <value> NULL </value>, <value> fish </value>, <value> -1 </value>, <value> 0 </value>, <value> 1 </value>, <value> f </value>, <value> t </value>, <value> F </value>, <value> T </value>, <value> True </value>, <value> False </value>, <value> TRUE </value>, <value> FALSE </value>, <value> y </value>, <value> n </value>, <value> Y </value>, <value> N </value>, <value> yes </value>, <value> no </value>, <value> Yes </value>, <value> No </value>, <value> YES </value>, <value> NO </value>, <value> maybe </value>, <value> Maybe </value>, <value> MAYBE </value> }
    ftfy
    FTFTFY -- needs XML to be moar 'enterprisey'.

    Too many values. You need to use a double between 0.0 and 1.0. 0.0 indicates absolutely false and 1.0 indicates absolutely true. .5 indicates "Maybe". Using a floating point number, you can express using various shades of certainty.

    if (statusNotValid->isProbablyNotValid() > .8) skipValidation = .1;
    
  • Obi-1 (unregistered)

    Simple Jedi Mind Trick These are not the droids you're looking for.

    Complex Jedi Mind Trick Droids other than these are not the droids you're not looking for.

  • saepius (unregistered) in reply to Andrew Richard
    Andrew Richard:
    delenit:
    venio:
    similis:
    Here are the minimum states needed for a universal boolean: boolean { <value> true </value>, <value> false </value>, <value> fileNotfound </value>, <value> NULL </value>, <value> fish </value>, <value> -1 </value>, <value> 0 </value>, <value> 1 </value>, <value> f </value>, <value> t </value>, <value> F </value>, <value> T </value>, <value> True </value>, <value> False </value>, <value> TRUE </value>, <value> FALSE </value>, <value> y </value>, <value> n </value>, <value> Y </value>, <value> N </value>, <value> yes </value>, <value> no </value>, <value> Yes </value>, <value> No </value>, <value> YES </value>, <value> NO </value>, <value> maybe </value>, <value> Maybe </value>, <value> MAYBE </value> }
    ftfy
    FTFTFY -- needs XML to be moar 'enterprisey'.

    Too many values. You need to use a double between 0.0 and 1.0. 0.0 indicates absolutely false and 1.0 indicates absolutely true. .5 indicates "Maybe". Using a floating point number, you can express using various shades of certainty.

    if (statusNotValid->isProbablyNotValid() > .8) skipValidation = .1;
    

    +1.333333333333333333333333

  • ƒÂ¢Ã (unregistered)

    Alex you overcomplicated it yourself! All you need is NAND. AND, OR, and NOT are made using different combinations of NAND gates.

  • wtf (unregistered) in reply to Obi-1
    Obi-1:
    Simple Jedi Mind Trick These are not the droids you're looking for.

    Complex Jedi Mind Trick Droids other than these are not the droids you're not looking for.

    Storm trooper: "Maybe so, old man, but the droids other than these that are not the droids we're not looking for are also not the droids we're looking for. They're not on our list at all. These droids, however, are definitely the ones we're looking for, and we're taking you in."

    (Good going, Obi-wan. There goes a bazillion dollar movie and toy franchise out the window.)

  • Valczir (unregistered) in reply to Mike D.
    Mike D.:
    Ajtacka:
    golddog:
    Now just imagine the fun E.H. has with such quandaries line-after-line and day-after-day.
    Does E.H. refactor this code when he comes across it, or leave it and bitch?

    That's acutally one of the things I find fun about my job; taking some crap code and refactoring it into something good. makes me feel I've made our little world slightly better.

    I agree with you, but... there are some hellhole offices that frown on refactoring - why waste time changing something that already works? Also, refactoring this could become a full-time job if there are enough lines like this.
    Because it always looks good to your boss when you spend the whole day working on something with no visible impact on the delivered product. Or, in other words: "Promote someone else who is actually productive."

    If it makes you feel better, remember that your own DNA is also full of junk code from sundry sources and has no comments.

    How do you know? All we get is the pre-compiled binaries - we have no idea what the source code looks like.

    I believe we need to start an online petition to God to open source his code. Because online petitions work.

  • Obi-1 (unregistered) in reply to wtf
    wtf:
    Obi-1:
    Simple Jedi Mind Trick These are not the droids you're looking for.

    Complex Jedi Mind Trick Droids other than these are not the droids you're not looking for.

    Storm trooper: "Maybe so, old man, but the droids other than these that are not the droids we're not looking for are also not the droids we're looking for. They're not on our list at all. These droids, however, are definitely the ones we're looking for, and we're taking you in."

    Obi-wan: I don't think so. Bvvwup, bvvwup. (Bloodbath ensues) Good going, old man, now this movie is Rated-R.

    FTFY

  • Someone (unregistered) in reply to venio
    venio:
    similis:
    Here are the minimum states needed for a universal boolean: boolean { true, false, fileNotfound, NULL, fish, -1, 0, 1, f, t, F, T, True, False, TRUE, FALSE, y, n, Y, N, yes, no, Yes, No, YES, NO, maybe, Maybe, MAYBE, yep, ok, proceed, affirmative, positive, correct, aye, fine, yar }
    ftfy
    Missed a few. AKISMET!!! this is not spam!
  • Ouch! (unregistered) in reply to wtf
    wtf:
    Ouch!:
    Pete:
    Morrell:
    oh dear god

    my answer is Maybe

    Maybe as in Nothing or Just True ?

    Just undefined >> skipValidationAnyway

    WTF are you doing with that bit shift operator?

    It's not a bit shift operator, it's monadic sequencing: http://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Control-Monad.html#v%3A>>

    Great, Akismet says linking to documentation is spam.

  • Wade (unregistered) in reply to Sigh
    Sigh:
    bertram:
    Sigh:
    Great, another Java moron that doesn't know how to code. Nothing to see here. Move along.

    And yes, once again for the second time in 3 days, TRWTF is Java.

    There is absolutely nothing about that code snippet that guarantees that it's Java. But thanks for playing.

    I know Java crap when I see it. You must not. First clue is Boolean.FALSE. That's the constant replacement for the Boolean type false. He used the Object reference rather than the primitive because the method compareTo (implements the Comparable interface) takes an object. Camel-case is the preferred standard for variable naming, which they got right.

    If you don't believe any of these statements, I refer you to Google.

    Push over VB, now there is something leaner!! Nice to know us VB programmers aren't the only ones who know how to write crap.

  • anon (unregistered) in reply to Drew
    Drew:
    Cbuttius:
    We could do skipValidation &&= predicate though.

    What language has that operator?

    Ruby, at least.

  • rfoxmich (unregistered)

    Yeah but is not is not not is.

  • (cs) in reply to Cbuttius
    Cbuttius:
    2. compareTo is a class method, and you can't just put if round your object. This isn't C++ with operator overloading.

    In Java 5 there is auto boxing so this is perfectly valid

  • The Nerve (unregistered) in reply to safarmer
    safarmer:
    Cbuttius:
    2. compareTo is a class method, and you can't just put if round your object. This isn't C++ with operator overloading.

    In Java 5 there is auto boxing so this is perfectly valid

    Boolean.FALSE is an object, so this is perfectly valid with or without autoboxing.

  • Spike (unregistered)

    I bet the author of that line of code prefers to brush his teeth by going up through his ass; and is probably Romanian*

    *a former coworker was Romanian and all of his logic was backwards like this example.

  • Larry (unregistered) in reply to Yazeran
    Yazeran:
    you only need one instruction to have a turing complete language ('subtract and branch if negative' as I recall).
    Whoa there pardner. We need NOP sleds so we can write portable buffer overflows!
  • IV (unregistered) in reply to similis
    similis:
    Here are the minimum states needed for a universal boolean: boolean { true, false, fileNotfound, NULL, fish, 0, 1, f, t, F, T, True, False, TRUE, FALSE, Y, N, Yes, No, YES, NO, maybe, Maybe, MAYBE }

    Wait, so C/++ booleans aren't universal? What happened to 2,3,4,5,6,...?

    In reality, we know that compilers give at least a whole byte to booleans because of the difficulties and slowness of trying to pack multiple booleans into a single byte. So it you use less than 256 values in your booleans, you are wasting space with a suboptimal solution.

  • Humble Apprentice (unregistered) in reply to Obi-1
    Obi-1:
    Obi-wan: I don't think so. Bvvwup, bvvwup. (Bloodbath ensues)
    Wow I never knew how to spell the lightsaber sound but that is so obviously correct! Imagine actually learning something useful at TDWTF!
  • John Muller (unregistered)

    I like the floating 0-1 for a bool as well,

    'Or' is the higher of two values, while 'And' is the lesser, 'Not' is 1-value...

  • Alun Harford (unregistered) in reply to Morrell
    Morrell:
    tri-state boolean... now that's nuts :)

    No.

    It only has 3 states.

    Tri-state booleans have 4 states. (See: http://www.oracle.com/technology/products/jdev/esdk/api1013/oracle/ide/util/TriStateBoolean.html for details)

  • Joey Alcorn (unregistered)

    Is this security by absurdity?

  • venio (unregistered) in reply to Humble Apprentice
    Humble Apprentice:
    Obi-1:
    Obi-wan: I don't think so. Bvvwup, bvvwup. (Bloodbath ensues)
    Wow I never knew how to spell the lightsaber sound but that is so obviously correct! Imagine actually learning something useful at TDWTF!
    I must be TRWTF, I thought that was supposed to be R2-D2 noises LOL!
  • iToad (unregistered)

    Here is your enterprisey boolean:

    <?xml version="1.0" encoding="utf-8"?>
    <boolean version="1.0">
      <value> true </value>
      <value> false </value>
      <value> fileNotfound </value>
      <value> NULL </value>
      <value> fish </value>
      <value> -1 </value>
      <value> 0 </value>
      <value> 1 </value>
      <value> f </value>
      <value> t </value>
      <value> F </value>
      <value> T </value>
      <value> True </value>
      <value> False </value>
      <value> TRUE </value>
      <value> FALSE </value>
      <value> y </value>
      <value> n </value>
      <value> Y </value>
      <value> N </value>
      <value> yes </value>
      <value> no </value>
      <value> Yes </value>
      <value> No </value>
      <value> YES </value>
      <value> NO </value>
      <value> maybe </value>
      <value> Maybe </value>
      <value> MAYBE </value> 
    </boolean>
    

    And as an extra bonus, the schema:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="boolean">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="value" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
          </xs:sequence>
          <xs:attribute name="version" type="xs:string"/>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    Yes, it does validate.

  • (cs) in reply to akatherder
    akatherder:
    Mike D.:
    Ajtacka:
    golddog:
    Now just imagine the fun E.H. has with such quandaries line-after-line and day-after-day.
    Does E.H. refactor this code when he comes across it, or leave it and bitch?

    That's acutally one of the things I find fun about my job; taking some crap code and refactoring it into something good. makes me feel I've made our little world slightly better.

    I agree with you, but... there are some hellhole offices that frown on refactoring - why waste time changing something that already works? Also, refactoring this could become a full-time job if there are enough lines like this.
    Because it always looks good to your boss when you spend the whole day working on something with no visible impact on the delivered product. Or, in other words: "Promote someone else who is actually productive."

    If it makes you feel better, remember that your own DNA is also full of junk code from sundry sources and has no comments.

    And "no visible impact" is a best case scenario.

    Actually, it might not be. After refactoring some legacy VBA code in a DB front-end that caused it to crash in a different part of the code than when it normally crashes, I basically got banned from maintenance programming.

    Now I only get to work on brand-spanking new .NET projects all by myself from start to finish. Boo hoo. >:D

  • sota (unregistered) in reply to Obi-1
    Obi-1:
    Simple Jedi Mind Trick These are not the droids you're looking for.

    Complex Jedi Mind Trick Droids other than these are not the droids you're not looking for.

    Yoda Mind Trick Not looking for not these other droids you are.

  • (cs) in reply to akatherder
    akatherder:
    Mike D.:
    Ajtacka:
    golddog:
    That's acutally one of the things I find fun about my job; taking some crap code and refactoring it into something good. makes me feel I've made our little world slightly better.
    I agree with you, but... there are some hellhole offices that frown on refactoring - why waste time changing something that already works? Also, refactoring this could become a full-time job if there are enough lines like this.
    Because it always looks good to your boss when you spend the whole day working on something with no visible impact on the delivered product. Or, in other words: "Promote someone else who is actually productive."
    And "no visible impact" is a best case scenario.

    The problem with this line of reasoning is that it is in the face of what software development methodology is supposedly about. Namely human factor -- the programmer, that is.

    Let me elaborate: the only reason for "modern" programming methodology, now and then, was to make it easier for people to deal with the code. Oftentimes trading off instantaneous convenience and agility for longer term maintainability and ease of understanding by others. So it is hopefully understood that quite often one will code in a particular way not because it's expedient to him/her, but because it will take longer, and it's OK because others in the group will be able to manage better.

    So in light of that, improving the quality of code is hardly counterproductive. It may not be productive if you just look at the person who is immediately dealing with the code, true. But it may be quite productive if you look at the big picture.

    Think about it like so: if I were to whip up a single dynamically-generated webpage, with some demands placed on scalability and whatnot, I'd probably code the whole thing up in plain old C, without a webserver or anything else in sight, talking directly to whatever backend data source is to be used. I did enough embedded programming to know how to do that. It'd certainly be fastest for me. I would directly use whatever async networking APIs are provided by the OS, etc. All low level and sweet and fast, but a typical web developer would probably be rather stumped upon seeing something like that, and that doesn't mean he is in the wrong of course.

    So I do appreciate that there will be other people who have to work on that code, thus I will leave the sometime expedient homemade coding for googling and reading up documentation for various higher level APIs, libraries and tools out there. So I may in fact be less productive in terms of lines of code (hey, I'll be reading for 80% of the time!), and may even develop a solution that is a few times slower than ultimately possible. But this can be well be still worth it if it lets others in the team deal with code that mostly builds on well documented concepts and solutions, and uses methods that are more familiar to those in the field. Even though web applications technically have to deal with asynchronous socket I/O and whatnot.

  • (cs) in reply to caffeine
    'worse than failure' mould

    It's so damp in here the place is now covered in worse-than-failure mould*.

    • UK spelling
  • (cs)

    The real WTF is that this piece of code skips validation when it's not valid.

    notValid = false != 0 ==> Don't skip validation notValid = false = true ==> don't skip validation notValid = false ==> don't skip validation notValid = true ==> skip validation

    But then we are left with the next quite existential preponderance. How do we know if it's valid or not, if we skip validation?

  • Fabiano (unregistered)

    Oh, god, what a boolean mess! I'm not a programming genius (I'm quite near to a codemonkey) but I've always looked for the simplest way to write a condition.

    I suppose ... if the state is valid the Validation is done.

    But it's quite tricky

  • Fabiano (unregistered)

    I suspect... :-D

    .. !=0 is useless and I think the overmentioned condition equals to:

    doValidation = false; if (!statusIsNotValid) { doValidation = true; }

    another (better) way

    skipValidation=false; if (statusIsNotValid) { skipValidation = true; }

    and THE BEST and simpler way (The only resonable way):

    skipValidation = statusIsotValid;

    the boolean skipValidation return value equals to statusIsNotValid.

    Am I right?

  • logical.. (unregistered) in reply to wtf
    wtf:
    No, not in English at least.

    can't not = MUST (ie, can't avoid) CAN misunderstand = can misunderstand (or not) (but this doesn't appear in Matt's sentence) n

    ahh, the old converse vs contrapositive.

    I am not an animal, I am a human. I am a man!

  • L. (unregistered) in reply to similis
    similis:
    Gozer Gozerian:
    bertram:
    Morrell:
    tri-state boolean... now that's nuts :)

    You must be new here ;)

    That's right Morrell, a tri-state boolean is actually considered minimum among professionals. Also a four and five-state booleans are sometimes used. Only six and above ones can be a bit nuts. ;)

    Here are the minimum states needed for a universal boolean: boolean { true, false, fileNotfound, NULL, fish, 0, 1, f, t, F, T, True, False, TRUE, FALSE, Y, N, Yes, No, YES, NO, maybe, Maybe, MAYBE }

    Mhh I'm pretty sure we could find quite a few more in some infamous languages like VFP (yes it's ugly so what) : .T. and .F. Anyone care to complete this boolean_of_doom ?

  • Bert (unregistered)

    that piece of code is a big no-no

  • (cs) in reply to someGuy
    someGuy:
    Someone who can't be bothered to login from work:
    At a basic level you could just have NAND and NOR, because they're functionally complete.

    actually you just need nand, you can mimic nor using it ;)

    FTFY -- actually you just need nor, you can mimic nand with it.

  • FIA (unregistered)

    I don't understand why everyone's complaining? This is a WTF yet Shakespeare wrote "To be or not to be" and he's hailed as a flippin genius.

    Bah.

  • Fabiano (unregistered)

    @FIA

    I don't understand if our are joking... I don't think romance/tragedy's style is related to programming' style. IMHO I think that being concise and avoiding ambiguous statements is mandatory when programming /IMHO

  • JohnFx (unregistered)

    I ran into some code just last weeek that used the "Anti-Boolean" type.

    bool IsNotAuthenticated;

    Reading conditional statements that use these make my head hurt.

  • (cs) in reply to Gozer Gozerian
    Gozer Gozerian:
    bertram:
    Morrell:
    tri-state boolean... now that's nuts :)

    You must be new here ;)

    That's right Morrell, a tri-state boolean is actually considered minimum among professionals. Also a four and five-state booleans are sometimes used. Only six and above ones can be a bit nuts. ;)

    For future ease of reference, shouldn't the nomenclature be standardized?

    Three-state boolean = troolean Four-state = foolean Five-state = quoolean [pronounced cool-lee-ann]

    States greater than five could be grouped either as droolean or eff-yoolean.

  • Pete (unregistered) in reply to Ouch!
    Ouch!:
    Pete:
    Morrell:
    oh dear god

    my answer is Maybe

    Maybe as in Nothing or Just True ?

    Just undefined >> skipValidationAnyway

    Bravo, a completely pointless expression, that's the way we like them !

  • nasch (unregistered) in reply to madjo
    madjo:
    The real WTF is that this piece of code skips validation when it's not valid.

    notValid = false != 0 ==> Don't skip validation notValid = false = true ==> don't skip validation notValid = false ==> don't skip validation notValid = true ==> skip validation

    I reached the opposite conclusion.

    Original:

    if (statusIsNotValid.compareTo( Boolean.FALSE ) != 0) skipValidation = false;

    Simplifying one thing at a time, and assuming !=0 means false:

    if (statusIsNotValid.compareTo( Boolean.FALSE ) != 0) validate = true;
    
    if (statusIsValid.compareTo( Boolean.TRUE ) != 0) validate = true;
    
    if (!statusIsValid) validate = true;

    So if the status is not valid, then validate. Really, whether I'm right and you're wrong, you're right and I'm wrong, or somehow both of us are wrong, the real WTF is just what it claimed to be: the code is way too hard to understand.

  • Ouch! (unregistered) in reply to nasch
    nasch:
    madjo:
    The real WTF is that this piece of code skips validation when it's not valid.

    notValid = false != 0 ==> Don't skip validation notValid = false = true ==> don't skip validation notValid = false ==> don't skip validation notValid = true ==> skip validation

    I reached the opposite conclusion.

    Original:

    if (statusIsNotValid.compareTo( Boolean.FALSE ) != 0) skipValidation = false;

    I'd simplify it differently. The contract of compareTo/equals is that a.compareTo(b) == 0 iff a.equals(b), so

    if (!statusIsNotValid.equals(Boolean.FALSE)) skipValidation = false;
    if (statusIsNotValid.equals(Boolean.TRUE)) skipValidation = false;
    if (statusIsNotValid.booleanValue()) skipValidation = false;
    // auto-unboxing if Java 1.5 or later:
    if (statusIsNotValid) skipValidation = false;
    

    That last one is even readable.

    So if the status is not valid, then validate. Really, whether I'm right and you're wrong, you're right and I'm wrong, or somehow both of us are wrong, the real WTF is just what it claimed to be: the code is way too hard to understand.
    Right. I wonder whether it was deliberate obfuscation.

Leave a comment on “Boolean Illogic”

Log In or post as a guest

Replying to comment #:

« Return to Article