PHP MVC: Default values for the constructor parameters [closed] - php

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Before I begin:
My question was put on hold as primarily opinion-based. But I've done my best to reedit it in a more precise way again. In the hope, that its content will support its reopening.
So here is my question again:
It's about my HMVC project, a PHP framework, in which the M, V & C components are encapsulated in "independent" blocks (module directories). The project should not contain any static class members, static methods, singletons or service locators. I am using a dependency injection container, therefore beeing able to provide inversion of control (IoC).
In a class AbstractTemplate I assign the needed root paths of the template files as default values to the parameters of the class constructor:
abstract class AbstractTemplate {
public function __construct(
, $appLayoutsPath = '[app-root-path]/Layouts/Default'
, $moduleLayoutsPath = '[module-root-path]/Templates/Layouts'
, $moduleTemplatesPath = '[module-root-path]/Templates/Templates'
) {
//...
}
}
But in this way I couple the class to a hard-coded representation of the file system.
Therefore I considered passing the default values by using a separate class, which in turn holds the required values as class constants:
class Constants {
const APP_LAYOUTS_PATH = '[app-root-path]/Layouts/Default';
const MODULE_LAYOUTS_PATH = '[module-root-path]/Templates/Layouts';
const MODULE_TEMPLATES_PATH = '[module-root-path]/Templates/Templates';
}
abstract class AbstractTemplate {
public function __construct(
, $appLayoutsPath = Constants::APP_LAYOUTS_PATH
, $moduleLayoutsPath = Constants::MODULE_LAYOUTS_PATH
, $moduleTemplatesPath = Constants::MODULE_TEMPLATES_PATH
) {
//...
}
}
This way I couple the abstract class to the concrete implementation Constants.
I'd like to ask you:
Can the second option be tested without problems?
Is there another concrete possibility to provide default values and in the mean time to preserve a good testability?
I appreciate your answers and thank you for your time.

You can argue for both and you will not be worng since it is just an example detatched from any "real" code. But in my opinion this should be your starting code:
abstract class AbstractTemplate {
const DEFAULT_APP_LAYOUTS_PATH = '[app-root-path]/Layouts/Default';
const DEFAULT_MODULE_LAYOUTS_PATH = '[module-root-path]/Templates/Layouts';
const DEFAULT_MODULE_TEMPLATES_PATH = '[module-root-path]/Templates/Templates';
public function __construct(
$appLayoutsPath = AbstractTemplate::DEFAULT_APP_LAYOUTS_PATH,
$moduleLayoutsPath = AbstractTemplate::DEFAULT_MODULE_LAYOUTS_PATH,
$moduleTemplatesPath = AbstractTemplate::DEFAULT_MODULE_TEMPLATES_PATH
) {
//...
}
}
So you have your constants and you may reuse it (hopefully in the same class or in whatever class makes it "real", and not outside of it!)
You could argue that "class Constants" would be better if you are going to reuse the constants from it in many different classes. The problem with that approach is that it goes against very basic OOP principles. That is: You should have just one object that does sth for you with theese pathes. And if you need different things to be done you just reuse this one object in many different objects in many different ways...
Also Unit Testing or Dependency Injection and Inversion of Controll does not change anything here. But if you are providing code that you "know" that will only be used with IoC, you could argue if having any defaults is good idea at all and if it would not be better to inject everything from container...

I will probably go with option #2. I like to separate things out (using Separation of Concerns principles), and code reuse (Don't Repeat Yourself principle). It wasn't immediately clear to me from the question if you intend to reuse the default values in multiple classes or not. If you do, Option #2 is even better, since you have to change the actual string default values only in one place.
Not really. You are in a way creating a type that has default parameters. Imagine your Constants class is a type of int. Is there a real issue that your class depends on an integer type? Sometimes you have to have some variables in your class, and Constants is one of those variables.
Your class will always depend on Constants, so you won't be able to easily swap in&out different constants. That can be an issue if you want to have a different set of constants for i.e. testing, or another environment (development, production, testing, etc)
Personally I think I'd off-load the default values to a configuration text file, which can be different in different environments
Config file way
File called 'config/my-config.php';
/**
* Config for default
*/
return array(
'APP_LAYOUTS_PATH' => '[app-root-path]/Layouts/Default'
);
In your application:
$config = require 'config/my-config.php';
echo $config['APP_LAYOUTS_PATH']; //'[app-root-path]/Layouts/Default';
If-then-else way (can be combined with config files)
if ($mySpecificCondition)
$appLayoutsPath = '[app-root-path]/Layouts/Default';
else
$appLayoutsPath = '[app-root-path]/Layouts/NonDefault';
Or
switch ($mySpecificCondition)
{
case 'prod':
$configFile= 'config_path/production.config.php';
break;
case 'devel':
$configFile= 'config_path/development.config.php';
break;
case 'test':
$configFile= 'config_path/test.config.php';
break;
}
$config = require $configFile;
To clarify you may have a situation where you have the same file name with different contents on different environments. Or you may wish to have different parameters based on a condition. The above gives some ideas.
In my case I use both methods for different things. i.e. I have the same file name with different contents for email/IP configuration for prod/development. But for something like operating system default font file folder placement, I use if/then/else. if (OS == WIN) $path = X; else $path = Y;
Also remember to use Keep It Simple principle. You can always refactor your design later. Think about how your design will play out in the future, of course, but don't make it overly-complicated until you have to.

