Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Write code that fits in your head

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Write code that fits in your head

We all agree that “clean code” is important — yet the moment we try to define it, opinions both converge and diverge: readable, maintainable, tested, robust, flexible… all these words hide very different meanings depending on the team and the context.

At the same time, we often notice that iteration after iteration, development speed tends to slow down. Maintaining a steady pace or estimating reliably becomes a constant struggle, even with good quality metrics and established best practices in place.

What if part of the problem didn’t come from a lack of technical skill or knowledge, but rather from a misunderstanding of our own cognitive limits?

In this talk, we’ll explore how cognitive science sheds light on the way we read, understand, and modify code. We’ll see how these insights can help us move beyond sterile debates about “quality” versus “over-engineering” — to identify factual criteria, define simple heuristics, and build development habits that support long-term collective understanding. Ultimately, we’ll learn how to write — and evolve — code that fits in our heads.

Sources :
📚 The Programmer's Brain by Felienne Hermans :
https://www.felienne.com/book

📚 Code That Fits in Your Head by Mark Seemann
https://blog.ploeh.dk/2021/06/14/new-book-code-that-fits-in-your-head/

🔗 Arnaoudova's Linguistic Antipatterns
https://www.linguistic-antipatterns.com/

🔗 The Roles of Variables by Jorma Sajaniemi
https://saja.kapsi.fi/var_roles/index.html

🔗 Naming as a process
https://www.digdeeproots.com/articles/naming-process/

🔗 The DDD Crew
https://github.com/ddd-crew

📺 EPIC refactoring by Bryan Beecham
https://agilealliance.org/resources/videos/epic-refactoring-applying-the-epic-continuous-improvement-cycle/

Avatar for Julien VITTE

Julien VITTE

October 22, 2025
Tweet

More Decks by Julien VITTE

Other Decks in Programming

