Engineering Manager💫


     @SmaineDev

🖊  smaine-milianni.medium

      ismail1432

     smainemilianni

🍿 github.com/ismail1432/conferences

👋🏽 Smaïne MILIANNI

Good news 👍🏽

 👎🏻 and Bad News

@SmaineDev

Good news

Bad News

OUR job is to solve 

PEOPLE's problem

Someone has already solveD 

this problem

Design Patterns 🧩

@SmaineDev

💡Common Patterns - 🗜️How to? - 🗺️ Real Examples
 @SmaineDev

3️⃣ Categories

🛠️ Creational

How to create objects efficiently

 

🏗️ Structural

How to combine objects to build flexible and bigger systems

 

💬 Behavioral

 How objects talk and work together

 @SmaineDev

How to generate a PDF based on the signature level

🧠 USE CASE

🧠 USE CASE

🧠 USE CASE

🧠 USE CASE

🧠 Strategy

Change the behavior without modifying the code — simply by switching strategies.

🧠 Strategy

 @SmaineDev

🧠 Strategy

 @SmaineDev

🧩Defines a family of algorithms that are interchangeable

⚙️Allows dynamic selection of the algorithm at runtime

✏️Eliminates large conditional blocks (if/else, switch)

🍄Promotes flexibility and extensibility in the code

🔌 USE CASE

 @SmaineDev

🎥 replay

🔌 Adapter

Makes two incompatible interfaces work together by using an adapter object that translates the calls.

🔌 European plugs 

🔌 US plugs 

 @SmaineDev

🔌 Adapter

 Database

 @SmaineDev

Makes two incompatible interfaces work together by using an adapter object that translates the calls.

Replace a DoctrineRepository with an HttpRepository

🔌 Adapter

🔌 Adapter

🔌 Adapter

Messenger 📬
DoctrineTransport, AmqpTransport, InMemoryTransport...
Mailer 📨
SendmailTransport, SmtpTransport, EsmtpTransport...
 @SmaineDev

🔌 Adapter

🤝Bridge incompatible interfaces

👝 Reuse legacy/external code

🧲 Enable a unified contract

💅 Simplify dependency swapping

🏭 USE CASE

Create an object depending of a context or an environment

 @SmaineDev

🗣️ We use an external provider but we don't want to rely on it

in local/staging/ci environment

🏭 Factory

SYmfony Form Factory 🏭

Create an object without worrying about its internal construction.

📦 Pass the form type and options to the factory.

🎯Factory decides which concrete class to create and how to hydrate it with extensions, child types...

✅ Get a ready-to-use object without worrying about its internal construction.

🏭 Factory

 @SmaineDev

🔨 Encapsulate object creation logic
🎛️ Provide a unified way to instantiate objects
🌀 Enable polymorphism without new everywhere
🔄 Simplify swapping implementations

🛠️ USE CASE

 @SmaineDev

Create a complex objects step by step, depending of options and/or configuration

🛠️ BUILDER 

 @SmaineDev

🛠️ Doctrine query Builder 

🛠️ Builder

Build an object step by step

💡Construct complex objects step by step without huge constructors.

🤓 Objects with many optional fields or configurations.

Separate construction from representation.

🪞 PROXY

An intermediary object between a client and a target object, in order to control or add behavior when accessing that object.

💤 Lazy loading

🗃️ Caching

🚔 Access control

🪞 DOCTRINE PROXies

🪞 DOCTRINE PROXies

🪞Proxy creation

Inherits from your entity

Adds an __initializer__ (closure)

Contains the ID and minimal metadata

🕸️Access Interception

Overridden methods (getters...)

Calls the __initializer__ 

if the object isn’t loaded yet

👋🏽 On Demand loading

The initializer calls Doctrine’s UnitOfWork → targeted SQL

Hydrates the full object

✅ Object initialized

The initializer is set to null

The object now behaves like a normal entity

Doctrine doesn’t give you your entity directly → it gives you a proxy subclass that only loads the data when you actually need it.

🧚‍♂️Avoids unnecessary SQL queries

🤖Automatically handles lazy relationships

🔬Transparent to the developer

🪞PROXY

🛡 Access control: intercept calls to enforce permissions, authentication, or rules before delegating to the real object.

Lazy loading: delay the creation of a heavy object or connection (e.g., database, remote API) until it’s actually needed.

🔍 Monitoring / Logging: add logging, metrics, or performance monitoring around calls without modifying the target class.

🧹 Resource management: handle opening/closing connections, caching, or cleanup after using the real object.

When a user register, I need to :

Generate an invoice

Decrease the available capacity

