- T.R.U.E.
- Transparent: Consequences of changing the code should be obvious in the code it is changing and in distant code it relies upon
- Reasonable: The cost of changing the code should be porportional to any benefits one might gain. (Small change == Small gain, big change == big gain)
- Usable: Existing code should be usable in new and unexpected contexts
- Exemplary: The code itself should encourage those who change it to perpetuate those qualities
It is useful to think of classes as sentient beings. When writing new methods on a class, perform the mental exercise of asking 'Does this make sense?'.
One of these things is not like the other!
- Hello Mr/Mrs
RecurringBooking
, what is yourfrequency
? - Hello Mr/Mrs
Booking
, what is yourdate_start
? - Hello Mr/Mrs
QuotesController
, can youinfer_email_from_current_user?
? - Hello Mr/Mrs
API::V3::BookingsController
, can youmap_booking_instruction_data
?
CreditAdjuster
adjusts the credits a user has.ProPaymentStrategy
is a strategy for how to pay a pro for the bookings they perform.ChargeRecurringBookingService
is a service class that charges bookings on active cleaning plans and identifies bookings on cleaning plans which need charging.- This is an example of a class that does too much
If you need to use and / or, your classes are doing too much!
class
es should be designed to fufill a single responsibility.
-
Exemplary code as a message to future developers. If we allow classes with poorly designed boundaries in our codebase, it will lead to future developers adding to the mess.
-
It is important to take into account the balance of improve it now vs improve it later. It cannot be ignored that every decision has a price.
attr_reader
,attr_writer
andattr_accessor
are your friends- Difference between instance variables and their getter/setter methods
- Make code easier to mock/stub for testing
- Depending on complicated data structures as a recepie for disaster
- Complicated structures like nested arrays often obscure the data they are holding. Using objects that respond to semantically accurate messages help bring this to the surface.
- Designing methods that have one responsibility.
- Smaller methods promote DRY code and expose reusable components
- Avoid the need for comments
- Pick out commented code blocks and move them to their own method, the method name should document the behavior
- If documentation is still needed, doc blocks can be added for individual methods.
- Easily transportable code for easier refactoring
- Embracing open ended questions instead of an either/or mindset.