Pre-Declare All Private/Local Variables

Pre-declare all private/local variables?

It's generally a good rule of thumb for variables to define and initialize them before use. That includes not only definition and initial value but also validation and filtering of input values so that all pre-conditions a chunk of code is based on are established before the concrete processing of the data those variables contain.

Same naturally applies to object members (properties) as those are the variables of the whole object. So they should be defined in the class already (by default their value is NULL in PHP). Dynamic values / filtering can be done in the constructor and/or setter methods.

The rule for visibility is similar to any rule in code: as little as necessary (the easy rule that is so hard to achieve). So keep things local, then private - depending if it's a function variable or an object property.

And perhaps keep in the back of your mind that in PHP you can access private properties from within the same class - not only the same object. This can be useful to know because it allows you to keep things private a little bit longer.

For instance, I have the (temporary) result of a calculation. Should I pre-declare this variable?

This is normally a local variable in a function or method. It's defined when it receives the return value of the calculation method. So there is no need to pre-declare it (per-se).

...

function hasCalculation() {
$temp = $this->calculate();
return (bool) $temp;
}

...

If the calculation is/was expensive it may make sense to store (cache) the value. That works easily when you encapsulate that, for example within an object. In that case you'll use a private property to store that value once calculated.

Take these rule with a grain of salt, they are for general orientation, you can easily modify from that, so this is open to extend, so a good way to keep things flexible.

Declare local variables as late as possible or at the nearest curly brace they belong?

This is what McConnell says in his must-read book Code Complete 2:

Ideally, declare and define each variable close to where it’s used. A declaration establishes a variable’s type. A definition assigns the variable a specific value. In languages that support it, such as C++ and Java, variables should be declared and defined close to where they are first used.

He also recommends keeping variables alive for as short a time as possible, and to minimize scope.