Clean Code
I fully agree with George Dryser in that option 2 is cleaner. I don't quite agree with him on his second point though:
I'd strongly recommend not to avoid entire functionality such as static class members purely for design or stylistic considerations, it's there for a reason.
The language features exist, but that doesn't necessarily mean that they should be used for this particular purpose. Also, the question isn't as much about style as much as it is about (de-)coupling.
Interdependence
To address your 3rd point:
... class Constants is introducing this interdependence/coupling ...
There's no interdependence here, since AbstractTemplate depends on Constants, but Constants has no dependencies. Your 2nd option can be tested, but it's not very flexible.
Coupling
In your 2nd point you say:
Is there a real issue, that each class using option 2 will depend on a Constants class?
The issue isn't that there's a dependency being introduced, but what kind of dependency. Reading values from a specific, named member of the application is tight coupling, which you should try to avoid. Instead, make the default values constant only to those classes that read the values:
How objects that implement IDefaultsProvider get their values does not concern the AbstractTemplate class at all.
Possible Solution
For the sake of being thorough, I'm going to reinvent the wheel here.
In PHP, the interface for IDefaultsProvider can be written like this:
interface IDefaultsProvider {
/** Returns the value of a variable identified by `$name`. */
public function read($name);
}
The interface is a contract that says: "When you have an object that implements IDefaultsProvider, you can read default values using its read() method and it will return the default value you requested".
I'll get to specific implementations of the interface further below. First, let's see how the code for AbstractTemplate might look like:
abstract class AbstractTemplate {
private static function getDefaultsProvider() {
// Let "someone else" decide what object to use as the provider.
// Not `AbstractTemplate`'s job.
return Defaults::getProvider();
}
private static function readDefaultValue($name) {
return static::getDefaultsProvider()->read($name);
}
public function __construct(
, $appLayoutsPath = static::readDefaultValue('app_layouts_path')
, $moduleLayoutsPath = static::readDefaultValue('module_layouts_path')
, $moduleTemplatesPath = static::readDefaultValue('module_templates_path')
) {
//...
}
}
We've gotten rid of Constants and its members (const APP_LAYOUTS_PATH etc). AbstractTemplate is now blissfully ignorant of where the default values come from. Now, AbstractTemplate and the default values are loosely coupled.
The implementation of AbstractTemplate only knows is how to get a IDefaultsProvider object (see method getDefaultsProvider()). In my example, I'm using the following class for that:
class Defaults {
/** #var IDefaultsProvider $provider */
private $provider;
/** #returns IDefaultsProvider */
public static function getProvider() {
return static::$provider;
}
/**
* Changes the defaults provider instance that is returned by `getProvider()`.
*/
public static function useInstance(IDefaultsProvider $instance) {
static::$instance = $instance;
}
}
At this point, the reading part is complete, since AbstractTemplate can get a defaults provider using Defaults::getProvider(). Let's look at bootstrapping next. This is where we can start to address different scenarios like testing, development and production.
For testing, we might have a file called bootstrap.test.php that's included only when tests are being run. It needs to be included before AbstractTemplate, of course:
<?php
// bootsrap.test.php
include_once('Defaults.php');
include_once('TestingDefaultsProvider.php');
Defaults::useInstance(new TestingDefaultsProvider());
The other scenarios require their own bootstrapping as well.
<?php
// bootsrap.production.php
include_once('Defaults.php');
include_once('ProductionDefaultsProvider.php');
Defaults::useInstance(new ProductionDefaultsProvider());
... and so on.
What remains to be done are the implementations of IDefaultProvider. Let's start with TestingDefaultsProvider:
class TestingDefaultsProvider implements IDefaultsProvider {
public function read($name) {
return $this->values[$name];
}
private $values = [
'app_layouts_path' => '[app-root-path]/Layouts/Default',
'module_layouts_path' => '[module-root-path]/Templates/Layouts',
'module_templates_path' => '[module-root-path]/Templates/Templates',
// ... more defaults ...
];
}
It might actually be as simple as that.
Let's assume that, in production, we want the configuration data to reside in a configuration file:
// defaults.json
{
"app_layouts_path": "[app-root-path]/Layouts/Default",
"module_layouts_path": "[module-root-path]/Templates/Layouts",
"module_templates_path": "[module-root-path]/Templates/Templates",
// ... more defaults ...
}
In order to get to the defaults in the file, all we need to do is read it once, parse the JSON data and return the default values when requested. For the sake of this example, I'm gonna go with lazy reading & parsing.
class ProductionDefaultsProvider implements IDefaultsProvider {
public function read($name) {
$parsedContent = $this->getAllDefaults();
return $parsedContent[$name];
}
private static $parsedContent = NULL;
private static function getAllDefaults() {
// only read & parse file content once:
if (static::$parsedContent == NULL) {
static::$parsedContent = static::readAndParseDefaults();
}
return static::$parsedContent;
}
private static readAndParseDefaults() {
// just an example path:
$content = file_get_contents('./config/defaults.json');
return json_decode($content, true);
}
}
Here's the whole shebang:
Conclusion
Is there a better alternative to provide default values?
Yes, provided that it's worth the effort. The key principle is inversion of control (also IoC). The purpose of my example was to show how IoC can be implemented. You can apply IoC to configuration data, complex object dependencies or, in your case, defaults.
If you only have a few default values in your application, it might be overkill to invert control. If there's plenty of default values in your application or if you cannot expect the number of defaults, configuration variables, etc to stay very low in the future though, you might want to look into dependency injection.
Inversion of Control is too generic a term, and thus people find it confusing. As a result with a lot of discussion with various IoC advocates we settled on the name Dependency Injection.
— Martin Fowler
Also, this:
Basically, instead of having your objects creating a dependency or asking a factory object to make one for them, you pass the needed dependencies in to the object externally, and you make it somebody else's problem.
 — SO Answer to "What is Dependency Injection?" by wds
