SitePoint Sponsor |
|
User Tag List
Results 1 to 11 of 11
Thread: __construct vs. setProperty()
-
Nov 8, 2005, 06:28 #1
- Join Date
- Nov 2005
- Location
- Germany
- Posts
- 235
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
__construct vs. setProperty()
Hello,
since I'm pretty new to OOP I'd like to have a few comments on these two approaches to a constructor. I have two class properties, which sort of belong together (IDs) and are pretty essential (I cannot imagine any circumstances where they don't need to be set), so I could put them in the parameter list of _construct() (see class BigConstructor). But that would make the parameter list long and ugly. To avoid this I could have a setId() method which would have to be called every time I instantiate the class (CompactConstructor). Not nice either.
PHP Code:<?php
class BigConstructor {
// ugly ugly ugly parameter list
public function __construct($objectId, $catId, \
& $dbHandler, dbselect & $dbAbstract) {
$this->caseId = $objectId;
$this->catId = $catId;
// ... and some more
}
}
class CompactConstructor {
// nice parameter list
public function __construct(& $dbHandler, dbselect & $dbAbstract) {
// ...
}
public function setIds($objectId, $catId) {
$this->caseId = $objectId;
$this->catId = $catId;
}
}
// ready to use!
$bc = new BigConstructor(...);
// two steps neccessary to use this!
$cc = new CompactConstructor(...);
$cc->setIds(1,1);
?>
Please let me know how you usually handle this.
Thanks in advance,
Christoph
-
Nov 8, 2005, 06:46 #2
- Join Date
- Jun 2004
- Location
- Copenhagen, Denmark
- Posts
- 6,157
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
The general rule is that if the object can't exist without the properties, they should be injected through the constructor. However, when you have many parameters in the constructor it may be a sign that your object is doning too much, so you may want to refactor. It's not a definitive, and the problem is so complex that it has spawned solutions such as dependency-injection container and service-locator.
In you particular case - without knowing exactly what the class is supposed to do - I would make a guess that dbHandler and dbselect needn't be injected. Wouldn't it make the class more flexible, if the methods, in which you need theese instances, took them as arguments ? That way, the same object could be used with more than one database.
Alternatively, if the object is only created within another class, a heaveweight constructor isn't that bad at all. The problem is mostly there, if the user has to craete instances manually all the time.
-
Nov 8, 2005, 08:10 #3
- Join Date
- Sep 2004
- Location
- Zagreb, Croatia
- Posts
- 830
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
If a single database connection is used throught your application (as is often the case), it might be wise to make it into either a Highlander or Borg (i.e. Singleton or Multistate -- I just love the Python names
).
-
Nov 8, 2005, 10:01 #4
- Join Date
- Nov 2005
- Location
- Germany
- Posts
- 235
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Hello,
thanks for the input, it's very helpful.
Originally Posted by kyberfabrikken
Originally Posted by BerislavLopac
Thanks again,
Christoph
-
Nov 8, 2005, 12:26 #5
- Join Date
- Jun 2004
- Location
- Copenhagen, Denmark
- Posts
- 6,157
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by FrlB
Don't get me wrong - sometimes it's much easier to simply create a singleton, but changing your design from passing variables (the proper path) to using singletons (the wrong path) is a weakening of your implementation. I often create singletons in the early drafts of my code, but end up refactoring them out again, as the code consolidates.
-
Nov 8, 2005, 12:38 #6
- Join Date
- Jan 2003
- Posts
- 5,748
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
You do? I'm happy enough to use and retain the use of a Singleton, but in saying that I have only ever used it in one place, for creating one instance of a database connection, and no where else.
Would knowing that now, still inpede the application and it's future development?
-
Nov 8, 2005, 17:56 #7
- Join Date
- Sep 2003
- Location
- Bristol, UK
- Posts
- 145
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I have a rule that all methods I write have no more than two parameters. In some cases I allow an optional third parameter, but this is usually removed later after refactoring.
If you find you have a method with a long list of parameters try to think about what those parameters are for, where they're coming from, etc.
For instance, in my opinion - and I'm obviously going to have to make some wild assumptions about the responsibility of your class because the purpose of all your parameters isn't clearly stated - I would reduce the number of of parameters to 3.
PHP Code:class RefactoredConstructor {
public function __construct($objectId, $catId, Storage_Accessor $storage);
}
interface Storage_Accessor {
public funciton __construct($dbname, $dbConnection, $dbAdaptor);
public function getById();
public function getByCatId();
public function store(...);
}
Kindof Introduce Parameter Object & Preserve Whole Object
HTHAlways open to question or ridicule
-
Nov 8, 2005, 18:03 #8
- Join Date
- Jul 2004
- Location
- canada
- Posts
- 3,193
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
A Question arose from sleepeasy's post,
I have a user class, which has a register function. Now, i have about 10 fields in register form.
What is the best method to pass them to function??
-
Nov 8, 2005, 18:32 #9
- Join Date
- Sep 2003
- Location
- Bristol, UK
- Posts
- 145
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
I assume that the register() function you have is responsible for inserting a user's details into a database? And it might look something like:
PHP Code:class User {
register($username, $email, $dob, $icq, ...);
}
Use the user class just to store user properties. Instantiate a user and then populate it's properties either directly or via "setter" methods.
You would then pass this user object to your new class that would be responsible for inserting this new user into the database.
PHP Code:class User_Store {
public function store(User $user) {
// ...
}
}
// just for illustration
$newUser = new User();
$newUser->setName($_POST['name']);
$newUser->setEmail($_POST['email']);
$userStore = User_Store::getInstance();
$userStore->insert($newUser);
This may not seem like a big deal but when you start dealing with optional parameters things start to get messy. Forms often contain data that is optional.
The worse case scenario is that you add an optional parameter, and then decide to add another parameter which is not optional which will alter the order of the parameters, requiring all code to adapt to these changes.
You would also need to modify the body of the register() function.
Using my approach (in PHP5) you would only need to modify the body of the User_Store::store() method.
However, what I forgot to mention in my previous post is that a lot of this comes down to how you feel about functions with lots of parameters.
HTHAlways open to question or ridicule
-
Nov 8, 2005, 19:06 #10
- Join Date
- Jul 2004
- Location
- canada
- Posts
- 3,193
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Thanks, that answers many question.
the technique when i couldn't think of anything, i used, was
i just passed ($_POST) to a validate function in register class. and it would return 1 or 0 on validatation (checking required filed), and then if one, then pass then call the register function.
i dint pass anything to register function, because while using that validate class, it sets class variables, and register class uses those values.
But, your method makes more sense.
thanks
-
Nov 9, 2005, 08:59 #11
- Join Date
- Nov 2005
- Location
- Germany
- Posts
- 235
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by sleepeasy
Originally Posted by kyberfabrikken
Originally Posted by sleepeasy
Anyway, as a newbie in this forum I really appreciate all your ideas,
Christoph
Bookmarks