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" ? )
Related
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.
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 8 years ago.
Improve this question
Class A
{
public function __construct(Foo $foo, Bar $bar, MyCustomType1 $mct)
{
//...
}
//...
public function getFooBarFunction()
{
$this->foo->aMethod();
$this->bar->anotherMethod();
//some other execution here
}
}
Class B
{
public function __construct(Foo $foo, Bar $bar, MyCustomType2 $mct)
{
//...
}
//...
public function getFooBarFunction()
{
$this->foo->aMethod();
$this->bar->anotherMethod();
//some other execution here (same of Class A)
}
}
Class C
{
public function __construct(Foo $foo, Bar $bar, MyCustomType3 $mct)
{
//...
}
//...
public function getFooBarFunction()
{
$this->foo->aMethod();
$this->bar->anotherMethod();
//some other execution here (same of Class B and Class A)
}
}
As you can see this code doesn't respect the DRY principles. I can easily collapse getFooBarFunction() into another class and use that method.
A) Create a SuperClass and migrate getFooBarFunction() into it. I need to replicate __construct() also ($this-> references).
Pros
- quite easy to do
- I can create an interface for MyCustomType(s) and use that into construct in substituion of concrete class(es)
Cons
- what if child class need to add a parameter into construct phase?
- what if I can't group MyCustomType(s) under same interface?
B) Create a SuperClass and use setters to "inject" Foo and Bar objects
Pros
- quite easy too
- I don't need to share constructor
Cons
- what if I forgot to inject parameters? Have I to add additional explicit checks into SuperClass and raise exceptions?
C) Create a SuperClass and let getFooBarFunction() accept Foo and Bar objects
Pros
- quite easy too
- I don't need to share constructor
Cons
- Is really necessary, in that case, inheritance?
D) Create an indipendent class (service?) and let A,B,C instantiate it and use it directly
What's best approach (or the "best practice") and why? There are any others?
UPDATE
Class A, Class B and Class C are some objects that doesn't share any information each others (they represent a Room, a Service, a Supplement). Only common feature is that every class has a relationship with i18n table (each one with his own table). So my getFooBarFunction() is only a function used to retrieve static types (stored somewhere, it's not important) that indicates the type of i18n text (title, description, short name, and so on)
UPDATE2 Real code
private function getTextTypeNameEntity()
{
$text_type_repository = $this->getTextTypeRepository();
$text_type_name_id = $this->container->getParameter('foo_project.text_type.name');
$text_type_name = $text_type_repository->findOneById($text_type_name_id);
return $text_type_name;
}
this function is getFooBarFunction()
Answer for update 2
You say this function only fetches text from an repository by an unique id. Without knowing the complete class this sounds like a code smell. A class should only do one thing and do it well. When you implement features, which are not strictly related, you extend the class over is boundaries. I would change the getFooBarFunction to only provide the text id:
public function getTextId() {
return 'some-awesome-unique-text-id';
}
Original post
When looking at the code you provided I can only see one difference, the MyCustomType. I would type hint a shared interface which implements the signature for each method that can be called (interface basics). This can also be applied to the Foo and Bar classes. By using interfaces you can more easily swap actual class implementations.
You said: "What if I cannot group my custom type under the same interface?". This is tricky and one of the hard things to do with interfaces. Think of interfaces as a contract. If you change the method signatures of a class, but tries to use it in place of another you are guaranteed to run into errors. This will also make your code harder to maintain/read as you will attempt to handle edge cases all over the place. Try to stick with the interface.
You said: "what if I forgot to inject parameters?". First off this should be considered a bug/error and you as developer is responsible, sorry :D
You then later said, "what if I need to pass another parameter during construction?". To me that sounds like a different class all together and should be treated as such. Then if you need another parameter anyway, you can just extend this class and overwrite only the constructor. Something like the following.
abstract class AbstractImplementation {
public function __construct(FooInterface $foo, BarInterface $bar, CustomInterface $custom) {
// Initialize properties.
}
/*
* This could also be declared abstract if each implementation
* is different.
*/
public function getFooBarFunction() {
// Perform basic actions
}
}
class ActualImplementation extends AbstractExample {
public function getFooBarFunction() {
// Perform specific actions
}
}
Then if you need another parameter you can do. This should be considered an edge-case.
class ExtendedImplementation extends ActualImplementation {
public function __construct(Extra $extra, FooInterface $foo, BarInterface $bar, CustomInterface $custom) {
parent::__construct($foo, $bar, $custom);
$this->extra = $extra;
}
}
Hope my thoughts can help you, happy coding!
I would opt for D + interfacing your classes. If getFooBarFunction() has nothing to do with the inner workings of A,B or C and the implementation is always the same in all classes then it shouldn't be a member of those classes. If the code calling A,B and C needs to know, that the method is there I would extract getFooBarFunction() in an interface and implement that in A,B and C. This way, the code outside can be sure the method is always there and is implemented in a working way.
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
Okay, this is really bugging me and I'm starting to think it all comes down to personal choice rather than a particular way of being more efficient or writing better code: Should I or should I not use getter/setter methods within a PHP project? The answers so far that I've read are rather conflicting and not entirely suited towards PHP, which is not a compiled language. For example, take this question on Stack Overflow ("Why use getters and setters?"). There's a number of good reasons presented as to why I should use them within my code, yet all the child comments mention how Accessors are evil and should be avoided, interspersed between a few more disturbing comments which mention that they should be avoided entirely because it "mucks up your code".
All I'm getting is conflicting answers, none of which are relevant to a interpreted PHP environment. Can someone shine some light on why/why not they should be used within PHP, and their rationale behind that decision? Does it really matter if we can simply define a property as private or protected and, anyway:
The encapsulation getters and setters offer are laughably thin
... quoted from "sbi" (Why use getters and setters?)
Personally, I still don't see how:
Class Foo {
public $bar;
function setBarType($val) {
$this->bar = $val;
}
}
$fee = new Foo();
$fee->setBarType(42);
is superior to this:
Class Foo {
public $bar;
}
$fee = new Foo();
$fee->bar = 42;
The blog post you linked to starts with a crucial sentence (emphasis added) :
Every getter and setter in your code represents a failure to encapsulate and creates unnecessary coupling.
Encapsulation is the most important idea of Object Oriented Programming. It essentially boils down to hiding complexity by wrapping it neatly inside classes. In an ideal world, when you use a class, you shouldn't have to know anything whatsoever about its inner workings or its state. Some people (like this blog author) will argue that having getters and setters is already way too much information about the insides of the class. In their view, a class should only have methods that enable us to tell an object to do something, never mind how it does it or what state it is in. Using a setter is not "telling the object to do something", it is mucking with the object's state from outside.
Instead of doing this :
$a = myObject();
// Querying object state, making a decision outside the object, and changing its state
if ($a->getWarbleFizz() < 42) {
$a->setYourWarbleFizzTo(42);
}
// Gee, I hope I made the right decision...
$a->nowDoSomethingUseful();
You should be writing code like this :
$a = myObject(42);
$a->doStuff();
Or this :
$a = myObject();
$a->doStuff(42);
Related reading : Tell, don't ask.
Because if the implementation of how the value is set changes (to a db), you don't have to change the callers. Another example is that you may need to do some checking on the value before setting it.
Having a method lets you intercept the setting/getting of that variable, doing it when it doesn't seem like you need it makes your code more change friendly.
Property getters
Languages like C# and recent versions of JavaScript allow you to intercept property reading and writing, so you can just use properties in languages that support it.
Object watchers
Some languages allow you to intercept the reading/setting of all JavaScript's Object.watch, or inaccessible properties with PHP's __get. This allows you to implements getters and setters but you get a performance hit because of the overhead they create for every property access. This answer talks about other problems with getters and setters. Best practice: PHP Magic Methods __set and __get
Getters and Setters are OK, but...
Just making boilerplate getters and setters is better, but is almost as bad as public properties. If anybody can change your object's state (specially with multiple properties), it won't be well encapsulated. http://cspray.github.io/2012/05/13/stop-calling-them-getters-setters.html
A great profit of using a getter and setter is, whenever you need to make changes you only have to modify the getter and setter.
I'll try to explain with an example:
protected $date;
public function getDate(){
return $this->date;
}
public function setDate($date){
$this->date = $date;
}
Imagine there is a reason the date should always be incremented with one day. You will have to search in your entire project where you accessed your class member.
But by using getters and setters you could change the code to:
protected $date;
public function getDate(){
return $this->date;
}
public function setDate($date){
$date = new DateTime($date);
$date->modify('+1 day');
$this->date = $date;
}
One OOP principe is encapsulation. A class is responsible to all variables that are contained inside this class.
By setting a public variable, you are breaking that principe.
By creating an accessor (setter), you're indirectly breaking that principe by giving a chance for that value to be changed outside of the class.
The advantage of a getter is that the calling method don't need to care about how the data is retrieved. It only know that it will get the expected data and that's all. Here the encapsulation principe is respected.
The advantage of a setter is that the class have the chance to check the new value before applying it. In a perfect world, there is no need for accessors because a class can fully manage all his variables. In the real world, sometimes you need to set a value or get it from the outside.
The best way to approach the perfect world is to limit accesors only to the very few variables that have to be modified. And check setted values if possible.
About your example, the second solution is better because you save one level in the php stack. Your accessor is useless because you variable is public anyway (so, no encapsulation) and don't perform any additionnal check. But when possible, you SHOULD use accessor to check the data. If the data isn't needed anywhere else in your application, then, don't do any accessor.
If you don't use getters and setters in a language like PHP, which is not type safe, then how are you going to ensure the type of the object's property is correct?
I may be missing the point completely, but if you need access to a property from outside of the object, I think it's still the best option to use accessors...
Also, as Juon Mendes mentions: some languages offer you to intercept when the properties themselves are being addressed. This may also be coming to PHP
You could even have a public setter, and a protected getter:
class TimePeriod {
protected $Seconds = 3600;
public $Hours {
get { return $this->Seconds / 3600; }
set { $this->Seconds = $value * 3600; }
}
// This property is read only as there is no setter
public $Minutes {
get { return $this->Seconds / 60; }
}
/* public getter, protected setter */
public $Milliseconds {
get { return $this->Seconds * 1000; }
protected set { $this->Seconds = $value / 1000; }
}
}
The choice is up to you. Other important features of PHP 5 to consider are magic getter/setters:
http://www.php.net/manual/en/language.oop5.overloading.php#object.set
http://www.php.net/manual/en/language.oop5.overloading.php#object.get
The magic of this is that you are able to do something like the following and decide where to get/set variables without having to declare them beforehand:
Class Foo {
private $data = array();
function __set($name,$val) {
$this->$data[$name] = $val;
}
function __get($name) {
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
else {
return null;
}
}
Voila, something like this now happens automagically:
$fee = new Foo();
$fee->bar = 42;
IMO using getters and setters is a good practice and increases code readability too.
Apart from checking the value while setting, there is another example, consider if u call getMoviesList(). Now this get method can be implemented in anyway, it can get movies list from the local db, get it from the online web service and so on... So the code making the decision maybe inside this function. Wherever u call it from, u don't care about the location and how it gets it. U just get the movies list.
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.
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.