Use getters class or class properties? (Php)

What is considered best practice for writing OOP classes when it comes to using a property internally.

Consider the following class:

<?php Class Foo { /** * @var null|string */ protected $_foo; /** * @return null|string */ public function getFoo() { return $this->_foo; } protected function _doSomething() { $foo = $this->_foo; $result = null; // ... return $result; } } 

As you can see, im uses the _foo property in _doSomething (), although a subclass can override getFoo (), returning a computed value not stored in _foo; what a flaw.

What should I do?

  • mark getter as final, use the property inside (no additional function calls, force the end developer to use _foo as a property, since it is protected)
  • use getFoo () internally, mark _foo as private (additional function calls)

Both options are waterproof, however they are seriously concerned about all the extra function calls, so I prefer to use option 1, however option 2 will be more “true OOP” imho.

Also read http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private , which also offers option 2: /

Another related question; If a property has a setter, if this property is private, is it forcing end developers to use it in subclasses, or should it be an unwritten rule that the programmer carries to set a valid value for the property?

+4
source share
1 answer

The second approach, as you say, is the more correct path according to OOP. You are also right that calling a method has more costs in terms of CPU cycles than accessing a property as a variable. However, in most cases this belongs to the category of micro-optimization. This will not have a noticeable effect on performance, except that the value in question is heavily used (for example, in the innermost part of the loop). Best practice, as a rule, contributes to the correct work on the most productive, if as a result of this performance will not really suffer.

For simple variables, using a getter internally is not immediately obvious, but the method comes to your senses if you are dealing with a property that is populated from an external data source, such as a database. Using a getter allows you to retrieve data from the database in a lazy way, that is, on demand, and not earlier than necessary. For instance:

 class Foo { // All non-relevent code omitted protected $data = NULL; public class getData () { // Initialize the data property $this -> data = array (); // Populate the data property with a DB query $query = $this -> db -> prepare ('SELECT * FROM footable;'); if ($query -> execute ()) { $this -> data = $query -> fetchAll (); } return ($this -> data); } public function doSomethingWithData () { $this -> getData () foreach ($this -> data as $row) { // Do processing here } } } 

Now with this approach, every time you call doSomethingWithData, the result is a call to getData, which in turn executes the database query. It is wasteful. Now consider the following similar class:

 class Bar { // All non-relevent code omitted protected $data = NULL; public class getData () { // Only run the enclosed if the data property isn't initialized if (is_null ($this -> data)) { // Initialize the data property $this -> data = array (); // Populate the data property with a DB query $query = $this -> db -> prepare ('SELECT * FROM footable;'); if ($query -> execute ()) { $this -> data = $query -> fetchAll (); } } return ($this -> data); } public function doSomethingWithData () { foreach ($this -> getData () as $row) { // Do processing } } } 

In this version, you can call doSomethingWithData (and indeed getData) as often as you like, you will never run more than one database lookup. In addition, if getData and doSomethingWithData are never called, database searches are never performed. This will lead to a big performance gain, as finding a database will be expensive and should be avoided whenever possible.

This leads to some problems if you work in a class that can update the database, but it is not difficult to work around. If a class makes updates in its state, your installers can simply be encoded so that they successfully delete the state associated with it. Thus, the data will be updated from the database the next time the recipient is called.

+4
source

Source: https://habr.com/ru/post/1388735/


All Articles