Duck-typing in PHP

Posted on by Matthias Noback

For quite some time now the PHP community has becoming more and more professional. "More professional" in part means that we use more types in our PHP code. Though it took years to introduce more or less decent types in the programming language itself, it took some more time to really appreciate the fact that by adding parameter and return types to our code, we can verify its correctness in better ways than we could before. And although all the type checks still happen at runtime, it feels as if those type checks already happen at compile time, because our editor validates most of our code before actually running it.

To make it perfectly clear: this is all very awesome. In fact, I hope that PHP will change to become more of a static language than a dynamic one. I can very well remember the times when we actually relied on PHP doing the type juggling for us, but I'm happy we've left that phase behind. I think that nowadays many PHP developers agree that silent type conversions is not something which is very useful, nor safe.

But sometimes it's good to remember what's possible with PHP, due to it being a dynamic scripting language. I recently encountered a situation where I wanted to build a generic repository, which would be able to keep track of entities, allowing the user to store and retrieve them by their ID.

class SomeEntity
    public function id()
        return $this->id;

class GenericRepository
    public function store($object)
        $id = $object->id();

    public function getById($id)
        return ...;

So, what are the types we should introduce in this scenario? $id might be a simple string, although these days identifier strings will often get wrapped in their own dedicated value object. Maybe we could enforce an interface for Id type of objects? But then people won't be able to use a simple string anymore. Do I want to force that upon them? The same goes for the objects that our repository is going to store. $object might be typed as an Entity interface (since an object with identity is basically what we call "entity"), which has a method id(), which returns an identifier:

interface Id
    public function __toString() : string;

interface Entity
    public function id() : Id

Do we want to force the term Entity onto the user's code? Do we want to force users to implement the Id interface? What if there is no user we can force? What if the "entity" we want to store in our repository is defined in a third-party library?

It doesn't have to be that way. Hey, it's PHP! We only want the user to provide an object which we can use in the following way:

