I have a very common situation here. And for years I haven\'t found if what i am doing is RIGHT by industry standards.Consider an application which connects to the database,
Sure there is a way. First off, get up to speed on dependency injection and similar techniques, and read about service layer since that's what you need here.
As far as a service layer is concerned, you need some kind of Configuration Service, which will be the module that parts of your application will query for configuration information - connection strings, URIs, etc:
interface IConfigurationService
string ConnectionString
bool IntegratedSecurity
bool EncryptProfiles
It should be pretty straightforward that there is only one instance of IConfigurationService
in your system, but this is achieved with a DI container of choice, not with Singleton pattern.
Next, all your DAL services will get a reference to the IConfigurationService
:
class FooDal : IFooDal
IConfigurationService ConfigurationService
so that they can now use IConfigurationService.ConnectionString
to get hold of the connection string.
In general global state, be it a global class or a singleton, should be avoided wherever possible.
The ideal solution would be to have your application load up the connection string out of config and inject it into any classes that need it. Depending on the size of your application, an IoC container like Unity or Castle Windsor can help, but certainly isn't a required part of the solution.
If that isn't an option and you're stuck maintaining global state (because of the existing codebase or whatever), I don't know that there's a huge difference between the two approaches you've suggested.
Update: Just to clarify, forget all the stuff about IoC containers for now, "Inject" is just a fancy way of saying "pass in as a parameter" (either to the class's constructor, or via a property, or whatever).
Rather than having a data access class have to ask for the connection string (from some sort of global or a singleton), have it passed in via the constructor or a property.
Update #2: I think there's still some misunderstanding as to what this approach entails.
It basically comes down to whether your data access class looks like:
public class DataAccessClass
{
public DataAccessClass()
{
_connString = SomeStaticThing.GetConnectionString();
}
}
or
public class DataAccessClass
{
public DataAccessClass(string connString)
{
_connString = connString;
}
}
These articles (and in fact, many of the articles in that blog) detail a number of reasons why the latter is better than the former (not least because the former is almost impossible to unit test).
Yes, at some place there is going to have to be some static guy responsible for grabbing the connection string in the first place, but the point is that your dependencies on static methods are limited to that one spot (which is likely going to be your Main method in the process of bootstrapping your application), rather than sprinkled throughout your whole codebase.
It depends.
Keep in mind that a singleton:
A global only provides global access, but makes no guarantees about the number of instantiations.
And the final option, of course, is to use a local variable. That is, pass the config info around as a a parameter to the constructor or wherever it's needed.
Choosing between the first two should be somewhat easy. Is it a disaster if two instances of the class exist? I'd say probably not. I may want to instantiate my own config class to supply separate options to one specific component of the app, or to initialize my unit tests.
There are very few cases where you need to guarantee that exactly one instance will exist. For this reason, a global may be a better choice than a singleton.
The choice between local and global is trickier. Global mutable state is generally best avoided. Immutable state is less of a problem, and won't lead to the same synchronization/concurrency/scalability problems that global mutable state will.
But often, it may be preferable to have it as a local variable you pass around to the components that need it. This can be done manually, simply passing it to the constructor of an object that needs DB access, or it can to some extent be automated with an IoC container.
But in any case, if it is not global, then your code becomes more generic, and more portable. If it has hidden dependencies on classes and global data that must exist for the code to work, then it can't easily be used in other projects, or if you refactor the entire codebase too much.
It also becomes harder to unit test, again because the code won't even compile unless some external data exists that we'd ideally like to leave out of our test.
as @Anton said, you need to have an interface that exposes something like
interface IConfigurationService
string ConnectionString
Then whenever one of your class needs your connection string, you provide it with an implementation of IConfigurationService upon construction containing the valid string. You need to find a valid place to create your implementation when you app starts (probably the time where you'll get your database adress), and to pass it along to the class needing it.
Even though it might seems a lot of work compared to singleton or global, this will lower coupling in your code hence improving reusability and make unit testing easier, and is pretty straightforward once you convince yourself that globals are (mostly) evil :)
As mentionned before, there are IoC container that will provide the framework to do that, but it might be overkill in your case, plus its nice to use the pattern for yourself before letting the work to a "magic box"
it's nice to see so many creative solutions to such a simple problem ;-)
salient facts, from OP question:
so, there is no way around the use of a static element; whether it's a global variable (hard to do in .NET, really, without an enclosing class), a static class, or a singleton really doesn't matter. The shortest-path solution would be a static class initialized by the Program class that processed the command-line.
Every other solution would still require static access to the passed-in connect-string, though they may hide this behind one or more layers of indirection.
I'm not saying that you don't want to dress up the basic solution with something fancier, but it is not necessary, and it does not eliminate the fundamentally static/global nature of the connect-string as described.
If all you're storing is a string (possibly along with a bunch of other global application settings), I would just use a static class with a bunch of properties to hold all that. A singleton is more code & maintenance work, but it's unnecessary work in this case, since your properties class isn't going to DO anything; just hold things.