Skip to main content

Summary — making class design calls at work

From the god class in chapter 1 through the refactoring practice in chapter 13, we have built up 13 chapters' worth of criteria. When you face real code, you do not need to recall all 13 chapters from the start. This chapter gathers everything so far into a checklist you can come back to whenever a call is hard to make.

What Part 1 has built up​

Part 1 (chapters 1 to 7) covered class design principles that do not depend on any framework. Starting from the god class (chapter 1), we built up one criterion at a time: encapsulation and tell-don't-ask (chapter 3), splitting classes by the single responsibility principle (chapter 4), choosing between inheritance and composition (chapter 5), and depending on abstractions through interfaces (chapter 6).

Chapter 7 consolidated all of that into a single yardstick: cohesion and coupling. The single responsibility principle is a means of keeping cohesion high, and the dependency inversion, open-closed, and interface segregation principles are means of keeping coupling low. The Liskov substitution principle sits as the precondition that makes those coupling-lowering techniques work at all.

What Part 2 has built up​

The applied half, Part 2 (chapters 8 to 13), applied those principles to real Laravel code. Starting from diagnosing the Fat Controller and the Fat Model (chapter 8), we layered on criteria: the responsibilities of an Eloquent model (chapter 9), extraction into service classes (chapter 10), dependency injection with the Laravel container (chapter 11), and design with Form Requests and custom exceptions (chapter 12). Chapter 13 applied all of it end to end to a single controller.

As stated at the top of chapter 13, no new criterion appeared along the way. It was only a matter of applying the criteria from the previous 13 chapters in order.

A checklist for real work​

With your own class, or the code you are reviewing, in front of you, run through the following questions in order. Anything that applies is the next place to work on.

Looking at a class on its own​

  • Can the reasons this class would change be narrowed to one? (chapter 4)
  • Is a public property left in a state where it can be rewritten directly from outside? (chapter 3)
  • Is the caller peeking at the class's internal state to make a decision or a calculation? (chapter 3)

Looking at how classes relate​

  • Has inheritance ended up with several axes? Does the number of combinations grow as they are added? (chapter 5)
  • Does it depend directly on a concrete class, so that merely swapping the implementation forces a rewrite of the dependent class? (chapter 6)
  • Can conditional branching be resolved by adding an implementation rather than modifying existing code? (chapter 7)
  • Does a derived class betray the behavior the base class leads users to expect? (chapter 7)
  • Does an interface force a dependency on methods that are not used? (chapter 7)

Looking at the Laravel implementation​

  • Does the processing written in the Eloquent model complete entirely within the representation and interpretation of the model's own data? (chapter 9)
  • Is there still processing in the controller that coordinates several concerns? (chapter 10)
  • Is single responsibility preserved after the extraction into a service class, or was it just a file split? (chapter 10)
  • Are dependencies on interfaces resolved by the Laravel container? Is any bind() registration missing? (chapter 11)
  • Have request shape checks been extracted into a Form Request, and intent-carrying exceptions into custom exception classes? (chapter 12)

This guide has deliberately stayed within class design itself. DDD tactical patterns (value objects, entities, aggregates, the repository pattern) and layered Clean Architecture implementations (the use case layer, the presentation layer, managing transaction boundaries) are left outside its scope.