Send a confirmation email

Send a Slack notification

Update the database

Log the registration event 

Trigger marketing automation 

...

👀 OBSERVER

A Subject notify the observers that an event occurs

SUBJECT

OBSERVER #1

OBSERVER #2

notify($obj)

handle($obj)

handle($obj)

OBSERVER #3

handle($obj)

👀 OBSERVER

OBSERVER vs EVENT DISPATCHER

Observer (classic)

Event Dispatcher

🪢 Coupling

The Observer often knows the Subject directly or its interface → stronger coupling.

Loose coopling,

Listeners don't know the emitter

🚠 Event

handling

Simpler, often custom-coded

Advanced: propagation, priority, named events.

🗺️ Extensibility

Rich system (dynamic add/remove listeners...)

Basic: just a notification and sometimes a state.

📢 EVENT DISPATCHER

kernel.controller

kernel.exception

kernel.request

kernel.view

kernel.response

kernel.terminate

console.command

form.pre_submit

...

 

prePersist

postPersist

preUpdate

postUpdate

preRemove

postRemove

...

Design Patterns, le trésor est dans le vendor

 @SmaineDev

Do You Know the

 @SmaineDev

🎁 USE CASE

 @SmaineDev

🤕 Docx mimetype is often not well detected by Symfony validator

😡 Customers complains because their docx cannot be used

The mimetype of a Docx can be:

✅application/vnd.openxmlformats[...].document 
❌null
❌application/octet-stream
❌application/zip

🎁  USE CASE 

 @SmaineDev

🎁 Decorator

Dynamically add new behavior to an object
without modifying its original class, by wrapping it
in another object that implements the same interface.

The mimetype of a Docx can be:

✅ application/vnd.openxmlformats[..].document 
❓ null => Decorator 🎁
❓ application/octet-stream => Decorator 🎁
❓ application/zip => Decorator 🎁

Decorate the Symfony MimeTypeGuesser to inspect the document if it's a real docx

 Powerful tool to override the behavior of your favorite framework

🏛️ USE CASE: Convert DOCX to PDF

⏏️ Upload

🗃️ Storage

📄 Conversion

🏛️FACADE

class DocxUploaderConverter
{
  public function uploadAndConvert(File $docxFile): File
  {
   //... 🍯 Tambouille
   1️⃣ Upload
   2️⃣ Storage
   3️⃣ Conversion
   
   return $pdfFile;
  }
}

🎯 Goal: Provide a simplified and unified interface to a complex subsystem.

🤝 Hides the internal complexity of multiple services/objects.

🚪 The client only uses one entry point, without knowing the details.

✅ Benefits: easier usage, reduced coupling, improved readability.

💡Facades in Symfony provide one simple entry point for developers, hiding dozens of internal services, adapters, and configurations behind a clean API.

🏛️FACADE

🏛️Template

🎯 Goal: Define a fixed workflow 

while letting subclasses customize certain steps.

Symfony provide us a simple way to trigger a script within our application with a command line

Console Commands

Each command has its own behavior but follows the same workflow (initialize → interact → __invoke/execute).

🔄CHAIN OF RESPONSABILITY

The Chain of Responsibility pattern lets a request pass through a chain of handlers, and the first handler that can handle it does. It decouples the sender from the receiver.

source: https://refactoring.guru/design-patterns/chain-of-responsibility

Serialize

Deserialize

Serializer

💡The serializer doesn’t normalize/denormalize by itself.

🔁 It loops through available normalizers.

❓It asks each one: “Do you support this data?”
🙋🏿‍♂️ The first normalizer that says yes handles the data.

🔄CHAIN OF RESPONSABILITY

All of this has been made possible thanks to Ryan. 🫡

Design Patterns

 @SmaineDev

Design Patterns List ⏭️

🏗️ Creational

A single global instance

Singleton

Factory

Delegate creation

Builder

Construction of an object step by step

Prototype

Create an object by copying an existing one

🧩 STRUCTURAL

Bridge

Separate abstraction from implementation

Composite

Hierarchical tree structures

Facade

Simplified Interface

Convert Interface into another one

Adapter

Flyweight

Sharing objects to save memory

Proxy

Surrogate or access control

🔩Behavioral

Strategy

Interchangeable algorithms

Observer

Automatic notification

Template

Skeleton of an algorithm

Pass the request along a chain

Chain of responsability

Iterator

Sequential traversal

Memento

Save and restore state

Mediator

Centralize communication

State

Change behavior base on state

Visitor

New operations without modifying structure

Mediator

Centralize communication

Command

Encapsulate a request

Mediator

Centralize communication