I need to create a fairly massive class that coordinates the work of a number of objects. For his work you need to send him about fifteen objects. Without them, his work is not possible, so it was decided to send all the objects through the constructor. Naturally, the constructor for 10+ arguments looks just awful! There is an alternative to sending all objects through properties, but this method has its drawbacks. We'll have to sculpt additional checks on null and throw exceptions. Yes, and a third-party developer, if you need to work with such a class, will have to spend extra effort not to miss any important feature.

How to be? A lot of arguments in the constructor? Or a lot of properties required to fill?

  • one
    I wonder how your class coordinates the work of the classes, if the class is something like a drawing. Anyway. Show me sample code, what's so terrible about a big constructor? And what is the problem of properties? They can be filled with default values ​​in the constructor with no arguments, and then initialize the necessary ones. - eastwing
  • 3
    and not whether to divide the class once so many parameters takes? - Ruslan_K
  • "I wonder how your class coordinates the work of the classes" I got a little bit stuck here, I meant instances. "and not to split the class once so many parameters takes?" Of course, it is possible to divide, but, in my opinion, it will not be correct. - user211023
  • 2
    Sample code would obviously not be superfluous. - BlackWitcher

2 answers 2

There is such an anti- God pattern as the Divine Object . His main feature is that he can do anything. Such an object violates the principle of sole responsibility , and, most likely, it can be divided into three or four unrelated classes.

If you look at the same situation from a different angle, you can talk about it as an error of decomposition: jumping down several levels. For example, a substance consists of molecules, a molecule of atoms, atoms of protons, neutrons and electrons, protons and electrons of quarks. Naturally, we can say that the molecules are made up of protons and electrons, and this is true, but by missing atoms, you get a very confusing picture of the molecule. Atoms can significantly simplify the model.

Bob Martin in Clean Code describes one of the code smells: calling methods of different levels of detail. This is the case when decomposing molecules, the programmer sometimes works with them as with a set of atoms, and sometimes as with a set of elementary particles.

Most likely in this case, you can abandon the fifteen classes, in favor of three or four, each of which consists of three or four smaller classes.

The number of classes you have will increase, as intermediate ones will appear; but each of them will now be easy to understand.

On the other hand, there are situations when a large number of parameters is quite acceptable. Martin Fowler described the Registry pattern, which provides access to a set of objects of the same type. Let's say you need 5 or 6 repositories and, instead of transferring them one by one, you start a register of repositories and transfer only this object. At the same time, the registry itself now transfers all the repositories that are in your program as design parameters. Since all repositories belong to the same category of objects, the registry code is simple and straightforward. In this case, the registry designer has 15-20 parameters and it still looks awful. I would call this incident an inevitable evil, and would attribute its cause to the limited expressive means of the language. In general, sometimes we just have to write like that, because otherwise the language does not allow. But be careful - before deciding that everything with your code is in order, check that it is not about the first case: a divine object and a mix of levels of detail.

  • one
    Everything is cool, but where do the numbers most likely can be divided into three or four classes? And not for seven, for example. - Vladimir Gamalyan
  • @VladimirGamalian My personal opinion, which is likely to be difficult to document, is that this is the skill of the programmer: to design it is understandable. Help is that we are talking about the model, and not about reality. In reality, any program consists of primitive processor commands, and classes, patterns, and messages are conventions that help programmers write and understand large programs. Therefore, 14-15-16 primitives can be combined into 1 class by 15, 7 by 2 and 4 by 4. The last option personally seems to me the most understandable. - Mark Shevchenko

If you want to reduce the record when creating instances of your control class, then you should first think about the default values. For example, you have the properties you need, which you initialize in the constructor without arguments with valid values, something like this:

public class SomeManager { public object Property01 {get; set; } public object Property02 {get; set; } public int Property03 {get; set; } public double Property04 {get; set; } public string Property05 {get; set; } public int Property06 {get; set; } public DateTime Property07 {get; set; } public object Property08 {get; set; } public object Property09 {get; set; } public object Property10 {get; set; } public object Property11 {get; set; } public SomeManager() { Property01 = null; Property02 = null; Property03 = 100; Property04 = 0.33; Property05 = "Здесь был Вася"; Property06 = 8; Property07 = DateTime.UtcNow; Property08 = null; Property09 = null; Property10 = null; Property11 = null; } } 

Accordingly, when working with instances of this class, you will be able to create them in the desired configuration without writing out the coat in the half-screen. Like this:

 var man1 = new SomeManager() { Property01 = SomeList, Property05 = "Никаких Вась здесь не было" } 

Or so:

 var man2 = new SomeManager() { Property03 = 42, Property04 = 0.5, Property07 = DateTime.Now.AddDays(-1) } 

You can also overload the constructor as many times as you need, but if there are many options, the solution is so-so.


On the other hand - in most cases, the use of class managers is desirable to avoid ( upd - I mean God-objects from another answer). Maybe you reconsider the architecture?

  • "On the other hand, in most cases, the use of class managers is desirable to avoid." - why? - BlackWitcher
  • @BlackWitcher has written so far, a second answer has appeared, in which they answered much better than me - eastwing
  • And, thanks, it is clear now what you meant. I was surprised because I am quite calm about classes like any Print - Report and other managers who solve one (and only one) task assigned to them without violating the principles of SOLID. And here I thought that this is about some kind of registry manager or similar objects that can be turned into a factory, for example. They answered quite rightly about God , and the question was initially set up very general, therefore I asked the author of the question a sample code. :-) - BlackWitcher
  • Well, based on the question, I understood that the author has a manager of very different objects, because he writes about the handling of zeros and exceptions. That is, apparently, some objects have no properties / fields - eastwing
  • Yeah, here you can only assume, but initially it can be objects similar in any one characteristic, but with differences in other characteristics. A commonplace example is transport, but it can also be different, water, air, land ... Each of which can also be divided into subcategories, for example, land - railway and auto. Well, etc. Accordingly, it turns out that there seems to be a community, but there is a difference (that’s why checks for null). In general, it’s me that as long as the author of the question doesn’t give more specific information and / or code, it’s difficult to answer more specifically than it’s already answered) - BlackWitcher