public function store($object) { 
    $id = $object->id();

     * $id should be a string, or usable as a string (i.e. it has a __toString() method)
     * In fact, we might as well just cast it to a string to be sure:

    $id = (string) $id;


The funny thing is, whatever value the user provides, we can already do this. As long as the method id() exists on the object and PHP can successfully cast its return value to a string, we're fine. As long as we don't define any type at all for the $object parameter, PHP will do no type checking and will just try to do whatever you ask it to do, and throw warnings/errors/exceptions whenever it fails.

The only problem, one that many of us including myself will find a very big problem: our IDE isn't able to help us anymore. It won't be able to verify that methods exist or that passed function argument types are correct. It won't let us click to class definitions, etc. In other words, we loose our ability to do a little bit of the type-checking before runtime.

How to fix this? By helping your IDE to figure it out. PhpStorm for example allows you to define @var or @param annotations to make intended types explicit.

public function store($object) {
    /** @var Entity $object */

// or (this might show some IDE warnings in the user's code):

 * @param Entity $object
public function store($object) {

So, even when $object doesn't actually implement, it will still be treated by the IDE as if it does.

This, by the way, is known as duck typing. Type checks happen at runtime:

With normal typing, suitability is assumed to be determined by an object's type only. In duck typing, an object's suitability is determined by the presence of certain methods and properties (with appropriate meaning), rather than the actual type of the object.

Introducing the php-duck-typing library

The only problem of simply adding a type hint to a value like this is that PHP will simply crash at some point if the passed value doesn't meet our expectations. When we call store() with an object that doesn't really match with the Entity interface, we would like to give the user some insight into what might be wrong. We'd like to know what was wrong about the object we passed to store(), e.g.:

  • The object doesn't implement the Entity interface.
  • It does offer the method id().
  • id() doesn't return an object with a __toString() method though.

In other words: we need some proper validation!

Let me introduce you to my new, highly experimental open source library: php-duck-typing. It allows you to run checks like this:

public function store($object) {
    // this will throw an exception if the object is not usable as Entity:


Just wanted to let you know that this exists. I had some fun exploring the options. Some open issues:

  • Could an object with a __toString() method be used as an actual string value?
  • What about defining other types which we can use as pseudo-types, e.g. arrays as traversables, arrays as maps, etc.?

I'd be interested to hear your thoughts about this.

For now, this library at least supports the use case I described in this article. I'm not sure if it has a real future, to be honest. Consider it an experiment.

PHP duck-typing Comments

Convincing developers to write tests

Posted on by Matthias Noback

Unbalanced test suites

Having spoken to many developers and development teams so far, I've recognized several patterns when it comes to software testing. For example:

  1. When the developers use a framework that encourages or sometimes even forces them to marry their code to the framework code, they only write functional tests - with a real database, making (pseudo) HTTP requests, etc. using the test tools bundled with the framework (if you're lucky, anyway). For these teams it's often too hard to write proper unit tests. It takes too much time, or is too difficult to set up.
  2. When the developers use a framework that enables or encourages them to write code that is decoupled from the framework, they have all these nice, often pretty abstract, units of code. Those units are easy to test. What often happens is that these teams end up writing only unit tests, and don't supply any tests or "executable specifications" proving the correctness of the behavior of the application at large.
  3. Almost nobody writes proper acceptance tests. That is, most tests that use a BDD framework, are still solely focusing on the technical aspects (verifying URLs, HTML elements, rows in a database, etc.), while to be truly beneficial they should be concerned about application behavior, defined in a ubiquitous language that is used by both the technical staff and the project's stakeholders.

Please note that these are just some very rough conclusions, there's nothing scientific about them. It would be interesting to do some actual research though. And probably someone has already done this.

I think I've never really encountered what you would call a "well-balanced test suite", with a reasonable number of unit tests (mainly used to support development), integration tests (proving that your code integrates well with external dependencies including external services) and acceptance tests (proving that your application does what its stakeholders expect it to do). [Edit: in fact, former co-workers at Ibuildings - Reinier Kip and Scato Eggen - have created a project with a well-balanced testsuite. It was a technically sound project, delivered within budget, well on time. If you see them, please ask them to write a blog post about their experiences.]

Psychological impediments

I have also seen many developers who still didn't write any (or a sufficient number of) tests.

When I was still working as CTO at Ibuildings I wrote several articles to explain to developers that you can't get away with not writing tests anymore. Though I think it's sad that a lot of software still gets released without any tests at all, I wrote my articles in a very kind manner as to not offend anyone. I really don't like scaring people into testing, or pushing feelings of guilt on them. We all need to understand that to start testing should not be a matter of peer pressure. You need the insight that it will make your life and that of your team members easier, and you need to be internally motivated to do it. Also, you need some strong arguments for it, in case your environment (co-workers, managers, customers) try to convince you to stop "wasting time" by writing tests.

If you recognize yourself or your team in any of the things I've said above, please use the following articles as a way to revive the discussion about testing inside your team or your company. Keep the testing spirit alive. And for now and ever, may this day be remembered as Testing Awareness Day! Just kidding.

1. Why write tests?

The world of "software testing" is quite a confusing one and it takes several years to understand what's going on and how to do things "right". In no particular order:

  • Developers use different words for different types of tests, but also for different types of test doubles.
  • Developers are looking to achieve widely varying goals by writing tests.
  • Developers have divergent views on the cost of writing and maintaining a test suite.
  • Developers don't agree on when to test software (before, during, after writing the code).

If you're a programmer it's your inherent responsibility to prove that the production software you deliver:

  • ... is functioning correctly (now and forever)
  • ... provides the functionality (exactly, and only) that was requested

I don't think anybody would not agree with this. So taking this as a given, I'd like to discuss the above points in this article and its sequel.

Continue reading Why write tests? »

2. Does writing tests makes you go faster or slower?

The price you pay for writing automated tests consists of the following parts (and probably more):

  • You need to become familiar with the test frameworks (test runners as well as tools for generating test doubles). This will initially take some time or make you slow.
  • If your code is not well designed already, or if you're not producing clean code yet, writing the tests will be a pain. This will slow you down and may even lead you to giving it up.
  • If you're not very familiar with writing tests, you'll likely end up with tests that are hard to maintain. This will slow you down during later stages of the project.

Continue reading Does writing tests makes you go faster or slower? »

3. When to write tests?

Now we need to answer one other important question that should guide you in your daily quest to improve the quality of the code you deliver: when should you write a test?

Continue reading When to write tests? »

PHP testing unit testing functional testing Comments

DDD Europe Conference Report - part III

Posted on by Matthias Noback

In previous articles I've already spent a few words on some of the talks I watched at DDD Europe that made quite an impact on my thoughts about software development and design. The design part is often the most philosophical one. Design talks are often less practical. Speakers use metaphors to bring their message across and take note of other disciplines than software engineering to discover useful design principles and heuristics.

Rebecca Wirfs-Brock: Design Matters

The opening keynote of the second day was particularly philosophical. To be honest, I didn't know Rebecca. She is co-author of several important books on object design: "Designing Object-Oriented Software" and "Object Design: Roles, Responsibilities, and Collaborations". It should be interesting to take a look at these some time.

Rebecca explained the concept of a heuristic, which is an approach to problem solving. It entails a pragmatic method which might not lead to the best answer, but probably gives you a good-enough answer to use until a better one is needed. She posed the question: how many people are in this room? You could for example count 10 people, then find out how many of those groups of 10 people are in the room. Or you could multiply rows and columns and subtract a certain amount. It's clear that it won't give you the correct answer, but if you have all the time in the world, you could simply count attendees one by one.

Heuristics often conflict amongst each other. Picking a single heuristic is also subject to your knowledge of the immediate context (you won't know everything there is to know). And while you build up experience in the field, you discover which heuristics work best. Everyone has their own list of heuristics based on what they encountered so far.

Of course, you learn from other people about their heuristics. I've been thinking about it before, but now I can put words to this: since we all have limited experience in our field (we work in different domains, with different team sizes, using different languages, frameworks and libraries, etc.). I personally feel obliged to share what I found out, what I have learned, in order to save other people some trouble. I know many other people do too, and I strongly encourage the reader to the same thing. I'm thinking about books like Analysis Patterns by Martin Fowler or the book on Docker Swarm by Viktor Farcic, which is obviously a clean reflection of a messy struggle to find out the best way to make it work.

Rebecca teaches an important lesson: our list of heuristics only reflects what is our personal, current State of The Art (SOTA). As an example: when we try to answer the question whether we should develop a rich domain model, an anemic domain model, use Active record, Data mapper or Transaction script - we can only answer that question according to what we currently know, and have experienced. And even if we rely on pattern books like PoEAA or GoF, they only tell so much about the context in which to apply a pattern. It couldn't be otherwise, since pattern book authors don't know about the context of the project you are working on right now. So, it would be good to keep developing your own heuristics and: you don't need to feel bad for not knowing every heuristic yet.

In the last part of the talk Rebecca covered a number of characteristics of lively design, a concept from Christopher Alexander's work. Apparently, his work is an interesting source of inspiration for software design. I don't recall most of what Rebecca mentioned towards the end, but remembered one particular idea of "the void", which referred to the clarity at the center of a piece of software. You won't find the clarity in the code, since it's basically clutter around a clear idea, something the creator of the software had in mind and tried to implement by writing code.

Further reading:

Prof. David West: The Past (1968) and Future of Domain (driven) Design

I must admit I've read only half of David West's book Object Thinking - Developer reference but will put it on my reading list again. David had some interesting things to tell, about the history of software engineering and its future.

In his talk, David talks about the "divorce" that happened between "software engineers" and the "business". In the beginning (in the 1960's), these were one and the same. No one had had an education in software development. Business people wrote programs; it was part of the job. Eventually "software engineering" as a profession, including its own scientific foundation, was defined. From that moment on, it wasn't natural anymore for programmers to know all about the domain for which they were writing software.

Direct effects of this dramatic change were: programmers started focussing on requirements (and negotiations). Business people started hating IT people, because they delivered late and inadequate software (because they didn't understand what they were building and how and by whom it was going to be used). IT started to be something that held businesses back, a necessary evil. And while the business world started adopting "agile" principles in the 80's, it took many years for the IT industry to follow.

David warns us that our intense focus on the machine, on technology, isn't productive in the end. Domain-Driven Design, if we want to do it, needs practicing. David taunts us, by saying that "DDD isn't going to happen". We like to indulge in interesting technical elements, while, to be successful at design, and in particular domain-driven design, we need to have multiple areas of expertness (and several more areas of shallow knowledge). This is a huge challenge.

First, we need to read other books than just computer books. We need to be ready to take the right decision, take the correct action, in every possible situation. This seems like a super-human thing to accomplish, but David thinks that with a "Zen mind" it is possible to transcend our skills and go to the full breadth.

Further reading:

Nick Tune: Domain Discovery: Business Model Canvas Workshop

I had watched Nick's talk Strategic and Collaborative Domain-Driven Design in which he mentioned the Business Model Canvas, which seemed to me like an interesting tool to figure out how a business works, what its value proposition is, its customer segments are, etc. This is not language I'm used to using on a day-to-day basis but, what every DDD practicioner will tell you: you have to dive a lot deeper into the business you're working for. So, I decided to join Nick's workshop and with my "team" worked on filling in the canvas for an imagined business.

Some of the take-aways:

  • It's a useful, simple format for understanding a business. In fact I'm going to map my new business on a canvas soon!
  • It's very hard to make a canvas for an imagined business. Next time I'll make sure to pick an existing one. Our group had a lot of discussions about things we couldn't decide in the first place.
  • It is relatively easy to think about useful innovations for a business, once you see it laid out on the canvas.

In short: creating a business model canvas (perhaps with some colleagues) is highly recommended!

Eric Evans: Keynote

The closing keynote of the conference was by Eric Evans. It was a fascinating talk really. He started out with putting some things straight. As developers get in to DDD, they become perfectionists about it. We look for principles, rules, anything to hold onto, since the journey we set out to make is not a calm and safe one. We learn lots of new concepts and want to be certain about things. Should we design a bounded context to align with exactly one subdomain? Should we have a (micro)service per bounded context? As we learn from speakers like Rebecca (who's talk I described above): it depends. While we try to get it right, we will figure out for ourselves what works well, and what doesn't. Anyway, we shouldn't try to do everything right from the start, or do it right once and for all. In fact, this perfectionism about bounded contexts is a bit ironic, because a bounded context is meant to "acknowledge the mess", and to keep it within boundaries.

Eric continues with a discussion about a peculiar aspect of Java time's API: adding periods of time to an existing timestamp using the plus() method. Eric shows why this isn't the right name for the method and offers several suggestions to improve the API. In general, his advice is to "give awkward names to awkward concepts".

The last topic Eric covers is that of path-dependence. The bridge to this last topic is actually quite subtle. He ends the discussion of the plus() method by talking about how adding periods of time (like "3 months") is different from adding other periods of time which would in theory amount to the same result (like "2 month", "1 month"). He ends with the idea that life, as well as software, is path-dependent: where you end up, depends on what the path looked like. One particular pattern in the path of software development using bounded contexts is this:

  1. You work with cohesive teams, and produce coherent bounded contexts.
  2. A reorganization means you'll split, start sharing code (since you have "already implemented this somewhere else"), then finally trashing the result because it's not good enough in the end.
  3. From there teams will "bubble off", work on nice, clean bounded contexts on their own. And eventually you will be back at 1.

Eric finishes by encouraging us to "broaden our aesthetic". We should appreciate alternative solutions, solutions that may not be good according to our own State-of-the-Art. We should appreciate "legacy" applications more, and admire what a company can accomplish using them. And we shouldn't get ourselves stuck in the perfectionism that DDD often seems to provoke.


I've thoroughly enjoyed Domain-Driven Design Europe 2017 and I can recommend this conference to any software developer. See you next time (I hope)!

DDD conference report Comments