How to create an object with lots of properties?

Hi.

To illustrate the question I will give you spherical example in vacuum.

There is a class whose purpose is to record product data to the file. The method write() takes as parameter an object of class Product and I am sure that the object has the desired properties.

Class ProductWriter
{
 public function write(Product $product)
{
 // write to file
}
}


Product has many properties (20): name, description, price, size, color, shape, etc., etc., And some properties are mandatory, part optional.

How to write a Product class?

My options:

1) the Constructor of the Product class takes an associative array of parameters. Designer checks for required fields. I think this method is not the best: the client code does not know which keys must be present in the input array.

2) Create a bunch of properties and getters/setters for them:
Class Product
{
 private $name;
 private $price;
 // ...

 public function setName() {}
 public function setPrice() {}
 // ...

 public function getName() {}
 public function getPrice() {}
 // ...
}


But again - where the client code to know that after creating the object, you have to call some setters?

$product = new Product();
$product->setName('name');
$product->setPrice('0.0');


3) Well and the trash - a constructor with 20 parameters:
Class Product
{
 function __construct($name, $price, $color, $size, ....)
{

}
}


So, of course, clientkey code accurately specify all the required fields. But don't do that, it is written in books))

If we talk about options # 1 and # 2: actually this class no one except myself would not use. And I know exactly what you need to fill in about the product. But I would like to solve the problem "beautiful".

PS. I expect comments like: why one common class of product? Create subclasses with only the desired properties and you will have happiness.
Is the answer that my example with the product of the conditional. In my case, the really essence with a bunch of properties, from which nothing can inherit and divide into more simple entities.
June 3rd 19 at 19:32
6 answers
June 3rd 19 at 19:34
Solution
Mandatory parameters should be set in the class constructor - this will ensure their obligatory instructions, optionally using getters and setters. In addition should reconsider whether all mandatory fields are required - or some did not + possible options should you pack in the objects-values
All fields are really mandatory. We are talking about the certificate: serial number, name, Inn, snils, etc a bunch of fields, from which no escape. It turns out the constructor with lots of parameters? - Kamron12 commented on June 3rd 19 at 19:37
it's difficult to say something without knowing the full list of fields, probably some of them can be put in value objects - bryana.Renn commented on June 3rd 19 at 19:40
at the INN certificate , no social security number and full name - only a man. Can be divided into classes. Information about the person and so on. - Roderick_Quitzon56 commented on June 3rd 19 at 19:43
OK , I put it incorrect. These fields belong to the owner of the certificate (subject field).

But the owner of the certificate is:
1) Surname
2) first name middle Name
3) Common name
3) Street
4) Location
5) Country
6) Email
7) INN
8) social security number
9) bin

that too much for constructor parameters - Kamron12 commented on June 3rd 19 at 19:46
I then see another entity address. I don't know what is the common name - Roderick_Quitzon56 commented on June 3rd 19 at 19:49
well from what I see here, you need at least 3 values:
Owner, the Certificate and Address. - bryana.Renn commented on June 3rd 19 at 19:52
Maxim refers to the objects DTO - Data Transfer Object - Otto_Baumba commented on June 3rd 19 at 19:55
DTO, it's a different thing ...I mean it is VO - Value Object - bryana.Renn commented on June 3rd 19 at 19:58
, then it is an Entity, a Value Object does not have an integral identity, which in practice means that value objects do not have fields-ID, in the question it is about the Product object, after all. Another property/characteristic VO - interchangeability, i.e., a simple replacement of the existing object with a different instance nothing should break, as it applies to the properties of different products? - Otto_Baumba commented on June 3rd 19 at 20:01
maybe I'm wrong and misunderstood differences, would be glad of your clarification - Otto_Baumba commented on June 3rd 19 at 20:04
here's what I found, if you follow this rule then I agree with you: a value Object must always belong to one or more entities, it cannot live their own lives. And the lifetime values must depend on the time of life of their parent entities. - Otto_Baumba commented on June 3rd 19 at 20:07
June 3rd 19 at 19:36
Make an associative array. Missing properties to add default values or vomiting exception when missing the required property.
The worst thing you can do in this case is to accept an associative array of parameters. - Kamron12 commented on June 3rd 19 at 19:39
, "...because ... " – you probably previously sent message, did not finish. - bryana.Renn commented on June 3rd 19 at 19:42
Because this heinous practice. To interact with these classes uncomfortable. Static analysis tools are not able to tell what exactly array must be passed. That is, the programmer of the client code is forced to go and watch the design implementation. And if you want type checking to that the horror of the tie, you have to fence your own validation, which will forget and work slower than typehinting at the language level.

Pay attention to the answer , here's how to do it right. - Roderick_Quitzon56 commented on June 3rd 19 at 19:45
this is a good solution. if the designer many parameters is an indication that the class will change the field. be added to clean it up. to make the class more secure is to make these fields for the class. For example, to leave only the required fields. For creating objects use factories and builders. This will protect from errors during the creation.
Sometimes should abandon static checking.
And almost always premature optimization. - Kamron12 commented on June 3rd 19 at 19:48
By the way, this decision is straight from the books)) Textbook.
Object - oriented analysis and design. McLaughlin.
)
but there is more not about the designer.) - Roderick_Quitzon56 commented on June 3rd 19 at 19:51
June 3rd 19 at 19:38
To see if the relationship between the properties. Perhaps there is a group of related properties that can be distinguished in separate classes.

Required properties - the constructor parameters, and other properties.

See also create patterns, e.g. factory method and Builder.
June 3rd 19 at 19:40
You can use a set of getters-setters if you don't want to cut a great designer, but the object creation be delegated to the Builder (if the data for example request or third-party API), or the factory. But then the product itself should hide behind the interface so that client code could not create a product with empty properties. You can not even keep the class of products, and return the instance of the anonymous class implementera ProductInterface
June 3rd 19 at 19:42
Wrap half of this kind of Value Object-s and everything will be fine - the easiest, proven method.
June 3rd 19 at 19:44
I'd rather split the task into 2 parts: object creation and its use.
Object creation:
- In addition to the mandatory may be conditionally required (this is the case when the assignment of one parameter makes mandatory some number of parameters) and optional.
- When all parameters are mandatory, then write the constructor.
- Initialize conditionally mandatory parameters may make sense to wrap a helper class that can be made available only in the context of the main class, and in its implementation to enable validation of the parameters passed.
- Build classes conditionally required and optional parameters, in addition to direct parsing of parameters, can be implemented using factories, which will contain a fewer number of parameters, and set is omitted in the correct default values.
Instead of factories, you can hide your class behind the facade with a more simple interface.
- Also, you can create several methods of construction of the object, a constructor is implemented in a controller, which will call the correct, depending on the parameters passed.
Use list:
- Conditionally mandatory parameters can not avoid creating methods that take the entire tuple of related parameters. It is the individual setters for each property.
- In addition to the set/get methods access you can use direct access to the properties, all or some, especially if there is a mutual dependence of the parameters, and create a validator for the entire set of constructor parameters can not be avoided.

If the answer is the most common, I would have done something like that.

Find more questions by tags OOPPHPProgramming