• (nodebb)

    foo += "f";

    foo += "i";

    foo += "r";

    foo += "s";

    foo += "t";

  • Ron Fox (google)

    TRWTF is assuming that 'most languages' are like Java "In most languages, strings are immutable." :-P

  • KingCrunch (unregistered)

    One method of AdminWS starts with 'Can*', another one with 'Check*'. This said for 2 of 3 methods the boolean return value seems to be reasonable. And regarding TransactionType vs TransactionCode: That looks like Legacy-Code to me, that previously had to translate between two systems (of different ages) and parts of that are still in place. That's just a technical debt.

  • getwiththetimes (unregistered)

    "But the real prize here is where the parameter int TransactionType."

    Why don't you read your articles?

  • foxyshadis (unregistered) in reply to Ron Fox

    "Most languages" is entirely correct, even if you consider uncommon languages. C is an outlier, especially today, in not having and defaulting to immutable strings.

  • Roboticus (unregistered)

    I'm doubtful of "most languages", I'd like to see some reference before accepting that. I expect that "most new languages" may have immutable strings, though I wouldn't be certain of it.

  • Pedant (unregistered)

    C: effectively immutable strings, use sprintf to format C++: std::string is immutable if you use const Java, C#, VB: immutable string + stringbuilder. Also Java optimizes concatenation. Python: immutable strings. Ruby: mutable string, s << "append". immutable via freeze Perl: mutable strings. Javascript: immutable string, optimized concatenation Haskell: fully immutable, prefer tricks like intercalate Elisp: immutable strings, but highly optimized buffers are first class Scheme: mutable and immutable strings

    elisp, Java, C#, VB fit. C, Python and Javascript don't have a string builder idiom. Ruby, Scheme, Perl and C++ all have flatly mutable strings.

    I grade this claim flatly wrong.

  • (nodebb)

    And there are folks who insist StringBuilder() is the worst thing you can do - use String() and "+=" instead because it's "better" than StringBuilder.Append(). TRWTF is not knowing the difference. No, wait, TRWTF is people who TEACH this kind of WTFery as defacto standard.

  • Anonymous') OR 1=1; DROP TABLE wtf; -- (unregistered) in reply to Pedant

    Objective-C: Immutable strings. No StringBuilder idiom, instead use NSMutableString to get mutable strings.

  • Ingo (unregistered)

    Making a vague claim even more vague by restricting it to "new" languages without saying what makes a language "new".

  • Adam Feather (google)

    they wrote every method to return a boolean value indicating success or failure. This meant if any function needed to return a value, that could only be done as an out or ref

    Would you be against a return object which encapsulated details of failure? i.e. if the login fails an object is returned which looks something like:

    var loginResult = new LoginResult { LoginSuccess = false, Reason = LoginErrors.InvalidEmailAddress, LoginAttemptCount = 1, etcetera... };

    return loginResult;

  • Bytemaster (unregistered) in reply to Bananafish

    For a while in .Net I thought the opposite - that StringBuilder is always better. StringBuilder has overhead every time. What I finally came down to as a general rule was if you are using a fixed number of items to concatenate and are doing it in one line, then use concatenation. Otherwise, generally use StringBuilder. Always use StringBuilder if you are concatenating in a loop. Initialize with a reasonable size when you can reasonably know or guess the target or minimum size of the final string.

  • (nodebb)

    Don't compilers just (or should) optimize this anyway?

  • Ritesh (unregistered) in reply to antoshka

    Your foo was uninitialized. I just see werewtrretgdretregreggragrgargraeggfirst

  • (nodebb) in reply to Bytemaster

    Concats on a String and Append() on a StringBuilder (in Java) both have overhead - but StringBuilder will have much less, especially if you instantiate a StringBuilder with a reasonable size which then will have no more overhead than appending bytes to the end of the significant data in the memory structure for that object. Even if the size of the StringBuilder is overrun, it takes less overhead to expand it than to instantiate a new String object for each concatenation.

    The use of String instantiated as a concatenation of several existing Strings in one statement (as in your reply) makes perfect sense. It makes NO sense to use String if you are concatenating several strings by way of multiple statements or by way of a loop. If you are creating a long String (dynamic web content?), it makes more sense to create a StringBuilder(4000) than to create a StringBuilder(2000) and overrun it by 1 character (thus expanding it to 2200, 2500 or 3000, depending on version/build and some settings). In this case, concatenating 50 characters to a 2000-character String 5 times will result in the overhead required to instantiate 5 new objects of type String, but performing this operation with 5 Append() methods will only need to instantiate one additional StringBuilder object. Much cleaner.

    StringBuilder is usually a better option even though we are taught to avoid it all the time in Java. It is especially useful in situations you describe, Bytemaster. When used to concat multiple strings in a one-line statement, some argue String is a better object. Not sure. I personally do the same as you and use String if the content is immutable or in the case of a one-line construct (such as in messages). I prefer StringBuilder if I will have multiple appends, and I have even used StringBuilder constructs as a form of fixed-length record (in a COBOL kind of way) to build a single record using information gathered from multiple other objects (foreign keys, for instance). StringBuilder has excellent methods for placing a String into a particular location - which String does not - and it is easy enough to pull this data and create persistent objects from a single controller class rather than have every class touch data.

  • (nodebb) in reply to Sumireko

    Not as you might expect. Yes, the compiler can optimize, but the compiler has no idea if at run time if you are concatenating a 2-byte String to a 200-byte String, vice versa, or a 200-byte string to a 4-Mb String. it does not know what the value will be for any variables that contain or will contain foreign data. The only thing that doesn't change is the specifcations for the language and, in the case it is an objective language, the object class itself.

  • frits (unregistered)

    This whole nonsense about immutable strings can be overcome with a List<char> object. When you want to return a string, just (in C#) call ToArray() and construct a string from the resultant array. You guys are making this shit too complicated.

  • John Wiltshire (google) in reply to Bananafish

    Note that in Java there is no "+" or "+=" operator on the native "String" object. It always compiles to a StringBuilder under the hood. Check out the bytecode.

  • (nodebb)

    Hey, a pattern is a pattern.

  • (nodebb)

    TRWTF this time is Remy. As well as the "most languages" claim, the HTML comments left me shaking my head even more.

    This code sample isn't exactly as submitted, but I've altered it to make it extremely clear what's going on.

    It's a CodeSOD entry. Shouldn't we generally be looking at the actual code submitted? You could always explain in the actual article, if necessary. If nothing else, a less obvious error is more likely to be one where readers might think "hey, I should watch out for that" rather than "that dumbass, I would never do that". I admit, it's a judgement call, and your primary responsibility here is entertainment rather than education, so it could go either way. Still, I think CodeSOD articles should be sticking closer to the actual specifics than other articles.

    Easy Reader Version: concat("This", " is ", " pretty ", " awful ").

    ... and the Easy Reader Version is doing the exact opposite of what the code in the article is doing: adding multiple strings together without a StringBuilder, while the article code is using a StringBuilder to hold a single string literal.

  • Exceptional (unregistered) in reply to Adam Feather

    a return object which encapsulated details of failure?

    Otherwise known as an exception

  • AP (unregistered) in reply to Exceptional

    "Otherwise known as an exception" ... Nope!

    The returned object is received by the caller. The exception is received by the most recent catch block on the stack equipped to do so.

  • (nodebb) in reply to Bananafish

    StringBuilder is usually a better option even though we are taught to avoid it all the time in Java.

    Whoever taught you that was an idiot.

    Java's string concatenation operators actually compile to StringBuilder calls (except that concatenation of constants can be optimised at compile time). The reason for preferring the concatenation operators is that they give much shorter and clearer source code. The reason for preferring direct StringBuilder use is that it is more efficient in many situations (especially where a loop is involved). Use the right tool.

  • (nodebb) in reply to dkf

    Same with C# (according to Microsoft's specs).

    // Look at awesome me! I can use StringBuilders, too! StringBuilder returnValue = new StringBuilder(); for (i=0; i<stringList.Length; i++) { if (i>0) { returnValue = new StringBuilder(returnValue.ToString() + new StringBuilder(separator).ToString()); }; returnValue = new StringBuilder(returnValue.ToString() + new StringBuilder(stringList[i]).ToString()); }; return returnValue.ToString(); // Oh... you say string.Join(separator, stringList) would've been better? // DUDE. NOT COOL.

    Addendum 2016-06-23 05:45: Do BBCode tags work here?

      // Look at awesome me! I can use StringBuilders, too!
      StringBuilder returnValue = new StringBuilder();
      for (i=0; i<stringList.Length; i++) {
        if (i>0) { returnValue = new StringBuilder(returnValue.ToString() + new StringBuilder(separator).ToString()); };
        returnValue = new StringBuilder(returnValue.ToString() + new StringBuilder(stringList[i]).ToString());
      };
      return returnValue.ToString();
      // Oh... you say string.Join(separator, stringList) would've been better?
      // DUDE. NOT COOL.
    
    
  • Aonymus (unregistered)

    This is the best WTF in a long time! A pure code wtf - did lol a bit

  • Jonathan (submitter) (unregistered) in reply to Adam Feather

    I would recommend against that except at the point you are going to display it to your user. I will explain why.

    In OO languages like C# (as was this example), we are encouraged to practice good encapsulation and separation of concerns into different classes and/or methods. This means it can be completely ordinary to be 5 or 10 levels deep on your call stack when you encounter an error, like for example "Could not connect to server". Now we have the problem that the error needs to propagate up the call stack to the end user. One way to do this is to make each method return an object which has properties like "string ErrorMessage; bool Success; object response;", then for each caller of the object, they in turn need to inspect the result of the object to see if an error occurred, so the code might be something like:

    var response = GetResponseFromServer();
    if (!response.Success)
    {
         return new ErrorObject{Success = false, ErrorMessage = response.ErrorMessage, response = null };
    }
    // All good, let's use the response:
    DoAnotherFunctionWithTheReponse(response.reponse);
    ....
    

    And you have do this on every level, it becomes a huge mess.

    The great thing about throwing an exception instead is that it travels all the way up your call stack to last try..catch block. And if the only try...catch block is right by the code where the user initiated the request, you could present a message box, or in the case of a web service, wrap the exception in an easy to consume "error occurred response" which might look like your example response.

    Also, keep in mind that you can easily make your own exceptions if you need more information, for example you could make an "AuthenticationFailedException" class which includes a specific detail about that kind of exception, then in your try...catch, you catch that exception specifically and present it in a specific way to the user.

    Here is an example of a "top level" call of a service, the actual patterns I use are a little different in practice, but this should give you the idea. Be aware that because the code below is wrapped in a transaction, the transaction would be rolled back if an exception occurred.

    public void DoBusinessProcess(string user, string pass, int var1, int var2)
    	try
    	{
    		using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, IsolationLevel.ReadCommitted))
    		{
    			CheckUserHasPermission(user, pass); // This could throw a AuthenticationException
    			DoSpecialBusinessProcess(var1, var2); // This could throw a BusinessViolationException saying something like "Numbers must be positive"
    			LogRequest("The number adding service was used."); // This could throw a bunch of different kinds of exceptions, perhaps it was not able to connect to the database, or write to a file on the hard disk
    			ts.Complete();
    		}
    	}
    	catch (AuthenticationException e)
    	{
    		MessageBox.Show("Authentication failed: " + e.AuthenticationFailureDetails);
    	}
    	catch (BusinessViolationException e)
    	{
    		MessageBox.Show("An error occurred, please check your input and try again: " + e.Description);
    	}
    	catch (Exception e)
    	{
    		// An unknown exception occurred, don't reveal potentially sensitive information (like a stack trace) to the user:
    		MessageBox.Show("An unknown error occurred, please try again. If the error persists, contact the system administrator for more information.");
    	}
    	
    	MessageBox.Show("Success!");
    }
    
  • Jonathan (submitter) (unregistered) in reply to Sumireko

    Except that we are all "compilers" in that we need to look at code, understand what it does, and can then decide what needs to be done with it. The StringBuilder in this case was completely superfluous, it never concatenated any string.

    It added noise to the code which I had to first understand, then do a double mental check to be sure I wasn't making an incorrect assumption, before being able to ultimately filter it out while "compiling" the code it in my head.

  • Adam Feather (google) in reply to Jonathan (submitter)

    Thanks, Jonathan. I appreciate you taking the time to respond.

    Your argument about being forced to propagate a custom object back up the call stack is compelling, particularly, as you say, if dealing with a call stack of any depth. You certainly save yourself the propagation/coding effort by simply handling the exception near the end user.

    My immediate thought about using that approach - catching low thrown exceptions high - is that you would, potentially, need to be aware of the implementation details at the lower levels in order to catch the specific exceptions that could bubble up. Imagine you're authenticating via a web service and the web service is unavailable or actively refuses your connection. The top level try/catch would need to be aware a NetworkConnectionException (or whatever) could be thrown at the lower levels. Would that be a leaky abstraction?

    To some extent I think custom exceptions could be used to get around this issue. Though that does make me think about tightly coupling layers or functionality together.

  • (nodebb) in reply to dkf
    Java's string concatenation operators actually compile to StringBuilder calls (except that concatenation of constants can be optimised at compile time). The reason for preferring the concatenation operators is that they give much shorter and clearer source code. The reason for preferring direct StringBuilder use is that it is more efficient in many situations (especially where a loop is involved). Use the right tool.

    Isn't that what I said? That StringBuilder is "better" even though we're told to avoid it for some unknown reason? And, BTW, the guy who told me that has a PhD in Computer Science from MIT so, yes, he's an idiot!

  • notme (unregistered)

    The developers who wrote those did not believe in throwing exceptions, since an uncaught exception could cause the program to crash. Instead, they wrote every method to return a boolean value indicating success or failure. This meant if any function needed to return a value, that could only be done as an out or ref parameter.

    I think this is the default MO in Rust.

  • DWalker (unregistered) in reply to Pedant

    Fortran? Cobol? IBM 370/390 Mainframe assembler?

  • DWalker (unregistered) in reply to DWalker

    That was in reply to the post enumerating some programming languages and their string-mutable-ness.

  • m (unregistered)

    a propos 'did not believe into throwing exceptions'; I'm sure the tdwtf'ers can help me with this: I recently inherited a vb.net project where exceptions are thrown, caught in the same procedure converted to a return code (viz. one of enum {success, failure}) which, in case of failure, makes the caller raise an exception, which will be caught within the same procedure, and so on . . . I don't think my (former) colleague is malicious enough to come up with this ‘design’ on their own, so where TF did they get this from? I'm mostly a C person and would give a lot for exception handling; having exceptions and using them only for ‘goto fail;’ totally drives me mad.

  • Nobi Nobita (unregistered)

    Catted strings are mutable. And if you don't mind, I'd rather play with strings before they pass through cat than after.

  • Old C Hand (unregistered)

    Excuse my ignorance, but why is returning values by out or ref so bad? It's a design pattern that is used heavily in libc and POSIX and iirc, is exactly what the out keyword in C# is designed to do...

  • David (unregistered) in reply to Old C Hand

    Returning values by out is usually less clear than returning them by returning them. Looking at e = f(a, b) offers no clue what f modifies or what e means; even if it's clear e is an error, which of a and b are modified is hard to tell or remember. try {b = f(a);} catch {...} is entirely clear about what role b is playing, and in most cases it's reasonable to assume that a is not changed.

    libc and POSIX are C-based, and C doesn't have exception handling, so it's this or errno (another pretty bad tool). The number of times C/POSIX programmers ignore errors is almost amazing; virtually every I/O statement can return an error, but how often do you see someone checking the return result of printf?

Leave a comment on “Built Up”

Log In or post as a guest

Replying to comment #:

« Return to Article