New Blog Post:

New Blog Post:
How to Replace Global Variables with a Static Class
http://capecodgunny.blogspot.com/2014/07/how-to-replace-global-variables-by.html #delphi

Comments

  1. I think nobody would cry alot about some string global variables. The downside of global variables is: even in unit tests you have to use them! If you have a global variables of type TAppManager, which uses TAppData which uses TAppSerializer which uses TAppFunctions which uses ... etc.. You need all this stuff in a unit test and it cant be exchanged. The better method is Depency Injenction. Your SUT just get an IAppManager which require no more units. In "reallife" you give him a TAppManager, in unit tests you give him a TAppManagerMock.

    ReplyDelete
  2. Fabian S. Biehn Well said ;)

    Putting global variables into a static class is like putting poo in a cardboard box. It still smells.

    I am not saying that you must never ever use global variables but be aware where you use them and what information they contain or if you are sending information over them to other parts of your application. Because usually that results in hard to test and maintain code.

    ReplyDelete
  3. thanks for the post Michael, I will consider to use this technich on next project; I use lots of globals - hey, my program even has 2 or 3 GOTOs and several ShowMessage :) .

    ReplyDelete
  4. Stefan Glienke Thank you for the link to the clean code video in your comment on the blog post.

    ReplyDelete
  5. I use interfaces for factory objects, so in unit tests I insert an other factory than in "real life" ;-)

    ReplyDelete
  6. Fabian S. Biehn And your interfaces are global variables or ...?

    ReplyDelete
  7. I (Yes, me personally, I can't blame anybody else.) introduced one global variable gblSomething (which contains data about the currently active data object in my main application at work) and have regretted it ever since. It got referenced nearly everywhere in the code and in the end made it impossible to use that code in other programs that worked on several of these objects in parallel or even didn't use such an object but called code that referenced it. It took me and my team ages to get rid of all the references again. Now it's a field of my main form and gets passed as a parameter to all objects and methods that need it. Many, that previously referenced it, didn't actually need that object but were better called with a file name instead.
    Still later, I introduced another global variable gblLogger, which is an interface to a logging api (Actually, it's not a global variable but a function that returns a variable stored in the implementation section of a unit. You could call it a singleton if you are into design patterns.). I thought this should be safe, because you always write to the same logging facility inside your program, so initializing it once for the whole program should be what you want? Wrong. It turned out that in many modules I sometimes wanted to log to a different log file to keep theses messages separated from the main file, usually for debugging that particular module. Now, most objects get an ILogger interface passed in the constructor. It's an optional parameter which is initialized with NIL and in that case uses the gblLogger global variable. I'm still not sure whether that's good design, but it works for most cases.
    I learned: Global variables are evil, whether they are strings, object instances or interface variables. Unfortunately I still forget that lesson once in a while because something must be done fast. Hm, this sounds like a blog post I should write some time...

    ReplyDelete
  8. Like others before me commented, I agree 99% that global variables can easily become a nightmare; with that said, please keep in mind that there are often small projects that simply don't worth the extra care -- i.e. one time projects -- however, it's a good idea to be consistent whenever possible and avoid global variables.

    In my projects, the globals are:
    - Logger;
    - Parsed command line switches -- almost became a nightmare, but thankfully, there aren't that many;

    Bottom line, global variables aren't the greatest solution, be it primitive types, class instances, interfaces, etc. IMO, in the ideal scenario, each class will do it's thing based on parameters passed to constructor or it's methods, same applies for functions/procedures within units; as soon as a class, function/procedure modifies a global variable, you're asking for nights of debugging to come + all decisions from that point on will most likely have to rely on one or more global states, in effect, you're asking for more trouble (:

    ReplyDelete
  9. Thomas Mueller nope, they are parameter of the constructor if I need them always or properties if they are optional

    ReplyDelete

Post a Comment