Pre-declare all private/local variables?

后端 未结 4 997
我寻月下人不归
我寻月下人不归 2020-11-27 06:31

This may be a basic question, but it has kept me wondering for quite some time now.

Should I declare all private/local variables being private? Or is this only neces

相关标签:
4条回答
  • 2020-11-27 07:17

    Since you're talking about private, protected and public I take it you're talking about properties, instead of variables.
    In that case: yes, you should declare them beforehand.

    Because of how PHP objects are designed, an array (properties_table) is created on compile time. This array ensures that accessing a given property is as fast as possible. However, if you add properties as you go along, PHP needs to keep track of this, too. For that reason, an object has a simple properties table, too.
    Whereas the first (properties_table) is an array of pointers, the latter is a simple key => value table.
    So what? Well, because the properties_table contains only pointers (which are of a fixed size), they're stored in a simple array, and the pointers are fetched using their respective offsets. The offsets are stored in yet another HashTable, which is the ce->properties_info pointer.

    As bwoebi pointed out to me in the comments: getting the offset (HashTable lookup) is a worst-case linear operation (O(n)) and predefined property lookups are constant-time complex operations (O(1)). Dynamic properties, on the other hand need another HashTable lookup, a worst-case linear operation (O(n)). Which means that, accessing a dynamic property takes in average about twice as long. Authors of the Wikipedia can explain Time-Complexity far better than I can, though.

    At first, access modifiers might seem irrelevant. As you go along, you'll soon find that sometimes, you just don't want to take the chance that some property of some object gets modified by some bit of code. That's when you see the value of private.
    If an object contains another object, that holds all sorts of settings that your code will rely upon, for example, you'll probably use a getter method to access those settings from the outside, but you'll leave that actual property tucked away nicely using private.

    If, further down the line, you're going to add data models and a service layer to your project, there's a good change you'll write an (abstract) parent class, if only for type-hinting.
    If those service instances contain something like a config property, you'll probably define that getter in the parent class (to only define it once). private means that only the current class has access to a property, but since you're not going to have an instance of the parent to work with, but an instance of the child, you'll see why protected is invaluable when dealing with larger projects, too.

    As far as temporary variables are concerned, be it in methods, functions or anywhere else, you don't have to predeclare them, except for, in certain cases arrays:

    public function foo()
    {
        $temp = $this->getSomeValue();
        return $temp ? $temp +1 : null;
    }
    

    Is perfectly valid, and wouldn't work any better if you were to write

    public function foo()
    {
        $temp;// or $temp = null;
        $temp = $this->getSomeValue();
        return $temp ? $temp +1 : null;
    }
    

    However, it's not uncommon to see simething like this:

    public function bar($length = 1)
    {
        for ($i=0;$i<$length;$i++)
        {
            $return[] = rand($i+1, $length*10);
        }
        return $return;
    }
    

    This code relies on PHP being kind enough to create an array, and assign it to $return when the $return[] = rand(); statement is reached. PHP will do so, but setting your ini to E_STRICT | E_ALL will reveal that it doesn't do so without complaining about it. When passing 0 to the method, the array won't be created, and PHP will also complain when it reaches the return $return; statement: undeclared variable. Not only is it messy, it's also slowing you down! You're better off declaring $return as an array at the top of the scope:

    public function bar($length = 1)
    {
        $return = array();//that's it
        for ($i=0;$i<$length;$i++)
        {
            $return[] = rand($i+1, $length*10);
        }
        return $return;
    }
    

    To be on the safe side, I'd also check the argument type:

    /**
     * construct an array with random values
     * @param int $length = 1
     * @return array
     **/
    public function bar($length = 1)
    {
        $length = (int) ((int) $length > 0 ? $length : 1);//make length > 0
        $return = array();
        for ($i=0;$i<$length;$i++)
        {
            $return[] = rand($i+1, $length*10);
        }
        return $return;
    }
    
    0 讨论(0)
  • 2020-11-27 07:20

    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.

    0 讨论(0)
  • 2020-11-27 07:26

    If you are using it in the context of the whole class, then yes, you should define your variable as a member of the class.

    However, if you are talking about a local variable within the context of a single function and the variable does not need to be used elsewhere (or is not returned), then no.

    Essentially you need to determine the importance and scope of your variable before deciding whether to make it a class property or not.

    For example:

    <?php
    
    class Test {
        private $test; // Private property, for use in the class only
        public $public_test; // Public Property, for use both internally and external to the class as a whole
    
        public function testing() {
            $local = 5; // Local variable, not needed outside of this function ever
    
            $this->test = rand(1, 5);
    
            $calc = $local * $this->test; // Local variable, not needed outside of this function ever
    
            $this->public_test = $calc / 2; // The only thing that the whole class, or public use cares about, is the result of the calculation divided by 2
        }
    
    }
    
    0 讨论(0)
  • 2020-11-27 07:31

    In most if not all cases: yes.

    If the variables are class properties they absolutely should be declared before use.

    If the variable is local to a function, declare it in that function before you use it. Function variables are confined to the function's scope (local variables). They don't have to be declared before use but it's good practice to do so, and it gets rid of a warning message if you do. If they are not used anywhere else, they should not be properties though,

    0 讨论(0)
提交回复
热议问题