We have an object that performs some useful work. He needs to pass a set of parameters, options. Suppose that the number of parameters can go up to 10. What is more correct and beautiful - transfer parameters in the usual way, or create a class of options to store these parameters and transfer it?

For example:

internal class Options { public bool Debug { get; set; } public bool Verbose { get; set; } public bool StopOnErrors { get; set; } public bool SkipExisting { get; set; } public bool CheckOnly { get; set; } public bool Pause { get; set; } public char FieldDelimiter { get; set; } public char ListDelimiter { get; set; } public Options() { Debug = false; Verbose = true; CheckOnly = false; StopOnErrors = true; SkipExisting = false; Pause = false; FieldDelimiter = ','; ListDelimiter = ';'; } } 
  • you can, for example, use myfunc (params object [] list) msdn.microsoft.com/en-us/library/w5zay9db(v=vs.120).aspx - Konst
  • one
    @Konst - fine - six booleans separated by commas - Igor
  • Do you have one type of worker? Do parameter values ​​vary from call to call? or some of them are global settings (debug / verbose)? Operations nesolko? Is the set of parameters for operations different, or partially coincides? Does a worker object have an internal state that should be maintained between operation calls? - PashaPash

6 answers 6

Need to! But only if the parameters are logically related.

Methods with more than 3-5 parameters become difficult to maintain. And encapsulation, as always, comes to our aid: we hide several parameters inside a class and pass an instance of this class as a method parameter. Martin Fowler in his classic book on refactoring highlights this in a separate case: Introduce Parameter Object .

In your case, as an alternative, it is also worth considering passing as many parameters as a class dependency, not a method .

    Yes, in fact it is just a repetition of the structures from the nickle-level languages ​​(in terms of the functionality used, of course), and such a thing is called a data transfer object / business object . It is often criticized for the actual absence of behavior, but, in my opinion, it performs exactly the role for which it was created - strict data transfer (in PHP, for example, an array of anything can be chased back and forth, like approaching “fixes” field names and forcing the consistency of the code) and you do not need to demand something else from it. The only thing that needs to be said is, as far as I know, there are out of the box structures in C #, and it’s probably better to use them if no behavior is foreseen (sometimes minimum formatting or pull-up of other DTOs is built into the DTO).

    In any case, the structure, the object - it will be better than a dozen parameters, because it completely kills the readability of the code.

      Personally, I vote for the class.
      Benefits weight:

      1. Less confusion when passing parameters.
      2. If there are a lot of functions accepting these parameters, say, then changes will need to be made only in the Options class.
      3. You can always resort to almost the old approach of passing parameters, just by slightly changing the syntax:
        instead

         someMethod(true, false, ... ); 

        use

         someMethod(new Options { Debug = true, Verbose = false, ... }); 

        I, too, will speak for a separate class, even if it does not include behavior. In addition to the above arguments in favor of a class, I would also note that in the case of a class, you can transfer the logic of validating its members (and therefore the parameters passed to the method) into the class itself, rather than performing a bunch of possible checks for validity inside the method

          From the point of view of OOP, such a class is not a class. But this does not mean that it can not be used.

          PS There is another possibility in C # - named parameters. They look simpler than Options — but they are harder to pass along the chain to other methods. Compare:

           someMethod(new Options { Debug = true, Verbose = false }); 

          and

           someMethod(debug: true, verbose: false); 

            I suggest not to make a separate class for options. And do not pass options with parameters. Make these options properties of the object that "does the work."

            As a last resort - to separate the options of the worker, and the parameters of the operation. Options to make properties, parameters to transfer parameters (one object, or individual, as it is more convenient).

            • As a result, it turns out that the processing parameters are screwed into a copy profitably, and before using it, you have to change all the parameters for some reason, so that everything is clear. And if it is then reused, then the other code must be sure that a state is preserved between the two calls. Then it turns out such things . - etki
            • The same arguments apply to the class of options - processing parameters are for some reason screwed into a third-party class, and before transferring it to the operation, it is necessary for some reason to change all the parameters so that everything is clear. If a copy of the worker is reused - does it have a state? If not, do not reuse. If there is - then where is the guarantee that it will correctly survive two calls with a different set of options? IMHO, Debug and Verbose should not be an operation parameter at all - neither a class nor an object, nor a property. And the assumptions that there the topicaster wants to make can be sucked from your finger as much as you like - PashaPash