Skip to main content

From assumptions to assertions

In your journey as a developer you not only develop applications, you also develop yourself. You and I both know there's more to developing than writing code that works, it's writing good code that works well. If you're like me then you probably started developing websites from scratch, later decided you wanted to build your own CMS and so on. In that stage as a developer you are usually very focused on getting stuff to work and not really on the unhappy paths.
As you continue to write code and continue to develop yourself you will eventually find yourself writing code like this, keep an eye on the is not null checks:
$lastOrder = null;

if ($user->getOrders()->count() > 0) {
    $orders = $this->filterByCompleted($user->getOrders());
    $lastOrder = $orders->last();
}

if ($lastOrder !== null) {
    if ($order->getBillingAddress() === null) {
        $order->setBillingAddress($lastOrder->getBillingAddress());
    }

    if ($order->getShippingAddress() === null) {
        $order->setShippingAddress($lastOrder->getShippingAddress());
    }
}
In the code above we retrieve the last order and use some information from there if it's missing in our current order (prefilling). Code like this is quite common and is sprinkled through most codebases I've worked with and contributed to. The problem with this code is that we're still making assumptions instead of assertions, just like we did back when we didn't check for unhappy paths at all and assumed all was good. The big cause of this are the is not null checks, they're a habit some of us have and it's not doing us as much good as we think it's doing.
Just to give you some insight, the $orders variable is of type Doctrine\Common\Collections\ArrayCollection and the last() functionactually uses PHP's end() function, if we check the documentation on that we can see that end() returns false when the array is empty. This may be something you already knew but this is not necessarily something you think about everytime you write code. With this in mind we can see that our code is flawed, it will run the if $lastOrder is not null check, pass and it will try to run $lastOrder->getBillingAddress() while $lastOrder is set to false. Our assumption was: "if $lastOrder is not null, it must be an object of type Order", just like we're assuming that $order->getBillingAddress()'s default value is null.
This brings me to the point of blacklisting vs whitelisting, I strongly believe we should be whitelisting in this case to turn assumptions into proper assertions. The above code could be rewritten as:
if ($lastOrder instanceof OrderInterface) {
    if (!$order->getBillingAddress() instanceof AddressInterface) {
        $order->setBillingAddress($lastOrder->getBillingAddress());
    }

    if (!$order->getShippingAddress() instanceof AddressInterface) {
        $order->setShippingAddress($lastOrder->getShippingAddress());
    }
}

Comments

Popular posts from this blog

PHP-FPM tuning: Using ‘pm static’ for max performance best php training trivandrum

PHP-FPM tuning: Using ‘pm static’ for max performance Lets take a very quick look at how best to setup PHP-FPM for high throughput, low latency and a more stable use of CPU and memory. By default, most setups have PHP-FPM’s PM (process manager) string set to  dynamic  and there’s also the common advice to use  ondemand  if you suffer from available memory issues. However, lets compare the two management options based on php.net’s documentation and also compare my favorite for high traffic setups…  static  pm: pm = dynamic  – the number of child processes is set dynamically based on the following directives:  pm.max_children, pm.start_servers,pm.min_spare_servers, pm.max_spare_servers . pm = ondemand  – the processes spawn on demand (when requested, as opposed to dynamic, where pm.start_servers are started when the service is started. pm = static  – the number of child processes is fixed by...

Memory leak in 7.x json_decode()? Best Php Training Trivandrum

Memory leak in 7.x json_decode()? There appears to be a memory leak in 7.x json_decode(). I've uploaded a huge JSON file to demonstrate the problem. Here is the sample code: <?php echo memory_get_usage(false) . ' : ' .memory_get_usage(true) . PHP_EOL; $json = json_decode(file_get_contents('http://zaremedia.com/big.json')); echo memory_get_usage(false) . ' : ' .memory_get_usage(true) . PHP_EOL; unset($json); echo memory_get_usage(false) . ' : ' .memory_get_usage(true) . PHP_EOL; Below is output from 7.x and then 5.6: // Running on 7.0 and 7.1 349608 : 2097152 27245512 : 29360128 375552 : 29360128 The process starts with 0.3mb used / 2.0mb allocated. After json_decode(), it's 27.2 / 29.4mb, after unset, it's 3.7mb / 29.4mb -- The second value (memory allocated by php via emalloc()) has not been freed, though PHP's gc has correctly freed up the object usage. // Running on 5.6 221136 : 262144 31577064 : 35913728 420104 : 86507...

Deploy your Symfony application on AWS Elastic Beanstalk using CloudFormation best php training trivandrum

Deploy your Symfony application on AWS Elastic Beanstalk using CloudFormation The problem I was looking for a way to quickly create a Minimum Viable Stack on AWS with the following properties: Be setup in less than 10min Be able to run a Symfony application Using PostgreSQL on RDS Deployment is easy and fast Non AWS experts can create the MVS But I couldn’t find any out-of-the-box tools so I looked for a solution. Here I describe my journey which ended up with a ready-to-go CloudFormation configuration. Elastic Beanstalk I started working with  Elastic Beanstalk , the PAAS of AWS,  which seemed to be exactly what I needed . Thanks to  this article  on Elastic Beanstalk configuration files and  this one  on how to deploy a Symfony application, I was able to run my application  after some debugging cycles . My problem after that was that I couldn’t reuse my configuration to recreate the whole environment ...