The important thing for me is following naming conventions (Sun's Java Code Conventions are widely used). As for where are they first declared, I'd delay the declaration as much as possible for performance reasons (declaring a var you might not use is kind of a waste). Unless you know in advance it is going to be used for sure, in that case you can group it with other vars to improve readability. I think that is what JCC says about it.

Private variables in the @implementation

When declaring variables in the @implementation region, you are declaring instance variables, not properties. You do not @synthesize ivars. If you want to declare private properties hidden from the public .h file, you can create them like so:

@interface ParticipantMaterials ()

@property (nonatomic) NSUInteger uintProp;
@property (nonatomic, copy) NSString* strProp;

@end

This is called a class extension.

Instance variables are considered strong by default, unless you specify the __weak type modifier.

PHP variables are shown undefined

That is because your function sam() is not referring to the variables you have declared before as variables of your object. Instead it echos the variables you have just defined within your function sam(), which are - of course - undefined.

This should work:

class Roxy {
public $name;
public $xclass;
public $age;

public function sam() {
echo $this -> name;
echo $this -> xclass;
echo $this -> age;
}

}

$kush= new Roxy();

$kush->name="sachin";
$kush->xclass=12;
$kush->age=21;

$kush->sam(); // > sachin > 12 > 21

+ class is a reserved keyword in php. You shouldn't use it. Instead use xclass for example.

PHP Set variable in __construct()

In PHP, this is called "object overloading", you can add/set new properties on (almost) any instance on the fly. However, you shouldn't do this. These properties make your code more error prone, less maintainable and overloaded properties that are added are slower: details here.

Pre-declaring properties allows for better documentation, your IDE's auto-completion function is actually worth something then, and you don't get in the habit of relying on something that doesn't always work. I tend to write my data models along these lines:

class DataModel
{
/**
* @var int
*/
protected $id = null;

/**
* @var string
*/
protected $name = null;

/**
* @var \DateTime
*/
protected $birthday = null;

public function __construct(array $data)
{}//set values
public function __set($name, $value)
{
throw new \BadMethodCallException('Do not attempt overloading, use getters and setter');
}
}

I define getters and setters for all of the properties, to ensure type safety, and validation can be done. I expressly disable overloading because of the risk of typo's, and difficult debugging. I often find myself disabling __sleep, __serialize and all those magic methods for pretty much the same reason.

Forward declarations for variables?

In C++, a variable declaration must be prefixed with extern:

extern A Unit[10];

// ...

A Unit[10] = { ... };

(Note that in C++ you can omit the leading struct.)

Variable declaration placement in C

It compiles successfully because GCC allows the declaration of s as a GNU extension, even though it's not part of the C89 or ANSI standard. If you want to adhere strictly to those standards, you must pass the -pedantic flag.

The declaration of c at the start of a { } block is part of the C89 standard; the block doesn't have to be a function.

Can I pre-declare variables for destructuring assignment of objects?

When you are destructuring an Object,

  1. you need to use the same variable names as the keys in the object. Only then you will get one to one correspondence and the values will be destructured properly.

  2. and you need to wrap the entire assignment in parenthesis if you are not using declaration statement, otherwise the object literal in the left hand side expression would be considered as a block and you will get syntax error.


So your fixed code would look like this

'use strict';
let cat, dog, mouse;
let obj = {cat: 'meow', dog: 'woof', mouse: 'squeak'};
({cat, dog, mouse} = obj); // Note the `()` around

which is equivalent to

'use strict';
let obj = {cat: 'meow', dog: 'woof', mouse: 'squeak'};
let {cat, dog, mouse} = obj;

Is it necessary to set values to a variable two times?

Nope, absolutely not. In fact, if I were to come across the snippet you posted, I'd probably replace it with:

echo 'hello';

Because (some PHP internals stuff):

$output = '';

initializes a new PHP value (zval), sets it to type string, sets the length to 0, and alloates memory for an empty C string (1 byte: {'\0'}). Then:

$output = 'hello';

Does the exact same thing, but decrements the reference count for the zval you've just created. Its' now not referenced anywhere, and the allocated memory will be freed. This is pointless overhead.

echo $output;

Is fine, it just passes the second zval you've created to the echo construct. But why assign it to a variable in the first place? Why not simply pass the string directly by writing echo 'hello';?


So when should you declare variables up front:

  • When you're concatenating strings in a loop
  • When you're using an operator + assignment shorthand in an expression (*=, ++, |=, ...)
  • When the variables are properties
  • When your assigning variables in a conditional statement, and use it later on (the variable might not be declared then).

Some examples, starting with concatenation:

$string = '';
foreach ($arr as $k => $v) {
//concatenate
$string .= $k . ' => ' . $v;
}

Shorthand stuff:

$doesNotExist += 123;//evaluates to null + 123 => 0 + 123
$newVar++;//is the same as $newVar = null + 1;

This issues a notice (because $doesNotExist doesn't exist of course). You can do this, but only after making sure the variables you use in expressions like these actually exist:

//$i is initialized, ++$i is safe here
for ($i=0;$i<10;++$i)
echo $i;
function doubleInt($x)
{
$x *= 2;//safe, $x is argument, so will exist
echo $x;//use the variable safely
return $x;
}

Next properties (more details on why predeclared properties are faster can be found here)

class Foo
{
/**
* @var int
*/
protected $foo = 0;

/**
* @var array
*/
public $bar = [];
}

predeclared variables are marginally faster, you can define the visibility of them, and they stop you from relying on public variables added on the fly (overloaded properties, as PHP calls them). It makes your code easier to understand/maintain/test and less error prone, especially if you don't allow dynamic properties to be added by implementing a __set method:

public function __set($name, $val)
{
throw new \RuntimeException(
sprintf(
'%s does not have a property %s',
__CLASS__,
$name
)
);
}

Lastly, this is mainly because most IDE's don't handle these scenario's well:

//some code
if ($someVar === true) {
$newVar = 123;
}
//more code
$x *= $newVar;//if $someVar !== true, $newVar is null here

In these cases, it's better to write:

$newVar = 1;//default value
if ($someVar === true) {
$newVar = 123;
}


Related Topics



Leave a reply



Submit