When To Use Static Classes And Methods

Many PHP developers can probably relate when they hear misinformation such as “Python has better package management”, “PHP is a slow scripting language”, “The language is not object-oriented”, fractal bad design, etc etc.

What is worse is that many of these misconceptions rank first on Google.

The use of static has the same problem.

This is part 2 of an article about the use of static class and methods in PHP.

The first section of the article that debunked erroneous misconceptions about static was published here:Debunking The Myths Of Static Methods and VariablesTo recap some of the articles points, using static you can:Have inheritance and public/protected/private accessors function the same.

Can use create polymorphism with Interfaces and Abstract classesStatic Methods are testable.

Have inversion of control with dependency injection.

Unknown side effects are from the programmer, not for a method being static.

OOP can have side effects as wells.

Now we can dive into the benefits of static classes, methods and variable, and when to use them.

Benefit: Increased SpeedWhen an object is instantiated with the new keyword, there is actually a performance cost associated with that action.

Code that is not instantiated as an object with the new keyword actually runs about 10%-20% faster.

As an example, let's say we are copying a file from one location to another on our server.

We can write a multi-step function like so:<?php$file= '/path/to/file.

txt';$desination = '/new/path/to/file.

txt';$result = false;if(file_exist($file)) { $result =copy($file, $destination); unlink($file);}return $result;Now we can encapsulate the above code in either an instance or a static method.

The function will look like so://Interchangable with instance vs staticfunction($current_file, $new_file) { $result = false; if(file_exist($current_file)) { $result = copy($current_file, $new_file); unlink($current_file); } return $result;}The above code does not have a state or potential for side effects.

If the file is copied is returns true if is everything fine, otherwise false.

Now let’s see say we have 100,000 files to copy.

<?php$file= '/path/to/file.

txt';$desination = '/new/path/to/file.

txt';for($i=0; $i<1000000; $i++) { //Instance Version $filemanger = new FileManager(); $file->copy($file, $destination); //Static Version FileManager::copy($file, $destination);}For a test you can run on your local, you may use the following gist:The results were:Instance Time: 2.

1042990684509Static Time: 1.

8717567920685Two benefits have occurred:You can speed up our code by not using new, which over 100000 files can be a significant improvement.

Our code is shorterNow yes we can make improvements like instantiating the FileManager outside the loop in this scenario which will result in only one instantiation being executed, but the point of the test is to prove the new keyword takes more time to execute.

The takeaway is if your object does not need to be instantiated, then static can be faster.

Benefit: Improved Memory UtilizationThere will be instances in our applications that we want to utilize shared variables across many scopes instead of each instance having its own copy of the variables.

While there are obvious examples of this use case such as a Registry in an MVC or a User’s Session data (will discuss later) that should be constant across the runtime of an application, another good real-life example is writing an importer.

The US Patent Office has there data available for download, and when you unzip their XML files it's over 350GB worth of information.

Parsing through their data, you will notice it has a lot of repeat values in the XML because it's not normalized.

Patents have attribute data, such as each patent belonging to a class type, utility type, status etc.

If we have multiple importers running checking against the attributes, its a memory advantage to keep that data static.

Example://Static Repoclass DataTypes { //Lets say this array is full of data public static $utiltiyType = array(); //Lets say this array is also full of data public static $classTypes = array(); public static function hasUtility($key) { return isset(self::$utiltiyType[$key]); } public static function hasClass($key) { return isset(self::$classTypes[$key]); }}//The Code In Exection$streamer=XmlStringStreamer::createParser('file.

xml');while ($node = $streamer -> getNode()) { check1($node); check2($node);}function check1($node) { if(DataTypes::hasUtility($node->utility)) { //Do Something }}function check2($node) { if(DataTypes::hasClass($node->class)) { //Do Something }}In this example, the use of static when used across multiple functions of different scopes is able to better utilize memory by referencing the data at the same point in memory and not a copy.

Its akin to referencing a pointer.

In the right scenario, static can have memory improvements.

Use Case: Building MicroservicesMany of the programming concepts come from the era of large monolithic applications.

Inversion of Control techniques such as Dependency Injection was needed because in a large application a small change can have cascading side effects across the entire system.

Its why monolithic code bases are so hard to iterate through.

Microservices do not have the same problems or constraints.

Here is an example of a simple Socket Server that receives input from a client and sends an email:The static part is here://Decrypt our encrypted messageSecurity::init();$message = Security::decrypt($message);If the developer wants to change that code with something else, they can easily do so without system-wide effects.

The microservice is only 60 lines of code and is its own isolated system.

We don’t have monolithic problems.

That is one of the key points of microservices, an architecture that is easy to modify without affecting other parts of the system.

There is no need to have massive layers of abstractions or over-architecting the perfect design.

If the developer does not like something, they change it.

If a developer finds themselves spending an obscene amount of time planning and building the application layer of a microservice, it might be too large to be considered a microservice.

Adding the benefits of increased speed and ability to share memory, static can work nicely in microservices with minimal negative impact.

Use Case: Encapsulating Similar Functions For OrganizationFunctional programming is a great way to improve your code, and we talk about the benefit of using functional programming in microservices here.

But there may come a point in your code when you wish to organize those functions in a more intuitive way.

For example, let's say we write a bunch of math functions:function add($value1, $value2) { return $value1+$value2;}function subtract($value1, $value2) { return $value1-$value2;}function multiply($value1, $value2) { return $value1*$value2;}That are called like so:$value = add(5,2);These are pure functions that do not have a state or cause any side effects.

But remembering where they are and how they are called can be a little be difficult.

You can encapsulate them as static functions inside a class like so:class Math { public static function add($value1, $value2) { return $value1+$value2; } public static function subtract($value1, $value2) { return $value1-$value2; } public static function multiply($value1, $value2) { return $value1*$value2; }}And you would call them as:$value = Math::add(5, 2);This approach still follows the same principles of functional programming, we have just made a slightly more intuitive and organized way of accessing those functions.

Use Case: Enforcing Global Standards Across An ApplicationIn some applications, we want to enforce global standards in an organized and encapsulated way.

A great example is a User Session in an application.

When a user is logged in and visits a page in your application, their information will be referenced in several locations.

Let’s say we are loading a dashboard for Joe Smith.

A flow of processes might look like this:Load Joe’s MessagesLoad Joe’s PreferencesFind Joe’s Recent PostsGet Joe’s Profile ImageA representation of in code can look like this:<?phpclass Session { private static $_name = 'Joe Smith'; private static $_id = 293840213; public static function getID() { return self::$_id; } public static function getName() { return self::$_name; }}//Pretend this is Laravals Facade for Models//Will return iterabe objects$posts = Posts::find(array('user_id' => Session::getID()));$messages = Messagesa::find(array('user_id' => Session::getID()));'//etc//etcBecause the session data is static and also non-mutable, this approach enforces:Consistency across the application, it will always be JoeSecurity from accidentally or maliciously have the data of the current user be a changedPer our points above, improves memory by referencing the same data and speed without using the new operatorStatic Is Not A Magic BulletTo wrap-up, while static does have use cases in which it can excel over using instances, it's not a magic bullet for everything and there are use cases when static should not be used.

Some of the use cases are:In large monolithic applications in higher level implementations.

Being used in low-level implementations where there is no abstraction is debatable.

In instances where isolated states are required.

Because static is persistent, it can exist in states where you do not want it too.

Holding obscene amounts of data.

Static if you are not careful can have issues with the Garbage Collector, and data can end up persisting even when longer being used by your applicationBottom line, learn when and how to use static.

It exists for a reason and is not all bad, just developers that misuse it.

.

. More details

Leave a Reply