Imagine you have this class
class Ai1ec_Less_Parser_Controller {
/**
* @var Ai1ec_Read_Variables_Startegy
*/
private $read_variable_strategy;
/**
* @var Ai1ec_Save_Variables_Strategy
*/
private $write_variable_strategy;
/**
* @var Ai1ec_Less_Variables_Collection
*/
private $less_variables_collection;
/**
* @var Ai1ec_Less_Parser
*/
private $ai1ec_less_parser;
/**
* We set the private variables in the constructor. I feel that there are too many parameters.
* Should i use setter instead and throw an exception if something is not set?
*
* @param Ai1ec_Read_Variables_Startegy $read_variable_strategy
* @param Ai1ec_Save_Variables_Strategy $write_variable_strategy
* @param Ai1ec_Less_Variables_Collection $less_variables_collection
* @param Ai1ec_Less_Parser $ai1ec_less_parser
*/
public function __construct( Ai1ec_Read_Variables_Startegy $read_variable_strategy,
Ai1ec_Save_Variables_Strategy $write_variable_strategy,
Ai1ec_Less_Variables_Collection $less_variables_collection,
Ai1ec_Less_Parser $ai1ec_less_parser ) {
}
}
I need those variables to be set and so i set them in the constructor ( but that look like too many parameters ). Another option would be to use setters to set them and then in a method throw an exception if one of the required variables is not set like this
public function do_something_with_parser_and_read_strategy() {
if( $this->are_paser_and_read_strategy_set === false ) {
throw new Exception( "You must set them!" );
}
}
private function are_paser_and_read_strategy_set () {
return isset( $this->read_variable_strategy ) && isset( $this->ai1ec_less_parser );
}
Do you think that one of the two methods is better?And why?
Class naming Controller somehow reflects MVC, or in general – any mechanism responsible for processing sequence.
Data object classes tend to have many fields in any case – it is their responsibility.
Regular object relying on many other objects could be possibly missing a point.
There are four objects, as I see: read, save, parse and provide collection interface to something.
Why shall one have different interfaces for reading and writing? Could this not be combined into one?
Parser shall be a library on itself, thus there may be no reason to combine it anywhere, although it could possible use readers/writers for itself, and, in return, provide collection. Thus could it be possible that parser would take an argument of reader and return a collection object?
That is more about specific case.
In general – having many arguments to the method (or initializing many fields within an object by other objects of different domains) indicates some sort of design flaw.
Kind of on-topic might be this article on Constructor Initialization – it advises to use in-constructor initialization. Just be sure to follow up to the point:
And as Ray has written – there is a possibility to initialize using setters, and there is article on that too. To the extent of my view – I think that Martin Fowler really summarizes these cases pretty well.