This is actually an interesting question, and there's an easy (but ugly) fix to it (see below).
So I'm asking if there's a better way to do it.
What I'd like to do is making an object constructor return something else rather than a new instance.
Here's an example of what I'm trying to achieve:
$GLOBALS['object_cache']=array();
class Test {
public function __construct($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$GLOBALS['object_cache'][$id]=$this;
}
}
$t0=new Test(0);
$t1=new Test(1);
$t01=new Test(0);
// modifying $t01 would presumably also modify $t0
The easy (but ugly?) fix:
$GLOBALS['object_cache']=array();
class Test {
public static function create($id=0){
if(isset( $GLOBALS['object_cache'][$id] ))
return $GLOBALS['object_cache'][$id];
$new=new Test();
$GLOBALS['object_cache'][$id]=$new;
return $new;
}
}
$t0=Test::create(0);
$t1=Test::create(1);
$t01=Test::create(0);
// modifying $t01 would presumably also modify $t0
What do you guys think? Example 1 doesn't work, by the way; it returns a new instance regardless of the return statement.
So am I missing something, or is the better way the second one?
PS: No need stating the obvious about patterns (factory/singleton)...
Omg. Constructor cannot return anything.
It is called factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern and it is a common practice to instantiate objects.
ps: Store the instances in static class variable and second solution will not be so weird like now.
You could also use a procedural version:
class Test {
function __construct($i) {}
}
function Test($i) {
static $cache;
if (isset($cache[$i])) {
return $cache[$i];
}
else {
return $cache[$i] = new Test($i);
}
}
It's slightly nicer on the eyes, and allows for e.g. instant fluent Test(1)->do()->else() calls.
Basically what you're trying to do is implementing a Singleton pattern combined with a Factory method pattern. Anyone should be able to tell how it works if you document it in your technical documentation (and in your comments), so the first way can be used.
The second solution actually seems less obvious to me.
Related
Within the class, I created a set method if what that is called that accepts data.
<?php
public function set_name($name)
{
$this->name = ucwords(trim($name));
// return $this->name;
}
?>
My question is, do I have to return the result of the function or not necessary. If not why? I know in the display() method you have to return like so: return $this->name;. I'm really confused.
You don't have to return anything.
However, it's good practice to return something on certain functions to perform tests on it, even if it's just true or false, to clarify that the function performed correctly.
Given your code, generally, I personally don't set a return on setters. So it's fine not to return anything.
For example, you may want to test that your name only contains letters and return false if it doesn't
<?php
public function set_name($name) {
if(preg_match("/[A-Za-z]+/", $name) {
$this->name = ucwords(trim($name));
return true;
} else {
return false;
}
}
?>
Then you'd call it by:
<?php
if(!set_name($name)) {
echo "There was an error";
}
?>
However, this doesn't comply with mvc framework.
In Object Oriented programming language return the value is the best. Otherwise it will be childish and hard to maintain bugs when your sites grow bigger and it tend to errors prone.
You don't HAVE TO return the result in a setter function, the best use is to make some getter functions to get the datas.
Otherwise my point of view with setter is to return $this. With this little trick you can chain up setter functions.
For exemple :
class C
{
private $arg;
private $arg2;
function setArg($NewArg)
{
// your tests or so
$this->arg = $NewArg;
return $this;
}
function setArg2($NewArg)
{
// your tests or so
$this->arg2 = $NewArg;
return $this;
}
function getArg()
{
return $this->arg;
}
function getArg2()
{
return $this->arg2;
}
}
And you can use it that way :
$Item = new C();
$Item->setArg('hello')
->setArg2('hi');
$Item->getArg(); // return 'hello'
$Item->getArg2(); // return 'hi'
It's more semantic in this case. Do I expect a function called set_name to give me the name? No, not really, that sounds silly. In this case, I wouldn't return anything.
Because a function should only do one thing, you should always be able to reduce the choice to a binary "yes, I'd expect it to return something" or "no, that doesn't make any sense" decision.
Generally speaking your methods should do what somebody would expect them to do just by looking at their names (some people will hate me for saying this).
It's always a good idea to put yourself in the position of a programmer who has to work with your code. If had to use a method called: set_name() he would never expect it to return something.
Your methods always should do what one would expect them to do and complain to the outer environment through exceptions. Not more, not less.
If you put this into practice: Congratulations. You have just built yourself a great and reliable alarm bell for methods that are doing too much (seperation of concerns) and you're a step closer to clean software design.
Of course that's not something you would force come hell or high water (nothing is), but that's something you need to decide by yourself. If you cannot do that for whatever reasons (for example method chaining, which has been mentioned several times) , you could provide a good documentation of your class(es) and make clear what the methods actually do.
I was trying to find a way to execute some code to alter the results of an objects methods without actually touching the object's code. One way I came up is using a decorator:
class Decorator {
private $object;
public function __construct($object) {
if (!is_object($object)) {
throw new Exception("Not an object");
}
$this->object = $object;
}
protected function doSomething(&$val) {
$val .= "!!";
}
public function __call($name, $arguments) {
$retVal = call_user_func_array(array($this->object, $name), $arguments);
$this->doSomething($retVal);
return $retVal;
}
}
class Test extends BaseTest {
public function run() {
return "Test->run()";
}
}
$o = new Decorator(new Test());
$o->run();
That way it will work properly but it has one disadvantage which makes it unusable for me right now - it would require replacing all lines with new Test() with new Decorator(new Test()) and this is exactly what I would like to avoid - lots of meddling with the existing code. Maybe something I could do in the base class?
One does not simply overload stuff in PHP. So what you want cannot be done. But the fact that you are in trouble now is a big tell your design is flawed. Or if it is not your code design the code you have to work with (I feel your pain).
If you cannot do what you want to do it is because you have tightly coupled your code. I.e. you make use of the new keyword in classes instead of injecting them (dependency injection) into the classes / methods that need it.
Besides not being able to easily swap classes you would also have a gard time easily testing your units because of the tight coupling.
UPDATE
For completeness (for possible future readers): if the specific class would have been namespaced and you were allowed to change the namespace you could have thought about changing the namespace. However this is not really good practice, because it may screw with for example autoloaders. An example of this would be PSR-0. But considering you cannot do this either way I don't see it is possible what you want. P.S. you should not really use this "solution".
UPDATE2
It looks like there has been some overload extension at some time (way way way back), but the only thing I have found about it is some bug report. And don't count on it still working now either way. ;-) There simply is no real overloading in PHP.
Found something (a dead project which doesn't work anymore that enables class overloading): http://pecl.php.net/package/runkit
Possibly another project (also dead of course): http://pecl.php.net/package/apd
I am not a PHP programmer, but I think that AOP is what you are looking for. You can try some frameworks, for example listed in this answer.
From the Wikipedia article on the decorator pattern:
Subclass the original "Decorator" class into a "Component" class
So I think you're supposed to keep the class to be decorated private and expose only the already-decorated class.
I need some advice on how I can proceed with this issue.
Using PHP
An example would be:
class BuilderClass {
function getClass($id, $some, $vars){
$dbResult = new db_Class::getDbRows($id, $some, $vars);
foreach(...)
// Build something from the database values
return self;
}
}
So what I want to do is to create a test case where I somehow mock the db results.
I have not found any great way to do this, please point me in the right direction or similar to get this working for me.
I could change something within the builder itself for example call a class that runs the function: FunctionRunner::runStaticFunction("db_Class", "getDbRows", $args, $something_else); But at the moment I don't know if that is possible neither. Any research articles that cover this or any sites that explain this. I'd appriciate anything at the moment.
Thanks
/Marcus
Split the operations of retrieving data from database, and building the data.
class BuilderClass {
function getClass($id, $some, $vars){
$dbResult = new db_Class::getDbRows($id, $some, $vars);
return doGetClass($dbResult);
}
function doGetClass($dbResult) {
foreach(...)
// Build something from the database values
return self;
}
}
That way, you can test doGetClass in isolation from calling the database .
As often the case, inability to easily write tests for your functions is caused by a flaw in your application design. In this case the db_Class is tightly coupled to your BuilderClass.
A proper solution would be to have a Database object in your BuilderClass using dependency injection, and mocking that injection to return a static result.
class BuilderClass
{
protected $oDatabase;
public function __construct(db_Class $oDatabase) {
$this->oDatabase = $oDataabse;
}
public function getClass($someVars) {
$this->oDatabase->getDbRows($someVars);
}
}
This way, the Database object is easily replaced with a stub.
There are many ways to do this, but since we are talking PHP, you could leverage the magic class loader function.
Simply put, if you want to mock the data access layer, you just create an object with the actual name of the data class, and the autoloader is never called.
Want to actually access the database? don't define the class and the autoloader will be called when something tries to access the database, which should then know what to do to load the class.
Mostly my autoloaders, when I use them, tend to look something like this;
function __autoload($className)
{
if(file_exists('../includes/'.$className.'.php'))
require_once('../includes/'.$className.'.php');
}
I'm trying to get my head round Unit Testing and there's one more piece of the jigsaw I need to find.
What I'm trying to do is write tests for the following code. In this case, I've got a really simple Front Controller (written in PHP).
class frontController
{
public function routeRequest($oRequest)
{
$sClassname = $oRequest->getController();
$sMethod = $oRequest->getAction();
$oController = new $sClassname();
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
The problem I have is because the code creates new objects. I can easily mock the request object so that I can tightly control what it will actually do within my test case. I'm not sure the best way to actually replace the controller with a test double.
This article from IBM suggests having a factory method for creating my controller and then overriding this with a specific class used for testing:
class frontController
{
public function routeRequest($oRequest)
{
$sMethod = $oRequest->getAction();
$oController = $this->createController($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
protected function createController($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
and then for testing perhaps something like this:
class testFrontController extends frontController
{
public function setMockController($oMockController)
{
$this->oMc = $oMockController;
}
protected function createController($oRequest)
{
return $this->oMockController;
}
}
(note this isn't quite what the article says, but I'm thinking it would be most useful to me if it did this)
Another solution could be to have another class that creates the controller. This would then be a dependent class of the frontController. This way I can replace the factory/creation class during testing with a test double. Something like this:
class frontController
{
public function routeRequest($oRequest, $oControllerFactory)
{
$sMethod = $oRequest->getAction();
$oController = $oControllerFactory->create($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
class controllerFactory
{
public function create($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
I guess the dependency injection could be taken care of in the front controller constructor or via a setter instead of a parameter to the actual "route" method.
I think I prefer option 2.
Is either of these two methods the right way of going about testing this kind of thing?
(perhaps "good way" would be better word here!)
Any thoughts or suggestions on option 1 vs option 2 appreciated or indeed any alternatives. Remember - the key thing is about how to test an object that itself creates other objects as part of its execution.
Thanks!
You might find this article handy.
It discusses how object creation should be separated from the actual running of the application.
I generally find factories to be a good thing to use for this scenario. In addition to the swappability aspect, it means that additional parameters, data, or dependencies required by the object being created can be stored by the factory, and so the object which actually requests the new object doesn't have to know anything about them...
You do not want to use the real controller but a mock, right ?
It seems to me the simplest way to achieve this would be to subclass the request so that it returns the name of a MockController.
I assume you have thought through your assertions so as to define the goal of what exactly you are testing. Keep in mind that unit tests are going to be testing the returns from your methods, which, in this case, is $oResponse (whatever this may be). As a result, your test assertions will be based on this return value. Since I don't know what that return value is from your code snippets, I can only demonstrate an example that you can complete.
I would recommend PHPUnit for your testing as it seems to be the most complete package for PHP imho (many are fans of SimpleTest, as well ... to each their own).
It would look something like this (Please note that I have left out includes for brevity. Read the PHPUnit documentation for more information):
class AimTest extends PHPUnit_Framework_TestCase{
private $_controller = null;
private $_request = null;
public function setUp(){
$this->_controller = new frontController();
//what does this object's type?
$this->_request = new requestObject();
}
public function testObjectCreation(){
/*
* note, that this is only one of several assertions that could
* be made depending on the return value
*/
$return = $this->_controller->routeRequest($this->_request);
//tailor to what you expect your output to be
$this->assertTrue($return == "my expected output");
}
Hope I didn't miss the mark completely on your stated purpose. Moral of the story is that you can only test what your methods return. If you want to test object instantiation from a method, use the instanceof PHP function against a method that returns that object after instantiation.
I am trying to learn OO and classes and all that good stuff in PHP, I am finally learning the sytax good enough to use it some and I am curious if there is any benefit of starting a new object instead of just using static methods...let me show some code for what I mean...
<?PHP
test class
{
public function cool()
{
retunr true;
}
}
//Then calling it like this
$test = new test();
$test->cool();
?>
OR
<?PHP
test class
{
public static function cool()
{
retunr true;
}
}
//Then calling it like this
test::cool();
?>
I realize this is the most basic example imaginable and the answer probably depends on the situation but maybe you can help me understand a little better
For your example, it is better to use a static function, but most situations will not be so simple. A good rule of thumb to start with is that if a method doesn't use the $this variable, then it should be made static.
Think of classes like 'blueprints' to an object. you want to use the static method when it is a general function that could apply to anywhere, and use methods when you want to reference that specific object.
Here is an article that discusses differences in performance between these concepts:
http://www.webhostingtalk.com/showthread.php?t=538076.
Basically there isn't any major difference in performance, so then the choice is made based on your design.
If you are going to create an object several times, then obviously a class makes sense.
If you are creating a utility function that isn't tied to a particular object, then create a static function.