Don't use inheritance as another way to copy/paste code.
class EmailRubbish
{
public function sendEmail(string $email, string $subject): void
{
// spam poor user...
}
}
// Is a Cart some kind of Email?
class RubbishCart extends EmailRubbish
{
public function rubbishCheckout(): void
{
// do checkout stuff
$this->sendEmail($this->user->getEmail(), 'Payment succeeded, you are now poorer!');
}
}
// Is Love some kind of Email? 💔
class RubbishLove extends EmailRubbish
{
public function youWillLoveMyMum(): void
{
// do Love stuff ❤️ (NOT WITH MY MUM!!)
$this->sendEmail($this->user->getEmail(), 'You have a new match on Tinder!');
}
}
That's called "horizontal code reuse", as opposed to the "vertical code reuse" of inheritance.
READ the Law of Demeter
final
is your friend. It pushes you to use DI and avoid inheritance and bad patterns. Use it as much as possible. Please read : When to declare classes final by Ocramius.
Service locator, i.e $this->getRepository(User::class)->find($id);
is bad! Read PSR-11 paragraph 1.3. PhpStorm is not your friend by allowing go to on this, most language servers won't. Use DI properly and inject only what you need (cf. Symfony 4, auto wiring and stuff).
UUID has been here for over 15 years, there is absoluetly no excuses to still use Auto increment Id.
When you create an object with an attribute wich is an auto increment id you have an invalid object. Why? Because you first have to store it to the db to get this id, so you can't send it back for instance. Instead use UUID. Even better: no one will ever iterates over the few likes you had on Tinder... 🍌✂️🍑
Setters & Getters are useless on entities. What is the point of using a Serializer to call setters & getters? Create DTO.
Don't use an ORM to deal with a large amount of data, it's not design for this. It hydrates objects, Reflection classes and do a lot of other stuff that is not initialy designed for. Consider memory leaks.
Entities are not a db table representation, they are a model ought to do stuff.
Don't use EAGER. You will have n+1 query performances issues. Use join in your Repositories. If you use Extra Lazy it probably means you've reach the limit of the ORM and will face UnitOfWork that will create memory leaks.
One usually don't need them. One usually does $user->getProducts() rather than $product->getUsers(). Think about when you will serialize/deserialize those Collection.
It's an ORM hack, they will trigger the event each time you serialize or deserialise the object. Don't use them. They're a performance killer and make stuff very complicated to debug and understand. The only case would be for internal state mutation like to update a dateTime.
Go for immutable entities, just append data. No more cache problems, you can do analytics, etc. Go Event Sourcing, Go Kafka 😋
Stop making soft delete, it's mutation. Your db is then half invalid think about the queries problem you will have billions of entries.
Entity are supposed to be always valid. Don't use Symfony Validator for it. Any invalid object should be pushed in a different objetc. Use DTO (Data Transfert Object).
Use Annotations for private package and use XML for OpenSource stuff. XML make it easier to replace the maping.
They're good for your grand ma blog and still... Don't use them. Period.
One should make the difference between:
- functional testing (i.e: you Mock nothing)
- integration testing (i.e: you only Mock your code)
- unit testing (i.e: you Mock everything outside the method)
Create Mock only your own code not dependencies! First because most of the time you can't, as usually depencies have their classes declared final
so one can't inheritate to create a Mock and pass TypeHint and because their is no need. Then because you don't know how the dependency work and their behaviour might change. For example if one day $myUserRepo->find($id)
return something else than your Object or Null your test will pass but your code will fail. But you can Mock the Interface your dependency implement instead. If you need to Mock the class you are testing (Partia Mocking), it's probably because your classes does too much and is violating SOLID.
"I love the fact that whenever I think of doing something wrong, phpspec and prophecy tell me to get back on the right path. If you don't want to design properly, phpspec is not the tool for you. There's no such thing as "over design"." - Jakub Zalas
This is said... uses PHP-DI, take a look at Nette, we are in 2019 we uses components not Frameworks. No one cares about Frameworks anymore. Frameworks = Coupling = Rubbish. No one cares about how one method works as long as there is an interface that works. Think Design by Contract.
It's hard to scale a monolithic app. What would the Parliement look like if all the people of a country were going there to vote? Send a representant, somone who will communicate for you, an interface. It's more DevOps stuff I know. But no more Git conflicts, no more code you don't care about, it's SOLID, it's King Kong!