home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,776 of 33,346   
   Balog Pal to Richard   
   Re: Unit Testing Frameworks (was Re: Sin   
   02 Jan 13 17:39:56   
   
   From: pasa@lib.hu   
      
   On 1/2/2013 6:34 AM, Richard wrote:   
   > In my experience, the main problem that singletons create for unit   
   > testing in C++ is that singletons are just another name for global   
   > variable.  I don't think anyone questions the idea that having your   
   > code coupled to global variables makes it harder to unit test.  I   
   > don't see why the assertion that having your code coupled to   
   > singletons makes it hard to test is any more difficult to understand.   
      
   Then I guess you similarly don't see how functions create an abstraction   
   layer. Do you make all the data in classes public as well? Why not? you   
   suggest there is no difference...   
      
   > The other problem with singletons   
      
   Hm, what was the FIRST problem again?  I mean with singletons, not your   
   inability to see a difference.   
      
   > is that people just assume those   
   > resources will be cleaned up when the process exits.   
      
   That sounds like a problem with the implied people.   
      
   > This means that   
   > if you have two unit tests that both interact with the same singleton,   
   > then executing one test can perturb the results of the other test.  It   
   > becomes more difficult, if not impossible, to reset the environment   
   > between tests without launching each test as its own executable.   
      
   Did you read at least the starting post of this subthread? The objects   
   used in the test cases were created on the stack frame, so could not   
   possibly escape for crosstalk.  More importantly it was shown that you   
   can provide the exact same object through the singleton access function   
   that you would pass as function argument.   
      
   So any problems related to lifetime or crosstalk would be the same using   
   the suggested cool alternatives. Or the lack of them as well.   
      
   Certainly the method required to use the access function instead of a   
   direct global variable.   Kinda proving that there is significant   
   difference and your claim at the front is largely mistaken.   
      
   > You may be writing your singletons in such a manner as to sidestep all   
   > these problems and therefore you don't understand why someone would   
   > say that singletons are PITA when it comes to unit testing.  However,   
   > if this is the case I would assert that you are in a very small   
   > minority when it comes to people who write singletons.   
      
   Possibly so, but that should lead to abandon bashing singletons and   
   focus on the REAL issue: the problems dragged in these discussions are   
   normally manifestation of the "Idiot at the wheel" or the "Set, Fire,   
   Aim" pattern (antipattern).   Where messing up singletons or globals is   
   just a tiny spot.   
      
   And the cure is hardly bashing singletons, or especially suggesting to   
   replace them with potentially even more painful tactics like DI, but to   
   either weed out the incompetent or train to have UNDERSTANDING. Of   
   methods and consequences. Or how to look at alternatives, and evaluate   
   their actual pros/cons, instead of empty claim words.   
      
   > In fact, I can't think of a single case of trying to cover legacy code   
   > with unit tests where the code was easy to test if it interacted with   
   > a singleton.   
      
   Huh, I think most people with industrial experience would state the same   
   leaving out the 'with singletons' part.  Let's try you: how many legacy   
   systems did you find where code was easy to test? (Well, there's no real   
   consensus on meaning of 'legacy code', but one currently pretty popular   
   book, Feathers'  "Working with legacy code" *defines* it as stuff   
   without tests. ;-)   
      
   IME all legacy code I looked at was messed up in a zillion ways,   
   including accidental and deliberate things. Presence of singletons   
   hardly made the problem top 20 list. Probably not even plain old   
   globals.   And the problems about writing tests started not even at   
   technical level but at missing information about what the desired   
   behavior is.   Then followed by general spaghetti effect and especially   
   UI coupling.  Anyone solving those problems would just laugh at globals.   
      
   > Invariably, the easiest way to decouple such legacy code   
   > is to extract an interface around the singleton and then have the SUT   
   > interact with the interace which it receives via dependency injection.   
      
   What is pretty much like famous picture of the waterfall water   
   conveniently flowing down from its bottom to top. To start refactoring   
   you'd need a system that is correct, AND have tests too to make it safe.   
   In reality you start without any of that. Any modification to the code   
   is an unmitigated risk. Also with DI you dig a serious hole into the system.   
      
   While in C++ we can use non-intrusive methods of testing. Or intrusion   
   limited packaging. Or limited to test environment.   
      
   No, DI is absolutely not something you NEED to start testing.   
      
   DI may have its uses, but I surely would not trust anyone without very   
   good understanding of all the alternatives to do modification on a   
   carefully BALANCED legacy system.  Especially for a sake of some theory.   
      
   > That doesn't eliminate the singleton, but it does effectively make it   
   > not look like a singleton from the perspective of the consuming class.   
      
   What is a serious change of behavior -- the information of 'same   
   instance' is lost, and the system must start dealing with possible   
   ALIASING. On top of any unmanaged complexity it already has.   
      
   Or just take the lazy approach assuming that all the pointers are really   
   carrying the same value until someone starts believing that all those   
   pointers surely have some purpose other than obfuscation and posts a   
   different instance. In the live system, not some stripped and isolated   
   test cases.   Guess how happy the next maintainer of the system (with my   
   luck probably ME, as other inventors have tendency for the "take the   
   money and run" approach, or just fold after some time) will be?   
      
   > Once all the consumers are treating the singleton just like any other   
   > class, you're left asking yourself the question of why you bothered to   
   > go through the trouble to enforce the singleton nature of it in the   
   > first place.   
      
   Ok, unlike the other DI proponents, please be the first one explaining   
   why aliasing is not a problem. The example is there little upstream,   
   let's look again: having foo(A* a, B* b) that formerly called   
   GetLogger().Log() will now call a-> or b-> or both or start some   
   discovery logic?   
      
   > Every time a singleton is suggested, it isn't suggested because there   
   > is a NEED to enforce that there be one and only one instance of the   
   > object, the argument is always made because someone observes that at   
      
   [continued in next message]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca