Skip to main content
More general description, previous was tailored to the database example and some parts of reasonning in that example.
Source Link
  • Compared to sending a request to the database and receiving the response allocating and freeing an object (of type DatabaseHelper) costs very little computing power.
    Trying to optimise allocations at this point in designing your system (and without measurements) is to early.
    So this is not a reason to replace the fields db and defaultSchema with method parameters.

    Should the values be shared among similar calls?
    If yes, then make them fields and do not pass them each time as parameters.
    In this case, using fields avoid repetition and prevents mistakenly using the wrong value.
  • You worry:

    Are the two (or more) values closely related (and do they form a concept)?

    And if i want to call my operation method 1000 times with different db/defaultShema variables each, then i have to instance 1000 temporary DatabaseHelper objects.

    If yes, then

    Most often systems use one database and one or two schemas.
    Are you really requesting data from 1000 different database schemas or even from 1000 different databases?
    If 100+ DatabaseHelper instances is not a realistic scenario, then the number of instances is not an argument against having the fields db and defaultSchema.

    • Is the caller this concept?
      If the caller is not this concept, then make the values fields. This using a higher level of abstraction in the calling code and thus can help with adhering to the single responsibility principle. It helps to prevent using the wrong combination of values.
  • You can have both db and defaultSchema as fields and as method parameters.
    There can be an instance method public object selectData(string sqlSelectClause, string sqlFromClause, string sqlWhereClause) and a static method public static object selectData(Database db, string schema, string sqlSelectClause, string sqlFromClause, string sqlWhereClause). The instance method can forward to the static method and the static method can do the heavy lifting. (Static methods often have no side-effects which makes for easier testing.).
    The static method can be public so that calling code that does really need it can divert from the default database and schema.

    Are you (at every call site) creating an object instance, setting the fields (via constructor or properties, calling the same method, and then discarding the object without any other logic that belongs in between?
  • Do you really want to bother calling code with details such as to which database to connect and in which schema the tables/view reside?
    Given the name DatabaseHelper, I expect the responsibility of the class is to help other classes/methods with accessing data in some kind of database. Isn't it easier for clients of the DatabaseHelper to just receive a DatabaseHelper from their clients or from the config and use it to retrieve/store data?
    (You might even ask if DatabaseHelper is helping enough. Do its clients need to be bothered with providing parts of SQL statements? However, this depends on the classes surrounding DatabaseHelper, their responsibilities, and level of abstraction.). If receiving a DatabaseHelper and being able to retrieve and store data without being bothered with needing to know a database and scheme is easier, then it is an argument against calling the operations in DatabaseHelper with custom database and schema and an argument in favour of providing publicly only instance methods without parameters for database and scheme.

    If yes, then use method parameters. Vector Zita has a good point: just creating an object, setting its fields, and immediately using it once is wasteful. IMHO, the cognitive burden you cause to you code's readers is worse than the possible extra computations.

A static method that receives all its input via parameters is easier to test, since it is insulated from side-effects of other methods. It is also less likely to introduce side-effects itself.
You can combine the advantages of a static method's testability and an instance method's encapsulation by providing both and having the instance method forward to the static method.

If you choose to combine the values into fields of some object, you have to decide if the values (database and schema in the example) and the operations (dabaseOperation1) should belong to the same class or that the operation accepts the values-object as parameter:

  • Look into the fly-weight pattern where they do use something like your database and schema parameters, especially read the part on when to use the fly-weight pattern, what it brings you, and its trade offs.

    Is the ...Helper-class actually a bag of not very closely related procedures for which no better place was found?
    If yes, that would make moving some of them into a coherent class an improvement.
  • See also the repository pattern, it might help you in what you are doing with the DatabaseHelper.

    Would (a subset of) the methods in DatabaseHelper and the fields database and schema form a coherent unit? And do the operations make sense as something a database and schema object can do? If yes, then combine the fields and the (subset of the) fields.

Look into the fly-weight pattern where they do use something like your database and schema parameters, especially read the part on when to use the fly-weight pattern, what it brings you, and its trade offs.

  • Compared to sending a request to the database and receiving the response allocating and freeing an object (of type DatabaseHelper) costs very little computing power.
    Trying to optimise allocations at this point in designing your system (and without measurements) is to early.
    So this is not a reason to replace the fields db and defaultSchema with method parameters.

  • You worry:

    And if i want to call my operation method 1000 times with different db/defaultShema variables each, then i have to instance 1000 temporary DatabaseHelper objects.

    Most often systems use one database and one or two schemas.
    Are you really requesting data from 1000 different database schemas or even from 1000 different databases?
    If 100+ DatabaseHelper instances is not a realistic scenario, then the number of instances is not an argument against having the fields db and defaultSchema.

  • You can have both db and defaultSchema as fields and as method parameters.
    There can be an instance method public object selectData(string sqlSelectClause, string sqlFromClause, string sqlWhereClause) and a static method public static object selectData(Database db, string schema, string sqlSelectClause, string sqlFromClause, string sqlWhereClause). The instance method can forward to the static method and the static method can do the heavy lifting. (Static methods often have no side-effects which makes for easier testing.).
    The static method can be public so that calling code that does really need it can divert from the default database and schema.

  • Do you really want to bother calling code with details such as to which database to connect and in which schema the tables/view reside?
    Given the name DatabaseHelper, I expect the responsibility of the class is to help other classes/methods with accessing data in some kind of database. Isn't it easier for clients of the DatabaseHelper to just receive a DatabaseHelper from their clients or from the config and use it to retrieve/store data?
    (You might even ask if DatabaseHelper is helping enough. Do its clients need to be bothered with providing parts of SQL statements? However, this depends on the classes surrounding DatabaseHelper, their responsibilities, and level of abstraction.). If receiving a DatabaseHelper and being able to retrieve and store data without being bothered with needing to know a database and scheme is easier, then it is an argument against calling the operations in DatabaseHelper with custom database and schema and an argument in favour of providing publicly only instance methods without parameters for database and scheme.

  • Look into the fly-weight pattern where they do use something like your database and schema parameters, especially read the part on when to use the fly-weight pattern, what it brings you, and its trade offs.

  • See also the repository pattern, it might help you in what you are doing with the DatabaseHelper.

  • Should the values be shared among similar calls?
    If yes, then make them fields and do not pass them each time as parameters.
    In this case, using fields avoid repetition and prevents mistakenly using the wrong value.
  • Are the two (or more) values closely related (and do they form a concept)?
    If yes, then
    • Is the caller this concept?
      If the caller is not this concept, then make the values fields. This using a higher level of abstraction in the calling code and thus can help with adhering to the single responsibility principle. It helps to prevent using the wrong combination of values.
  • Are you (at every call site) creating an object instance, setting the fields (via constructor or properties, calling the same method, and then discarding the object without any other logic that belongs in between?
    If yes, then use method parameters. Vector Zita has a good point: just creating an object, setting its fields, and immediately using it once is wasteful. IMHO, the cognitive burden you cause to you code's readers is worse than the possible extra computations.

A static method that receives all its input via parameters is easier to test, since it is insulated from side-effects of other methods. It is also less likely to introduce side-effects itself.
You can combine the advantages of a static method's testability and an instance method's encapsulation by providing both and having the instance method forward to the static method.

If you choose to combine the values into fields of some object, you have to decide if the values (database and schema in the example) and the operations (dabaseOperation1) should belong to the same class or that the operation accepts the values-object as parameter:

  • Is the ...Helper-class actually a bag of not very closely related procedures for which no better place was found?
    If yes, that would make moving some of them into a coherent class an improvement.
  • Would (a subset of) the methods in DatabaseHelper and the fields database and schema form a coherent unit? And do the operations make sense as something a database and schema object can do? If yes, then combine the fields and the (subset of the) fields.

Look into the fly-weight pattern where they do use something like your database and schema parameters, especially read the part on when to use the fly-weight pattern, what it brings you, and its trade offs.

Source Link

There are several things you should consider; these might help you to decide whether to use fields or method parameters:

  • Compared to sending a request to the database and receiving the response allocating and freeing an object (of type DatabaseHelper) costs very little computing power.
    Trying to optimise allocations at this point in designing your system (and without measurements) is to early.
    So this is not a reason to replace the fields db and defaultSchema with method parameters.

  • You worry:

    And if i want to call my operation method 1000 times with different db/defaultShema variables each, then i have to instance 1000 temporary DatabaseHelper objects.

    Most often systems use one database and one or two schemas.
    Are you really requesting data from 1000 different database schemas or even from 1000 different databases?
    If 100+ DatabaseHelper instances is not a realistic scenario, then the number of instances is not an argument against having the fields db and defaultSchema.

  • You can have both db and defaultSchema as fields and as method parameters.
    There can be an instance method public object selectData(string sqlSelectClause, string sqlFromClause, string sqlWhereClause) and a static method public static object selectData(Database db, string schema, string sqlSelectClause, string sqlFromClause, string sqlWhereClause). The instance method can forward to the static method and the static method can do the heavy lifting. (Static methods often have no side-effects which makes for easier testing.).
    The static method can be public so that calling code that does really need it can divert from the default database and schema.

  • Do you really want to bother calling code with details such as to which database to connect and in which schema the tables/view reside?
    Given the name DatabaseHelper, I expect the responsibility of the class is to help other classes/methods with accessing data in some kind of database. Isn't it easier for clients of the DatabaseHelper to just receive a DatabaseHelper from their clients or from the config and use it to retrieve/store data?
    (You might even ask if DatabaseHelper is helping enough. Do its clients need to be bothered with providing parts of SQL statements? However, this depends on the classes surrounding DatabaseHelper, their responsibilities, and level of abstraction.). If receiving a DatabaseHelper and being able to retrieve and store data without being bothered with needing to know a database and scheme is easier, then it is an argument against calling the operations in DatabaseHelper with custom database and schema and an argument in favour of providing publicly only instance methods without parameters for database and scheme.

  • Look into the fly-weight pattern where they do use something like your database and schema parameters, especially read the part on when to use the fly-weight pattern, what it brings you, and its trade offs.

  • See also the repository pattern, it might help you in what you are doing with the DatabaseHelper.