Declare static types to keep bugs away?

Introduction

A lot of programmers feel that for any larger projects static types offer a huge benefit.
Readability too, not only validation.
Some argue that tests can replace types, I agree if we are only talking about code validation.
But static types are empowering in other situations too. Reading code is easier since types describe code and fewer assumptions have to be made about inputs and outputs. Basically, additional documentation which is always in sync with the code.

What about functional style?

In the last iteration of talk about improving correctness and avoiding bugs, we tried to do things in a functional way.
http://inchoo.net/magento/programming-magento/less-bugs/
We tried to use some “higher” level constructs and to bring some benefits of functional programming with PHP, but in all honesty, it simply does not look so nice with currently available syntax.
I am still confident semantic benefits are real, but I am unsure because all that visual noise makes it hard to actually read and understand the code.

Here are 2 RFCs that would probably help a lot:
https://wiki.php.net/rfc/arrow_functions
https://wiki.php.net/rfc/pipe-operator

Since the chance of getting sexy syntax soonish is not so great (I hope PHP will get there) and closures do not automatically detect used variables and you have to list them explicitly let’s try something else.

Static types and immutability

2 obvious improvements which fit into low hanging fruit category: “immutability” and “strict typing”. Since I feel that being familiar with type systems will help in understanding huge benefits of immutability, let’s examine what kind of empowering restrictions can we place in our code!

I believe that benefits of static types rise with the complexity of software being written.
For example, I feel that Magento 2 would benefit a lot from static typing.

Humans have limited working memory. So, when writing software we can help ourselves by making code easier to understand. Having smaller pieces which operate on some contracts makes it simpler to both create and assemble those pieces. Static types bring a benefit of knowing what type of variable we have and which type of variable we need to return.

Input and Outputs

Functions should be tight in their return types and values and it can be argued that they should be wide in parameters accepted.
Functions which have return type being different depending on some logic flag can be hard to debug. Especially if error propagates further into the code and you gotta re-run debugger quite a few times to even get an idea about “how did that value get here?”.
With PHP7.0 we got the ability to declare return types on functions:
https://wiki.php.net/rfc/return_types

It looks and works OK, but it can be improved in some ways (from what I got by quickly skimming past versions of RFC, those issues could be covered).
First missing part is that it should be OK to tighten return type. (Only part of child classes, less generic)
This does not work (yet??):
Forgive me for bad OOP example 🙂

class Implementation {}
class BugFreeImplementation extends Implementation {}
 
class Software {
	public function produce() : Implementation {
		return new Implementation();
	}
}
 
class DifferentSoftware extends Software {
	// Does not work
	public function produce() : BugFreeImplementation {
		return new BugFreeImplementation();
	}
}
 
class DifferentSoftware extends Software {
	//Works, but consumers of our new and better method of producing software
	// can not know it is bug-free
	//Fact that it indeed is bug-free is just an implementation detail!
	//Program to interface, not to implementation!
	public function produce() : Implementation {
		return new BugFreeImplementation();
	}
}

Benefits

What are benefits of this? We are guaranteed that whenever we call product function, we will have a variable of type Implementation.
It will not be an array of somethings, a string or a null.

Future

While we are on the topic of null, there is actually RFC for that.
https://wiki.php.net/rfc/nullable_types
This would work like Option, Maybe or however they are called in other typed languages.

If the return type is ?Implementation, it can either be a null or Implementation AND NOTHING ELSE!

Powerful in cases where you call a function which may or may not return a value.
For example, retrieving a single entity from the database.

Hopefully, we will be able to use such type system improvements in future versions of PHP.

In all honesty: enforcing static type rules on large projects is a quite large improvement.
But, having more powerful type system would help a lot and make it easier.
PHP DocBLocks allows some of that power but does not really enforce it.

Classes vs Traits

I actually hoped to include traits in this post, but I think it is better to handle them separately.
Traits are really useful building blocks which we can use to compose classes.
While it may not initially seem so, when I think about their usages, they often overlap with dependency injection.
So hopefully, in next post we will cover traits, then a little on benefits on immutability and then perhaps an exploration of dependency injection and its benefits and drawbacks.

 

Reading Material:

https://pchiusano.github.io/2016-09-15/static-vs-dynamic.html

https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface

http://wiki.c2.com/?DesignByContractAssertionsVsUnitTestsVsTypes


About Marin Grizelj

Backend Developer

Marin works as a Backend Developer, a position that matches his specialities - databases, network protocols and feeling for code organisation. His biggest wish is to buy a bus, gather his friends and travel the world.

Read more posts by Marin / Visit Marin's profile

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.