I come across this regularly when refactoring code. Say I have a base class and I read some configuration parameters and stuff them into properties like this
public BaseClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
And then I call a method in another class like this
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod(_property1, _property2, _property3);
Is it better to do that? What if I only needed the AppSettings values inside of the OtherClass class? then I could just load them up as private props and initialize them in the constructor and the referencing class/caller wouldn't need to be concerned with the settings.
public OtherClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
My implementation would then simply be
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod();
This one bugs me but I am not really sure why. Which is a better practice and why? And I apologise I am missing something obvious. It happens sometimes lol.
Thanks -Frank
In my view, it depends on what goal of your class.
If class belongs to domain classes, so there is no need to have a dependency to ConfigurationManager class. You can create a constructor and supply necessary data:
public class FooClass()
{
public Property1 {get; private set;}
public FooClass(string property1)
{
Property1 = property1;
}
}
If FooClass belongs to Service Layer, then, in my view, it is eligible to have a dependency to ConfigurationManager class.
I can't really comment on "better" as that's quite subjective, but it's at the very least factual to say that passing the parameters into the method, rather than having the method go and get them itself, is a form of dependency injection. Dependency injection has advantages in that it reduces the number of things the class has to know how to do/reduces the number of other classes any given class needs to do its work. Typically in OO design we look for ways to reduce the dependencies a class has on other classes. You might also see the concept referred to in general as low coupling. Classes that are not highly coupled to other classes are easier to reuse as independent modules within multiple programs
In your example, OtherClass (and/or BaseClass) needs to know what a ConfigurationManager is, which means it needs a reference to its namespace, needs to have system.configuration.dll available on the target etc just so that it can go and get some basic things (strings) that contain info necessary to do its work. If you instead give the strings to the method then it can do its work without knowing what a ConfigurationManager is - you can use it in an app that doesn't even have a ConfigurationManager anywhere, maybe because it gets its config from a database or perhaps it's part of a unit test that gets some contrived data directly from hard coding to ensure a given result is always obtained
When you're down with the concept that the data a class needs to do its work can come from above it starts to make more sense why systems that pass data around like this can work with an inversion-of-control container; essentially software that creates instances of objects for you according to some preconfigured rules about where to get the data that should be passed in. An IoC container can look at an object and decide what arguments to pass to (e.g. its constructor) based on a consistent set of rules, and take another step towards removing dependencies by further reducing use of the word "new". Think of it like writing a config file to describe which of your objects need what instances of other classes to do the work. You craft your IoC container setup so it makes one IniFileConfigSettingsProvider instance and then provides that instance to any object that needs some kind of IConfigSettingsProvider to do its work. Later you switch away form ini files and go to Xml files. You create a class called XmlFileConfigSettingProvider, register it with the IoC and it becomes the new instance that is passed to any class needing an IConfigSettingsProvider. Critically, you made another class, registered it with the IoC and then it gets used throughout your program but you never made an instance of it yourself
If you ever heard the phrase "new is glue" concepts like this are generally what it alludes to - when your OtherClass says var x = new ConfigurationManager... x.Settings["a"].... the use of the word new has suddenly hard wired it to needing a ConfigurationManager; it can't function without knowing what it is. The strive these days is generally to have a class accepting a "passed-in provider of settings that complies with some interface" or "passed-in primitives that are settings" - things that are either implementation specific but obey a generic interface, or ubiquitous in the language and need no special imports respectively. Perhaps either of your mentioned approaches bug you because deep down you feel that neither of them need to depend on ConfigManager; whether they both need settings or not, they can get them passed in, from something higher up the chain that should be making the decisions as to what settings to use
There will be pros and cons of every design and coding choice. As they say, same pattern may not fit everyone. So one has to customize based on need.
Mainly, decision should be based on use cases of your application. Let me provide few scenarios to describe it. Suppose items configured in AppSettings will not change in life-time of the your application then you can have an approach in which dependencies with AppSettings are least. In particular an approach as var foo = otherClass.SomeMethod(_property1, _property2, _property3);. This matches with OOD principles as classes will focus on business logic.
But if you see add/modifying/deleting items (even in rare situations) during life time then above approach would be difficult to maintain. For example without restarting your application/WebServer if AppSettings needs to be reloaded based on certain conditions. One may argue why such settings will be kept in AppSettings, which is very valid too. If your application demands such scenarios then it would be better to use ConfigurationManager.AppSettings without worrying about dependencies. One can opt to extend it have wrapper class (Singleton pattern) to manage and provide access to ConfigurationManager.AppSettings.
Related
I have an IoC question that for the moment is abstract. I have not yet chosen an IoC framework for started coding. I am still mentally planning the methods I am going to use for an imminent project.
My coding style generally follows this pattern:
A Processor of some kind is instantiated and passed a Business Object.
The processor in turn will instantiate a Validator to validate that the passed business object is valid for the given process.
If the Business Object is found to be valid, then a Persistence Object will be instantiated. The Persistence object is responsible for transformations such as encryption, caching, and grouping multiple requests together in a single transaction for object graphs.
Then, the business object instantiates a DataLayer that will have the job of persisting the Business Object to the database, or pulling it from the database as the case may be (or a text file, or a webservice, whereever the data may live.)
My ideal structure is that a Processor knows about a Validator and a Peristence object, but not an AccessLayer. A persistence object knows about an access layer, but cannot directly instantiate or invoke a process. This way there are clearly defined layers that can be seperated as necessary
Finally, this process is agnostic to input or output and immutable based on the application type. In other words, I could use the same Processor to add a business object in a web app as I would in a desktop app. Obviously, the Model/View/Controller would change depending on the app type, but the rules for adding or selecting a business object remain universal.
My problem is this. I don't like that my AccessLayer in turn needs to pull the connection string from the config file, for instance. Maybe I want my users to be able to specify a config file or a Db Table for settings. Having the access layer check the config file to see if it should use the config file is circular and silly. And the Access Layer cannot likewise call a Persistence object to pull the settings, or query the Application Framework to see if it is a web app with a Web.Config or a desktop app with DbSettings.
So I was thinking that the best thing for me to do is to use an IoC container of some kind. I could then inject whatever settings I needed. This could also allow me to mock objects for testing, which is another difficult (but not impossible) task with my current method. So from my reading, my vague Processor implementation would look like this:
public class VagueProcessor{
public VagueProcessor(IValidator validator,
IPersistence persistence,
IAccessLayer accessLayer,
ISettings settings) { ... }
}
Here is my snag. In the application I am planning, the Business Object have a variety of implementations each with their own configurable rules. Say one BO is for the state of CA and another for the state of NY, and both states have their own special rules to be validated by their governing bodies. So the validator could be a CAValidator or a NYValidator just depending on the state of the Business Object.
Ok, so my question after all that preamble and backstory is this: in this scenario, would I pass a ValidatorFactory to the Processor and the Factory would instantiate the appropriate type of Validator based on the state of the Business Object? And if so, would I register each type with the IoC container, or just the Factory?
Thanks for your thoughts on this matter!!
That's a vague question as you don't have a problem yet, only the idea.
From what I understand from your question, I'd say:
The IOC solves the problem of creating the new object, not exactly deciding which object to create. In most IOC containers you can at some level choose the implementation you're asking, but in your case the logic looks very application centric, and no IOC container will help you deciding which one to use. In that case, you should indeed have a factory passed to your processor where you can ask something like factory.CreateValidatorFrom(myBusinessObject).
Internally, that factory can still use DI to instantiate each component. If you use .NET Core DI for example, you can pass a IServiceProvider to the factory, and call inside the factory serviceProvider.GetService<CAValidator>(). All DI providers will have an object like that.
So, in a sense, the factory and the DI can co-exist and each of them solve part of the problem. If you're using DI, you shouldn't ever have to instantiate the actual class. That will make it easier for each validator to have their own dependencies and you don't have to care how to get them.
And yes, in that case you'd register each validator in the DI, and also the factory. In cases like this, you can easily loop through all of them through reflection and register them dynamically by name or interface, if that is bothering you.
And in the end, if you're using .NET Core, I strongly suggest you to simply use the built-in DI. It's simple and good enough for most cases.
Validation is a crosscutting concern, so typically the validation service doesn't know about the details of the object it is validating. It only knows about its boolean valid state and how to get validation errors that are typically displayed on the UI.
As a crosscutting concern, the validation rules are abstracted from the services that read them. This is usually done via an interface and/or .NET attributes.
public class ValidateMe : IValidatableObject
{
[Required]
public bool Enable { get; set; }
[Range(1, 5)]
public int Prop1 { get; set; }
[Range(1, 5)]
public int Prop2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!this.Enable)
{
/* Return valid result here.
* I don't care if Prop1 and Prop2 are out of range
* if the whole object is not "enabled"
*/
}
else
{
/* Check if Prop1 and Prop2 meet their range requirements here
* and return accordingly.
*/
}
}
}
The validation service then only needs to have a mechanism to process the rules (returning a true/false for each rule) in order to ensure all of them are valid, and a way to retrieve the errors for display.
The validation service can do all of this by simply passing the model (the runtime state) to the service.
if (validationService.IsValid(model));
{
// persist
}
This can also be done using a proxy pattern to ensure that it always happens if the interface and/or attributes are available to process.
NOTE: The term Business Object implies that you want to build some sort of Smart Object Framework using objects that know how to save and retrieve their own state (internally implementing CRUD). This sort of design doesn't lend itself to DI very well. That isn't to say you can't use DI and a Smart Object design at the same time, it is just more difficult to build, more difficult to test, and then more difficult to maintain.
A design that uses models to abstract the runtime state of the application away from the services that use the models makes for an easier path. A design that I have found works pretty well for some applications is Command Query Segregation, which turns every update or request for data into its own object. It works well with a proxy or a decorator pattern to implement crosscutting concerns. It sounds strange if you are used to working with smart objects, but a loosely coupled design like this is simpler to test which makes it just as reliable, and since query and command classes are used like
var productDetails = this.queryProcessor.Execute(new GetProductDetailsQuery
{
ProductId = id
});
Or
// This command executes a long and complicated workflow,
// but this is all that is done inside of the action method
var command = new AddToCartCommand
{
ProductId = model.Id,
Quantity = model.Qty,
Selections = model.Selections,
ShoppingCartId = this.anonymousIdAccessor.AnonymousID
};
this.addToCartHandler.Handle(command);
it is almost as easy to use. You can even easily break out different steps of a complicated workflow into their own commands so it can be tested and verified at each step of the way, which is something that is difficult to do on a smart object design.
I have a class A that depends on 10 other classes. According to Dependency Injection pattern, i should pass all dependencies of A by its constructor.
So lets assume this constructor (of course this is not a working or real code, since I am not allowed to post the real code here)
public ClassA(ClassB b, ClassC c, ClassD d, ClassE e, ClassF f, ClassG g, ClassH h, ClassI i) {
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
this.g = g;
this.h = h;
this.i = i;
}
I have read on Martin Fowler's book about refactoring that having a method with a lot of parameters is a code smell and should not happen.
My question is: is this OK when we are talking about DI? Is there a better way of inject dependencies without breaking Martin Fowler's rules?
I know I could pass the dependencies through properties, but that may cause errors since no one is really sure what should be pass in order that the class works.
EDIT
Thanks for all your answers. I will try now to demonstrate some of class A dependencies:
1 - A class to access a DB
2 - Another class to access another DB (yes, i need to perform operations on two databases)
3 - A class to send error notifications by email
4 - A class to load configurations
5 - A class that will act as timer for some operations (maybe this one can be avoided)
6 - A class with business logic
There any many others that i am trying to get rid of, but those are really necessary and I dont see any ways of avoiding them.
EDIT
After some refactoring now i have 7 dependencies (down from 10). But I have 4 DAO objects:
CustomerDAO
ProcessDAO
ProductsDAO
CatalogDAO
Is it correct do create another class called MyProjectDAO and inject those DAOS onto it? This way I will have only one DAO class that aggregates all DAO objects of my project. I dont think this is a good idea because it violates the Single Responsibility Principle. Am I right?
In my experience:
Try to design your class so it needs fewer dependencies. If it needs that many, it may have too many responsibilities.
If you're really convinced that your class design is appropriate, consider whether it may make sense for some of those dependencies to be joined together (e.g. via an adapter which takes responsibility for one "big" operation your class needs by delegating to a few of the dependencies). You can then depend on the adapter instead of the "smaller" dependencies.
If every other bit really makes sense, just swallow the smell of having a lot of parameters. It happens sometimes.
Can you justify (to yourself) why the class depends on 10 other classes? Are there member variables you use to tie together a subset of those classes? If so, that indicates that this class should be broken up so that the extracted class would depend on the subset and the variables that tie such state together goes in the extracted class. With 10 dependencies, it's possible that this class has simply grown too large and needs to have its internals broken up anyway.
A note regarding your final sentence: such order dependency can also be a code smell, so it's probably good not to expose it in your interface. In fact, consider whether or not the order requirements are because operations need to be carried out in a specific order (it is the complexity of the algorithm or protocol), or because you've designed your classes to be inter-dependent. If the complexity is due to your design, refactor to eliminate the ordered dependency where possible.
If you cannot refactor (the complexities are all essential and you just have a terrible coordination problem on your hands), then you can abstract the ugliness and keep users of this class shielded (builder, factory, injector, etc).
Edit: Now that I have thought about it, I am not convinced that essential complexities of your algorithm or protocol cannot be abstracted a bit (though that might be the case). Depending on your specific problem, similarities in the manipulations of those dependent classes might either be better solved with the Strategy pattern or the Observer pattern (event listeners). You might have to wrap these classes in classes that adapt them to slightly different interfaces than what they currently expose. You'd have to evaluate the tradeoff of having the code in this monster class become more readable (yay) at the expense of up to 10 more classes in your project (boo).
I'd also like to make an addendum to abstracting the construction of this class. It seems important that any class that depends on this class also use the Dependency Injection pattern. That way, if you do use a builder, factory, injector, etc. you don't accidentally rob yourself of some of the benefits of using the DI pattern (the most important in my mind is the ability to substitute mock objects for testing).
Edit 2 (based on your edit):
My first thought is "what, no logging dependency?" :)
Even knowing what the dependencies are, it's difficult to offer useful advice.
First: what are the responsibilities of everyone? Why does this class depend on controller code (the business logic) and on Model code (two different database access classes, with DAO classes)?
Depending both on DAOs and DB access classes is a code smell. What is the purpose of a DAO? What is the purpose of the DB classes? Are you trying to operate at multiple levels of abstraction?
One of the principles of OO is that data and behavior get bundled into little things called classes. Have you violated this when you created this business logic class distinct from the objects it manipulates distinct from the DAO distinct from this class? Related: Take a brief diversion into SOLID.
Second: A class to load configurations. Smells bad. Dependency Injection helps you identify dependencies and swap them out. Your monster class that depends on certain parameters. These parameters are grouped into this configuration class because...? What is the name of this configuration class? Is it DBparameters? if so, it belongs to the DB object(s), not to this class. Is it generic like Configurations? If so, you've got a mini dependency injector right there (granted, it is probably only injecting string or int values instead of composite data like classes, but why?). Awkward.
Third: The most important lesson I learned from Refactoring was that my code sucked. Not only did my code suck, but there was no single transformation to make it stop sucking. The best I could hope for was to make it suck less. Once I did that, I could make it suck less again. And again. Some design patterns are bad, but they exist to allow your sucky code to transition to less sucky code. So you take your globals and make them singletons. Then you eliminate your singletons. Don't get discouraged because you've just refactored to find that your code still sucks. It sucks less. So, your Configuration loading object may smell, but you might decide that it isn't the smelliest part of your code. In fact, you may find that the effort to "fix" it isn't worth it.
Yes - a method taking this many parameters should be considered a code smell. Is this method truly only doing one thing and one thing only?
If this is still true you can still lower the number of dependencies by looking at the relationships between the dependencies - are any of them closely related, could they be coupled into aggregate dependencies? E.g. you could refactor by creating a new class K that uses A, B and C internally (injected into class K by constructor, then using composition) - so the number of parameters to the method would be reduced by two.
Rinse and repeat until aggregating doesn't make sense anymore and/or you have a reasonable number of parameters.
Also see a related blog post: "Refactoring to Aggregate Services"
I'd also advise to redesign your application. In case it is not possible you can pass your IoC container as a constructor parameter. If you do not want to couple your code with a concrete implementation you can always abstract it. The code will look something like this.
public interface IAbstractContainer
{
T Resolve<T>();
}
public class ConcreteContainer: IAbstractContainer
{
private IContainer _container; // E.g. Autofac container
public ConcreteContainer(IContainer container)
{
_container = container;
{
public T Resolve<T>()
{
return _container.Resolve<T>();
}
}
public classA(IAbstractContainer container)
{
this.B = container.Resolve<ClassB>();
this.C = container.Resolve<ClassC>();
...
}
}
A ConcreteContainer instance is injected the usual way.
I am developing a kind a translator from language A to B (yeah, it kinda is like a compiler). A translation is generally from several different files and each one of them has the same 3 sections to translate. So, the way I did it, I kind of have it the following way:
When I instantiate a translator and give it some data, it will need to generate all the needed FileTranslator classes. As I shouldn't do the new in Translator, I should ask for a factory from above. The same happens in the Sections translators. This poses the problem that I'm forced to create a lot of boilerplate factories. Moreover, each one of the translators might need even more factories to generate some other classes they might want to use.
Am I thinking this the wrong way or is it just the way it is? I am not allowed to use any kind of DI/IoC framework in this project, btw.
Edit:
I'm afraid I am not getting my message get sent across.
In this specific case, as my Translator class needs to be able to generate at any moment some FileTranslator, it would need a FileTranslatorFactory. I know I can have an IoC Container do the wiring for me, but the IoC Container in itself will not save me for the problem of having to code up the code of the FileTranslatorFactory itself. Am I right?
Now, the problem is that a FileTranslator will also have to be able to generate whenever it needs SectionATranslators, SectionBTranslators and SectionCTranslators (and do not think they are any similar because their names are -- they are totally different and have nothing to do with each other!). So I'd have to define factories for each one of them. So for such a simple 5 classes system, I'd need to create 4 (!!!) factories.
Being that I don't want my domain objects to depend on an IoC-Container and that I don't want to have a single factory for all the 4 kinds of objects that seem to need one, am I still missing something?
The fact that there is a lot of boilerplate code involved in handcranking DI for class hierarchies like this is WHY the frameworks exist. Sorry, but unless you can get whoever decided on the no DI/IoC frameworks rule to change their mind, you are either going to be writing lots of boilerplate code, or you will end up writing a framework yourself.
EDIT - with a completely fictitious framework, to keep this as agnostic as possible, but explaining how you can eliminate all but one call into the container in many scenarios.
So, with an implementation of Translator like:
public class Translator
{
private ITranslator translatorInstance;
public Translator()
{
SomeContainer container = SomeContainer.CreateFromConfig(configFilePath);
// this is the ONLY point we touch the container
translatorInstance = container.GetMeA<ITranslator>();
}
// implementation
}
We can see that this works as a factory, and is the only class that needs to know about the container itself. An implementation of one concrete implementor of ITranslator could therefore be:
public class FileTranslator : ITranslator
{
// private fields
public FileTranslator( ISectionATranslator sectionAtrans,
ISectionBTranslator sectionBtrans,
ISectionCTranslator sectionCtrans)
{
this.sectionAtrans = sectionAtrans;
// etc
}
// implementation
}
Note here that FileTranslator knows nothing about which concrete classes actually implement the interfaces it depends on, nor does it need any sort of factory. In fact, the container will do this for you. There are several ways containers work this stuff out, one example is explicit config, something like:
<!-- absolutely fictitious configuration file, but similar to many frameworks -->
<ContainerConfig>
<ObjectResolver interface="ITranslator">
<ConcreteType type="FileTranslator">
<ConstructorInjection>
<Argument ordinal="0" type="SectionATranslator" />
<Argument ordinal="1" type="SectionBTranslator" />
<Argument ordinal="2" type="SectionCTranslator" />
</ConstructorInjection>
</ConcreteType>
</ObjectResolver>
</ContainerConfig>
Many frameworks don't even need you to define the specific constructor arguments, you can just state that if you want a ISectionATranslator then return a SectionATranslator and it will automatically create these before calling the constructor.
Also note that some frameworks provide the option to define these type resolution rules in code, using fluent style APIs, and some allow you to define multiple potential ways of resolving a particular type, via some name (perhaps a "Production" implementation versus a "UnitTest" implementation).
Note that I have kept the above deliberately vague because I don't want to say which framework is best (and to be honest, I think it depends on your individual needs) - check elsewhere on StackOverflow for framework comparisons, and please try a few out (perhaps you can try some without telling your boss!). Hopefully, however, the above shows why an IoC container can make your code much cleaner by removing the need for layers upon layers of factory classes.
I'm working on a project that's using the MS Application Blocks. I see the 'Unity' dll is available to me. It's version 1.1 by the way. How can I use dependency injection here?
I have a class
public class ScheduleDataDetailsDC
{
public int ScheduleID;
public List<ScheduleRateLineItem> MinRateList;
public List<ScheduleRateLineItem> MaxRateList;
public List<ScheduleRateLineItem> VotRateList;
public List<ScheduleLOSRateDC> LosRateList;
public List<ScheduleRateParamsDC> RateParams;
}
So when I new it up I am doing this...
new ScheduleDataDetailsDC{
LosRateList = new List<ScheduleLOSRateDC>()
, MaxRateList = new List<ScheduleRateLineItemDC>()
, MinRateList = new List<ScheduleRateLineItemDC>()
, RateParams = new List<ScheduleRateParamsDC>()
, VotRateList = new List<ScheduleRateLineItemDC>()
}
Can Unity 1.1 Help me in anyway here? I would like to just be able to use var x = new ScheduleDetailsDC(), and those 5 inner lists be initialized for me. Can Unity do anything for me here? Please note I've never used DI before.
Thanks for any pointers,
~ck in San Diego
The best thing to do would be to initialise the lists in the constructor and deny direct access to them from other classes by making them into properties:
public class ScheduleDataDetailsDC
{
public ScheduleDataDetailsDC()
{
this.MinRateList = new List<ScheduleRateLineItem>();
//inialise other lists
}
public List<ScheduleRateLineItem> MinRateList { get; private set; }
...
}
It doesn't seem as though dependency injection can really be of use here since the class seems to be a simple data container, although it's difficult to tell without more context.
Yes Unity can help you, but I think it's not the case. You can just initialize your lists incide your object giving them default instances, Unity as any other IoC container shouldn't be used as a simple object builder (despite it could).
I'm not sure specifically what the details of the 1.1 release of Unity are, but generally speaking whenever you are using an Inversion of Control Container, you have to go through the following steps:
Register the types your IoC container (Unity in your case) knows about. This includes all of the main types that you plan to request, plus all of the dependent types. In your case you will need to let it know about ScheduleDataDetailsDC, and what, exactly needs to go into each of the lists that are considered dependencies
Your types should specify all of the required dependencies as constructor arguments. This is what the IoC Container will look at to determine what needs to be injected. If you have optional dependencies then you can use Property Injection to support that (if your IoC container supports it, which I think Unity does)
You must request an instance of your registered type from the container. How exactly you do this depends on you container. There should be a method like Get<T>() or Resolve<T>. Generally your going to request instances of the "Highest Level" classes, i.e the ones that are used somewhere near the entry point for your software. If you do this, and you have applied Dependency Injection for all dependent classes down the line (and you've correctly registered all of the dependent types) you should get an object with all of it's dependencies supplied, and likewise all of that objects dependencies should be supplied, and on down the line.
You also tend to see Interfaces used in conjunction with IoC a lot since you can bind a concrete type to the interface type, and then specify that interface as your dependency. This allows you to apply business rules and configuration values during the binding process that will give you the ability to use different concrete implementations in cases where you would need to do such a thing.
So given all of this, it's hard to say exactly what would be involved in utilizing Unity in the situation you've outlined above. Firstly you would need to register ScheduleDataDetailsDC, but to get the dependencies in place you would also need to register each of the List types, or more specifically each concrete object that would go in each list (and then, of course all of the dependencies for those classes). Since I'm not really sure what the roles of those lists are, it's hard for me to say how you could go about doing that (or even if you could go about doing that).
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?
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.
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;
}
}
We would constructor inject a class of type IMyAppConfig which is just a wrapper for all this kind of stuff.
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.
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.