The good news is that there are plenty of DI frameworks around:
Zend DI
Symfony DI
PHP-DI
Ray-DI
...

Option 2 is much cleaner and easier maintainable code example I would go with 2, code-hinting applications like phpStorm or DW will understand option 2 better.
I'd strongly recommend not to avoid entire functionality such as static class members purely for design or stylistic considerations, it's there for a reason.

Related

Scalable way of implementing the Registry pattern in PHP?

I was wondering if there's a good way to implement the registry pattern in PHP, let me be more clear:
I do know that a Registry is used when you need to keep track of the object you instantiate in order to reuse them and not re-instantiate them again from script to script, e.g. I have a Database class that I want to instantiate only once and then use for all my scripts and I do not want to re-instantiate it again and again. Another example could be a User class that represents an instance of the currently logged in user. I could not use a Singleton in this case, cause e.g. I need another User instance for example when I want to retrieve a friend of the currently logged in user etc.
So I came up with the idea that the Registry better suits this kind of needs in such cases.
I also know that there are two ways of implementing it, or better two ways in order to access the stored instances:
Explicitly or externally, meaning that the Registry should be called every time you need to recover an instance inside your scripts or you need to put an instance inside of it;
Implicitly or internally, meaning that you make kind of an abstract class with a getInstance() method that returns an instance with the get_called_class() late static binding feature, adds it to the registry and then return that instance from the registry itself taking care that if a $label parameter is passed to the getInstance() method, then that particular instance from the registry will be returned. This approach is kinda transparent to the consumer and in my opinion is cleaner and neater (I'll show both implementations, though).
Let's take a basic Registry (really simple implementation, just an example took from a book):
class Registry {
static private $_store = array();
static public function set($object, $name = null)
{
// Use the class name if no name given, simulates singleton
$name = (!is_null($name)) ? $name: get_class($object);
$name = strtolower($name);
$return = null;
if (isset(self::$_store[$name])) {
// Store the old object for returning
$return = self::$_store[$name];
}
self::$_store[$name]= $object;
return $return;
}
static public function get($name)
{
if (!self::contains($name)) {
throw new Exception("Object does not exist in registry");
}
return self::$_store[$name];
}
static public function contains($name)
{
if (!isset(self::$_store[$name])) {
return false;
}
return true;
}
static public function remove($name)
{
if (self::contains($name)) {
unset(self::$_store[$name]);
}
}
}
I know, Registry could be a Singleton, so you never have two Registry at the same time (who needs them someone could think, but who knows).
Anyway the externally way of storing/accessing instances is like this:
$read = new DBReadConnection;
Registry::set($read);
$write = new DBWriteConnection;
Registry::set($write);
// To get the instances, anywhere in the code:
$read = Registry::get('DbReadConnection');
$write = Registry::get('DbWriteConnection');
And internally, inside the class (taken from the book) when getInstance is called:
abstract class DBConnection extends PDO {
static public function getInstance($name = null)
{
// Get the late-static-binding version of __CLASS__
$class = get_called_class();
// Allow passing in a name to get multiple instances
// If you do not pass a name, it functions as a singleton
$name = (!is_null($name)) ?: $class;
if (!Registry::contains($name)) {
$instance = new $class();
Registry::set($instance, $name);
}
return Registry::get($name);
}
}
class DBWriteConnection extends DBConnection {
public function __construct()
{
parent::__construct(APP_DB_WRITE_DSN, APP_DB_WRITE_USER, APP_DB_WRITE_PASSWORD);
} }
class DBReadConnection extends DBConnection {
public function __construct()
{
parent::__construct(APP_DB_READ_DSN, APP_DB_READ_USER,APP_DB_READ_PASSWORD);
}
}
Apparently referring to the registry indirectly (second case) seems more scalable for me, but what if some day I would need to change the registry and use another implementation, I would need to change that calls to Registry::get() and Registry::set() inside the getInstance() method in order to suit the changes or is there a smarter way?
Did someone of you came across this problem and found an easy way to interchange different registries depending on the type of application on the complexity etc.?
Should be a configuration class the solution? Or is there a smarter way to achieve a scalable registry pattern if it is possible?
Thanks for the attention! Hope for some help!
First of all. It's great that you spotted the problem of your approach by yourself. By using a registry you are tight coupling your classes to the registry where you pull your dependencies from. Not only that, but if your classes have to care about how they are stored in the registry and get grabbed from it (in your case every class would also implement a singleton), you also violate the Single-Responsibility-Principle.
As a rule of thumb keep in mind: Accessing objects globally from within a class from whatever storage will lead to tight coupling between the class and the storage.
Let's see what Martin Fowler has to say about this topic:
The key difference is that with a Service Locator every user of a service has a dependency to the locator. The locator can hide dependencies to other implementations, but you do need to see the locator. So the decision between locator and injector depends on whether that dependency is a problem.
and
With the service locator you have to search the source code for calls to the locator. Modern IDEs with a find references feature make this easier, but it's still not as easy as looking at the constructor or setting methods.
So you see it depends on what you are building. If you have a small app with a low amount of dependencies, to hell with it, go on with using a registry (But you absolutely should drop a classes behavior to store itself into or getting grabbed from the registry). If that's not the case and you are building complex services and want a clean and straightforward API define your dependencies explicitly by using Type Hints and Constructor Injection.
<?php
class DbConsumer {
protected $dbReadConnection;
protected $dbWriteConnection;
public function __construct(DBReadConnection $dbReadConnection, DBWriteConnection $dbWriteConnection)
{
$this->dbReadConnection = $dbReadConnection;
$this->dbWriteConnection = $dbWriteConnection;
}
}
// You can still use service location for example to grab instances
// but you will not pollute your classes itself by making use of it
// directly. Instead we'll grab instances from it and pass them into
// the consuming class
// [...]
$read = $registry->get('dbReadConnection');
$write = $registry->get('dbWriteConnection');
$dbConsumer = new DbConsumer($read, $write);
Should be a configuration class the solution? Or is there a smarter way to achieve a scalable registry pattern if it is possible?
That approach is encountered very often and you maybe have heard something about a DI-Container. Fabien Potencier writes the following:
A Dependency Injection Container is an object that knows how to instantiate and configure objects. And to be able to do its job, it needs to knows about the constructor arguments and the relationships between the objects.
The boundaries between a service locator and a DI-Container seem to be pretty blurry but I like the concept to think about it like that: A Service Locator hides the dependencies of a class while a DI-Container does not (which comes along with the benefit of easy unit testing).
So you see, there is no final answer and it depends on what you are building. I can suggest to dig more into the topic since how dependencies are managed is a core concern of every application.
Further Reading
Why Registry Pattern is antipattern. And what is alternative for it.
Service Locator is an Anti-Pattern
Do you need a Dependency Injection Container?

To inject or to new?

With regards to using class objects within another class what is the best practice? To pass the class objects in the class _construct statement or create a new class object?
Example 1:
class Foo {
private $bar;
public function __construct($bar){
$this->bar = $bar;
}
}
Or Example 2 :
class Foo {
private $bar;
public function __construct(){
$this->bar= NEW bar;
}
}
I'm aware that obviously it's taken for granted that the class file must already be included somewhere else, and in the first instance a class object of this type would need to exist already, but I want to know what the advantages are each method are, as I have a lot of classes I need to code that use a database object and I need the best way to pass this into the classes. Is there a third option that's better than these two?
From what I can understand, the advantage of the first one could be a few less lines of coding and in the case of a DB, not having a new connection created. The second one might be better however because it's more self contained? Anyhow I thought I'd ask the experts.
The first. (This approach is called Dependency Injection).
The constructor asks for whatever the object in questions needs in order to work. This way, it's pretty clear from the methods alone (what they need, and what they return), what it does. Without even looking at the source code.
A way to improve your code would be to introduce type hinting into your method:
class Foo {
private $bar;
public function __construct(Bar $bar){
$this->bar = $bar;
}
}
So that only Bar objects may be passed in.
Advantages of Dependency Injection
Very readable.
Ability to tell the method's dependencies without viewing the source code.
Makes Unit Testing possible.
*Saves kittens from God's wrath.
* Disclaimer: No kittens were harmed during the manifestation of this answer
You should go for option 1, as this is the simplest form of dependency injection.
In option 1:
classes are independent of each other
classes can be tested independent, using a mock for the bar class
In general, I'd chime in with the DI crowd for reasons outlined in How to Think About the “new” Operator with Respect to Unit Testing:
But the reason why Dependency Injection is so important is that within unit-tests you want to test a small subset of your application. The requirement is that you can construct that small subset of the application independently of the whole system. If you mix application logic with graph construction (the new operator) unit-testing becomes impossible for anything but the leaf nodes in your application.
Separating your code into creator graphs and collaborator graphs will help to keep your code maintainable and testable. Even better, code against interfaces and it will be very easy to swap out concrete implementations against other ones. This makes changing your code simple, because you don't have to wade through your code hunting for hardcoded dependencies.
For instance, assuming your Bar requires a Logger, you'd do
class Foo
{
private $logger;
public function __construct(LogInterface $logger)
{
$this->logger = $logger;
}
}
And then you pass in any concrete implementation implementing that LogInterface, like a Database Logger or a StdOutLogger or maybe a Composite Logger holding both of these. Another example would be a Database object. You can create that once in your bootstrap and then pass it to the objects making use of it.
When in doubt, go with Dependency Injection.
However, you don't always have to inject stuff. It depends whether the object (your Bar) is an Injectable or a Newable. To quote Misko Hevery:
An Injectable class can ask for other Injectables in its constructor. […] Injectables tend to have interfaces since chances are we may have to replace them with an implementation friendly to testing. However, Injectable can never ask for a non-Injectable (Newable) in its constructor. This is because DI framework does not know how to produce a Newable. […] Some examples of Newables are: Email, MailMessage, User, CreditCard, Song. If you keep this distinctions your code will be easy to test and work with. If you break this rule your code will be hard to test.
In a nutshell, when you have something that cannot be reasonably injected, because it is based on user-supplied or runtime information, you can new it. This is especially true for Value Objects and Data Types:
class Foo
{
private $storage;
public function __construct()
{
$this->storage = new SplObjectStorage;
}
}
There is no point in injecting SplObjectStorage. It's just a data type.
Others have already answered your question - definitely go with the first approach, which uses Dependency Injection.
I just wanted to chip in with another popular alternative you may not be aware of: using a Dependency Injection Container.
A great, simple example of this is Pimple; developed by Fabien Potencier, the man behind the Symfony frameworks.
Example 3:
# In a bootstrap file...
require_once '/path/to/Pimple.php';
$container = new Pimple();
$container['bar'] = function ($c) {
return new Bar(/** If bar has dependencies, put them here **/);
};
$container['foo'] = function ($c) {
return new Foo($c['bar']);
};
# You'd still inject the service using DI, because it's not good
# practice for your objects to rely directly on the container
class Foo {
private $bar;
public function __construct($bar){
$this->bar = $bar;
}
}
# The difference would be how you call Foo...
$foo = $container['foo'];
# So now your code doesn't need to know about the dependencies, and it's easy
# to change them at any time by making a single change in your configuration
Symfony2 uses a more robust Container, which is also available as a standalone compenent. But Pimple is probably your best bet unless you're developing a large-scale application.
I'd say use the 1st option. While doing so, I'd say programming to abstractions is a better idea than programming to an implementation.
Your first option is a form of aggregation while the second is that of composition. The benefit you would get with abstractions is that your client class that uses class FOO will be able to get FOO to do some activity based on a particular implementation of the interface it decides to send into the constructor..
A C# example below
class Foo {
private IBar bar;
public Foo(IBar obj){
this.bar = obj;
}
public void myFooMethod()
{
bar.ExecuteMethod();
}
}
The class calling FOO
public class MyCallingClass
{
public void CallFooMethod()
{
IBar bar1Obj = new BAR1();
Foo fooObject = new Foo(bar1Obj);
fooObject.ExecuteMethod();
//or
IBar bar2Obj = new BAR2();
fooObject = new Foo(bar2Obj);
fooObject.ExecuteMethod();
//or
IBar bar3Obj = new BAR3();
fooObject = new Foo(bar3Obj);
fooObject.ExecuteMethod();
}
}
Now my calling class can pass any implementation of IBar to the FOO class.
Hope this helped.
Ok, Dependency Injection is wonderful, and helpful and saves kittens, so I'm not going to discuss it in detail.
Instead, I'm going to suggest you implement both solutions:
class Foo {
private $bar;
public function __construct($bar = null){
$this->bar = isset($bar) ? $bar : new Bar();
}
}
That way, you can use the default class by default, and if you need to change the functionality, you can do that too.

Pros and Cons of Interface constants [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
PHP interfaces allow the definition of constants in an interface, e.g.
interface FooBar
{
const FOO = 1;
const BAR = 2;
}
echo FooBar::FOO; // 1
Any implementing class will automatically have these constants available, e.g.
class MyFooBar implement FooBar
{
}
echo MyFooBar::FOO; // 1
My own take on this is that anything Global is Evil. But I wonder if the same applies to Interface Constants. Given that Coding against an Interface is considered good practise in general, is using Interface Constants the only constants that are acceptable to use outside a class context?
While I am curious to hear your personal opinion and whether you use Interface constants or not, I'm mainly looking for objective reasons in your answers. I dont want this to be a Poll Type question. I'm interested in what effect using interface constants has on Maintainability. Coupling. Or Unit Testing. How does it relate to SOLID PHP? Does it violate any coding principles that are considered Good Practise in PHP? You get the idea …
Note: there is a similar question for Java that listed some quite good reasons why they are Bad Practice, but since Java isn't PHP, I felt it justified to ask it within the PHP tag again.
Well, I think that it boils down to the difference between good and good enough.
While in most cases you can avoid the use of constants by implementing other patterns (strategy or perhaps flyweight), there is something to be said for not needing a half dozen other classes to represent a concept. I think what it boils down to, is how likely is there a need for other constants. In other words, is there a need to extend the ENUM provided by the constants on the interface. If you can foresee needing to expand it, then go with a more formal pattern. If not, then it may suffice (it'll be good enough, and hence be less code to write and test). Here's an example of a good enough and a bad use:
Bad:
interface User {
const TYPE_ADMINISTRATOR = 1;
const TYPE_USER = 2;
const TYPE_GUEST = 3;
}
Good Enough:
interface HTTPRequest_1_1 {
const TYPE_CONNECT = 'connect';
const TYPE_DELETE = 'delete';
const TYPE_GET = 'get';
const TYPE_HEAD = 'head';
const TYPE_OPTIONS = 'options';
const TYPE_POST = 'post';
const TYPE_PUT = 'put';
public function getType();
}
Now, the reason that I chose those examples is simple. The User interface is defining an enum of user types. This is very likely to expand over time and would be better suited by another pattern. But the HTTPRequest_1_1 is a decent use-case, since the enum is defined by RFC2616 and will not change for the lifetime of the class.
In general, I don't see the problem with constants and class constants as being a global problem. I see it as a dependency problem. It's a narrow distinction, but a definite one. I see global problems as in global variables which are not enforced, and as such create a soft global dependency. But a hard-coded class creates an enforced dependency, and as such create a hard global dependency. So both are dependencies. But I consider the global to be far worse since it's not enforced... Which is why I don't like to lump class dependencies with global dependencies under the same banner...
If you write MyClass::FOO, you're hard-coded to the implementation details of MyClass. This creates a hard-coupling, which makes your code less flexible, and as such should be avoided. However, interfaces exist to permit exactly this type of coupling. Therefore MyInterface::FOO doesn't introduce any concrete coupling. With that said, I wouldn't introduce an interface just to add a constant to it.
So if you're using interfaces, and you're very sure that you (or anyone else for that matter) won't need additional values, then I don't really see a huge issue with the interface constants... The best designs wouldn't include any constants or conditionals or magic-numbers or magic-strings or hard-coded anything. However, that adds additional time to the development, as you must consider the uses. My view is that most times it's absolutely worth taking the additional time to build a great solid design. But there are times when good enough really is acceptable (and it takes an experienced developer to understand the difference), and in those cases it's fine.
Again, that's just my view on it...
I think that its usually better to handle constants, specially enumerated constants, as a separate type ("class") from your interface:
define(TYPE_CONNECT, 'connect');
define(TYPE_DELETE , 'delete');
define(TYPE_GET , 'get');
define(TYPE_HEAD , 'head');
define(TYPE_OPTIONS, 'options');
define(TYPE_POST , 'post');
define(TYPE_PUT , 'put');
interface IFoo
{
function /* int */ readSomething();
function /* void */ ExecuteSomething(/* int */ param);
}
class CBar implements IFoo
{
function /* int */ readSomething() { ...}
function /* void */ ExecuteSomething(/* int */ param) { ... }
}
or, if you want to use a class as a namespace:
class TypeHTTP_Enums
{
const TYPE_CONNECT = 'connect';
const TYPE_DELETE = 'delete';
const TYPE_GET = 'get';
const TYPE_HEAD = 'head';
const TYPE_OPTIONS = 'options';
const TYPE_POST = 'post';
const TYPE_PUT = 'put';
}
interface IFoo
{
function /* int */ readSomething();
function /* void */ ExecuteSomething(/* int */ param);
}
class CBar implements IFoo
{
function /* int */ readSomething() { ...}
function /* void */ ExecuteSomething(/* int */ param) { ... }
}
Its not that you are using just constants, you are using the concept of enumerated values or enumerations, which a set of restricted values, are considered a specific type, with a specific usage ("domain" ? )

Reasoning Behind PHP5 Protected Variables

Can you explain what the reasoning would be on why I would want to use "protected" versus "public" or "private" on some class variables and methods in PHP5? I've just yet to find a case where I thought I needed "protected", and have either opted for "public" or "private" based on the intent. Even when working in teams, I have still yet to find a case (based on my knowledge thus far) of why "protected" is necessary for class variables and methods.
For instance, the Flourish library's fDate class provides a lot of functionality but not everything I need. So I extended w/ my own class.
I soon found out that its core internal variable, fDate::$date (time in seconds since 1970), was a private property. This made it impossible for me to access it in my subclass ThriveDate. Once the maintainer of Flourish changed it to a protected property, I was able to use it and thus adequately extend fDate.
Since you never know who might need to extend your class, and by how much, in the future, it's always best to make every internal property protected, unless there are great reasons for the property to never be modified by subclasses.
TL;DR: Private properties should be as rare as public properties: e.g. used almost never.
With protected its possible for an object of the class or any subclass to access that property. So its useful, if you want this restriction.
This is not strictly necessary, you can also make every property public, but then you will lose every control, who access and/or changes it. Also others may get confused, what all these "public properties" are good for, for which they have access to.
On the other hand you can make every property private, but then also every subclass can not access it anymore.
What about a real life example:
<?
// burguers.php
/* abstract */ class BurguerClass {
// nobody knows about these secret function
private function addSecretRecipeSauce() { ... }
// these one can can change in subclasses
// cannot be called globally
protected /* virtual */ function addBread() { ... }
protected /* virtual */ function addSalad() { ... }
protected /* virtual */ function addMeat() { ... }
protected /* virtual */ function addExtraIngredients() { ... }
// these one it can be access globally
public /* virtual */ function makeBurguer() {
$this->addBread();
$this->addSalad();
$this->addMeat();
$this->addExtraIngredients();
$this->addSecretRecipeSauce();
}
}
/* concrete */ class CheeseBurguerClass extends BurguerClass {
protected /* virtual */ function addCheese() { ... }
public /* override */ function makeBurguer() {
$this->addBread();
$this->addSalad();
$this->addMeat();
$this->addExtraIngredients();
// we add this one:
$this->addCheese();
}
}
/* concrete */ class RanchStyleBurguerClass extends BurguerClass {
protected /* override */ function addExtraIngredients() { ... }
}
/* concrete */ class EastCoastVegetarianStyleBurguerClass extends BurguerClass {
protected /* override */ function addMeat() {
// use soy "meat"
}
protected /* override */ function addExtraIngredients() { ... }
}
function burguers_main() {
$Cheesburguer = new CheeseBurguerClass();
// can be access
$Cheesburguer->makeBurguer();
}
// execute it
burguers_main();
?>
You just open the "Can I have a Cheesburguer" Software Development company. You are the C.E.O., you have several subordinates. You teach subordinates they can make new products based on the "burguerClass" recipe, and make new recipes.
You tell your employees how to "addBread" , "addSalad", "addMeat", "addExtraIngredients", and that operations can be changed by new ones, but cannot sell them separately, only can used in the "makeBurguer" operation.
But, you dont teach your employees the "addSecretRecipe" operation.
The way I understand it is that Private methods and properties cannot be seen by classes that extend; whereas Protected methods and properties can be seen but used only by the class it is defined within.
http://php.net/manual/en/language.oop5.visibility.php
when designing classes, isn't it normal to have private and public
variables or properties.
Granted my OOP experience is very limited, having
access to OOP development in CA-Visual Objects, Clipper, VB, and ASP.
But it was normal to have a series of public properties one could access
directly and then properties that could only be access by the class itself.
Of course in VB and ASP these were defined with Get, Let and Set methods,
but you could still access them directly.
You could also design properties that were read only as well.
Perhaps this is because of operator overloading...
I use protected methods and attributes rather than private mainly for testing purposes. This way it's much easier to create class mocks when writing unit tests.
OOP doesn't ends at organizing your code to classes (as structured programming doesn't ends at splitting code to functions). PHP is a script language, so when using it as OOP language, we should set up contstraints for ourselves.
I was very lucky, when I first met OOP, the language was Java, and the book was Bruce Ekcel - Thinking in Java (you can purchase it on Amazon or other stores, also previous editions can be downloaded from here for free: http://www.mindviewinc.com/Books/downloads.html ). I can recommend that book, even for PHP programmers. If you're not complete beginner, you will understand everything, and adopt it to PHP. I'm trying to programming in PHP like if it were Java (at least, the OOP part; there're no such cool associative arrays in Java, as in PHP).
Also, private, protected, and public categories are not too precise. Public should be split to "API method" and "can be called from other classes" (see "friendly"), protected should distinguish between "should be overwritten" and "must be implemented".
Learn OOP, it's worth.
There's one more thing I wanna to say, a basic pattern of OOP: use getters/setters, don't use public properties, if you use public properties, you just graved it to rock. Say, there's a status flag, now it has 2 possible state values, but if you wanna extend it, all the code must be revised, which use it. Use setState() and getState(), which functions first are simple ($this->state = $param; and return $this->state), but there will be no problem with extending the meaning of state, then you should re-write only these methods, even in the case, if the state is a derived value (e.g. its value is calculated from more flags).
There're several less or more deep similar topics in OOP, this getter/setter is probably the most important of the basic ones.
So, my tips are:
use OOP, it's your friend;
use PHP as like it were JAVA (a strict OOP language), and not like in FORTRAN.

Is it reasonable to have a fair amount of public properties in a class?

Or in more specific words, is it "ok" to not be relying on setters and getters?
I'm dealing with a class that checks the availability of rooms and sets public properties of which there are more than a dozen. Things such as:
unitNumber
roomTypes ( array )
codeCorporate
codeGroup
numberKids
numberAdults
numberRooms
currency
minRate
maxRate
soapServer
units ( array )
hotelId
And after an object is instantiated those properties are set with $this-> inside various methods. However the code that deals with the object often sets public properties directly instead of using getter/setter methods:
$object->something = 3;
foreach ($object->things as $thing ) { }
If I have the time to refactor this class..
Should I stick all of these properties in a data array that's a private property, and define __set and __get methods?
Should I make a single getter method for each of the properties?
In my opinion, it is rarely a good idea to have any public members. It increases coupling between classes, and makes refactoring very complicated (should you need it.)
Setters/Getters are the way to go, and the very small performance penalty that you pay for it is usually either optimized away, or trumped by elegance.
To answer your question about array vs. single-getter-per-var, it's a matter of taste. I tend to only keep variables of a similar type within an array, and separate the rest.
I personally have yet to find a truly good reason for a public property, though im open for suggestion :-)
Although i much prefer specified getters/setters for each property (whether that's a proxy to a generalized get($name) or not). I assume you have other code already that uses direct assignment so in that case i would say to proceed with using the magic __get/__set methods.
I think most people will recommend using setters & getters. Right now you're limited to simply setting & fetching the property, but what if you want to log when that property is accessed? Or perhaps you want to run the value by a validation function first (email, phonenumber, zip code, etc). Maybe you'll need to call another function, or set another property. I think you see where I'm heading with this. By using setters & getters, you add a valuable layer of encapsulation to your classes, and 99% of the time this is worth the extra typing you'll need to do ;) Imagine trying to do the examples above without setters & getters. It'd be a big headache to say the least.
Edit: I forgot to mention Doctrine. It's an object relation mapper (ORM) that can automatically setup setters & getters for you (amongst other things). You can check it out at http://www.doctrine-project.org/
I would take a step back and ask some more general questions:
Why am I having to expose this much information; what is using it and why?
Is this class really just a data structure without behavior, in which case should be a private class to some other class?
Does this class serve a single purpose, or is it on the path to becoming monolithic?
You may discover that you are able to create views of an instance of a class to export to a database, display in a form, etc. Check out the "Builder" and "Acyclic Visitor" patterns to start with.
Regarding accessors, I do not see a need to use them for what you are describing: retrieving class properties and internal state information, aka a struct. However, for attributes of a class I could see the benefit in certain cases, but more for retrieving attributes, not for mutations of your object's state.
If I may add my grain of salt several months later :
It is very un-OO to have public properties. Everything should be encapsulated, simply because (among other reasons) using direct attribute manipulation doesn't give you ways to easily refactor or perform (more) control checks when some external source modifies the field. For example, let's say you have a class with many fields that is used throughout a project several times, and that project contains several thousands of files; it's a project that has been running and expanded for a few years now. Let's say that the company is changing it's business model, or that a problem is found with some of the field's data type and now is required to have some validation; will you duplicate that validation in all those thousands of source code that is directly accessing the public member? In PHP, the solution may be simple, but not in most OO programming language (i.g. Java). The fact is that OO is based on encapsulation. In short, encapsulation doesn't only produce clean code, but also highly maintainable (not to say cost-effective and cohesive) code.
Your suggestion of having a private member (array) being manipulated by __get / __set is good. This way, if you need some extra validation along the road, simply create your setter and/or your getter and it will be the end of it. Some may argue with that being counter productive as the code completion cannot kick-in on __get / __set. IMHO, relying on code completion is simply lazy coding. But then again, having every member have it's own getter and/or setter allows you to write a more comprehensive API documentation. Personally, I usually use that technique for internal or very general purpose classes. If all your fields do not require any validation, or there are as you said several dozen of them, then using magic methods would be acceptable, in my opinion.
The bottom line is to avoid direct member access on class instances, period. How you decide to achieve this is strictly up to you. Just make sure that the API is well documented the more abstract you make it.
On a final note, in PHP, if you already have classes that are being used that are not encapsulating their fields, for example something like
class SomeObject {
public $foo;
public $bar;
public $baz;
//...
}
you can simply fix this class without having to refactor anything with something like :
class SomeObject {
private $_foo; // having underscore as prefix helps to know what's private/protected
private $_bar; // inside the code.
private $_baz;
public function __get($name) {
$methodName = 'get'.ucfirst($name);
if (method_exists($this, $methodName)) {
return $this->{$methodName}();
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function __set($name, $value) {
$methodName = 'set'.ucfirst($name);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function getFoo() { return $this->_foo; }
public function setFoo($value) { $this->_foo = $value; }
public function getBar() { return $this->_bar; }
public function setBar($value) { $this->_bar = $value; }
public function getBaz() { return $this->_baz; }
public function setBaz($value) { $this->_baz = $value; }
}
And then
$obj = new SomeObject();
$obj->foo = 'Hello world'; // legacy code support
$obj->setFoo('Hello world'); // same thing, but preferred
And you satisfy both the OO paradigm and having direct access to attributes of an instance. You could also have __call() check for prefix 'get' or 'set' and call __get() and __set() accordingly, but I would not go that far, though this would truly enable general purpose classes to access it's private members via ->member and ->getMember()/->setMember()

Categories