Oh Dear! monitors your entire website, not just the homepage. You'll get a notification as soon as your website is down, a monthly uptime report, a warning a few days before your SSL certificate expires and much more! Start your free 10 day trial now!

Writing readable PHP: decrease indentation by returning early

Original – by Freek Van der Herten – 2 minute read

In this short post, I'd like to give you a tip on writing readable PHP.

When working older code, or code submitted through PRs, I sometimes see this pattern:

public function doSomething($someParameter)
{
    /** can be any kind of test */
    if ($someParameter === 0) {
        // do the actual work
    }
}

At the beginning of the function, there's a test being performed. The actual work is in the if block.

This can be refactored by reversing the condition and using an early return.

public function doSomething($someParameter)
{
    if ($someParameter !== 0) {
        return;
    }

    // do the actual work
}

Doing this has a couple of benefits:

  1. A level of indention is lost. This alone makes it more pleasant to read. You don't need to keep in your head that the code is wrapped in something.
  2. Using an early return is great for humans too. When somebody reading your code is interested in the case concerning the early return, he or she doesn't need further that that early return. In the first example, there could still be some code to be executed after the if block.
  3. When you're respecting a line length limit (you should), you now have more characters available when performing the actual work.

This technique also works when there are multiple conditions. Consider this function:

public function doSomething($someParameter, $someOtherParameter)
{
    /** can be any kind of test */
    if ($someParameter === 0) {
        if ($someOtherParameter === 0) {
            // do the actual work
        }
    }
}

By using early returns, you can rewrite it to something more readable.

public function doSomething($someParameter, $someOtherParameter)
{
    if ($someParameter !== 0) {
        return;
    }

    if ($someOtherParameter !== 0) {
        return;
    }

    // do the actual work
}

You may be tempted to rewrite combine that if statement.

