Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Clean Code in PHP

You're reading from   Clean Code in PHP Expert tips and best practices to write beautiful, human-friendly, and maintainable PHP

Arrow left icon
Product type Paperback
Published in Oct 2022
Publisher Packt
ISBN-13 9781804613870
Length 264 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Authors (2):
Arrow left icon
Alexandre Daubois Alexandre Daubois
Author Profile Icon Alexandre Daubois
Alexandre Daubois
Carsten Windler Carsten Windler
Author Profile Icon Carsten Windler
Carsten Windler
Arrow right icon
View More author details
Toc

Table of Contents (18) Chapters Close

Preface 1. Part 1 – Introducing Clean Code
2. Chapter 1: What Is Clean Code and Why Should You Care? FREE CHAPTER 3. Chapter 2: Who Gets to Decide What “Good Practices” Are? 4. Chapter 3: Code, Don’t Do Stunts 5. Chapter 4: It is about More Than Just Code 6. Chapter 5: Optimizing Your Time and Separating Responsibilities 7. Chapter 6: PHP is Evolving – Deprecations and Revolutions 8. Part 2 – Maintaining Code Quality
9. Chapter 7: Code Quality Tools 10. Chapter 8: Code Quality Metrics 11. Chapter 9: Organizing PHP Quality Tools 12. Chapter 10: Automated Testing 13. Chapter 11: Continuous Integration 14. Chapter 12: Working in a Team 15. Chapter 13: Creating Effective Documentation 16. Index 17. Other Books You May Enjoy

Best practices – where do they really come from?

When we are talking about “best practices," we can differentiate three cases, as follows:

  • Principles that have been proven for decades to work, which also are deduced from common sense: In this category, we can—for example—find design patterns. In short and if you do not know them, these are tools that fix recurrent programming problems. They have been here for decades and are known by millions of developers.
  • Choices made because we had to make them: Here, we can find things such as code style, naming conventions, and so on. Technically, it does not matter if you would like to use camelCase or snake_case to name your files. But if everyone is following the same rule, it is easier for everybody to understand each other.
  • “Technical” best practices: Some “best practices” are actually dictated by technical constraints and features. A concrete example is “method name guessing” in PHP: Hypertext Preprocessor (PHP). Let’s say you would like to guess “getters” (accessors) and “setters” (mutators) of an attribute of a PHP class. You are likely to try methods starting with get, set, is, and so on. If everyone has their own rules about naming accessors and mutators, you can be sure that someday and without warning, things will blow out.

Design pattern principles

The design patterns case describes objective solutions to solve problems. You can dislike them and how the code is being organized by them but cannot say that they are objectively bad. Because your thoughts on them do not matter, they work.

Talking about principles that have been present for decades, we can highlight four famous ones: DRY, KISS, YAGNI, and SOLID.

DRY

DRY stands for Don’t Repeat Yourself. This principle simply states that you should never have, in your application, two authorities doing the very same thing. It may sound obvious, but applying this may not always be a reflex, especially when you are new to application programming. Having the same responsibility at two separate places in your code means maintaining those two places every time you fix something. It means having to think about these two places at each change (and someday, you are going to forget one, for sure). Also, how is any developer maintaining your source code supposed to know which one to use if two things have the same responsibility?

KISS

KISS stands for Keep It Simple, Stupid. Sometimes, we complicate our lives. We can see two main reasons for this, as follows:

  • First, we try to do complicated things with our code, but these stunts do not bring anything valuable and complicate the code. We will see later in this book in detail why we absolutely need to avoid this.
  • The second reason is a lack of perspective on what we are doing. We have spent many hours trying to solve something, and we are too much “into it." Some rest is necessary to get this perspective and, sometimes, start it all over again.

Both cases are recurrent and prevent us from going straight to the point and keeping things simple. When you feel you are going “too far," think of this acronym to get back on the rails.

YAGNI

YAGNI stands for You Aren’t Gonna Need It. In some way, it goes hand in hand with the KISS principle. It is quite common (not to say part of our daily lives as developers) to want to find a solution to a problem by thinking about the future. Indeed, we regularly have this thought: “If tomorrow I need to do such and such a thing, at least this will already be in place.” The reality is that, in general, no—we will never have the need that we want to try to foresee. Then, by trying to get ahead of a task that may never exist and whose functional constraints are unknown, not only do we waste time, but we also complicate our lives by thinking too far ahead. We move away from our initial goal, which is to find a quick, viable, and robust solution.

We are not psychic, and we cannot know all the problems that will appear if the task we predicted appears. You will quickly realize that if you keep things simple and without superfluous additions to try to get ahead of the game for the next day, you will have a healthy, no-frills code base. This means a faster understanding of the code, greater ease in navigating through it, and making changes when they are really needed. Plus, you will probably save yourself a lot of bugs. It is always complicated (if not impossible) to justify that a bug was made in your source code because you developed and spent time on something that was not asked of you. If your job as a developer requires you to collaborate directly with the customer, you should know that the customer will not pay you for something they did not ask for. You will have worked for free, which is never ideal.

Caution: It is obviously necessary to take this on a per-case basis. We can take as an example magic numbers. Magic numbers are constant values, mainly numbers, hardcoded and without any explanation of their meaning.

Verdict: Two weeks later, everyone has forgotten what this number corresponds to. We will then think of using well-named code constants. However, there is a huge chance that the value of this code constant will never change because the needs would have changed. At first sight, it would be strange to want to declare a constant to use it everywhere. The purpose of code constants is to add semantics to fixed values and allow us to easily change that value everywhere it is used in the code, at once. This is, in a sense, contrary to YAGNI (since these values will probably never change).

However, we can see the value of using constants. Perspective and reflection are always necessary, whatever the clean-code principles applied.

SOLID

Finally, maybe the most famous one, SOLID. Let’s see what these letters stand for:

  • S stands for single-responsibility principle (often abbreviated to SRP). Very simply, it means that a class in your code must respond to only one task. Obviously, the size of that task is the key point here. We are not talking about creating a class with only one available method. Rather, we are talking about creating a logical breakdown. A very concrete example is the model-view-controller (MVC) architecture. The important thing to remember is that you must avoid having catch-all classes, grouping together database operations, Hypertext Markup Language (HTML) rendering, business logic, and so on. The breakdown must be logical. An example of a breakdown could be a class for generating HTML, a class for database interactions for a given object, and so on.
  • O stands for open/closed principle (OCP). You will often find the following definition for this principle: a class must be open to extension and closed to modification. Concretely, in the code, this is materialized by the strong use of polymorphism and the use of interfaces rather than by conditional branching with multiple if and else statements. Indeed, if you use conditional branching, you incur a modification of the class, and this can quickly become unmanageable if you have more than two cases. By extending a class and overloading the methods you are interested in, you get concise code, well broken up and without branching of several hundred lines.
  • L stands for Liskov substitution principle (LSP). Behind this complicated name is actually something quite trivial. In fact, this principle simply says that when you use an interface implementation, you should be able to replace it with another implementation without having to modify the implementation in any way. In the code, this translates into the fact that the implementations of an interface must be similar, especially regarding the return values of the methods (if one implementation returns a string when calling the foo method and another implementation returns an object, it will be complicated). Fortunately, the typing of return values exists in recent versions of PHP, limiting the possibilities of violation of this principle.
  • I stands for interface segregation principle (ISP). This describes that a class implementing an interface should not be forced to implement or depend on other methods of the interface that it does not use. Concretely, this principle will prevent you from creating an interface with dozens of methods in it that are there just in case. It is better to create several interfaces (joining the principle of single responsibility), even little ones, with a very precise goal and responsibility. Then, you’ll be able to implement them unitarily in your class.PHP allows a class to implement as many interfaces as we want, so this works perfectly fine. Thanks to this, the implementation we describe will only know the methods that are useful to it. Otherwise, we would end up with dozens of methods with an empty body or returning a null value. When you put it like that, you realize that it does not sound like very "clean code."
  • Finally, D stands for dependency inversion principle (DIP). Once again, this is a term that may seem complex at first glance but hides a much simpler reality. Very concretely and in the code, it materializes by using interfaces and abstraction rather than implementations. For example, when you type the argument of a method, you use the interface as the type. This will allow you to make full use of polymorphism and to take full advantage of Liskov substitution. By using the interface as a type, you will be able to send as an argument to the function any implementation of the interface. To give an example, if you need to send emails in an application, chances are you will create a MailerInterface interface. You will then have one implementation per mail service. By typing the argument with the interface, the method will be able to receive any implementation and use the right email service for your case.

We can quickly realize that these principles are very much linked. They work together, and they allow a strong decoupling, a strong separation of responsibilities, and a fluid thinking when you have these principles in mind while writing code. It can be extremely helpful to remember these principles; at least, it is a particularly good thing to know their existence. Apart from the SOLID principle, you can see that KISS, DRY, and YAGNI are pretty common-sense and logical. Remembering them from time to time can be beneficial and can help us to put up barriers when we get a little off track.

Bonus – Scouts’ principle

Something that can also be added, which is also a common-sense principle, is the “Scouts’ principle." We all know those groups of young people and teenagers that act with a benevolent purpose and show a great deal of altruism. The Scouts go camping in the woods, build a fire, and spend the night there. Once they get up in the morning, they might put out the fire and put away their stuff, but most of all, they clean up the place to make it cleaner than it was before they arrived (at least, in theory).

As a developer, it is the same. Be a Scout. When exploring and browsing the code, if time and context allow, it is often a particularly clever idea to clean up where you see some technical debt. If you are going through places in the code base and think “this is really bad," maybe this is an opportunity to make it more manageable and cleaner. If everyone gets on board, the quality of the project’s source code can rise very quickly.

Of course, this “Scouts’ principle” must be done in accordance with your project constraints, time constraints, and customer needs. Moreover, it is quite risky, and you must know when to stop. When you send your changes to your team for review, the changes and cleanup you have done must be consistent. You do not want to rewrite half the application every time you find a little thing, which leads to another, then another, and so on. It’s more about cleaning up the things that are relevant to what you’re doing. It can be extremely complicated to stay focused and fixed on your context. There is no genuine answer to “when to stop”; it will depend a lot on the time you have and your task. However, there is nothing to stop you from writing down things that you want to come back to but that unfortunately were not related to what you were doing, that seemed too energy- and time-consuming, or that simply require further reflection with the team.

On the opposite side, code style, naming conventions, and similar things are subject to tastes and habits. Everyone has their own tastes and habits, so decisions need to be made. As we discussed earlier, it is so much easier to talk together when we all follow the same rules.

So, who decides these best practices in a team or an organization? Well, generally, it is a consensus after lengthy discussions about the subject at the beginning of a project. Because yes—“best practices” are not something that you can always apply everywhere, and you should be aware of this. You should be aware of the context you are in.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image