Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing a (somewhat) complex object

When I create classes, simple constructors tend to be the norm. On one of my current projects, a movie library, I have a Movie domain object. It has a number of properties, resulting in a constructor as follows:

public Movie(string title, int year, Genre genre, int length, IEnumerable<string> actors)
{
    _title = title;
    _year = year;
    _genre = genre;
    _length = length;
    _actors = new List<string>(actors);
}

This isn't terrible, but it's not simple either. Would it be worthwhile to use a factory method (static Movie CreateMovie(...)), or a perhaps an object builder? Is there any typical pattern for instantiating domain classes?

UPDATE: thanks for the responses. I was probably overthinking the matter initially, though I've learned a few things that will be useful in more complex situations. My solution now is to have the title as the only required parameter, and the rest as named/optional parameters. This seems the all round ideal way to construct this domain object.

like image 805
Grant Palin Avatar asked Aug 24 '10 16:08

Grant Palin


People also ask

What is a complex object?

Complex objects are the objects that are built from smaller or a collection of objects. For example, a mobile phone is made up of various objects like a camera, battery, screen, sensors, etc. In this article, we will understand the use and implementation of a complex object.

What is a complex object in Oodbms?

Complex objects are built from simpler ones by applying constructors to them. The simplest objects are objects such as integers, characters, byte strings of any length, booleans and floats (one might add other atomic types).


1 Answers

I don't see anything wrong with your constructor's interface and don't see what a static method will get you. I will have the exact same parameters, right?

The parameters don't seem optional, so there isn't a way to provide an overload with fewer or use optional parameters.

From the point-of-view of the caller, it looks something like this:

 Movie m = new Movie("Inception", 2010, Genre.Drama, 150, actors);

The purpose of a factory is to provide you a customizable concrete instance of an interface, not just call the constructor for you. The idea is that the exact class is not hard-coded at the point of construction. Is this really better?

 Movie m = Movie.Create("Inception", 2010, Genre.Drama, 150, actors);

It seems pretty much the same to me. The only thing better is if Create() returned other concrete classes than Movie.

One thing to think about is how to improve this so that calling code is easy to understand. The most obvious problem to me is that it isn't obvious what the 150 means without looking at the code for Movie. There are a few ways to improve that if you wanted to:

  1. Use a type for movie length and construct that type inline new MovieLength(150)
  2. Use named parameters if you are using .NET 4.0
  3. (see @Heinzi's answer) use Object Initializers
  4. Use a fluent interface

With a fluent interface, your call would look like

 Movie m = new Movie("Inception").
   MadeIn(2010).
   InGenre(Genre.Drama).
   WithRuntimeLength(150).
   WithActors(actors);

Frankly, all of this seems like overkill for your case. Named parameters are reasonable if you are using .NET 4.0, because they aren't that much more code and would improve the code at the caller.

like image 157
Lou Franco Avatar answered Oct 03 '22 23:10

Lou Franco