I have a method like this:
public function create (array $hash) {
$id = $hash[ID_KEY];
$this->store[$id] = $hash;
}
I want to guard it against bugs caused by bad input.
For instance, my code can mistakenly pass $hash with
$id = '' or $id = null,
in which case it will be stored silently referenced by null. Instead I want to see a warning and revise my code to get rid of it. So I guess the best way is to throw Exception:
if (! $id) throw new Exception("Hash with empty id");
Note that I am using empty strings as default values for several method arguments and for default return values, so this kind of bug can easily occur. (Using null instead of empty string here doesn't seem to change anything, even if it is not recommended by Uncle Bob.)
The problem is -- there are many methods like that. Is it really best practice to guard each of them for each argument that can become null but shouldn't?
For instance, another method does only reading. Then it seems there is no need to guard against null because nothing will ever be stored referenced by null, right? Or shall I still guard defensively, to prepare for the case I may somewhere in the future decide to allow storage referenced by null and forget to adjust the guards?
This sounds kind of the safest way but would clutter all methods with bulks of guarding code for all indices involved there. Is this really the best way?
EDIT.
I put more guards and indeed discovered few bugs that I wouldn't find otherwise. Also my tests didn't spot them.
Furthermore, it helped to better understand the role of read methods - to return value if found or return empty Array if not. The input $id = null goes under not found and hence also returns empty Array. That way the method is clean and consistent.
You can use PHP's is_null() and empty() to easily manage this kind of output.
Also I suggest you to write a list of function used only in debug (since you want to perfectionate your code). Call these function in each method you want to test and set a constant like DEBUG_MODE to handle the debug functions' behavior. All of this could be also done using unit testing, which would require more attention and time. But if you have both or want to learn something new, unit testing is clearly a better choice.
Also it is a good practice to handle ALL CASES you can think of. For instance, if your "reading method" expects not to find a null value (because you think there are none because you eradicated by testing over testing), if this "reading method" happens to find a null value a "ugly" PHP error would be shown somewhere, or worse, if error_report is shut you might never see a problem, or even worse, the code might continue its execution and utterly damage further data.
Related
I've seen tons of threads about what to return in case a PHP function fails. But they were all about PHP 4.
Now in my most recent (PHP 5) project, I want to enforce some sort of consistency with return types (I don't even know, if it's gonna be worth it down the road). So if the normal return type of a method is an array, what should I return in case the method fails?
null
empty array()
throw an exception instead
In C# I would return null, so should I write PHP constantly thinking what I would do in a strongly typed language? Or does something make more sense in this specific scenario? What are the pros and cons for each of the options?
If there was no error in performing the logic of your method (in which case I would suggest throwing an exception), I would say return an empty array. It would make an situation like this easier to deal with:
foreach($obj->method() as $item)
{
// ...
}
If YourClass::method() returned null, I would get an "Invalid argument supplied" warning, whereas returning an empty array would never trigger that.
Whatever you end up choosing, stick with it. No one likes working with an API whose return values are inconsistent, and have no logical meaning.
I would throw an exception on an unrecoverable error.
For example, let's say you have a method like getById($id). It is ok to return null if nothing is found. Now let's say you have another method, delete($id) that will itself call getById($id). In this case, if nothing is found (i.e: getById returned null) an exception should be thrown.
Remember that whenever you report an error with a return value, being a null, empty array or string, or even a integer, you will need to handle this error, probably doing some cleanup somewhere else depending on the returned value. This might lead to some dirty in all the methods/functions involved.
Using exceptions will allow you to handle and catch these errors at one place only (at the catch). So you dont have to replicate the code that checks for the error (was the return an empty array? was the return value 1, 2, or 9?, etc). Besides that, using exceptions lets you easily "catalog" the kind of error (like a business logic exception, or an invalid arguments) without writing a lot of if's along the source.
So if a function/method returns something (i.e: it terminated normally), the return value is something you can use (an empty array, a null, or empty string, are all valid return values). If a function/method throws an exception, clearly something went wrong.
Another important thing is that null can be equals to false, 0, and an empty string if you dont use strict checking (=== vs. ==) so this might lead to other kind of bugs. This is where exceptions can also be an advantage.
And of course, whatever you decide, the important thing is to be consistent with your choices along the code.
If a function really 'fails', then I would go for an exception. Exceptions are meant to indicate a failure.
Still, at some point you need to decide what to do with the exception, and then it might very well be that you decide that returning an empty array might be the best. That would for example be useful if you want to keep your existing foreach() loops working.
Thus, use exceptions, but think about where you want to catch them and process them into something useful for the user.
If the method fails it should be classified as an exception IMO this will allow you to properly catch the expected expections and act upon them.
I'm a strong believer in normalizing responses from functions and methods. It makes life a lot easier when you know what the function will return.
In short if it fails throw and exception if it doesn't ensure an array is returned, my $0.02
When i write down a function is a good practice to validate all the parameters of the function like this:
<?php
/**
* foo - Test function
*
* #param int $paramA
* #param str $paramB
* #param array $paramC
*
* #return something
*/
function foo($paramA, $paramB, $paramC) {
// verify all parameters
if(!is_int($paramA)) {
return 0; // or error msg
}
if(!is_string($paramB)) {
return 1; // or error msg
}
if(!is_array($paramC)) {
return 2; // or error msg
}
// some code in function scope that uses parameters
// and saves the results in $result
return $result;
}
or should i rely on the user that will use the function and assume that he knows what he is doing and forget about parameter validation?
Personally i prefer to validate all the parameter of the function and return error codes for consistency of the code and make my life easier afterwords.
Thank you in advance.
I think the answer is: it depends
It depends on who you are writing your code for. If you're looking for the most generalized answer, then yes, you should.
If your script will only ever be used by you and you know in your heart of hearts that you will always use it correctly, then you will (probably) be safe if you don't.
If your script is part of an API that will be distributed to many, many people, then you most definitely want to add error checking and provide good fall back error messages for people.
If you are part of a small team that will all be using the same code, I would also suggest that validating your arguments according to your particular context would be a good idea.
If it is an internal function that only you will be using, it is probably okay to not validate every single parameter like that. If it is a function that has parameters that depend on user input (for example, you get information through $_GET, and then pass that to a function), then it needs to be validated.
Never rely on a user or anyone else besides yourself to know what they are doing. Sometimes it can be helpful to validate things like this if you are writing code that you can re-use later (like if you were writing your own framework to use across all of your PHP projects). But if it is just one application-specific function that only you can call with parameters that only you define, I wouldn't worry about it.
Why validate your parameters:
Sometimes we really need a certain datatype for an operation. If you give me a string that is not representative of an integer and you use that as a search for a primary key in a database (usually an int), then you will have trouble.
It makes fixing your code easier. When you are checking parameters, you can throw individual exceptions and give messages that are very descriptive. This makes it easier to fix your code when something breaks, because you know exactly what went wrong.
Some tips on type checking:
In case you didn't know, is_int is pretty faulty. I think a valid check to see if it is an int is is_numeric($int) && $int==(int)$int.
You can specify types for objects and arrays, like so: function foo($paramA, $paramB, array $paramC).
Really depends on the type-strictness of what you're doing with those parameters.
Since PHP is weakly typed, you can get away with a lot by casting or just letting the implicit type conversion/coercion do it's thing.
And if you're just going to throw a bunch of guard conditions at the head of every function only to return errors, that's really not much different than PHP triggering errors of its own.
I beg to differ. I recently stumbled upon an article about a similar issue (null checks), but it seems to apply for type checking in php as well. I agree with the author.
Write code in a way that makes type checking redundant.
explicitly validate user input and cast the values to the required types as soon as possible.
In some exceptional cases, you can and should use exceptions instead of returning some obscure error numbers.
It is a very good practice to validate function arguments. I suspect you ask this question because on the other hand it makes your functions look longer and uglier. However with args module from NSPL, it is very easy to do. The function from your example will be:
function foo($paramA, $paramB, array $paramC)
{
expects(int, $paramA);
expects(string, $paramB);
// do something
}
// or type check several arguments
function sum($x, $y)
{
expectsAll(numeric, [$x, $y]);
return $x + $y;
}
More examples here.
I'm used to the habit of checking the type of my parameters when writing functions. Is there a reason for or against this? As an example, would it be good practice to keep the string verification in this code or remove it, and why?
function rmstr($string, $remove) {
if (is_string($string) && is_string($remove)) {
return str_replace($remove, '', $string);
}
return '';
}
rmstr('some text', 'text');
There are times when you may expect different parameter types and run different code for them, in which case the verification is essential, but my question is if we should explicitly check for a type and avoid an error.
Yes, it's fine. However, php is not strongly typed to begin with, so I think this is not very useful in practice.
Additionally, if one uses an object other than string, an exception is a more informative; therefore, I'd try to avoid just returning an empty string at the end, because it's not semantically explaining that calling rmstr(array, object) returns an empty string.
My opinion is that you should perform such verification if you are accepting input from the user. If those strings were not accepted from the user or are sanitized input from the user, then doing verification there is excessive.
As for me, type checking actual to data, getted from user on top level of abstraction, but after that, when You call most of your functions you already should now their type, and don't check it out in every method. It affects performance and readability.
Note: you can add info, which types is allowed to arguments for your functions by phpDoc
It seems local folks understood this question as "Should you verify parameters" where it was "Should you verify parameter types", and made nonsense answers and comments out of it.
Personally I am never checking operand types and never experienced any trouble of it.
It depends which code you produce. If it's actually production code, you should ensure that your function is working properly under any circumstances. This includes checking that parameters contain the data you expect. Otherwise throw an exception or have another form of error handling (which your example is totally missing).
If it's not for production use and you don't need to code defensively, you can ignore anything and follow the garbage-in-garbage-out principle (or the three shit principle: code shit, process shit, get shit).
In the end it is all about matching expectations: If you don't need your function to work properly, you don't need to code it properly. If you are actually relying on your code to work precisely, you even need to validate input data per each unit (function, class).
I'm wondering what you think the best practice is here-- does it buy you very much to type-check parameters in PHP? I.e have you actually seen noticeably fewer bugs on projects where you've implemented parameter type-checking vs. those that don't? I'm thinking about stuff like this:
public function __construct($screenName, $createdAt) {
if (!is_string($screenName) || !is_string($createdAt) {
return FALSE;
}
}
Normally within a PHP application that makes use of the skalar variable "types" is bound to actually string input (HTTP request). PHP made this easier so to convert string input to numbers so you can use it for calculation and such.
However checking scalar values for is_string as proposed in your example does not make much sense. Because nearly any type of variable in the scalar family is a string or at least can be used as a string. So as for your class example, the question would be, does it actually make sense to check the variable type or not?
For the code you proposed it does not make any sense because you exit the constructor with a return false;. This will end the constructor to run and return a not-properly-initialized object.
Instead you should throw an exception, e.g. an InvalidArgumentException if a constructors argument does not provide the expected / needed type of value.
Leaving this aside and taking for granted that your object constructor needs to differ between a string and an integer or bool or any other of the scalar types, then you should do the checks.
If you don't rely on the exact scalar types, you can cast to string instead.
Just ensure that the data hidden inside the object is always perfectly all-right and it's not possible that wrong data can slip into private members.
It depends. I'll generally use the type-hinting that is built into PHP for higher-level objects ((stdClass $obj, array $arr, MyClass $mine)), but when it comes to lower level values -- especially numbers and strings, it becomes a little less beneficial.
For example, if you had the string '12345', that becomes a little difficult to differentiate between that and the number 12345.
For everything else, the accidental casting of array to a string will be obvious. Class instances which are cast to strings, if they don't have a __toString, will make PHP yell. So your only real issue is classes which have a __toString method and, well, that really limits the number of times where it can come up. I really wonder if it is worth that level of overhead.
Checking function arguments is a very good practice. I suspect people often don't do that because their functions grow bigger and the code becomes uglier and less readable. Now with PHP 7 you can type-hint scalar types but there is still no solution for cases when you want your parameter to be one of two types: array or instance of \Traversable (which both can be traversed with foreach).
In this case, I recommend having a look at the args module from NSPL. The __constructor from your example will have the following look:
public function __construct($screenName, $createdAt)
{
expectsAll(string, [$screenName, $createdAt]);
}
// or require a non-empty array, string or instance of \ArrayAccess
function first($sequence)
{
expects([nonEmpty, arrayAccess, string], $sequence);
return $sequence[0];
}
More examples here.
Better documentation is more important when you're the only one interacting with the methods. Standard method definition commenting gives you well documented methods that can easily be compiled into an API that is then used in many IDEs.
When you're exposing your libraries or your inputs to other people, though, it is nice to do type checking and throw errors if your code won't work with their input. Type checking on user input protects you from errors and hacking attempts, and as a library letting other developers know that the input they provided is not what you're expecting is sometimes nice.
I am not really clear about declaring functions in php, so I will give this a try.
getselection();
function getselection($selection,$price)
{
global $getprice;
switch($selection)
{
case1: case 1:
echo "You chose lemondew <br />";
$price=$getprice['lemondew'].'<br>';
echo "The price:".$price;
break;
Please let me know if I am doing this wrong, I want to do this the correct way; in addition, php.net has examples but they are kind of complex for a newb, I guess when I become proficient I will start using their documentation, thank you for not flaming.
Please provide links that might also help me clear this up?
Your example seems valid enough to me.
foo('bar');
function foo($myVar)
{
echo $myVar
}
// Output: bar
See this link for more info on user-defined functions.
You got off to a reasonable start. Now all you need to do is remove the redundant case 1:, close your switch statement with a } and then close your function with another }. I assume the global array $getprice is defined in your code but not shown in the question.
it's good practice to declare functions before calling them. It'll prevent infrequent misbehavior from your code.
The sample is basically a valid function definition (meaning it runs, except for what Asaph mentions about closing braces), but doesn't follow best practices.
Naming conventions: When a name consists of two or more words, use camelCase or underscores_to_delineate_words. Which one you use isn't important, so long as you're consistent. See also Alex's question about PHP naming conventions.
Picking a good name: a "get" prefix denotes a "getter" or "accessor"; any method or function of the form "getThing" should return a thing and have no affects visible outside the function or object. The sample function might be better called "printSelection" or "printItem", since it prints the name and price of the item that was selected.
Globals: Generally speaking, globals cause problems. One alternative is to use classes or objects: make the variable a static member of a class or an instance member of an object. Another alternative is to pass the data as an additional parameter to the function, though a function with too many parameters isn't very readable.
Switches are very useful, but not always the best choice. In the sample, $selection could easily hold the name of an item rather than a number. This points to one alternative to using switches: use an index into an array (which, incidentally, is how it's done in Python). If the cases have the same code but vary in values used, arrays are the way to go. If you're using objects, then polymorphism is the way to go--but that's a topic unto itself.
The $price parameter appears to serve no purpose. If you want your function to return the price, use a return statement.
When you called the function, you neglected to pass any arguments. This will result in warnings and notices, but will run.