tags:

views:

65

answers:

5

I'm using

Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\MyProgram"

As the path to store several files used by my program. I'd like to avoid pasting the same snippet of code all over the my applcation.

I need to ensure that:

  • The path cannot be accidentally changed once its been set
  • The classes that need it have access to it.

I've considered:

  • Making it a singleton
  • Using constructor dependency injection
  • Using property dependency injection
  • Using AOP to create the path where its needed.

Each has pros and cons.

The singleton is everyone's favorite whipping boy. I'm not opposed to using one but there are valid reasons to avoid it if possible.

I'm already heavily using constructor injection through Castle Windsor. But this is a path string and Windsor doesn't handle system type dependencies very gracefully. I could always wrap it in a class but that seems like overkill for something as simple as a passing around a string value. In any case this route would add yet another constructor argument to each class where it is used.

The problem I see with property injection in this case is that there is a large amount of indirection from the where the value is set to where it is needed. I would need a very long line of middlemen to reach all the places where its used.

AOP looks promising and I'm planning on using AOP for logging anyway so this at least sounds like a simple solution.

Is there any other options I haven't considered? Am I off base with my evaluation of the options I have considered?

A: 

if you have a standard .net application, you should already have a settings - class. you could create a new setting and set that value as default value or so.

+3  A: 

I've never seen a problem with creating a static class like Environment for my own projects, when there's been strong enough need.

MyAppEnvironment.ApplicationFolder

If you're passing the value in using injection then you're either a) creating a class just to hold the value or b) passing in a string. The latter is bad, because your value should be constant. The former is valid, but seems like a fair overhead since there's only ever a single valid value (and you can still mock/fake that value for tests if you really need to).

I suppose you could inject your environment class, but for me this seems like overkill.

Dan Puzey
The only reason I don't like the static classes is they are hard to test.
Mark
@Mark: In what way? (+1 to the answer)
Adam Robinson
@Adam The class I'm testing now depends on something else, the static class. Also, when that static class depends on something else, like the environment settings, you really don't know what you're testing anymore.
Mark
@Mark: I guess I'm not getting how that (the dependence upon other objects) is specific to *static* classes.
Adam Robinson
@Adam: The class under test _has_ to use that static class. You can't fake it or mock it. You have no choice, so you're stuck with whatever it does...and you have to be concerned with what it does, which makes setting up the test more difficult.
Mark
@Mark: Gotcha, that does make more sense. You can't test your other class in isolation.
Adam Robinson
@Adam: He's referring to what Michael Feathers called "The Case of the Irritating Global Dependency". Basically, you want to test ClassA but it depends on StaticClassB. So there's no way to break the dependency on StaticClassB because its static. This is the biggest complaint most people have against singletons.
codeelegance
A: 

We would constructor inject a class of type IMyAppConfig which is just a wrapper for all this kind of stuff.

Mark
+1  A: 

It seems like what you have amounts to a global setting within your application. Using AOP o constructor injection to pass around this dependency seems like quite a bit of overkill since a simpler solution would do the trick.

My preference here would be to use a static property on a static class. I would add a specific write routine that prevents multiple sets. For example ...

public static class GlobalSettings {
  private static string s_path;
  public static string Path { get { return s_path; } }
  public static void UpdatePath(string path) {
    if ( s_path != null || path == null ) { throw ... }
    s_path = path;
  }
}
JaredPar
The thing is... at the moment it doesn't really need to be globally accessed. A handful of classes in a data persistence layer and a logger is all that uses it. That may change at some point but for now its not really needed at a global level.
codeelegance
A: 

My process is to always ask questions like these: What kinds of things can change? What would create the least amount of pain when those things change? What pieces can be re-used in other systems, and how can the pain of the reuse be minimized? Basically, how can these things be decoupled as much as possible?

With that in mind, the answer is really based on the details of the system that you are working on.

In whatever process uses this path, I would likely pass it down as a parameter. This would start at whatever action initiates the use of the path. Each method should "do one thing well", and if the path is part of that thing, then it should be a parameter. In the class that initiates the action (and in whatever classes control the lifetime of that class, etc.), I would likely make the path part of the constructor.

This is the method that I have used in the past, and it has served me well. For example, in one application I took this approach, and then later discovered a need to allow the user to change the path setting. By following this architecture (and avoiding a singleton) the objects that had already used the path could continue to use the old one without an error, but the new path was used correctly from the point of the change. It just worked.

And the classes can be migrated to a new project without a dependency on this particular detail.

Jeffrey L Whitledge