Transcript

  1. class User { public static string $foo = 'foo'; public

    int $id; public string $username; public function __construct(int $id, string $username) { $this->id = $id; $this->username = $username; } } ~60% du temps de développement to add a feature to find a bug to build an understanding of a larger system 1. 2. 3. Reading code is done for a variety of reasons: beginners will be able to process a lot less code than experts in the same time Katherine McKeithen - 1981 experts group informations in a logical way aka Chunks What you already know impacts to a large extent how efficiently you can read and understand code The more concepts, data structures, and syntax you know, the more code you can easily chunk, and thus remember and process Reading code Searching Comprehension Transcribing Incrementation Exploration
  2. Short term memory (STM) Cache or RAM of the brain

    Working memory (WM) The actual "thinking" happens here == STM applied to problem solving Stores some informations we encounter Mentally executes the code Long term memory (LTM) Stores informations for a very long time Retrieves related knowledge Informations travell from the STM into the WM Combined with informations from the LTM Working on code
  3. STM WM LTM Procedural or implicit Declarative or explicit experiences,

    context ... semantic episodic meanings, concepts, facts ... memories Germane cognitive load created by having to store your thought to LTM Intrinsic cognitive load How complex the problem is in itself ? Extraneous cognitive load What outside distractions add to the problem No cognitive load Cognitive phase Associative phase Autonomous phase Mysterious names Code smells Limited size: 7 +- 2 things time: 30s PSR-2 PSR-12 Cognitive load represents the limit of what the working memory can process. When you experience too much cognitive load, you cannot properly process code. There are two types of cognitive load that are relevant in programming: intrinsic cognitive load is created by the inherent complexity of a piece of code, extraneous cognitive load is added to code either accidentally (by the way it is presented) or because of gaps in the knowledge of the person reading the code. Perceptive Automated Fast Effortless Intuitive Automated Fast Effortless Analytical Controlled Slow Effortfull Cognitive biases Cognitive (over)load?
  4. STM WM LTM Germane cognitive load created by having to

    store your thought to LTM Intrinsic cognitive load How complex the problem is in itself ? Extraneous cognitive load What outside distractions add to the problem Perceptive system Automated Fast Effortless Intuitive system Automated Fast Effortless Analytical system Controlled Slow Effortfull Cognitive load Cognitive biases Mysterious names Code smells PSR-2 PSR-12 Limited size: 7 +- 2 things time: 30s
  5. WM LTM Procedural or implicit Declarative or explicit experiences, context

    ... semantic episodic meanings, concepts, facts ... memories Germane cognitive load created by having to store your thought to LTM No cognitive load Cognitive phase Associative phase Autonomous phase Intuitive Automated Fast Effortless Your LTM can be trained Analytical Controlled Slow Effortfull
  6. Uses good names Avoids cognitive overload Clear names help your

    LTM search for related information Improves performances of your STM Chunkable Properties of the code that fits in your brain
  7. public function post(?ReservationCommand $command): Response { if ($command === null)

    throw new InvalidArgumentException('command'); $reservation = $command->toReservation(); if ($reservation === null) return new Response(null, Response::HTTP_BAD_REQUEST); if (!$this->maitreD->willAccept($reservation)) return new Response(['error' => ReservationException::noSeatsAvailableAt($reservation->getAt())], Response::HTTP_INTERNAL_SERVER_ERROR ); $this->repository->create($reservation); return new Response(null, Response::HTTP_NO_CONTENT); } public function post(?ReservationCommand $command): Response { if ($command === null) throw new InvalidArgumentException('command'); $reservation = $command->toReservation(); if ($reservation === null) { return new Response(null, Response::HTTP_BAD_REQUEST); } if (!$this->maitreD->willAccept($reservation)) { return new Response( ['error' => ReservationException::noSeatsAvailableAt($reservation->getAt())], Response::HTTP_INTERNAL_SERVER_ERROR ); } $this->repository->create($reservation); return new Response(null, Response::HTTP_NO_CONTENT); } high level comments or line spaces to chunk larger pieces of code Chunkable code
  8. class ReservationRepository { /** * @param \DateTimeInterface $date // non

    valuable comment * * @return ArrayCollection|Reservation[] // high level comment * @return Collection<Reservation> // Phpstan or PhpStorm since 2021.2 compliant &#x1f609; **/ public function findAt(\DateTimeInterface $date): ArrayCollection { // ... return new ArrayCollection($reservations); } } high level comments or line spaces to chunk larger pieces of code Chunkable code
  9. use of design patterns helps to process code faster Consequences:

    Logical grouping of information that works together in the code Reduced amount of code in use public function post(?ReservationCommand $command): Response { if ($command === null) { // throw new InvalidArgumentException('command'); return Response::internalServerError(InvalidArgumentException('command')); } $reservation = $command->toReservation(); if ($reservation === null) { // return new Response(null, Response::HTTP_BAD_REQUEST); return Response::badRequest(); } if (!$this->maitreD->willAccept($reservation)) { /* return new Response( ['error' => ReservationException::noSeatsAvailableAt($reservation->getAt())], Response::HTTP_INTERNAL_SERVER_ERROR ); */ return Response::internalServerError( ReservationException::noSeatsAvailableAt($reservation) ); } $this->repository->create($reservation); // return new Response(null, Response::HTTP_NO_CONTENT); return Response::noContent(); } Chunkable code
  10. beacons var names, operators (+ - ...), structure (if, else,

    for ...) PSR-12: Extended Coding S… Php-fig PSR-2: Coding Style Guide -… Php-fig abk mrtpi gbar cat loves cake ".6 H"-​ h. /§63 Coding standards FTW!!! FIT coding standards to your needs $this->indirectVotes = [ "District 1" => [], "District 2" => [], "District 3" => [], + "District 4" => [], ]; $this->indirectVotes = [ "District 1" => [], "District 2" => [], - "District 3" => [] + "District 3" => [], + "District 4" => [], ]; Chunkable code
  11. Conventions Contains information about conventions your LTM is aware of

    A variable named j will remind you of a nested loop Domain knowledge Word like “customer” will have all sorts of associations in your LTM A customer is probably buying a product, needs a name and an address, and so on. Programming concepts Concept like a tree will also unlock information from the LTM A tree has a root, can be traversed and flattened, and so on CamelCase is faster to process than snake_case Beware the linguistic anti-​ patterns Use name molds to combine information Name molds are patterns in which elements in a variable name are typically combined OrderCreationCommand Domain language Programming concept (design pattern) $maxNumberOfBenefit $maxBenefit $maxBenefitNb $benefitMaxNumber Limit the number of name molds you use Anatomy of a good name There are only two hard things in Computer Science: cache invalidation and naming things. - Phil Karlton
  12. Data flow Result of a data flow saja.kapsi.fi An introduction

    to the roles of variables Roles of Variables Home Page Jorma Sajaniemi In programming, variables are not used in a random or ad-hoc way but there are several standard use patterns that occur over and over again. Immutable data Fixed value Stepper Most-​ recent holder Most-​ wanted holder Gatherer One-​ way flag Organizer Container Result from a single data flow element Follower Temporary Walker Traverse Count Check Pick accumulate store save passingly save until next Comprehension of large-​ scale programs: Roles can be used to characterize variables for maintenance programmers trying to comprehend existing code. Explaining errors: Roles of variables describe how variables are used. Any deviation from standard use patterns can be an indication of an error. Automatic error analysis can use such deviations to build explanations for errors. Variables have roles
  13. Sajaniemi variable roles Role (v. 2.0) Example Informal definition Fixed

    value maxStringLength A data item that does not get a new proper value after its initialization Stepper count A data item stepping through a systematic, predictable succession of values Most-​ recent holder inputData A data item holding the latest value encountered in going through a succession of unpredictable values, or simply the latest value obtained as input Most-​ wanted holder maximum A data item holding the best or otherwise most appropriate value encountered so far Gatherer sum A data item accumulating the effect of individual values Follower prev A data item that gets its new value always from the old value of some other data item One-​ way flag errorsOccurred A two-​ valued data item that cannot get its initial value once the value has been changed Temporary temp A data item holding some value for a very short time only Organizer sortArray A data structure storing elements that can be rearranged Container processQueue A data structure storing elements that can be added and removed Walker currNode A data item traversing in a data structure Variables have roles
  14. www.linguistic- antipatterns.com Linguistic Antipatterns This is a website to teach

    you to identify and fix linguistic antipatterns in your code Arnaoudova's Linguistic Antipatterns A class or namespace has two functions with similar names. confusable methods Inappropriately-​specific name Incorrect associated spec Missing implied return type Linguistic Antipatterns (LAs) in software systems are recurring poor practices in the naming, documentation, and choice of identifiers in the implementation of an entity, thus possibly impairing program understanding. Name/type mismatch Unexpected side effects The name of a field or function implies it is for a single usecase. However, the usage of that field or function is more general. A function has a name which strongly implies it has some property which the function does not. The name of a function strongly suggests a return type, but the function has no return value The name of a function suggests that it is pure, but it actually has an effect such as modifying some shared state or raising an exception. The name of a function / parameter / variable strongly suggests a return type, but the function / parameter / variable has a different type. Warning: linguistic antipatterns
  15. Ubiquitous Language Domain expert Product owner Data analyst Developer Developer

    Code source Tests Specs Documen tation Express domain knowledge With an ubiquitous language, the model is not just a design artifact. It becomes integral to everything the developers and domain experts do together. - Ward Cunningham A language structured around the domain model and used by all team members within a bounded context to connect all the activities of the team with the software with Ubiquitous language
  16. Eg; Enforce ubiquitous language When the code uses the wrong

    words apply Rename Class, Rename Method, Rename Field, Rename Variable and the like to the source code. For the data model use Rename Table, Rename Column, and Rename View. Change the user interface accordingly. SellItemsRequest $request OrderCreationCommand Domain language Design pattern $cart $itemRequest $cartItem 'EUR' currency Feitelson’s three-​ step model for better variable names 1 Select the concepts to include in the name. 2 Choose the words to represent each concept. 3 Construct a name using these words. Domain Knowledge ? Programming Concept? Is the name understandable without looking at the code? DOMAIN DRIVEN DESIGN Use the model as the backbone of a language. Use the same language in the code, diagrams, writing, and especially speech. UBIQUITOUS LANGUAGE
  17. Intention revealing interfaces SUPPLE DESIGN Name classes and operations to

    describe their effect and purpose, without reference to the means by which they do what they promise. INTENTION REVEALING INTERFACES Name classes and operations to describe their effect and purpose, without reference to the means by which they do what they promise. This relieves the client developer of the need to understand the internals. These names should conform to the ubiquitous language so that team members can quickly infer their meaning. Write a test for a behavior before creating it, to force your thinking into client developer mode.
  18. Data structures: directed and undirected graphs and different forms of

    lists Design patterns, such as the observer pattern Architectural patterns, such as Model–View–Controller Diagrams, such as entity relationship diagrams or sequence diagrams Modeling tools, such as state diagrams or Petri nets help you to solve problems help communicate information about programs to others Models "Models are simplified representations of reality, and the main goal of a model is to support you in thinking about a problem and ultimately solving it." Modeling helps building mental models
  19. model gives structure to UBIQUITOUS LANGUAGE cultivate rich model with

    names enter MODEL DRIVEN DESIGN Isolate domain expression with Express model with Express change with Express identity with Express state and computation with define model within Strategic design Tactical patterns CORE DOMAIN BOUNDED CONTEXT CONTINUOUS INTEGRATION CONTEXT MAP GENERIC SUBDOMAIN BIG BALL OF MUD ANTI CORRUPTION LAYER SEPARATE WAYS OPEN HOST SERVICE PUBLISHED LANGUAGE CONFORMIST CUSTOMER / SUPPLIER SHARED KERNEL work in autonomous, clean keep model unified by avoid overinvesting in assess / overview relationships with independant contexts form relate allied contexts through minimize translation supports multiple clients through formalize loosely couple contexts through segregate the conceptual messes translate and insulate unilaterally with free teams to go LAYERED ARCHITECTURE SERVICES REPOSITORIES ENTITIES DOMAIN EVENTS VALUE OBJECTS AGGREGATES FACTORIES Access with Access with encapsulate with act as root of encapsulate with encapsulate with encapsulate with encapsulate with push state changes with Domain Driven Design
  20. Model Driven Design Event storming Aggregate Design Canvas Bounded context

    canvas SERVICES REPOSITORIES ENTITIES DOMAIN EVENTS AGGREGATE VALUE OBJECTS Ubiquitous Language Domain-Driven Design Crew GitHub
  21. 7 vars (attributes / properties / temp) 7 actions 7

    concepts 7 slots for your STM Code That Fits in Your Head https://www.oreilly.com/library/view/cod e-​ that-​ fits/9780137464302/ Main Other things A fractal approach Refactoring Model : Hex Flower
  22. class OrderCreationUseCase { public function __construct( private OrderRepository $orderRepository, private

    ProductCatalog $productCatalog ) { } public function run(SellItemsRequest $request): void { $order = new Order(OrderStatus::CREATED, [], 'EUR', 0, 0); foreach ($request->getRequests() as $itemRequest) { $product = $this->productCatalog->getByName($itemRequest->productName); if ($product === null) { throw new UnknownProductException(); } $unitaryTax = round($product->price / 100 * $product->category->taxPercentage, 2); $unitaryTaxedAmount = round($product->price + $unitaryTax, 2); $taxedAmount = round($unitaryTaxedAmount * $itemRequest->quantity, 2); $taxAmount = $unitaryTax * $itemRequest->quantity; $orderItem = new OrderItem($product, $itemRequest->quantity, $taxAmount, $taxedAmount ); $order->items[] = $orderItem; $order->total += $taxedAmount; $order->tax += $taxAmount; } $this->orderRepository->save($order); } } order request product EUR OrderStatus:: Created unitaryT ax unitaryT axedAm ount taxedA mount taxAm ount orderItem 0 orderRepository productCatalog 100 2 itemRequest [] Refactoring Model : Hex Flower
  23. Code smells are parts of code that suffer from structural

    antipatterns: the code is correct but not structured in a way that is easy to process. Code smells harm cognition SWITCH STATEMENTS OBJECT-​ ORIENTATION ABUSERS BLO ATERS Une méthode est surchargée de commentaires explicatifs. Un opérateur sw itch complexe ou une séquence d'instructions if LONG METHOD BLO ATERS Une méthode contient trop de lignes de code. Généralement, toute méthode de plus de dix lignes devrait vous inciter à vous poser des questions. DATA CLUMPS DISPENSABLES Parfois, différentes parties du code contiennent des groupes identiques de variables. Ces groupes devraient être encapsulés en leurs propres classes LARGE CLASS DUPLICATED CODE DISPENSAB LES Deux fragments de code se ressemblent presque à l'identique. NO POSSIBILITY FOR EFFICIENT CHUNKING OVERLOADING THE CAPACITY OF THE WORKING MEMORY CHUNKING GONE WRONG COMMENTS DISPENSAB LES Une méthode est surchargée de commentaires explicatifs. CAN TRICK YOUR INTUITIVE SYSTEM
  24. a systematic process of improving code without creating new functionality

    that can transform a mess into clean code and simple design. Refactoring Outcomes Code cheaper to modify Code easier to understand When ? A necessary part of iterative and incremental development. You can’t plan the entire design up front You take working code and change the design to support new functionality. Before working on legacy code or code with technical debt Safe refactoring Reduce complexity Improve readability Refactoring CLEAN CODE Leave your code better than you found it. BOYSCOUT RULE
  25. Refactorings ? Reverse refactoring Cognitive refactoring aims to make the

    code easier to grasp for the current reader, even if it reduces overall maintainability. Find a code smell Apply a process Code is cleaner The code should become cleaner. ✓ The code's behavior must not change (from the user 's perspective) ✓ All existing tests must pass after ✓ Checklist a temporary action to understand the code right now. It’s an exploratory tool, not a change meant to remain. Scratch refactoring The goal is to get familiar with the code, not to actually clean it: you perform experimental refactoring without the constraint of preserving behavior exactly. The only rule is: revert your changes when you’re done.
  26. Intuitive Analytical Introduce business meaning. As mentioned earlier, apply Enforce

    Ubiquitous language, Intention Revealing Interfaces to explain what the method/class does functionally rather than how it does it technically. This increases the expressiveness of the code, facilitates functional evolutions, and avoids linking technical and business concerns. 1 2 3 4 Get Obvious Nonsense Find what it does Split into chunks Show context Get to Honest Get to obvious nonsense Get to Completely Honest Get to Does the Right Thing Get to Intention Revealing Get to Domain Abstraction Accept that the naming isn't good. Renaming with an obviously unrepresentative name at least avoids the trap of linguistic anti-​ patterns and forces developers to distrust the name. Accurately describe what the function does/what the class/variable represents. This reduces complexity by saving subsequent reviewers from having to analyze what's really behind the name. Even technical naming is fine at this stage. We're getting into the real refactoring, make sure you have auto tests to make sure you don't break anything! If the component is too big (And in the method name, class too long, ...), split it to simplify the behavior and responsibilities Naming as a Process Deep Roots Intuitive Analytical Reduces extraneous cognitive load Naming as a Process Find a code smell Apply a process Code is cleaner
  27. Improved Refactoring Checklist At most one test should fail on

    each step the Strangler Fig pattern The huge strangler figs grows into fantastic and beautiful shapes, meanwhile strangling and killing the tree that was their host => Progressively delete the old code base, in favor of a new one. Have the new code acts as a proxy for the old code. Users use the new system, but it just redirects to the old one. Re-​ implement each behavior to the new codebase, with no change from the end-​ user perspective. Progressively fade away the old code by making users consume the new behavior. Delete the old, unused code. 1. 2. 3. How To ? Create your code somewhere else. Unit test it. Identify where you should call that code from the existing code: the insertion point. Call your code from the Legacy Code. 1. 2. 3. 4. SPROUT TECHNIQUE Rename the old method you want to wrap. Create a new method with the same name and signature as the old method. Call the old method from the new method. Put the new logic before/after the other method call. Inline the old method 1. 2. 3. 4. 5. Wrap TECHNIQUE Adapt a green test to new incoming code make the test pass remove old tests Always green refactoring REFACTORING - Create new code somewhere else. - Unit test it. - Identify where you should call that code from the existing code - Call your code from the Legacy SPROUT TECHNIQUE REFACTORING - Rename the method. - Create a method with same name and signature. - Call the old method from the new one and put the new logic before/after the other method call. WRAP TECHNIQUE REFACTORING Gradually create new code around the edges of the old one. STRANG LER FIG The code should become cleaner. ✓ The code's behavior must not change (from the user 's perspective) ✓ All existing tests must pass after ✓ How to deal with Large refactorings ?
  28. Examine 1 Prepare Improve Clean 2 3 4 REFACTORING Examine

    Prepare Implement Clear EPIC find the program element(s) you want to transform. (AKA Identify). before you do the transformation, work on making that change easier. This can mean researching the impact of the planned change, or doing some preparatory refactorings to make it easier. follow safe steps to complete the design transformation. (AKA Refactor, Improve). remove any preparations or scaffolding that is not needed now the refactoring is completed. (AKA Clean). EPIC Refactoring Reverse refactoring Cognitive refactoring
  29. public function post(ReservationDto $dto): Response { $d = DateTime::createFromFormat(DateTime::ATOM, $dto->at);

    if ($d === false) { return new JsonResponse(['error' => 'Invalid date format'], Response ::HTTP_BAD_REQUEST); } if ($dto->email === null) { return new JsonResponse(['error' => 'Email is required'], Response ::HTTP_BAD_REQUEST); } if ($dto->quantity < 1) { return new JsonResponse(['error' => 'Quantity must be positive'], Response ::HTTP_BAD_REQUEST); } $reservation = new Reservation( $d, $dto->email, $dto->name ?? '', $dto->quantity ); $reservations = $this->repository->readReservations($d); $reservedSeats = array_sum(array_map(fn($r) => $r->quantity, $reservations)); if (10 < $reservedSeats + $dto->quantity) { return new JsonResponse(['error' => 'Not enough seats available'], Response ::HTTP_INTERNAL_SERVER_ERROR); } $this->repository->create($reservation); return new JsonResponse(null, Response::HTTP_NO_CONTENT); } At invalid Email null create reservation dto null quantity invalid name null too little capacity dto d r reservations Repository StatusCodes reservedSeats 10 1 Examine
  30. EXTRACT METHOD Move a code fragment to a separate new

    method (or function) and replace the old code with a call to the method. REFACTORING CLEAN CODE Leave your code better than you found it. BOYSCOUT RULE Prepare : Chunk the code public function post(ReservationDto $dto): Response { // Validate DTO $d = DateTime::createFromFormat(DateTime::ATOM, $dto->at); if ($d === false) { return new JsonResponse(['error' => 'Invalid date format'], Response ::HTTP_BAD_REQUEST); } if ($dto->email === null) { return new JsonResponse(['error' => 'Email is required'], Response ::HTTP_BAD_REQUEST); } if ($dto->quantity < 1) { return new JsonResponse(['error' => 'Quantity must be positive'], Response ::HTTP_BAD_REQUEST); } // Create reservation $reservation = new Reservation( $d, $dto->email, $dto->name ?? '', $dto->quantity ); // Validate seats availability $reservations = $this->repository->readReservations($d); $reservedSeats = array_sum(array_map(fn($r) => $r->quantity, $reservations)); if (10 < $reservedSeats + $dto->quantity) { return new JsonResponse(['error' => 'Not enough seats available'], Response ::HTTP_INTERNAL_SERVER_ERROR); } // Persist reservation $this->repository->create($reservation); return new JsonResponse(null, Response::HTTP_NO_CONTENT); }
  31. // Validate DTO $d = DateTime::createFromFormat(DateTime::ATOM, $dto->at); if ($d ===

    false) { return new JsonResponse(['error' => 'Invalid date format'], Response::HTTP_BAD_REQUEST); } if ($dto->email === null) { return new JsonResponse(['error' => 'Email is required'], Response::HTTP_BAD_REQUEST); } if ($dto->quantity < 1) { return new JsonResponse(['error' => 'Quantity must be positive'], Response::HTTP_BAD_REQUEST); } // Create reservation $reservation = new Reservation( $d, $dto->email, $dto->name ?? '', $dto->quantity ); At invalid Email null create reservation quantity invalid name null Parse Reservation dto 1 dto reservation r d MAGIC VALUES MYSTERIOUS NAME CODE SMELL When a code element like a function, class or variable has a name that is obscure or difficult to understand. What you want instead is for name to clearly communicate what the code element does and how to use it. Encapsulez ces paramètres dans une classe et remplacez l'utilisation de ces paramètres par une instance de la nouvelle classe.Whenever the code uses bad names, obscure technical names, strange RENAME REFACTORING FUNCTIONAL PROGRAMMING "A parser is just a function that consumes less-​ structured input and produces more-​ structured output." PARSE, DON'T VALIDATE ! Move a code fragment to a separate new method (or function) and replace the old code with a call to the method. EXTRACT METHOD REFACTORING Create a new method in the class that uses the method the most, then move code from the old method. Turn the code of the original method into a reference to the new method in the other class or else remove it entirely. MOVE METHOD REFACTORING CODE SMELL Create a new method in the class that uses the method the most, then move code from the old method to there. Turn the code of the original method into a reference to the new method in the other class or else remove it entirely. Implement: Parse, don't validate!
  32. Repository reservedSeats reservations reservation MaitreD // Validate seats availability $reservations

    = $this->repository->readReservations($d); $reservedSeats = array_sum(array_map(fn($r) => $r->quantity, $reservations)); if (10 < $reservedSeats + $dto->quantity) { return new JsonResponse(['error' => 'Not enough seats available'], Response ::HTTP_INTERNAL_SERVER_ERROR); } 10 MAGIC VALUES CODE SMELL Create a new method in the class that uses the method the most, then move code from the old method to there. Turn the code of the original method into a reference to the new method in the other class or else remove it entirely. CONNASCENCE OF CONVENTION CONNASCENCE Multiple components must agree on the meaning of particular values SOLID Gather together the things that change for the same reasons. Separate things that change for different reasons. SINGLE RESPONSIBILITY Créez une classe puis déplacez le code (méthodes/propriétés) responsable dans cette classe. SOLUTION EXTRACT C LASS REFACTORING Implement: Extract Specialized Service
  33. public function post(ReservationCommand $dto): Response { $reservation = $dto->parseReservation(); if

    ($reservation === null) { return new JsonResponse(['error' => 'Invalid reservation data'], Response::HTTP_BAD_REQUEST); } if (!$this->maitreD->willAccept($reservation)) { $error = ReservationException::noSeatsAvailableAt($reservation->at); return new JsonResponse(['error' => $error->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR); } $this->repository->create($reservation); return new Response(null, Response::HTTP_NO_CONTENT); } create reservation seats available dto reservation MaitreD Repository parse reservation reservation null 4 actions 5 vars CLEAN CODE 7 concepts / actions / vars to write Code that fits in yor head HEX FLOWER Clear error