if ($someParameter !== 0 || $someOtherParameter !== 0) {

In most cases, I don't do this for three reasons:

  1. Personally, I need more brainpower to parse this.
  2. It's easy to make mistakes (should I use || or &&) when there are more conditions
  3. Using early returns is easier to debug. You could put a breakpoint or dump statement inside those if blocks. That way, you know which condition causes an early return.

This post summarised: whenever you see some code executed within an if block, check if you can reverse the condition to lose a level of indentation.

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

You can comment on this post by replying to this tweet.
Shivam Mathur liked on 11th March 2020
Joseph Leedy 🇺🇸 liked on 10th March 2020
Evgeny Levinsky liked on 10th March 2020
Murali ⌘ Krishna liked on 10th March 2020
Jasper Poppe liked on 10th March 2020
Rik liked on 10th March 2020
Ruslan liked on 10th March 2020
Max liked on 10th March 2020
Anh Tuan liked on 10th March 2020
Pavlo Bezdverniy liked on 10th March 2020
repat liked on 10th March 2020
Johan Alvarez liked on 10th March 2020
Juan Pablo 👨🏻‍💻 liked on 10th March 2020
ericpugh replied on 10th March 2020
@freekmurze Your writing is always informative, thank you! Something I have a hard time with (maybe an idea for another post, or just something others struggle with) is applying a "pattern" to real-world code that doesn't quite fit. Like, this is the Almost-Strategy-Pattern.
KM liked on 10th March 2020
Mr.Miraj khan liked on 10th March 2020
Gareth Redfern liked on 10th March 2020
monish narwani liked on 10th March 2020
Hardik Shah liked on 10th March 2020
ericpugh liked on 10th March 2020
Amit Merchant liked on 10th March 2020
Jeff Kilroy liked on 10th March 2020
jopereyral liked on 10th March 2020
Alfredo K. Carreon liked on 10th March 2020
Martijn Driesen liked on 10th March 2020
Ahmed Abd El Ftah liked on 10th March 2020
Noe liked on 10th March 2020
yoohbf liked on 10th March 2020
Ryzsk Zkhie liked on 10th March 2020
𝚎𝚛://𝚌 liked on 10th March 2020
Musa  liked on 9th March 2020
DirtyToothBrush liked on 9th March 2020
Misbah ansori liked on 9th March 2020
Stijn Vanouplines liked on 9th March 2020
Devin Hyden liked on 9th March 2020
Mark Edward Tan liked on 9th March 2020
Franck liked on 9th March 2020
Javier ☕ liked on 9th March 2020
Muhammad Tauqeer liked on 9th March 2020
Toan Nguyen liked on 9th March 2020
Franky Braem 🇧🇪 liked on 9th March 2020
Jordi Rivero liked on 9th March 2020
Chase Somero liked on 9th March 2020
jack liked on 9th March 2020
Jose Alberto Lopez liked on 9th March 2020
Ferhat YEŞİLMEN liked on 9th March 2020
togo liked on 9th March 2020
Ikechukwu Nwakanma liked on 9th March 2020
Joiner Leal liked on 9th March 2020
Jose Blaq liked on 9th March 2020
Maarten de Graaf replied on 9th March 2020
Ah happy path en.wikipedia.org/wiki/Happy_path
Derick A liked on 9th March 2020
Michael Dyrynda liked on 9th March 2020
Erich Garcia Cruz 🇨🇺 liked on 9th March 2020
Alan Kawamara liked on 9th March 2020
Rodri liked on 9th March 2020
DN liked on 9th March 2020
Greg Upton liked on 9th March 2020
Arve Solland liked on 9th March 2020
Arto Ape Aaltonen liked on 9th March 2020
Ahmad El-Bardan liked on 9th March 2020
Frano Šašvari liked on 9th March 2020
Johannes Pichler liked on 9th March 2020
byron fichardt retweeted on 9th March 2020
Johannes Pichler retweeted on 9th March 2020
Craig Paul retweeted on 9th March 2020
Brian Gallagher retweeted on 9th March 2020
byron fichardt liked on 9th March 2020
Craig Paul liked on 9th March 2020
Scorp974 liked on 9th March 2020
Alexandre Corbeil liked on 9th March 2020
Martin Carlin liked on 9th March 2020
Brian Gallagher liked on 9th March 2020
Brian Gallagher replied on 9th March 2020
When I mentor people this is one of the first things I bring up. Return/exit as early as possible before doing any actual work.
Devron Baldwin replied on 9th March 2020
I've worked with codebases with 5 plus nestings deep and it has always been something that hurts my head. On the other hand I've met developers who seem to prefer all the code in one massive blob of doom
Stéphane Hulard retweeted on 9th March 2020
Hameed Rahamathullah retweeted on 9th March 2020
audetcameron liked on 9th March 2020
Scott Zirkel liked on 9th March 2020
Alexander von Studnitz liked on 9th March 2020
Jáchym Toušek liked on 9th March 2020
Luis Cortés liked on 9th March 2020
WaveHack liked on 9th March 2020
adrian retweeted on 9th March 2020
Spatie retweeted on 9th March 2020
Thibeault retweeted on 9th March 2020
Dries Vints retweeted on 9th March 2020
Benjamin retweeted on 9th March 2020
Marvin retweeted on 9th March 2020
Grummfy retweeted on 9th March 2020
Devron Baldwin retweeted on 9th March 2020
Beater liked on 9th March 2020
adrian liked on 9th March 2020
Mike liked on 9th March 2020
ahgood liked on 9th March 2020
Kawan Koding liked on 9th March 2020
Dries Vints liked on 9th March 2020
Pavinthan liked on 9th March 2020
Divan liked on 9th March 2020
walid liked on 9th March 2020
StoicDojo liked on 9th March 2020
Simon Kollross liked on 9th March 2020
Maulik Shah liked on 9th March 2020
Johann Rudolf liked on 9th March 2020
Michael Aguiar liked on 9th March 2020
Burak Erdem liked on 9th March 2020
Marvin liked on 9th March 2020
Miguel Piedrafita 🚀 liked on 9th March 2020
Devron Baldwin liked on 9th March 2020
$name replied on 9th March 2020
the guard clause.. my favorite code practice 👍😍
Burak Erdem replied on 9th March 2020
This tip is great for multiple conditions. Thanks.
Motorhome Fulltimer replied on 9th March 2020
I learned to program in asm in the 80s and 90s. Return early was the standard to optimise for speed. It has stuck with me ever since. When I see code that doesn't do this or worse mixes return early with nested ifs I tear my hair out...
José Cage liked on 9th March 2020
Dyos Deangey 📶 retweeted on 9th March 2020
Patrick Brouwers retweeted on 9th March 2020
Ray Bonander liked on 9th March 2020
Dyos Deangey 📶 liked on 9th March 2020
Christian Bottermann liked on 9th March 2020
Richard Radermacher liked on 9th March 2020
Mary liked on 9th March 2020
Sergii Shymko liked on 9th March 2020
Patrick Brouwers liked on 9th March 2020
Rod Elias liked on 9th March 2020
Dima replied on 9th March 2020
or maybe think about refactoring your code into doSomething() and doSomethingElse()
kronos_I retweeted on 9th March 2020
Ahmet Mirzabeyoğlu retweeted on 9th March 2020
Peter Brinck 🤘 liked on 9th March 2020
Leonardo Prabangkoro liked on 9th March 2020
Aamesh Tiwari liked on 9th March 2020
Lawrence Enehizena liked on 9th March 2020
Dinesh maduranga liked on 9th March 2020
Khorshed Alam liked on 9th March 2020
Franco Gilio liked on 9th March 2020
Abel Ponce liked on 9th March 2020
Irineu M Junior liked on 9th March 2020
Cristian Cardiño liked on 9th March 2020
Matheus Gontijo liked on 9th March 2020
Adam Tomat liked on 9th March 2020
theonlyub liked on 9th March 2020
Ahmet Mirzabeyoğlu liked on 9th March 2020
Kobrowsky replied on 9th March 2020
Fun fact: After reading return early often for some time I started writing this: if ($parameter != true) { return early; } Every damn time. It was stuck in my head :D
Khorshed Alam replied on 9th March 2020
Neat!
Shirshak replied on 9th March 2020
for readability returning is probably not good idea. :D
Lucas Fiege retweeted on 9th March 2020
Rizal Fakhri retweeted on 9th March 2020
Shade.codes retweeted on 9th March 2020
Marvin Collins Hosea retweeted on 9th March 2020
Dan Chadwick liked on 9th March 2020
Matt liked on 9th March 2020
Tom Witkowski liked on 9th March 2020
Karol Krakowiak liked on 9th March 2020
Wyatt liked on 9th March 2020
Lucas Fiege liked on 9th March 2020
Rizal Fakhri liked on 9th March 2020
Didik Tri Susanto liked on 9th March 2020
Alaerock liked on 9th March 2020
Roman Pronskiy liked on 9th March 2020
Alan Rezende liked on 9th March 2020
O'cakes liked on 9th March 2020
Alexander liked on 9th March 2020
Shade.codes liked on 9th March 2020
Alexander Jank liked on 9th March 2020
Chris White liked on 9th March 2020
Marvin Collins Hosea liked on 9th March 2020
hans 👀 liked on 9th March 2020
Alan Rezende replied on 9th March 2020
Ah nice! Thanks for the clarification
Matt replied on 9th March 2020
No, deeply nested if () { if () { if () { /* actual code here */ }}, per the screenshot
Alan Rezende replied on 9th March 2020
What anti-pattern? Using early returns?
Matt replied on 9th March 2020
I routinely reject MRs when I see this anti-pattern.
Alan Rezende replied on 9th March 2020
Nice tips.
Martin Bean replied on 9th March 2020
The link in, “You can comment on this post by replying to this tweet” at the bottom of the page points to a Tweet that doesn’t exist?