I prefer coding standards to be logical. This is my argument for why the following set of standards are not.
I need to know one of two things: (1) why I'm wrong, or (2) how to convince my team to change them.
camelCase: Functions, class names, methods, and variables must be camelCase.
Makes it hard to differentiate between variables and classes
Goes against PHP's lowercase/underscored variables/functions and UpperCamelCase classes
Example:
$customerServiceBillingInstance = new customerServiceBillingInstance(); // theirs
$customer_service_billing_instance = new CustomerServiceBillingInstance();
Functions/methods must always return a value (and returned values must always be stored).
This appears on hundreds of our php pages:
$equipmentList = new equipmentList();
$success = $equipmentList->loadFromDatabase(true, '');
$success = $equipmentList->setCustomerList();
$success = $equipmentList->setServerList();
$success = $equipmentList->setObjectList();
$success = $equipmentList->setOwnerList();
$success = $equipmentList->setAccessList();
The return value is rarely used but always stored. It encourages the use of copy-and-paste.
No static methods
Lines like the following appear thousands of times in the codebase:
$equipmentList = new equipmentList();
$success = $equipmentList->loadFromDatabase();
I would prefer:
$equipmentList = equipmentList::load();
What reason is there to not use static methods or properties? Aren't static methods responsible for non-instance-specific logic? Like initializing or populating a new instance?
Your code is not OOP unless everything returns an object
There's a piece of code that performs a query, checks it several ways for errors, and then processes the resulting array. It is repeated (copied+pasted) several times, so I put it in the base class. Then I was told returning an array is not OOP.
How do you defend these practices? I really do need to know. I feel like I'm taking crazy pills.
If you can't defend them, how do you convince the adamant author they need to be changed?
I would suggest trying to list down the goals of your coding standards, and weigh them down depending on which goals is the most important and which goals are less important.
PS: I don't speak PHP, so some of these arguments may contain blatantly incorrect PHP code.
camelCase: Functions, class names, methods, and variables must be camelCase.
Workplace's Apparent Reason: "consistency" at the cost of "information density in name".
Argument:
1) Since 'new' keyword should always be followed by a class, then you can easily spot illegal instantiation, e.g.:
$value = new functionName();
$value = new local_variable();
$value = new GLOBAL_VARIABLE();
would raise an alarm, because 'new' should be followed by a TitleCase name.
$value = new MyClass(); // correct
Relying on Case makes it easy to spot these errors.
3) Only functions can be called, you can never call variables. By relying on Case Rule, then we can easily spot fishy function calls like:
$value = $inst->ClassName();
$value = $inst->instance_variable();
$value = $GLOBAL_VARIABLE();
3) Assigning to a function name and global variables is a huge deal, since they often lead to behavior that is difficult to follow. That's why any statement that looks like:
$GLOBAL = $value;
$someFunction = $anotherFunction;
should be heavily scrutinized. Using Case Rule, it is easy to spot these potential problem lines.
While the exact Case Rule may vary, it is a good idea to have different Case Rule for each different type of names.
Functions/methods must always return a value (and returned values must always be stored).
Workplace's Apparent Reason: apparently another rule born out of blind consistency. The advantage is that every line of code that isn't a flow control (e.g. looping, conditionals) is an assignment.
Argument:
1) Mandatory assignment makes unnecessary long lines, which harms readability since it increases the amount of irrelevant information on screen.
2) Code is slightly slower as every function call will involve two unnecessary operation: value return and assignment.
Better Convention:
Learn from functional programming paradigm. Make a distinction between "subroutine" and "functions". A subroutine does all of its works by side-effect and does not return a value, and therefore its return value never need to be stored anywhere (subroutine should not return error code; use exception if it is really necessary). A function must not have any side-effect, and therefore its return value must be used immediately (either for further calculations or stored somewhere). By having side-effect free function policy, it is a waste of processor cycle to call a function and ignoring its return value; and the line can therefore be removed.
So, there is three type of correct calls:
mySubroutine(arg); // subroutine, no need to check return value
$v = myFunction(arg); // return value is stored
if (myFunction(arg)) { ... } // return value used immediately
you should never have, for example:
$v = mySubroutine(arg); // subroutine should never have a return value!
myFunction(arg); // there is no point calling side-effect free function and ignoring its return value
and they should raise warning. You can even create a naming rule to differentiate between subroutine and functions to make it even easier to spot these errors.
Specifically disallow having a "functiroutine" monster that have both a side-effect and return value.
No static methods
Workplace Apparent Reason: probably someone read somewhere that static is evil, and followed blindly without really doing any critical evaluation of its advantages and disadvantages
Better Convention:
Static methods should be stateless (no modifying global state). Static methods should be a function, not subroutine since it is easier to test a side-effect-free function than to test the side-effects of a subroutine. Static method should be small (~4 lines max) and should be self-contained (i.e. should not call too many other static methods too deeply). Most static methods should live in the Utility class; notable exceptions to this is Class Factories. Exceptions to this convention is allowed, but should be heavily scrutinized beforehand.
Your code is not OOP unless everything returns an object
Workplace Apparent Reason: flawed understanding of what is OOP.
Argument:
Fundamental datatypes is conceptually also an object even if a language's fundamental datatype doesn't inherit from their Object class.
If you can't defend them, how do you
convince the adamant author they need
to be changed?
By giving strong/valid arguments! Still I think you should only change them when your arguments are really strong! Because most of the programmers at work are used to these coding standards which is a big point why to use them.
==
Like others told before this is pretty subjective, but these are mine opinions/arguments.
1. camelCase: Functions, class names, methods, and variables must be camelCase.
I would use the PHP style if I code in PHP and the Camelcase style if I code in Java. But it does not matter which style you choose as long as you stay consistent.
2. Functions/methods must always return a value (and returned values must always be stored).
This is nonsense in my opinion. In almost all programming languages you have some sort of 'void' type. But from a testing point of view most of the times it is useful if your function are side effect free. I don't agree that your production code should always use the return value especially if it does not have any use.
3. No static methods
I would advice you to read static methods are death to testability from misko
During the instantiation I wire the
dependencies with mocks/friendlies
which replace the real dependencies.
With procedural programing there is
nothing to “wire” since there are no
objects, the code and data are
separate.
Although PHP is a dynamic language so it is not really a big problem. Still the latest PHP does support typing so that I still think most of times static methods are bad.
4. Your code is not OOP unless everything returns an object
I believe(not 100% sure) a truly OOP language should do this(return an object), but I don't agree with this like a of like languages like for example Java(which I believe is not trully OOP). A lot of the times your methods should just return primitives like String/Int/Array/etc. When you are copying and pasting a lot of code it should be a sign that something is not totally right with your design. You should refactor it(but first have a tests(TDD) ready so that you don't break any code).
Many of these coding standards are very subjective, but some important things to consider are:
Get a single set of code naming and style rules, and follow them. If you don't have already defined rules, make sure to get rules figured out. Then work at refactoring the code to follow them. This is an important step in order to make it easier for new developers to jump on board, and keep the coding consistent among developers.
It takes time and effort to change the coding standards your company puts in place. Any change to the rules means that the code really has to be gone through again to update everything to be consistent with the new standards.
Keeping the above in mind, and looking more along the lines of specific PHP coding standards. The first thing to look at is if your company uses any sort of framework, look at the coding standards for that framework as you may want to stick with those in order to stay consistent across all the code. I have listed links to a couple of the popular PHP frameworks below:
Zend Framework Naming Conventions and Zend Framework Code Style
Pear Code Standards
My personal preference in regards to your specific coding styles:
1. camelCase: Functions, class names, methods, and variables must be camelCase
Class names should be Pascal Case (Upper Camel Case).
So in your example:
class CustomerServiceBillingInstance
{
// Your class code here
}
Variables and functions I generally feel should be camel case.
So either one of these, depending on your preference in terms of underscores:
$customerServiceBillingInstance = whatever;
$customer_service_billing_instance = whatever;
2. Functions/methods must always return a value (and returned values must always be stored).
This one seems like extra code and like you could end up using extra resources. If a function doesn't need to return anything, don't return anything. Likewise, if you do not care about what a function returns, don't store it. There is no point in using the extra memory to store something you are never going to look at.
An interesting thing you may want to try on this one, is running some benchmarks. See if it takes extra time to return something and store it even though you are not looking at it.
3. Your code is not OOP unless everything returns an object
In this instance, I feel you have to draw the line somewhere. Performance wise, it is faster for you to do:
return false;
Than to do:
return new Boolean(false); // This would use up unnecessary resources but not add very much to readability or maintainability in my opinion.
Defending a coding standard
To defend a coding standard that you feel is right (or showing why another is not as good), you really are going to have to bring up one of two points.
Performance. If you can show that a particular coding standard is adversely affecting performance, you may want to consider switching.
Maintainability/Readability. Your code should be easy to read/understand.
The goal is to find the happy median between performance and the maintainability/readability. Sometimes it is an easy decision because the most maintainable option is also the best performing, other times there is a harder choice to be made.
Standards and conventions exist for many reasons, but most of these reasons boil down to "they make code easier to write and maintain." Instead of asking "is this the correct way to do X?" just cut right to the chase and ask if this criterion is met. The last point in particular is simply a matter of definition. OOP is a means, not an end.
Many of those are matters of taste. You can argue for or against camelCase all day.
However, the storing of return values that are never used is Wrong. There is no value to the code. The code is not executed. You might as well sprinkle $foo = 47 * 3; around the code.
Any code that is not doing something useful must be removed.
The bigger issue is, if you're working for a clueless manager, it may be time to move.
The one aspect of this that I don't see anybody else commenting on is the "2. Functions/methods must always return a value (and returned values must always be stored)."
If you're not using exceptions, then any function that can fail does have to return a value. The last clause is misworded; return values don't always need to be STORED, but they do always need to be CHECKED. Again, that's IF you're not using exceptions, which isn't common these days, but it's still worth mentioning.
As far as I know quite a few of the conventions you posted are encouraged by the Zend PHP Framework as well. You're not alone, I'm a Codeigniter user and my work is pretty big on using Zend Framework. These kind of naming conventions are absolutely ridiculous and I honestly can only see an advantage of using camelCase for variable names, not function names as it makes things confusing.
Read this: http://framework.zend.com/manual/en/coding-standard.naming-conventions.html
Do these coding conventions look familiar to you?
Related
What is the utility of the global keyword?
Are there any reasons to prefer one method to another?
Security?
Performance?
Anything else?
Method 1:
function exempleConcat($str1, $str2)
{
return $str1.$str2;
}
Method 2:
function exempleConcat()
{
global $str1, $str2;
return $str1.$str2;
}
When does it make sense to use global?
For me, it appears to be dangerous... but it may just be a lack of knowledge. I am interested in documented (e.g. with example of code, link to documentation...) technical reasons.
Bounty
This is a nice general question about the topic, I (#Gordon) am offering a bounty to get additional answers. Whether your answer is in agreement with mine or gives a different point of view doesn't matter. Since the global topic comes up every now and then, we could use a good "canonical" answer to link to.
Globals are evil
This is true for the global keyword as well as everything else that reaches from a local scope to the global scope (statics, singletons, registries, constants). You do not want to use them. A function call should not have to rely on anything outside, e.g.
function fn()
{
global $foo; // never ever use that
$a = SOME_CONSTANT // do not use that
$b = Foo::SOME_CONSTANT; // do not use that unless self::
$c = $GLOBALS['foo']; // incl. any other superglobal ($_GET, …)
$d = Foo::bar(); // any static call, incl. Singletons and Registries
}
All of these will make your code depend on the outside. Which means, you have to know the full global state your application is in before you can reliably call any of these. The function cannot exist without that environment.
Using the superglobals might not be an obvious flaw, but if you call your code from a Command Line, you don't have $_GET or $_POST. If your code relies on input from these, you are limiting yourself to a web environment. Just abstract the request into an object and use that instead.
In case of coupling hardcoded classnames (static, constants), your function also cannot exist without that class being available. That's less of an issue when it's classes from the same namespace, but when you start mix from different namespaces, you are creating a tangled mess.
Reuse is severly hampered by all of the above. So is unit-testing.
Also, your function signatures are lying when you couple to the global scope
function fn()
is a liar, because it claims I can call that function without passing anything to it. It is only when I look at the function body that I learn I have to set the environment into a certain state.
If your function requires arguments to run, make them explicit and pass them in:
function fn($arg1, $arg2)
{
// do sth with $arguments
}
clearly conveys from the signature what it requires to be called. It is not dependent on the environment to be in a specific state. You dont have to do
$arg1 = 'foo';
$arg2 = 'bar';
fn();
It's a matter of pulling in (global keyword) vs pushing in (arguments). When you push in/inject dependencies, the function does not rely on the outside anymore. When you do fn(1) you dont have to have a variable holding 1 somewhere outside. But when you pull in global $one inside the function, you couple to the global scope and expect it to have a variable of that defined somewhere. The function is no longer independent then.
Even worse, when you are changing globals inside your function, your code will quickly be completely incomprehensible, because your functions are having sideeffects all over the place.
In lack of a better example, consider
function fn()
{
global $foo;
echo $foo; // side effect: echo'ing
$foo = 'bar'; // side effect: changing
}
And then you do
$foo = 'foo';
fn(); // prints foo
fn(); // prints bar <-- WTF!!
There is no way to see that $foo got changed from these three lines. Why would calling the same function with the same arguments all of a sudden change it's output or change a value in the global state? A function should do X for a defined input Y. Always.
This gets even more severe when using OOP, because OOP is about encapsulation and by reaching out to the global scope, you are breaking encapsulation. All these Singletons and Registries you see in frameworks are code smells that should be removed in favor of Dependency Injection. Decouple your code.
More Resources:
http://c2.com/cgi/wiki?GlobalVariablesAreBad
How is testing the registry pattern or singleton hard in PHP?
Flaw: Brittle Global State & Singletons
static considered harmful
Why Singletons have no use in PHP
SOLID (object-oriented design)
Globals are unavoidable.
It is an old discussion, but I still would like to add some thoughts because I miss them in the above mentioned answers. Those answers simplify what a global is too much and present solutions that are not at all solutions to the problem. The problem is: what is the proper way to deal with a global variable and the use of the keyword global? For that do we first have to examine and describe what a global is.
Take a look at this code of Zend - and please understand that I do not suggest that Zend is badly written:
class DecoratorPluginManager extends AbstractPluginManager
{
/**
* Default set of decorators
*
* #var array
*/
protected $invokableClasses = array(
'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
);
There are a lot of invisible dependencies here. Those constants are actually classes.
You can also see require_once in some pages of this framework. Require_once is a global dependency, hence creating external dependencies. That is inevitable for a framework. How can you create a class like DecoratorPluginManager without a lot of external code on which it depends? It can not function without a lot of extras. Using the Zend framework, have you ever changed the implementation of an interface? An interface is in fact a global.
Another globally used application is Drupal. They are very concerned about proper design, but just like any big framework, they have a lot of external dependencies. Take a look at the globals in this page:
/**
* #file
* Initiates a browser-based installation of Drupal.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
/**
* Global flag to indicate that site is in installation mode.
*/
define('MAINTENANCE_MODE', 'install');
// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the system requirements page for more information.';
exit;
}
// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();
Ever written a redirect to the login page? That is changing a global value. (And then are you not saying 'WTF', which I consider as a good reaction to bad documentation of your application.) The problem with globals is not that they are globals, you need them in order to have a meaningful application. The problem is the complexity of the overall application which can make it a nightmare to handle.
Sessions are globals, $_POST is a global, DRUPAL_ROOT is a global, the includes/install.core.inc' is an unmodifiable global. There is big world outside any function that is required in order to let that function do its job.
The answer of Gordon is incorrect, because he overrates the independence of a function and calling a function a liar is oversimplifying the situation. Functions do not lie and when you take a look at his example the function is designed improperly - his example is a bug. (By the way, I agree with this conclusion that one should decouple code.)
The answer of deceze is not really a proper definition of the situation. Functions always function within a wider scope and his example is way too simplistic. We will all agree with him that that function is completely useless, because it returns a constant. That function is anyhow bad design. If you want to show that the practice is bad, please come with a relevant example. Renaming variables throughout an application is no big deal having a good IDE (or a tool). The question is about the scope of the variable, not the difference in scope with the function. There is a proper time for a function to perform its role in the process (that is why it is created in the first place) and at that proper time may it influence the functioning of the application as a whole, hence also working on global variables.
The answer of xzyfer is a statement without argumentation. Globals are just as present in an application if you have procedural functions or OOP design. The next two ways of changing the value of a global are essentially the same:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
In both instances is the value of $z changed within a specific function. In both ways of programming can you make those changes in a bunch of other places in the code. You could say that using global you could call $z anywhere and change there. Yes, you can. But will you? And when done in inapt places, should it then not be called a bug?
Bob Fanger comments on xzyfer.
Should anyone then just use anything and especially the keyword 'global'? No, but just like any type of design, try to analyze on what it depends and what depends on it. Try to find out when it changes and how it changes. Changing global values should only happen with those variables that can change with every request/response. That is, only to those variables that are belonging to the functional flow of a process, not to its technical implementation. The redirect of an URL to the login page belongs to the functional flow of a process, the implementation class used for an interface to the technical implementation. You can change the latter during the different versions of the application, but should not change those with every request/response.
To further understand when it is a problem working with globals and the keyword global and when not will I introduce the next sentence, which comes from Wim de Bie when writing about blogs:
'Personal yes, private no'. When a function is changing the value of a global variable in sake of its own functioning, then will I call that private use of a global variable and a bug. But when the change of the global variable is made for the proper processing of the application as a whole, like the redirect of the user to the login page, then is that in my opinion possibly good design, not by definition bad and certainly not an anti-pattern.
In retrospect to the answers of Gordon, deceze and xzyfer: they all have 'private yes'(and bugs) as examples. That is why they are opposed to the use of globals. I would do too. They, however, do not come with 'personal yes, private no'-examples like I have done in this answer several times.
The one big reason against global is that it means the function is dependent on another scope. This will get messy very quickly.
$str1 = 'foo';
$str2 = 'bar';
$str3 = exampleConcat();
vs.
$str = exampleConcat('foo', 'bar');
Requiring $str1 and $str2 to be set up in the calling scope for the function to work means you introduce unnecessary dependencies. You can't rename these variables in this scope anymore without renaming them in the function as well, and thereby also in all other scopes you're using this function. This soon devolves into chaos as you're trying to keep track of your variable names.
global is a bad pattern even for including global things such as $db resources. There will come the day when you want to rename $db but can't, because your whole application depends on the name.
Limiting and separating the scope of variables is essential for writing any halfway complex application.
Simply put there is rarely a reason to global and never a good one in modern PHP code IMHO. Especially if you're using PHP 5. And extra specially if you're develop Object Orientated code.
Globals negatively affect maintainability, readability and testability of code. Many uses of global can and should be replaced with Dependency Injection or simply passing the global object as a parameter.
function getCustomer($db, $id) {
$row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
return $row;
}
Dont hesitate from using global keyword inside functions in PHP. Especially dont take people who are outlandishly preaching/yelling how globals are 'evil' and whatnot.
Firstly, because what you use totally depends on the situation and problem, and there is NO one solution/way to do anything in coding. Totally leaving aside the fallacy of undefinable, subjective, religious adjectives like 'evil' into the equation.
Case in point :
Wordpress and its ecosystem uses global keyword in their functions. Be the code OOP or not OOP.
And as of now Wordpress is basically 18.9% of internet, and its running the massive megasites/apps of innumerable giants ranging from Reuters to Sony, to NYT, to CNN.
And it does it well.
Usage of global keyword inside functions frees Wordpress from MASSIVE bloat which would happen given its huge ecosystem. Imagine every function was asking/passing any variable that is needed from another plugin, core, and returning. Added with plugin interdependencies, that would end up in a nightmare of variables, or a nightmare of arrays passed as variables. A HELL to track, a hell to debug, a hell to develop. Inanely massive memory footprint due to code bloat and variable bloat too. Harder to write too.
There may be people who come up and criticize Wordpress, its ecosystem, their practices and what goes on around in those parts.
Pointless, since this ecosystem is pretty much 20% of roughly entire internet. Apparently, it DOES work, it does its job and more. Which means its the same for the global keyword.
Another good example is the "iframes are evil" fundamentalism. A decade ago it was heresy to use iframes. And there were thousands of people preaching against them around internet. Then comes facebook, then comes social, now iframes are everywhere from 'like' boxes to authentication, and voila - everyone shut up. There are those who still did not shut up - rightfully or wrongfully. But you know what, life goes on despite such opinions, and even the ones who were preaching against iframes a decade ago are now having to use them to integrate various social apps to their organization's own applications without saying a word.
......
Coder Fundamentalism is something very, very bad. A small percentage among us may be graced with the comfortable job in a solid monolithic company which has enough clout to endure the constant change in information technology and the pressures it brings in regard to competition, time, budget and other considerations, and therefore can practice fundamentalism and strict adherence to perceived 'evils' or 'goods'. Comfortable positions reminiscent of old ages these are, even if the occupiers are young.
For the majority however, the i.t. world is an ever changing world in which they need to be open minded and practical. There is no place for fundamentalism, leave aside outrageous keywords like 'evil' in the front line trenches of information technology.
Just use whatever makes the best sense for the problem AT HAND, with appropriate considerations for near, medium and long term future. Do not shy away from using any feature or approach because it has a rampant ideological animosity against it, among any given coder subset.
They wont do your job. You will. Act according to your circumstances.
It makes no sense to make a concat function using the global keyword.
It's used to access global variables such as a database object.
Example:
function getCustomer($id) {
global $db;
$row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
return $row;
}
It can be used as a variation on the Singleton pattern
I think everyone has pretty much expounded on the negative aspects of globals. So I will add the positives as well as instructions for proper use of globals:
The main purpose of globals was to share information between functions. back when
there was nothing like a class, php code consisted of a bunch of functions. Sometimes
you would need to share information between functions. Typically the global was used to
do this with the risk of having data corrupted by making them global.
Now before some happy go lucky simpleton starts a comment about dependency injection I
would like to ask you how the user of a function like example get_post(1) would know
all the dependencies of the function. Also consider that dependencies may differ from
version to version and server to server. The main problem with dependency injection
is dependencies have to be known beforehand. In a situation where this is not possible
or unwanted global variables were the only way to do achieve this goal.
Due to the creation of the class, now common functions can easily be grouped in a class
and share data. Through implementations like Mediators even unrelated objects can share
information. This is no longer necessary.
Another use for globals is for configuration purposes. Mostly at the beginning of a
script before any autoloaders have been loaded, database connections made, etc.
During the loading of resources, globals can be used to configure data (ie which
database to use where library files are located, the url of the server etc). The best
way to do this is by use of the define() function since these values wont change often
and can easily be placed in a configuration file.
The final use for globals is to hold common data (ie CRLF, IMAGE_DIR, IMAGE_DIR_URL),
human readable status flags (ie ITERATOR_IS_RECURSIVE). Here globals are used to store
information that is meant to be used application wide allowing them to be changed and
have those changes appear application wide.
The singleton pattern became popular in php during php4 when each instance of an object
took up memory. The singleton helped to save ram by only allowing one instance of an
object to be created. Before references even dependancy injection would have been a bad
idea.
The new php implementation of objects from PHP 5.4+ takes care of most of these problems
you can safely pass objects around with little to no penalty any more. This is no longer
necessary.
Another use for singletons is the special instance where only one instance of an object
must exist at a time, that instance might exist before / after script execution and
that object is shared between different scripts / servers / languages etc. Here a
singleton pattern solves the solution quite well.
So in conclusion if you are in position 1, 2 or 3 then using a global would be reasonable. However in other situations Method 1 should be used.
Feel free to update any other instances where globals should be used.
Should I type hint everything (parameters and return values) whenever possible? And maybe even strive to write code that can be type hinted? In the real world with real developers which may or may not be less than stellar is there any drawback to type hinting whenever possible?
In my mind, code that breaks fast and furious is one that breaks before it can enter production most of the time.
Type hinting is the way to go. I would start with type hinting arguments (combined with interfaces), return values, and whenever you initialize a variable or property. Combined with doc blocks, and you have just documented your code in a way that allows others to pickup quickly.
function getValue(\Settings\Bar $foo) : string
{
$val = (string) $foo->value;
//..
return $val;
}
$myVal = (string) getValue($bar);
If anyone makes a mistake, the debugger will pinpoint you the exact location. Moreover use
declare(strict_types=1);
at the top of all your php pages to enforce type hinting and you are on your way to write enterprise level code using PHP.
Type hinting helps other developers or even you to understand the code better without deep diving into it. You don't have to understand internal logic of a class or a function, or search a manual or the Internet to know the type of a value that this or that function returns.
It also helps to prevent one from making silly errors. For example, one thinks that a function accepts an ArrayAccess object, but in reality, the function accepts just arrays which might cause an error.
The only drawback I can see is that it's hard to maintain type hinting and keep everything consistent due to nature of PHP itself.
So, it's heavily recommended to do type hinting whenever it's possible. With modern IDEs like PHPStorm it becomes pretty easy to maintain type hinting and keep it up to date and consistent.
I understand this IS NOT easily testable/mockable:
public function index(){
$jedi = new Jedi(); // <-- "new" operator used here
...
}
Using Dependency Injection, I understand this IS now easily testable/mockable:
public function index(JediInterface $jedi){
$jedi->doSomething();
...
}
But does it matter about the method arguments? Consider this code below, is it also easily testable/mockable?
public function index(JediInterface $jedi){
$jedi->setLightSaber(new BlueLightsaber()); // <-- "new" operator used in argument
return $jedi->getLightsaberColor();
}
Note:
The $jedi class has the method definition:
public function setLightSaber(LightSaberInterface $saber)
If the constructor of a BlueLightSaber has absolutely no side-effects and you don't see the type of lightsaber changing in the near future, I'd keep your implementation the way it is. Adding indirection always introduces extra complexity.
As for testability, you are now testing whether a Jedi works correctly with a BlueLightSaber (i.e. you are writing integrated tests rather than isolated tests for just the jedi), but that doesn't have to be a problem per se. While it's true that when integrated tests fail it will be more difficult to pinpoint the exact problem, if the lightsaber truly is an implementation detail of the jedi you're perhaps better of writing an integrated test. Isolated tests tend to get in the way of future refactorings when they know too much about the implementation details.
(more information on isolated vs integrated tests here)
Another point worth mentioning: you are mixing a query (get lightsaber color) with logic that changes state (set lightsaber) in a single method invocation. This might be confusing for developers that use your code and can often be separated for better understandability. This principle is called Command-Query Separation (CQS). Also, I tend to avoid changing state of input arguments (the jedi) as much as possible, as it can lead to the same confusing bugs as violating CQS.
No, becasuse the object is created inside the mehod. Imagine, how would you substitute BlueSaber with ChainSaw in a different program that uses index()?
It will affect the testability. Maybe not inmediately, but it will when you need to test some object that works different depending on the saber color (here it is alway blue and you can't change that). You can argue that in this exact example that does not happen, but in general, it will.
Also, maybe in the future you want to alter the way BlueLightsaber works, so it will log some info when being created. If you can't mock it, real logs will be written when testing.
There are lots of reasons. The better and harder way to learn them is trying to test legacy code plagued with direct object instantiations.
What is the utility of the global keyword?
Are there any reasons to prefer one method to another?
Security?
Performance?
Anything else?
Method 1:
function exempleConcat($str1, $str2)
{
return $str1.$str2;
}
Method 2:
function exempleConcat()
{
global $str1, $str2;
return $str1.$str2;
}
When does it make sense to use global?
For me, it appears to be dangerous... but it may just be a lack of knowledge. I am interested in documented (e.g. with example of code, link to documentation...) technical reasons.
Bounty
This is a nice general question about the topic, I (#Gordon) am offering a bounty to get additional answers. Whether your answer is in agreement with mine or gives a different point of view doesn't matter. Since the global topic comes up every now and then, we could use a good "canonical" answer to link to.
Globals are evil
This is true for the global keyword as well as everything else that reaches from a local scope to the global scope (statics, singletons, registries, constants). You do not want to use them. A function call should not have to rely on anything outside, e.g.
function fn()
{
global $foo; // never ever use that
$a = SOME_CONSTANT // do not use that
$b = Foo::SOME_CONSTANT; // do not use that unless self::
$c = $GLOBALS['foo']; // incl. any other superglobal ($_GET, …)
$d = Foo::bar(); // any static call, incl. Singletons and Registries
}
All of these will make your code depend on the outside. Which means, you have to know the full global state your application is in before you can reliably call any of these. The function cannot exist without that environment.
Using the superglobals might not be an obvious flaw, but if you call your code from a Command Line, you don't have $_GET or $_POST. If your code relies on input from these, you are limiting yourself to a web environment. Just abstract the request into an object and use that instead.
In case of coupling hardcoded classnames (static, constants), your function also cannot exist without that class being available. That's less of an issue when it's classes from the same namespace, but when you start mix from different namespaces, you are creating a tangled mess.
Reuse is severly hampered by all of the above. So is unit-testing.
Also, your function signatures are lying when you couple to the global scope
function fn()
is a liar, because it claims I can call that function without passing anything to it. It is only when I look at the function body that I learn I have to set the environment into a certain state.
If your function requires arguments to run, make them explicit and pass them in:
function fn($arg1, $arg2)
{
// do sth with $arguments
}
clearly conveys from the signature what it requires to be called. It is not dependent on the environment to be in a specific state. You dont have to do
$arg1 = 'foo';
$arg2 = 'bar';
fn();
It's a matter of pulling in (global keyword) vs pushing in (arguments). When you push in/inject dependencies, the function does not rely on the outside anymore. When you do fn(1) you dont have to have a variable holding 1 somewhere outside. But when you pull in global $one inside the function, you couple to the global scope and expect it to have a variable of that defined somewhere. The function is no longer independent then.
Even worse, when you are changing globals inside your function, your code will quickly be completely incomprehensible, because your functions are having sideeffects all over the place.
In lack of a better example, consider
function fn()
{
global $foo;
echo $foo; // side effect: echo'ing
$foo = 'bar'; // side effect: changing
}
And then you do
$foo = 'foo';
fn(); // prints foo
fn(); // prints bar <-- WTF!!
There is no way to see that $foo got changed from these three lines. Why would calling the same function with the same arguments all of a sudden change it's output or change a value in the global state? A function should do X for a defined input Y. Always.
This gets even more severe when using OOP, because OOP is about encapsulation and by reaching out to the global scope, you are breaking encapsulation. All these Singletons and Registries you see in frameworks are code smells that should be removed in favor of Dependency Injection. Decouple your code.
More Resources:
http://c2.com/cgi/wiki?GlobalVariablesAreBad
How is testing the registry pattern or singleton hard in PHP?
Flaw: Brittle Global State & Singletons
static considered harmful
Why Singletons have no use in PHP
SOLID (object-oriented design)
Globals are unavoidable.
It is an old discussion, but I still would like to add some thoughts because I miss them in the above mentioned answers. Those answers simplify what a global is too much and present solutions that are not at all solutions to the problem. The problem is: what is the proper way to deal with a global variable and the use of the keyword global? For that do we first have to examine and describe what a global is.
Take a look at this code of Zend - and please understand that I do not suggest that Zend is badly written:
class DecoratorPluginManager extends AbstractPluginManager
{
/**
* Default set of decorators
*
* #var array
*/
protected $invokableClasses = array(
'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag',
);
There are a lot of invisible dependencies here. Those constants are actually classes.
You can also see require_once in some pages of this framework. Require_once is a global dependency, hence creating external dependencies. That is inevitable for a framework. How can you create a class like DecoratorPluginManager without a lot of external code on which it depends? It can not function without a lot of extras. Using the Zend framework, have you ever changed the implementation of an interface? An interface is in fact a global.
Another globally used application is Drupal. They are very concerned about proper design, but just like any big framework, they have a lot of external dependencies. Take a look at the globals in this page:
/**
* #file
* Initiates a browser-based installation of Drupal.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
/**
* Global flag to indicate that site is in installation mode.
*/
define('MAINTENANCE_MODE', 'install');
// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the system requirements page for more information.';
exit;
}
// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();
Ever written a redirect to the login page? That is changing a global value. (And then are you not saying 'WTF', which I consider as a good reaction to bad documentation of your application.) The problem with globals is not that they are globals, you need them in order to have a meaningful application. The problem is the complexity of the overall application which can make it a nightmare to handle.
Sessions are globals, $_POST is a global, DRUPAL_ROOT is a global, the includes/install.core.inc' is an unmodifiable global. There is big world outside any function that is required in order to let that function do its job.
The answer of Gordon is incorrect, because he overrates the independence of a function and calling a function a liar is oversimplifying the situation. Functions do not lie and when you take a look at his example the function is designed improperly - his example is a bug. (By the way, I agree with this conclusion that one should decouple code.)
The answer of deceze is not really a proper definition of the situation. Functions always function within a wider scope and his example is way too simplistic. We will all agree with him that that function is completely useless, because it returns a constant. That function is anyhow bad design. If you want to show that the practice is bad, please come with a relevant example. Renaming variables throughout an application is no big deal having a good IDE (or a tool). The question is about the scope of the variable, not the difference in scope with the function. There is a proper time for a function to perform its role in the process (that is why it is created in the first place) and at that proper time may it influence the functioning of the application as a whole, hence also working on global variables.
The answer of xzyfer is a statement without argumentation. Globals are just as present in an application if you have procedural functions or OOP design. The next two ways of changing the value of a global are essentially the same:
function xzy($var){
global $z;
$z = $var;
}
function setZ($var){
$this->z = $var;
}
In both instances is the value of $z changed within a specific function. In both ways of programming can you make those changes in a bunch of other places in the code. You could say that using global you could call $z anywhere and change there. Yes, you can. But will you? And when done in inapt places, should it then not be called a bug?
Bob Fanger comments on xzyfer.
Should anyone then just use anything and especially the keyword 'global'? No, but just like any type of design, try to analyze on what it depends and what depends on it. Try to find out when it changes and how it changes. Changing global values should only happen with those variables that can change with every request/response. That is, only to those variables that are belonging to the functional flow of a process, not to its technical implementation. The redirect of an URL to the login page belongs to the functional flow of a process, the implementation class used for an interface to the technical implementation. You can change the latter during the different versions of the application, but should not change those with every request/response.
To further understand when it is a problem working with globals and the keyword global and when not will I introduce the next sentence, which comes from Wim de Bie when writing about blogs:
'Personal yes, private no'. When a function is changing the value of a global variable in sake of its own functioning, then will I call that private use of a global variable and a bug. But when the change of the global variable is made for the proper processing of the application as a whole, like the redirect of the user to the login page, then is that in my opinion possibly good design, not by definition bad and certainly not an anti-pattern.
In retrospect to the answers of Gordon, deceze and xzyfer: they all have 'private yes'(and bugs) as examples. That is why they are opposed to the use of globals. I would do too. They, however, do not come with 'personal yes, private no'-examples like I have done in this answer several times.
The one big reason against global is that it means the function is dependent on another scope. This will get messy very quickly.
$str1 = 'foo';
$str2 = 'bar';
$str3 = exampleConcat();
vs.
$str = exampleConcat('foo', 'bar');
Requiring $str1 and $str2 to be set up in the calling scope for the function to work means you introduce unnecessary dependencies. You can't rename these variables in this scope anymore without renaming them in the function as well, and thereby also in all other scopes you're using this function. This soon devolves into chaos as you're trying to keep track of your variable names.
global is a bad pattern even for including global things such as $db resources. There will come the day when you want to rename $db but can't, because your whole application depends on the name.
Limiting and separating the scope of variables is essential for writing any halfway complex application.
Simply put there is rarely a reason to global and never a good one in modern PHP code IMHO. Especially if you're using PHP 5. And extra specially if you're develop Object Orientated code.
Globals negatively affect maintainability, readability and testability of code. Many uses of global can and should be replaced with Dependency Injection or simply passing the global object as a parameter.
function getCustomer($db, $id) {
$row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
return $row;
}
Dont hesitate from using global keyword inside functions in PHP. Especially dont take people who are outlandishly preaching/yelling how globals are 'evil' and whatnot.
Firstly, because what you use totally depends on the situation and problem, and there is NO one solution/way to do anything in coding. Totally leaving aside the fallacy of undefinable, subjective, religious adjectives like 'evil' into the equation.
Case in point :
Wordpress and its ecosystem uses global keyword in their functions. Be the code OOP or not OOP.
And as of now Wordpress is basically 18.9% of internet, and its running the massive megasites/apps of innumerable giants ranging from Reuters to Sony, to NYT, to CNN.
And it does it well.
Usage of global keyword inside functions frees Wordpress from MASSIVE bloat which would happen given its huge ecosystem. Imagine every function was asking/passing any variable that is needed from another plugin, core, and returning. Added with plugin interdependencies, that would end up in a nightmare of variables, or a nightmare of arrays passed as variables. A HELL to track, a hell to debug, a hell to develop. Inanely massive memory footprint due to code bloat and variable bloat too. Harder to write too.
There may be people who come up and criticize Wordpress, its ecosystem, their practices and what goes on around in those parts.
Pointless, since this ecosystem is pretty much 20% of roughly entire internet. Apparently, it DOES work, it does its job and more. Which means its the same for the global keyword.
Another good example is the "iframes are evil" fundamentalism. A decade ago it was heresy to use iframes. And there were thousands of people preaching against them around internet. Then comes facebook, then comes social, now iframes are everywhere from 'like' boxes to authentication, and voila - everyone shut up. There are those who still did not shut up - rightfully or wrongfully. But you know what, life goes on despite such opinions, and even the ones who were preaching against iframes a decade ago are now having to use them to integrate various social apps to their organization's own applications without saying a word.
......
Coder Fundamentalism is something very, very bad. A small percentage among us may be graced with the comfortable job in a solid monolithic company which has enough clout to endure the constant change in information technology and the pressures it brings in regard to competition, time, budget and other considerations, and therefore can practice fundamentalism and strict adherence to perceived 'evils' or 'goods'. Comfortable positions reminiscent of old ages these are, even if the occupiers are young.
For the majority however, the i.t. world is an ever changing world in which they need to be open minded and practical. There is no place for fundamentalism, leave aside outrageous keywords like 'evil' in the front line trenches of information technology.
Just use whatever makes the best sense for the problem AT HAND, with appropriate considerations for near, medium and long term future. Do not shy away from using any feature or approach because it has a rampant ideological animosity against it, among any given coder subset.
They wont do your job. You will. Act according to your circumstances.
It makes no sense to make a concat function using the global keyword.
It's used to access global variables such as a database object.
Example:
function getCustomer($id) {
global $db;
$row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
return $row;
}
It can be used as a variation on the Singleton pattern
I think everyone has pretty much expounded on the negative aspects of globals. So I will add the positives as well as instructions for proper use of globals:
The main purpose of globals was to share information between functions. back when
there was nothing like a class, php code consisted of a bunch of functions. Sometimes
you would need to share information between functions. Typically the global was used to
do this with the risk of having data corrupted by making them global.
Now before some happy go lucky simpleton starts a comment about dependency injection I
would like to ask you how the user of a function like example get_post(1) would know
all the dependencies of the function. Also consider that dependencies may differ from
version to version and server to server. The main problem with dependency injection
is dependencies have to be known beforehand. In a situation where this is not possible
or unwanted global variables were the only way to do achieve this goal.
Due to the creation of the class, now common functions can easily be grouped in a class
and share data. Through implementations like Mediators even unrelated objects can share
information. This is no longer necessary.
Another use for globals is for configuration purposes. Mostly at the beginning of a
script before any autoloaders have been loaded, database connections made, etc.
During the loading of resources, globals can be used to configure data (ie which
database to use where library files are located, the url of the server etc). The best
way to do this is by use of the define() function since these values wont change often
and can easily be placed in a configuration file.
The final use for globals is to hold common data (ie CRLF, IMAGE_DIR, IMAGE_DIR_URL),
human readable status flags (ie ITERATOR_IS_RECURSIVE). Here globals are used to store
information that is meant to be used application wide allowing them to be changed and
have those changes appear application wide.
The singleton pattern became popular in php during php4 when each instance of an object
took up memory. The singleton helped to save ram by only allowing one instance of an
object to be created. Before references even dependancy injection would have been a bad
idea.
The new php implementation of objects from PHP 5.4+ takes care of most of these problems
you can safely pass objects around with little to no penalty any more. This is no longer
necessary.
Another use for singletons is the special instance where only one instance of an object
must exist at a time, that instance might exist before / after script execution and
that object is shared between different scripts / servers / languages etc. Here a
singleton pattern solves the solution quite well.
So in conclusion if you are in position 1, 2 or 3 then using a global would be reasonable. However in other situations Method 1 should be used.
Feel free to update any other instances where globals should be used.
Is there a naming convention or maybe some guideline on how to name function parameters?
Since forever, I have been doing it like this:
function divide( $pDividend, $pDivisor )
{ ... }
That way I'll always know which variables were passed as parameters.
(This one's PHP, but it should be applicable to most programming languages)
Is there one major reason against this?
Is there a better way to do this or is it probably best to just avoid such naming schemes?
If :
your functions/methods are well written and short (as they should be)
the variable names are descriptive enough
This practice is not needed.
If you need this, it means that the code written is not readable enough (functions/methods too long), cryptic variable/function names, bad OO practices, shortcuts, code debts, etc. :)
So it would be a signal that the code needs to be refactored/improved.
I think taking the advice of Code Complete regarding naming -anything- would be justified it's whole chapter 11 is on naming variables properly):
Don't name it j, k, i, m, n (unless it's just for an iteration) or "placeholder" or "test". When the "test" works, I often don't take the time to rename the variable wherever it's been listed.
Call it a descriptive name that's separate from the code's function ie "EmployeeComments" not "XMLEmp_Comment_File" because a lot of that information (XML, external file) could change, but that the program's working with "Employee Comments" won't
Keep it as broad and human readable as possible so you're coding in English (or your language) not $j=$k/sqrt($pi); or something equally unintelligible.
As for parameters specifically, I've never used the P notation. I like the idea, but if you named them right wouldn't it be clear they were the parameters for the function?
I've heard that some people will keep their function parameters one style, with the type of data a the first part of the variable (array = arr), and then capitalize the following words:
$arrFormData
where the rest of their variables are in a different style, where the words are all lower case, no type definition, and the words are separated by underscores.
$form_data
Personally, I tend to keep my variables the same as the rest of my variables, purely because on the first two lines of a function, I'm making sure that they are what I expect, or throwing an exception. After that, there shouldn't really be a difference between local variables and variables passed in. But, if it keeps your code clearer to type it one way, by all means.
You should follow general guidelines for how to name parameters as you would for other variables (names should be clear, accurate, specific, consistent, and usually 8-20 characters long).
As for the prefix, I would recommend the opposite: leave the parameter unmarked, and mark anything that you do with the parameter in the function as a separate variable. For example:
function upperCase($title) {
$upTitle = ucfirst($title);
return $upTitle;
}
In my example, I use a bare parameter, $title. After I transform the input, I call it something else to indicate that it is now in a transformed state, $upTitle. That way I know that it is no longer just the function parameter. Merely calling your parameter $pTitle does not give you quite the same advantage as this consistent approach.
If you think about it, your method marks all the parameters on the interface, which is not the best level. If you look at the API of your program, all your function parameters are marked with $p meaning parameter, which is redundant. You are saying, all of my parameters are parameters, which we already know since they are part of the API. So I would recommend dropping the prefix for the parameter and instead using a series of semantic prefixes that denote what you have done to the parameter to transform it within the function, as in my example.
I disagree with the previous suggestion that you should just make your code more clear. Having clear code does not remove the need for having clear naming conventions.
I have naming conventions for some variables, like member fields or static fields, because the declaration of the variable may be far away from the code where I use it. For parameters or local variables I do not use anything, as usually the variable definition is about ten lines away.
Especially in the all IDE camp people seem to get more and more to dislike any prefix or suffix, as "the IDE provides highlighting". Well, it doesn't help me, and I dislike having semantic information only available as color. However, I can see there point, as the variable name should make the most important information clear, and if it doesn't, nothing helps.
So, this is more about style. Good naming is more important than good prefixes. For the schemes: pick one, stick to it. This will help the poor maintenance developer. Yes, those are the people who usually also prefer { } around single statement blocks and so on, but it helps.
The greatest chance for confusion for me is in member functions. If possible, I like to see differences in naming between:
local variables: index
class member variables: m_index
class static variables: ClassIndex
global variables: INDEX
This can make it easier to track down what's happening where. However, I agree with Toto that it's best to make your functions short enough so that these conventions don't make or break your ability to figure out what's going on.
You can follow the PHP Coding Standards or Coding standard for php which is suggested to contribute in core php.
So after looking at all this, I decided to go with:
ClassName
methodName
propertyName
function_name (meant for global functions)
$variable_name
There are many ways to name variables (as you can see from the answers)
But as a general rule, they should be named such, that it is clear from just looking at the variable itself, what it does and what it is used for, right there and not have to go through thousands of lines of code to find out - and not just for who else might have to troubleshoot later but if your code is thousands of lines long for your own good if you yourself have to troubleshoot later
AND WHATEVER NAMING CONVENTIONS YOU CHOOSE BE CONSISTENT THROUGHOUT YOUR CODE - this cannot be iterated enough :)
Personally I use the following:
first part of the variable is for what it is
second part is for what it does/is used for
and for variables needed outside the function, class, etc. the third part is for the function, class, etc. it comes from
Ex:
I want to name the variable for a video thumbnail on the front page:
so i start with what it is (lower_case) - thumbnail
then I add on what it is used for (first letter upper_case) - Video
and since I need it on the front page outside the function I finish off with the function it came from (seperated by under_score) - getVideoAll
Giving me $thumbnailVideo_getVideoAll
That way no matter where I look at the variable in any part of the code (HTML, PHP, etc.) I know...
ah this is the thumbnail for the video I'm trying to show and if it for some reason doesn't work I firstly don't need to go anywhere to spell-check and secondly I know exactly what function, class it was called for (getVideoAll) and can just go there to troubleshoot
If I instead just had named it $tnVid I might personally have a vague notion of what it is but someone else looking at will have no idea that tn stands for (t)humb(n)ail, etc.
so to troubleshoot they would have to first look at the surrounding code to maybe infer that it is probable a variable for a thumbnail and second go through thousands of lines of code to find what function, class, etc. it came from - and that's hours of work just finding what you need to even start troubleshooting - instead of the 5 seconds it takes seeing $thumbnailVideo_getVideoAll and going -
ah this is the thumbnail for the video and I need to go to the function getVideoAll to troubleshoot