phparchitect-2019-08

(Rick Simeone) #1
http://www.phparch.com \ August 2019 \ 29

Education Station
Writing DRY, SOLID FOSS OOP CRUD Code

can over-complication of our software.
Complicated code leads to less main-
tainability, which leads to more bugs.


Back in 2014, the Heartbleed bug^2
hit the web. It was actually caused by
a bug that was added to the OpenSSL
library back in 2012 that caused a buffer
over-read when doing input validation.
While there were a few factors that led
to implementing the actual bug and not
noticing it for nearly two years, one of
the causes was overcomplication of the
software.
The OpenSSL maintainers built their
own memory management routines
and had emphasized performance over
security. This lead to the LibreSSL fork,
and massive code cleanup. LibreSSL
removed more than 90,000 lines of
code in the first week as they attempted
to reduce complexity and correct some
of the bad practices of the library.


A significant contributor to this
result was that two people maintained
OpenSSL. The library is so complex
that it reduced the number of people
that could actively maintain and work
on the code even on a volunteer basis.
Even with security software like this
being complex, it seems that OpenSSL
needlessly complicated their code.


When writing new software, we
should all strive to make the code as
simple as possible. This means avoiding
scope creep, resisting the temptation
of over-engineering functionality, and
writing code that is clear and self-doc-
umenting. If you ever find yourself
commenting a block of code to explain
what it does, then you are probably
making the code more complicated
than it needs to be.


Do not confuse fewer lines of code
with being simpler, either. One of the
downsides to Perl was its ability to be
incredibly terse at the expense of read-
ability. Do not try and be clever with
code just to remove lines—readability
is just as important.


2 Heartbleed bug:
https://en.wikipedia.org/wiki/Heartbleed


YAGNI
YAGNI stands for You Aren’t Gonna
Need It. It stresses the idea that you
should not build functionality until you
need it. Ron Jeffries, a co-founder of
Extreme Programming, wrote:

“Always implement things when
you actually need them, never
when you just foresee that you need
them.”

This idea goes hand-in-hand with
KISS. If we only write the code that is
needed now, we can help reduce the
complexity of the system by having less
moving parts. We can also deliver code
quicker by building what is needed
now, instead of adding additional time
writing functionality that we might
never use.

SOLID
SOLID is not a single idea like WET
or DRY, but a collection of ideas that
work together to write well structured
object-oriented code. By following the
SOLID principles, our code should be
much easier to write, maintain, and
extend over time. Let’s look at what
each letter in solid represents.

Single Responsibility Principle
Robert C. Martin coined the Single
Responsibility Principle, and it states
that every module, class, or function
should have a single responsibility.

Responsibility is defined as “a reason for
change,” but not a change in the state of
the application. When looking at the
various things that we can refactor in
a class, we expose the reasons we can
change a class.
The classic example is a report class
that generates and outputs a report.
If we need to refactor this class, we
have two parts we can refactor—the
processing of the report data, and then
the output of that data. If we originally
wrote the report to process the last 24
hours of data and output as a CSV, we
may want to change the timeframe, or
possibly the output to be a JSON, XML,
or even a PDF.
In this case, our report class has
two reasons for changing, and that
makes it harder to extend and main-
tain. We should break this single class
into a ReportGeneration class, and a
ReportOutput class. This split allows
us to reduce the classes into a single
responsibility as in Listing 3.
While the “bad” code might be
easier to write, it is harder to main-
tain in the long run. We need to start
adding switch statements and addi-
tional dependencies to the DailyReport
object. The “better” code allows us to
decouple the output from the genera-
tion completely, and each output type
can have their dependencies and logic.
It is also easier to extend, as anyone can
write child classes instead of needing to
override the DailyReport class directly.

Listing 3


  1. <?php

  2. // Bad:

  3. $report = new DailyReport();

  4. file_put_contents($report->generate('csv'), 'output.csv');

  5. file_put_contents($report->generate('pdf'), 'output.pdf');



  6. // Better:

  7. $rawData = $dataService->getData('24 hours');

  8. $reportGenerator = new ReportGenerator($rawData);

  9. $csvOutput = new CsvOutput();

  10. $pdfOutput = new PdfOutput();

  11. file_put_contents($csvOutput($reportGenerator->generate(), 'output.csv'));

  12. file_put_contents($pdfOutput($reportGenerator->generate(), 'output.pdf'));

Free download pdf