views:

218

answers:

6

Lets say that one has a class like Person that has associated with it some default settings implemented in a Setting class. Those settings might be things like "Default Title" or "First Name Required". Correspondingly, other classes like an Address class might also have some default settings. The Setting class persists each setting into a persistent store.

Should one implement a static method in each class like "SetDefaults()" that contains these settings so that an external method can call SetDefaults() on each object type? e.g. Person.SetDefaults() and then Address.SetDefaults()?

Or is there some better object oriented way of doing this?

[Update: this can't be in the constructor because SetDefaults() should be called from an external class at a particular point in time, rather than each time the object is constructed.]

+1  A: 

Why not set these defaults when you create the object (in the constructor). A default is -imho- a value that should be assigned to a property when no specific value is given to that property, so, I think it is a good idea to set those default-values when the object is created (in the constructor, or via a factory).

Or, am i missing something ?

Frederik Gheysels
Because the SetDefaults() method needs to be called by an external class, rather than each time an object is constructed.
Alex
@JBadda - you mean to set what the values of these defaults are going to be? Not a reset for the instance? I guess a static (i.e. a meta-method) would make sense, but no more so - and less flexibly - than dependazncy injecting a config object, interfaced if required
annakata
A: 

You can also implement Abstract factory pattern and configure factories with your settings. Or you can alternatively use IoC for injecting dependency into this factory classes.

Simple Factory class for Preson can look following:

public class PersonFactory
{
  private readonly ISettings settings;

  public PersonFactory(ISettings settings)
  {
    this.settings = settings;
  }

  public Person Create()
  {
     Person p = new Person();
     // ... you code for populating person's attributes form settings.
     return p;
  }
}
Jakub Šturc
I'm unsure that either of these directly addresses the question.
Alex
A: 

I'd put them in the constructor.

class Person
{
  public Person()
  {
    this.Settings = MakeDefault();
  }

  public Person(Settings settings)
  {
    this.Settings = settings;
  }
}
AZ
Can't be in the constructor - please see the update to the topic.
Alex
Why a downvote?. When i posted this response the op did not specify that restriction. I can't keep track of all questions i answer and when they are edited to mean something else
AZ
+3  A: 

I can't think of many occasions where defaults are truly spanning... given all the different use-cases that an object may go through (not least, things like deserialization - which could end up setting the defaults even though that isn't what was intended).

One option here is IoC; IoC containers like StructureMap have the ability to set properties after initialization, and that is then abstracted from the calling code.

Another option might be some kind of template instance (static), that instances can copy values from. But I think this is risky in a few scenarios. You also get problems if different threads (perhaps requests on a web-server) need different defaults. [ThreadStatic] isn't a good option (although it is an option).

Another option (that provides the greatest flexibility) would be to provide a user-settable factory... perhaps via a delegate or event mechanism - but I struggle to see why you might want this scenario. It isn't one I've seen very often...


re update: if it is only used by the external class; could it perhaps use something like an extension method (rather than the Person class having to know anything about this):

public static class PersonExt {
    public static void SetDefaults(this Person person) {
       // your code
    }
}

Since it sounds like the original Person class doesn't care about SetDefaults, this divorces the logic from Person neatly.

Marc Gravell
I think the extension method idea is interesting. The only disadvantage is that unlike a static (class method), it is less discoverable.
Alex
Less discoverable than pressing . and seeing it in intellisense?
Marc Gravell
Why assume I am using a *tool* with intellisense?
Alex
I'll let Jon answer that... http://stackoverflow.com/questions/932956#932963
Marc Gravell
A: 

You could create a settings class that encapsulate settings for all classes (Person, Address).

You could set default settings for say Person:

// Injected
Settings settings;
Setting personSetting = new ...;

...
settings.StoreSettingsFor(typeof(Person), personSettings);
dfa
A: 

You could also use a singleton to store this data if you wished, especially if the values are retrieved from storage somewhere as this would cut down on the number of times that the storage is accessed.

(In this instance storage can be datafile, registry, database.)

ChrisBD