The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Which pattern? Settings from two sources

Hello

I'm relative new to patterns, but I'm thinking that this problem is so common that there must be a know good way to solve it.

I have an application that runs on two systems (web and WinForms). The app need some user settings. Depending on the build, the settings are either in a database or in a file.
So I need some way to handle the loading and saving of those settings. I want the settings class to look the same to the objects that uses it.

Should I use some kind of dependency injection of a base load/save settings class, and then make two implementations, one for the file and one for the db. Is that a good way? or is there a better method?

Thanks a lot :-)
Karsten Send private email
Friday, December 14, 2007
 
 
I think the general guidance of programming to an interface rather than an implementation applies here rather than a specific design pattern.

You don't say which programming language you're using, but if I were to program this in Java then I'd create an interface containing methods for loading and saving settings. Other classes that require the loading and saving of settings would only know about this interface.

There would also be various classes that implement this interface e.g. one for file-based settings, another for database storage etc. This allows new implementations to be plugged in as required. At this point you might want to use a creational design pattern to handle the instantiation of these objects.

http://en.wikipedia.org/wiki/Creational_pattern
John Topley Send private email
Friday, December 14, 2007
 
 
Yeah, I agree with John, sounds like a job for the Abstract Factory Pattern to me!

http://en.wikipedia.org/wiki/Abstract_factory_pattern
John Conners Send private email
Friday, December 14, 2007
 
 
Hi again

Sorry guys, but I left out an important detail. I'm going to divide the solution into 3 projects, common, web and winforms. The common part is not able to see the web and winforms projects, so I don't think I can use the factory pattern, since the factory must be located in the common project.

Also I know about interfaces and I agree that using an interface is a more clean way than an abstract class.
Karsten Send private email
Saturday, December 15, 2007
 
 
"The common part is not able to see the web and winforms projects"

I'm not sure what "see" means to you here. Surely the web or winform (perhaps mutually exclusive) will be available at runtime? With Java we often get a fully qualified classname from configuration and use Class.forName(name).newInstance(). You can load classes in the runtime classpath even if they're not available at design or build time.

Does that work?
Stan James Send private email
Saturday, December 15, 2007
 
 
I think what the OP means is that his Web and WinForms projects reference the third assembly - containing the logic - and thus the third assembly cannot reference the Web or WinForms assemblies as this would create a circular reference. So there's no way for code in his third assembly to be able to call methods on types in his Web or WinForms assemblies; it has to be other way around.

If the goal is to have the Web or WinForms apps supply the settings-reading logic themselves, but otherwise not have the code dependent on knowledge of which method is being used and to use an interface contract, then this sounds like an ideal case for IoC and dependency injection. It's a simple way to create a plugin-based architecture that feels reasonably natural to work with.

You could do this fairly simply on your own using reflection; or use a container that is designed to work that way, like Castle Windsor (http://www.castleproject.org) or the Castle MicroKernel (since you're unlikely to need all the services Windsor provides).
.NET Guy Send private email
Sunday, December 16, 2007
 
 
Hi guys, thank you both for your replies!

.NET Guy you got me right. I'm going to have a look at the Castle project.
But I'm thinking that without using the castle project, it would be possible to declare a SettingsStorage (with load and save settings methods) interface in common assembly, which would be implemented in the web and winforms assemblies as needed.
The SettingsStorage object would then be injected into the Settings object in the common assembly. But how? should I use an assembler object to prepare the common settings object?
Karsten Send private email
Sunday, December 16, 2007
 
 
Well, typically DI tends to happen either at constructor or method level; you could make it part of your settings initialisation process to require a valid implementation of your ISettingsReader at construction time. Just make the constructor for Settings look something like:

public Settings(ISettingsReader reader) {}

and then you know that whenever you call Settings.GetSomeSetting() you have the correct settings reader instance already there.(That's less useful if you're using a static class or some kind of factory, of course - in which case, adapt accordingly and shift the DI to the factory method etc.) In this case, the mere fact that you're being called from either the Web or WinForms app is enough to know which is the right type of reader, and supply it. If you were having the user specify a reader type, or be able to supply their own, it would get more complicated.

There's several approaches to this - Google dependency injection to get various opinions on this topic. Suffice it to say that I don't think Martin Fowler really gets it, but the Castle guys definitely do.

(Inversion of Control is a slightly different - but related - topic. Basically, we've been unwittingly doing IoC since the early days of event-driven programming, since the flow of control is dictated by events, not the other way around. For the purposes of this discussion, we'll stick to the concept of DI, which is a type of IoC, but hardly defines it as an idea.)

The container-based approach (Castle MicroKernel / Windsor, Pico, Spring or Spring.NET) is excellent from the POV of making it damn easy to use (in Castle, almost everything you need is defined in config files) but is comparatively complex in terms of implementation. Not that different from most Java containers in that respect, though :-) Basically, the container takes care of, um, containing your objects, as well as selecting which ones to use and instantiating them and injecting *their* dependencies. So in theory all you have to do is tweak the right config files, say Container.GiveMe("SettingsReader") and hey presto, you get exactly what you need for the context you're in.

The reality is much, much more complex, of course, and heavy-duty container work - while extrememly productive in the course of serious enterprisey architecture astronautics - is usually contra-indicated when you're doing something small and light. In which case DI via the constructor will probably do.
.NET Guy Send private email
Sunday, December 16, 2007
 
 
Thanks a lot for your answer, it surely gave me a better understanding :-)
Karsten Send private email
Monday, December 17, 2007
 
 
we had the same problems when running our unit test and web site,  which was how to get the security & app settings.

So, we created an interface and a singleton in our common class.  The singleton returns an instance of an IConfig.  By default, the returned Iconfig looks at the tests.config file and the current user.  The web project has a "RunningInWebContextConfig : IConfig" class, which looks at the Web.Config & HttpContext.Current.User for the settings and security info.  The Application_Start event in the Global.asax sets the singleton's IConfig to the RunningInWebContextConfig.
Another Anonymous Coward
Tuesday, December 18, 2007
 
 
Hi,

Here's what I think would be a good solution-

The commons project should define the SettingsManager interface and a SettingsManagerFactory that has a getSettingsManager method that returns an instance of the SettingsManager implementation by reading the name of the concrete class from a resource bundle. Write one implementation called DatabaseSettingsManager in one of the dependent projects and FileBasedSettingsManager in the other. In both the projects, create the resource bundle file with the name of the respective implementation in it.
Shivkumar CM Send private email
Sunday, December 30, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz