• dkf (cs)

    Want to change the street name? Well, I guess you'd better also change the house number on the street. Because typos never happen.

  • iggy (unregistered)

    the real WTF is in the article itself:

    if (!this.isInsertMode) {

    . . if (!int.TryParse(this.txtStreetNo.Text, out iStrNum)) throw new Exception("Street number entered is not a valid integer."); if (propCurrent.StreetNumber != iStrNum) addrChanged = true;

    4. The fact that validation of the street number only takes place if the isInsertMode is true? No need to validate existing addresses, I guess.
    and
    For example, the existence of isInsertMode implies that there is an isUpdateMode counterpart.

    The code shows that there is a "not isInsertMode" but no update or insert mode at all.

  • QJo (unregistered)

    Somebody living at 11a Acacia Avenue may have trouble with this.

  • Bill P. Godfrey (unregistered) in reply to QJo
    QJo:
    Somebody living at 11a Acacia Avenue may have trouble with this.

    Sounds like a job for hexadecimal!

    My first home was called "White Heather Cottage". No street number.

  • Svempa (unregistered)

    Comparing strings with == in Java is bad practice. You usually get away with it due to the JVM caching strings, but it's still wrong.

  • Hasse de great (unregistered)
    Comment held for moderation.
  • Lothar (unregistered) in reply to Svempa
    Svempa:
    Comparing strings with == in Java is bad practice. You usually get away with it due to the JVM caching strings, but it's still wrong.

    This code isn't Java

  • no laughing matter (cs) in reply to Svempa
    Svempa:
    Comparing strings with == in Java is bad practice. You usually get away with it due to the JVM caching strings, but it's still wrong.
    This is C# not Java!

    Notice the class named string, not String. Also the LinQ which never existed in Java-Land (there's ScalaQuery, but that's a different language).

  • lol (unregistered) in reply to Svempa

    It's C#, which is actually a sane language if used properly :)

  • RFox (unregistered) in reply to lol
    lol:
    It's C#, which is actually a sane language if used properly :)

    All languages are sane if used properly...wait while I write the functionally identical code in FORTRAN ;-)

  • foo AKA fooo (unregistered)
    make sure they are are all look syntatically 'valid'
    This sentence is is not look syntatically 'valid' to me. Not even syntactically valid.

    I like WTF #5, closely followed by #5.

  • fa2k (unregistered)

    #i : Throwing an Exception, not a subclass

  • no laughing matter (cs) in reply to Hasse de great
    Hasse de great:
    OK, Ok! here it is:

    http://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/

    Unlike most of the "falsehoods programmers believe" i've seen so far, this one is actually useful as it has examples.

    (See "falsehoods programmers believe about time" or "falsehoods programmers believe about names" for counterexamples which are just boring lists).

    And this one also has an example from Gene Wirchenko!

  • Schol-R-LEA (cs)

    That it only handles US style mailing addresses, and poorly at that, is a WTF in potential; while they may be able to rely on it if they only deal with customers in the US, if they ever have an international client, they're screwed.

    Having the code return flat out when the address is changed without handling it at all is certainly a major WTF, and the code obviously won't work as intended as a result. The bigger WTF is that this wasn't caught in testing, if this actually went into production as the article seems to imply.

    That it doesn't handle things like post office boxes is a WTF, and one unlikely to get caught for a while. OTOH, it includes separate 'building number' and 'trailer number' fields for some reason, which implies that they are expecting a very specific set of addresses. Since neither of these are optional, that is a WTF if it's supposed to handle general addresses.

    The use of generic Exceptions, while not exactly a WTF, is definitely terrible practice. On second thought, given how many there are here, and what a pain in the butt it would be to handle them all, it is a WTF.

    As has already been mentioned, converting the street address number to an integer is going to break when an address like '22B' or '42 1/2' gets used somewhere. Major WTF.

    The use of if-if logic may have been a way of reducing the size of the conditional statements, but given that the pattern starts from the beginning of the code and is copy-pasted throughout the code, it is more likely just laziness. In any case, the fact that empty fields are simply bypassed is a WTF as well, agreed.

    While the use of Hungarian Notation in C# isn't quite a WTF (it's deprecated but not forbidden), the inconsistency with which it is done here is.

    (Actually, I would argue that HN is a huge WTF in and of itself, at least in an object-oriented language, but that's a pet peeve of mine. I've always seen the need to use HN or similar tricks as a sign that too many variables are in the immediate scope - if you need something to track variables themselves with, and your IDE isn't doing the job, You're Doing It Wrong.)

  • rt (unregistered) in reply to Schol-R-LEA
    Schol-R-LEA:
    if they ever have an international client, they're screwed.

    This.

    It's always annoying to order stuff internationally. Most websites insist that I must enter a state name, although there are no states in my country. Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).

    Why isn't there a big white text box where I can type in my adress the way I want? That's my problem if I screw it up.

  • Tim (unregistered)

    I really like if-if logic and often write nested 'if's when it would have been possible to use '&&'.

    Complex boolean expressions are one of the most difficult things to understand when viewing someone else's code because there isn't a way to nest them nicely. Using a nested 'if' allows the reader to take a mental break and regroup after the outermost 'if' before tacking the inner one;

  • not an anon (unregistered) in reply to Schol-R-LEA
    Schol-R-LEA:
    That it only handles US style mailing addresses, and poorly at that, is a WTF in potential; while they may be able to rely on it if they only deal with customers in the US, if they ever have an international client, they're screwed.

    Having the code return flat out when the address is changed without handling it at all is certainly a major WTF, and the code obviously won't work as intended as a result. The bigger WTF is that this wasn't caught in testing, if this actually went into production as the article seems to imply.

    That it doesn't handle things like post office boxes is a WTF, and one unlikely to get caught for a while. OTOH, it includes separate 'building number' and 'trailer number' fields for some reason, which implies that they are expecting a very specific set of addresses. Since neither of these are optional, that is a WTF if it's supposed to handle general addresses.

    The use of generic Exceptions, while not exactly a WTF, is definitely terrible practice. On second thought, given how many there are here, and what a pain in the butt it would be to handle them all, it is a WTF.

    As has already been mentioned, converting the street address number to an integer is going to break when an address like '22B' or '42 1/2' gets used somewhere. Major WTF.

    The use of if-if logic may have been a way of reducing the size of the conditional statements, but given that the pattern starts from the beginning of the code and is copy-pasted throughout the code, it is more likely just laziness. In any case, the fact that empty fields are simply bypassed is a WTF as well, agreed.

    While the use of Hungarian Notation in C# isn't quite a WTF (it's deprecated but not forbidden), the inconsistency with which it is done here is.

    (Actually, I would argue that HN is a huge WTF in and of itself, at least in an object-oriented language, but that's a pet peeve of mine. I've always seen the need to use HN or similar tricks as a sign that too many variables are in the immediate scope - if you need something to track variables themselves with, and your IDE isn't doing the job, You're Doing It Wrong.)

    Hrm...do we really need to rebuild Midlake, UT just to spite all those folks who pick apart addresses and try to divine meaning out of their individual bits?

    CAPTCHA: pecus. The system did a bunch of hocus-pecus on addresses, but got nowhere.

  • pjt33 (cs) in reply to no laughing matter
    no laughing matter:
    Hasse de great:
    OK, Ok! here it is:

    http://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/

    Unlike most of the "falsehoods programmers believe" i've seen so far, this one is actually useful as it has examples.
    The downside of that is that when the example is obviously wrong, you're not sure whether there are any genuine examples or not.

    (The example given for "A building number will only be used once per street" is of two addresses in different towns. If the falsehood is really meant to be "Every street name is globally unique" then I can't believe anyone would seriously believe that).

  • Anonymoose (unregistered)

    Rule #1 of address validation: Don't.

    Rule #2 of address validation: If you really must, make somebody else do it.

  • operagost (cs) in reply to not an anon
    not an anon:
    Schol-R-LEA:
    That it only handles US style mailing addresses, and poorly at that, is a WTF in potential; while they may be able to rely on it if they only deal with customers in the US, if they ever have an international client, they're screwed.

    Having the code return flat out when the address is changed without handling it at all is certainly a major WTF, and the code obviously won't work as intended as a result. The bigger WTF is that this wasn't caught in testing, if this actually went into production as the article seems to imply.

    That it doesn't handle things like post office boxes is a WTF, and one unlikely to get caught for a while. OTOH, it includes separate 'building number' and 'trailer number' fields for some reason, which implies that they are expecting a very specific set of addresses. Since neither of these are optional, that is a WTF if it's supposed to handle general addresses.

    The use of generic Exceptions, while not exactly a WTF, is definitely terrible practice. On second thought, given how many there are here, and what a pain in the butt it would be to handle them all, it is a WTF.

    As has already been mentioned, converting the street address number to an integer is going to break when an address like '22B' or '42 1/2' gets used somewhere. Major WTF.

    The use of if-if logic may have been a way of reducing the size of the conditional statements, but given that the pattern starts from the beginning of the code and is copy-pasted throughout the code, it is more likely just laziness. In any case, the fact that empty fields are simply bypassed is a WTF as well, agreed.

    While the use of Hungarian Notation in C# isn't quite a WTF (it's deprecated but not forbidden), the inconsistency with which it is done here is.

    (Actually, I would argue that HN is a huge WTF in and of itself, at least in an object-oriented language, but that's a pet peeve of mine. I've always seen the need to use HN or similar tricks as a sign that too many variables are in the immediate scope - if you need something to track variables themselves with, and your IDE isn't doing the job, You're Doing It Wrong.)

    Hrm...do we really need to rebuild Midlake, UT just to spite all those folks who pick apart addresses and try to divine meaning out of their individual bits?

    You're going to have to explain that one to me.

  • Adam (unregistered)
    5. Schizophrenic variable names (I'm thinking of you iStrNum. Are you a number? A String? An integer? Pick a side).

    Pretty sure iStrNum is short for street number, not string number. Although God forbid having to type the full word "Street"

    Captcha "minim": Always use the minim number of characters when naming variables, because who cares about clarity

  • anonymous (unregistered) in reply to Hasse de great
    Comment held for moderation.
  • Balu (unregistered)

    Number 5 ("I'm thinking of you iStrNum. Are you a number? A String? An integer? Pick a side") is not necessarily a WTF.

    Given that the variable is to identify the "street number", "StrNum" could be a valid abbreviation of "street number" and "iStrNum" very clearly indicates that this refers to the street number, converted to integer.

    And yes, it's C#, but the class name for strings in C# is still "String". You can use "string", but then you use the internal type, which of course maps to the "String" class. By convention, class names in C# start with capital letters, even though this is not enforced as it is in Java.

  • Steve The Cynic (cs) in reply to Schol-R-LEA
    Schol-R-LEA:
    (Actually, I would argue that HN is a huge WTF in and of itself, at least in an object-oriented language, but that's a pet peeve of mine. I've always seen the need to use HN or similar tricks as a sign that too many variables are in the immediate scope - if you need something to track variables themselves with, and your IDE isn't doing the job, You're Doing It Wrong.)
    This depends heavily on whether you are using Systems HN or Applications HN. SHN (prefix variable names with a wart indicating the in-language type of the variable) is, indeed, a WTF of the highest order, and the *need* to use it does suggest an excess of variables.

    AHN, on the other hand, is mild at worst. In AHN, the wart (it's still a wart, and mostly unnecessary in type-enforcing OO languages, as you say - C++, Java, C# are examples of type-enforcing languages, while JS, PHP, Python are not) indicates some property of the variable that cannot be captured in its language-level type.

    Imagine that I cannot derive my own classes from my language's string type, and I cannot create a wrapper class for them either. It's a reach, but perhaps my language is plain-old-C, where it is less of a reach. Now also imagine that I want to carry around different kinds of string, say "plain", "html-encoded", and so on. My AHN wart will indicate which of these a particular variable contains, and code reviewers should be able to spot the bogus code below:

      StringType htmlencProductName = ...;
      StringType plainProductName;
    

    plainProductName = htmlencProductName;

    In a proper implementation in a type-enforcing language, the assignment will either fail because there isn't a suitable override of operator =(), or it will find an implicit conversion, or the combination-specific assignment operator function will apply the conversion directly.

    In a language with the restrictions outlined above, however, we rely on the eyes of the reviewer to detect that no, it isn't appropriate to assign things that way. Or we build tools to do the same job. We also write functions like plainFromHtmlenc to do review-friendly conversions. (And it is destinationFromSource, not sourceToDestination - read the assignments below to see why...)

      plainProductName = plainFromHtmlenc( htmlencProductName );
      plainProductName = htmlencToPlain( htmlencProductName );
    In the first, the "plain"s clump together, as do the "htmlenc"s, while in the second, they do not. So stick with the first, folks, or don't do it like this at all.

    Petzold's original intent was AHN, and parts of the Windows APIs do indeed use this - look at the number of variables and function parameters named 'nSomething' that hold the number of Something, or the ones named 'cbWhatever' that hold a Count of Bytes, or the ones prefixed with sz that hold a String, Zero-terminated - while others, sadly, use the mutant monster that is SHN, the most egregious examples of which are the multitude of "lpBlahBlah" (pointers are no longer "long" (far), nor are they truly "short" (near) in the classic sense either) and the infamous wParam (no longer a WORD, thanks).

  • Chubber (unregistered)

    I'm still trying to make the leap from

    var propCurrent = (from addr in dbContext.Addresses
                          join prp in dbContext.Properties on addr.AddressID equals prp.AddressID
                          where prp.PropertyID == CurrentPropertyID
                          select addr).SingleOrDefault();
    

    to

       if (!int.TryParse(this.txtStreetNo.Text, out iStrNum))
    

    How does the mere setting of the local variable propCurrent automagically set this.txtStreetNo?

  • tharpa (cs) in reply to rt
    rt:
    Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)
  • dr memals (unregistered) in reply to Chubber
    Chubber:
    I'm still trying to make the leap from
    var propCurrent = (from addr in dbContext.Addresses
                          join prp in dbContext.Properties on addr.AddressID equals prp.AddressID
                          where prp.PropertyID == CurrentPropertyID
                          select addr).SingleOrDefault();
    

    to

       if (!int.TryParse(this.txtStreetNo.Text, out iStrNum))
    

    How does the mere setting of the local variable propCurrent automagically set this.txtStreetNo?

    the first block gets the original record from the database and the second from the current UI session
  • Ozz (unregistered)

    E-mail address validation is as bad. Even Facebook can't get that right. They keep telling me to confirm my e-mail address saying it is invalid. That address has been working just fine for well over a decade...

  • djingis1 (unregistered)

    ARWTF: All of this logic happens on (probably EntityFramework) model classes instead of business entities.

  • C-Derb (unregistered) in reply to rt
    rt:
    Schol-R-LEA:
    if they ever have an international client, they're screwed.

    This.

    It's always annoying to order stuff internationally. Most websites insist that I must enter a state name, although there are no states in my country. Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).

    Why isn't there a big white text box where I can type in my adress the way I want? That's my problem if I screw it up.

    No. Not this.

    Sometimes the potential of a handful of international clients isn't worth the trouble of planning for them. Catering to your largest market, not the smallest, usually produces better results. Maybe, just maybe, mailing stuff to international addresses is too "annoying" and this is their way of discouraging you from using their service. You aren't worth it.

    In other words, there's no reason to criticize this code for not handling international addresses if handling international addresses is not a requirement.

  • Steve The Cynic (cs) in reply to tharpa
    tharpa:
    rt:
    Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)
    The pedantic spelling of "role" is actually "rôle", even in English, although this has mostly fallen out of use. And don't get me started about the pronunciation difference between "blessed" and "blessèd".
  • no laughing matter (cs) in reply to C-Derb
    C-Derb:
    Sometimes the potential of a handful of international clients isn't worth the trouble of planning for them. Catering to your largest market, not the smallest, usually produces better results. Maybe, just maybe, mailing stuff to international addresses is too "annoying" and this is their way of discouraging you from using their service. You aren't worth it.
    Wait what? More than 50% of the world population (even much more, as the rest is only "a handful") now live in the USA?

    Learnt something new today!

  • joiner (unregistered)

    Where did this pattern come from ?

    addr.AddressID prp.PropertyID

    Why not addr.id and prp.id which makes it easier to do generic things to tables.

  • C-Derb (unregistered) in reply to no laughing matter
    no laughing matter:
    C-Derb:
    Sometimes the potential of a handful of international clients isn't worth the trouble of planning for them. Catering to your largest market, not the smallest, usually produces better results. Maybe, just maybe, mailing stuff to international addresses is too "annoying" and this is their way of discouraging you from using their service. You aren't worth it.
    Wait what? More than 50% of the world population (even much more, as the rest is only "a handful") now live in the USA?

    Learnt something new today!

    See, you assume that all businesses that use the internet and collect addresses will at some point want to cater to the entire world. But that's because you are an ass.

    Take, for example, pizza delivery. Why would my local pizza joint, over 1000 miles from any other country, spend any money or time at all to support international addresses when their delivery area is limited to, maybe 20 miles?

    We can debate why they'd want to do any address validation at all (probably needless), but for damn sure they don't need to consider international addresses.

  • chubertdev (cs)

    If this is using a FormView control, it's also missing exception handling. C# pretty much swallows exceptions for you with this control. I refactored one web app that I inherited to remove the FormView controls, just because of how many WTFs they caused.

    http://forums.asp.net/t/1466060.aspx?formview+exception+handling http://forums.asp.net/t/1490664.aspx?Formview+insert+silently+fails+no+exceptions+or+errors+how+to+diagnose+

  • slicer (unregistered)

    this:

        var propCurrent = (from addr in dbContext.Addresses
                          join prp in dbContext.Properties on addr.AddressID equals prp.AddressID
                          where prp.PropertyID == CurrentPropertyID
                          select addr).SingleOrDefault();
       if (propCurrent == null)
          throw new Exception("Property not found.");
    

    can be replaced by the simpler:

        var propCurrent = (from addr in dbContext.Addresses
                          join prp in dbContext.Properties on addr.AddressID equals prp.AddressID
                          where prp.PropertyID == CurrentPropertyID
                          select addr).Single();
    
  • chubertdev (cs) in reply to Steve The Cynic
    Steve The Cynic:
    tharpa:
    rt:
    Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)
    The pedantic spelling of "role" is actually "rôle", even in English, although this has mostly fallen out of use. And don't get me started about the pronunciation difference between "blessed" and "blessèd".

    So it becomes a filter to prevent pedantic dickweeds from using the site. Working As Designed™!

  • TheCPUWizard (cs)
    1. The inventive re-imagining of if-if logic. Because more curly braces make for better code.
    NO, because it makes placing breakpoints MUCH easier (For the vast majority of IDEs)
  • Gene Wirchenko (cs) in reply to no laughing matter
    no laughing matter:
    And this one also has an example from Gene Wirchenko!

    Actually, two of them. Addresses can be very weird. I also knew of a company with an address of "South Foot of Main Street", and apparently, that was fine with Canada Post.

    Ah, fame! I could use the fortune that supposedly goes along with it.

    Sincerely,

    Gene Wirchenko

  • Gene Wirchenko (cs) in reply to tharpa
    tharpa:
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)

    English does use more than just plain characters though the use of them has been going away in my lifetime. Example in reverse chronological order of use: cooperate, co-operate, coöperate.

    Sincerely,

    Gene Wirchenko

  • garaden (unregistered) in reply to tharpa
    tharpa:
    rt:
    Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)

    This strikes me as...

    ...naïve.

  • chubertdev (cs) in reply to garaden

    You're naive in your spelling.

  • Hannes (unregistered) in reply to rt
    rt:
    Schol-R-LEA:
    if they ever have an international client, they're screwed.

    This.

    It's always annoying to order stuff internationally. Most websites insist that I must enter a state name, although there are no states in my country. Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).

    Why isn't there a big white text box where I can type in my adress the way I want? That's my problem if I screw it up.

    "Not a valid zip code" is another nice one. Oh yeah, in the US the zip code I entered might not be valid, but it's the zip code of the town where I live.

    And people mistaking the 'ß' to be "some sort of 'b'" is annoying as well. (HINT: it's "some sort of 's'"!)

  • Hannes (unregistered) in reply to tharpa
    tharpa:
    rt:
    Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)

    Time for some Häagen Dazs, I guess.

  • foo AKA fooo (unregistered) in reply to chubertdev
    chubertdev:
    Steve The Cynic:
    tharpa:
    rt:
    Almost no website supports accented characters (No my name isn't "invalid" just because it contains an ë).
    Although it isn't a popular view, the English language does not contain accented characters. Thus, an English language website has no more obligation to support accented characters than it has to support Chinese characters. (FWIW, my middle name has an umlaut in its original transliteration.)
    The pedantic spelling of "role" is actually "rôle", even in English, although this has mostly fallen out of use. And don't get me started about the pronunciation difference between "blessed" and "blessèd".

    So it becomes a filter to prevent pedantic dickweeds

    And heavy metal bands
    from using the site. Working As Designed™!
    Invalid character "™", your post is rejected.

  • not an anon (unregistered) in reply to operagost
    Comment held for moderation.
  • garaden (unregistered) in reply to chubertdev
    chubertdev:
    You're naive in your spelling.

    How?

  • chubertdev (cs) in reply to garaden
    garaden:
    chubertdev:
    You're naive in your spelling.

    How?

    How what?

  • sailsman (unregistered) in reply to pjt33
    Comment held for moderation.
  • Coyne (cs) in reply to Steve The Cynic
    Steve The Cynic:
    In a language with the restrictions outlined above, however, we rely on the eyes of the reviewer to detect that no, it isn't appropriate to assign things that way. Or we build tools to do the same job. We also write functions like plainFromHtmlenc to do review-friendly conversions. (And it is destinationFromSource, not sourceToDestination - read the assignments below to see why...)
      plainProductName = plainFromHtmlenc( htmlencProductName );
      plainProductName = htmlencToPlain( htmlencProductName );
    In the first, the "plain"s clump together, as do the "htmlenc"s, while in the second, they do not. So stick with the first, folks, or don't do it like this at all.

    Actually, this same argument invalidates the AHN concept as well. Consider the proper ordering of variables for several names: plainProductionName, plainLineName, plainFactoryName, plainPlantName, htmlencProductionName, htmlencLineName, htmlencFactoryName, htmlencPlantName, htmlhrefProductionName, htmlhrefLineName, htmlhrefFactoryName, htmlhrefPlantName, uuencProductionName, uuencLineName, uuencFactoryName, uuencPlantName

    By ordering, the names are scattered across spaces that don't have any meaningful association; moreover, it's not easy to determine what variables are available for say, "LineName".

    It would be better to suffix, so the variables have "stems" in front, such as: ProductionName, ProductionNameHtmlEnc, ProductionNameHtmlHref, ProductionNameUuEnc, LineName, LineNameHtmlEnc, LineNameHtmlHref, LineNameUuEnc, FactoryName, FactoryNameHtmlEnc, FactoryNameHtmlHref, FactoryNameUuEnc, PlantName, PlantNameHtmlEnc, PlantNameHtmlHref, PlantNameUuEnc

Leave a comment on “Feeling Validated”

Log In or post as a guest

Replying to comment #:

« Return to Article