简体   繁体   中英

C# Best practices in object initialization

I have an Order object and the Order object contains a Person object which stores the information about the person who placed the order. When I populate the Order object am I supposed to populate the Person object as well? Or would I be better off calling order.GetPerson() whenever I need to access to the person who placed the order.

You may consider the LazyLoading approach. So that the Person data will be fetched and loaded when it is required (queried for the first time)

Lazy loading is a design pattern commonly used in computer programming to defer initialization of an object until the point at which it is needed

If resources are an issue then Shyju's answer makes sense. Otherwise, if you always know the person that's associated with the Order then, yes, populate it. Also, it's a good idea to make objects immutable as often as possible, and you probably can in this case; ie pass the person in through the constructor and never change it.

Is an Order object valid if the Person property is not set?

If order.Person must be set to a Person object so that order is in a valid state, then it's very likely that you want the Order constructor to accept a Person object. This is because constructors should always construct valid objects, not just partially-valid ones.

public class Order
{
    public Order(Person person)
    {
        this.person = person;      
    }

    public Person Person { get { return person; } }
    readonly Person person;
}

If, on the other hand, order.Person does not have to be initialized in order for Order to be considered valid, then your constructor doesn't require a Person parameter. Instead, you could make Person a read-writable property:

public class Order
{
    public Order() { … }
    public Person Person { get; set; }
}

If you do this, answer the following question:

Does it make sense that the Person property can be set several times, to different Person instances?

If yes, then all is fine with the approach shown just above.

However, I would answer with "no": An order can only be placed by one single Person , and this cannot change later on. You could consider making the property be settable once only, where subsequent attempts at setting it would trigger an exception:

    public Person Person
    {
        get { return person; }
        set
        {
            if (person != null) throw new InvalidOperationException;
            person = value; 
        }
    }
    Person person;

... however this might not be very intuitive. A better approach might be to set the Person property from the constructor and make the property read-only (as shown above). This might seem too restrictive, but will likely be more intuitive to all users of your Order object.

As the comment by Chris Sinclair indicates, it does come down to your design and considering how frequently you'll need the Person objects. If nearly every time you load Orders, you want the associated Persons as well (for display, or calculations, etc.) then it makes sense to always load the Persons to limit the number of database calls. If you hardly ever need the Person data, then it makes more sense to get the Person data in a late-bound/lazy-loading manner.

Consider this example. You retrieve all orders to display them in a grid. But when you populate the grid, you also want to display the Person info per order. If you load the Person data with each Order, you just loop the Orders and you have no more database calls. If you use lazy-loading of the Person data instead, then as you loop the orders you have to make an additional database call per Order to get the Person data. That's a lot of calls.

If appropriate, you could also split the difference and design load methods to which you can pass a flag of "LoadChildren." Doing so gives you the ultimate flexibility, but maintainability/readability is sacrificed because depending on where you are in code, you won't necessarily know if the Person data is populated or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM