Building Maintainable PHP Applications: Introduction
Table of Contents:
Introduction
Thinking data (CRUD) vs thinking business processes (behaviour)
Architectural Layers
Model-View-Controller
Hexagonal Architecture (Ports And Adapters)
Clean Architecture
Vertical Slices Architecture
Value Objects
The Repository Pattern
The Decorator Pattern
The Factory Method Pattern (named constructors)
The Factory Pattern
The Command Bus
The Event Bus
The Query Bus
Testing
Tell, Don’t Ask
Immutable Objects
Composition vs Inheritance
S.O.L.I.D.
Dependency Injection vs Service Location
Active Record vs Data Mapper
Test-Driven Development
Behaviour-Driven Development
Domain-Driven Design
Command Query Responsibility Segregation
Event Sourcing
Event Storming
The Aggregate Pattern
Entities
View Model Pattern
Read Model Pattern
Write Model Pattern
The Service Pattern
The Singleton Pattern
The Null Pattern
The Strategy Pattern
(More topics to be added soon)
Overview
Over the years, I’ve had a chance to work on different types of projects in my career, from startups that are built from scratch with a small team or alone, scale-ups and enterprise products with 100s of developers and thousands of features spanning over multiple applications (distributed systems) and I’ve noticed that the code becomes very hard to maintain, slow and very hard to work with after a while, regardless of how successful they are.
I’ve mostly worked with Laravel, Symfony and even native PHP and raw SQL at times so I’ve seen code that you wouldn’t want to touch it or work with it ever.
Recently, I heard something along the lines of:
One of the reasons why we rebuilt our product from scratch is because once you onboard bigger clients, you hit bigger problems and most of it comes down to the architecture and code structure, standards that you choose. I didn’t think that the project will be a business when I built it initially. No matter how much make up you put on a pig, it’s still a pig.
and I thought that this perfectly fits with this series of articles so I had to include it.
I’ve learned that maintaining a product is way harder than building it. You can write the code quickly and it will work, it will do the job, it may even help you build a successful business but it will be horrible to maintain it for the long run if the product survives.
Many people are against thinking for the long run whenever they write code and build products, and they have every right to do that, because who knows if the product will survive after the first year or two.
I’ve always been curious how to structure my code, the architecture of it, but I couldn’t figure out why most projects end up in the same state (more or less) after a while.
I wasn’t chasing perfection, but rather I wanted to learn how to become a better software engineer, so that I can design better products for the long term.
After reading a bunch of different discussions, books and discussing with many different people with different experiences, I noticed that there are ways to deal with complex code but it may be completely different and harder to build products that way.
This is because I am not used to writing code or thinking that way. I’ve spent most of my career doing almost the same thing but in the recent years I started exploring and experimenting with some different approaches to building products which will take a long time to get used to.
In this long series of articles I’ll share some of my learnings along the way, even though I know that this may not be for everyone or not everyone will like it but the idea is that people will learn something new from this, even if they never use it in their projects.
The idea is not to bash people’s experiences, ways of writing code but rather compare the good and the bad sides of each approach and learn something new.
Most tutorials, courses, articles, books, academies, colleges, discussions and other forms of learning resources mostly focus on the basics and/or the short term of building products, but they don’t focus on the long term.
This is because it will take years to create such content and/or that type of content is not really applicable for the target audience that wants to learn more about this stuff. It will also take a long time until the person gets to the point where they understand and connect the dots why one way may be better than another one. It also requires experience, people need to go through trial and error for them to understand why software needs to be built differently in order for it to be maintainable.
I want to do something slightly different with this series, to approach software development from a different angle from my experience. I think that this type of content is very rare or hard to find on the internet.
Some topics may contain more theory rather than code but it’s important to read all of the topics so that you can get a better understanding of what’s going on.
Each article will cover one topic at a time, some may be short, some may be longer and more practical with more complex code examples.
The code examples will be using mostly Laravel or Symfony (wherever applicable) but you don’t have to know or use those frameworks in your daily life. I’ll try to explain every step of the way in as much detail as possible or provide resources so that you can learn more about them.
First, I’ll start with simple code examples and later on move on to refactoring more complex code sample(s) from a real world scenario so that you can see the difference, the pros and the cons of each approach.
Let’s discuss these ideas and approaches so that we can learn from each other’s experience, that’s the main goal after all. I am also doing it for my own selfish reasons, to learn and experiment more but you probably knew that already.
Remember, it’s not about perfect code or “my code is better than yours”, but rather how to maintain the code even if that requires more thinking, more files to be created and code to be written.
I also spoke at the first PHP Skopje meetup on the same topic, which was my first ever public speaking experience.