patternphpMinor
A decent use-case for static property
Viewed 0 times
casedecentpropertyforusestatic
Problem
I'm currently writing a REST-tool that connects to a third-party server (duh). They offer a fairly large (if not too large) API in a single wsdl file, as well as separate wsdl's for each specific part of data you want to work on.
When writing my code, I created an abstract
Since all requests are available through a single, "master-api", there is only 1 user-password required to connect, so I've created the
Since it's not unlikely form me to be working with two, or three of these API-classes, I decided to create a private static property in the abstract class. This is to avoid excessive internal method calls, brought along by lazy-loading.
Is this a valid use-case for the
Anyway, here's some (grossly oversimplified) version of my code:
```
namespace MyLib;
use Tool\Application,
Tool\Command;//it's a CLI tool
use MyLib\Soap\Client;
use \Zend_Config;//can't help but liking the old Zend_Config
absctract class Api
{
//all properties have a getter, which lazy-loads the correct object, where possible
//can be injected through constructor, setter or via $this->command
private $app = null;
//inject via setter, get from application or command
private $config = null;
//inject via setter or child constructor
private $command = null;
/ This is the one /
private static $login;
public function __construct(Application $app = null)
{
$this->setApplication($app);
if (!is_callable(array($this, 'init')))
{
throw new \RuntimeException('Impossible, yet somehow '.get_class($this).'::init() cannot be called');
}
return $this->init();
}
abstract protected functoin init();
final private function getLogin()
{
When writing my code, I created an abstract
Api class, and a number of child classes, one for each subset of the API.Since all requests are available through a single, "master-api", there is only 1 user-password required to connect, so I've created the
getClient and setClient methods in the abstract class.Since it's not unlikely form me to be working with two, or three of these API-classes, I decided to create a private static property in the abstract class. This is to avoid excessive internal method calls, brought along by lazy-loading.
Is this a valid use-case for the
static keyword? It's the only time I'm using static in my entire code, and I have this acquired repulsion for using it. Anyway, here's some (grossly oversimplified) version of my code:
```
namespace MyLib;
use Tool\Application,
Tool\Command;//it's a CLI tool
use MyLib\Soap\Client;
use \Zend_Config;//can't help but liking the old Zend_Config
absctract class Api
{
//all properties have a getter, which lazy-loads the correct object, where possible
//can be injected through constructor, setter or via $this->command
private $app = null;
//inject via setter, get from application or command
private $config = null;
//inject via setter or child constructor
private $command = null;
/ This is the one /
private static $login;
public function __construct(Application $app = null)
{
$this->setApplication($app);
if (!is_callable(array($this, 'init')))
{
throw new \RuntimeException('Impossible, yet somehow '.get_class($this).'::init() cannot be called');
}
return $this->init();
}
abstract protected functoin init();
final private function getLogin()
{
Solution
Is it a "good" use-case? Not in my opinion. Is it "decent"? I think it is decent enough to get the job done if that is how you want to do it. The beauty of it is, anything is "decent" enough if it works for you, and things could always be "better". I find that I mostly use statics for Singletons and simple utility functions -- otherwise, the benefits rarely outweigh the drawbacks.
Personally, I would not go this route; even though it may make things easier to write initially, it would also make it hard to do any type of unit testing.
It seems like you may also be assuming that no one, ever, for any reason, may have more than one set of login details that they would like to use at the same time. While that might be true, I wouldn't want to make that assumption.
If it were me, I would approach this like any other adapter -- create independent classes with single responsibilities and use dependency injection for configuration/etc. Finally, I would create a facade which implements those responsibilities, and handles the dependencies, in order to provide an "easy to use" interface without taking away the user's ability to do things at a lower level.
To me, this would give you the most testability and maintainability, without placing constraints on the how someone else could use the code (and still provide an easy interface as well).
Of course, that is just my opinion.
Personally, I would not go this route; even though it may make things easier to write initially, it would also make it hard to do any type of unit testing.
It seems like you may also be assuming that no one, ever, for any reason, may have more than one set of login details that they would like to use at the same time. While that might be true, I wouldn't want to make that assumption.
If it were me, I would approach this like any other adapter -- create independent classes with single responsibilities and use dependency injection for configuration/etc. Finally, I would create a facade which implements those responsibilities, and handles the dependencies, in order to provide an "easy to use" interface without taking away the user's ability to do things at a lower level.
To me, this would give you the most testability and maintainability, without placing constraints on the how someone else could use the code (and still provide an easy interface as well).
Of course, that is just my opinion.
Context
StackExchange Code Review Q#28074, answer score: 2
Revisions (0)
No revisions yet.