A pretty popular myth about avoiding global state (singletons, multitons, registries, global variable, static variables/methods) is that it results in creating widely used objects more often than needed. The most common example in this case is a database connection. We try to avoid global state to let objects express their dependencies clearly: the object constructor should be as readable as “give me this, give me that and I will work”. Let’s talk about a situation where we instanciate a relatively complex set of domain objects including a service layer. For the example, we assume that we read an existing customer. We use the CustomerServiceLayer to retrieve the Customer, which uses the CustomerRepository to create the Customer object which needs a DatabaseConnection connection and passes a strategy (NameFormattingStrategy) to format the name of the customer to the Customer object and a CustomerDataMapper to allow the Customer object to save itself. Here are the constructor signatures of the involved components:
class Customer ...
public function __construct(
NameFormattingStrategy $nameFormattingStrategy
)
class CustomerRepository ...
public function __construct(
DatabaseConnection $connection,
CustomerDataMapper $dataMapper,
NameFormattingStrategy $nameFormattingStrategy
)
class CustomerServiceLayer ...
public function __construct(CustomerRepository $repository)
class CustomerDataMapper ...
public function __construct(DatabaseConnection $connection)
class DatabaseConnection ...
public function __construct(
string $host,
int $port,
string $username,
string $password,
string $database
)
So, all we do in the page controller, may it be a (page) controller or a plain PHP file is instanciating the service layer and its dependencies:
$databaseConnection = new DatabaseConnection(...);
$customerDataMapper = new CustomerDataMapper($databaseConnection);
$nameFormattingStrategy = new NameFormattingStrategy();
$customerRepository = new CustomerRepository(
$databaseConnection,
$customerDataMapper,
$nameFormattingStrategy
);
$serviceLayer = new CustomerServiceLayer($customerRepository);
$customer = $serviceLayer->getCustomerById((int)$_GET['customer_id]);
... pass it to the view, do nifty things ...
If other components, like the OrderRepository needs a database connection, just pass it to it. No need to let the order repository know how to get it. It is just there. In your unit test you can passed a mocked repository, a mocked database connection and a mocked data mapper depending on what particular part of the chain you are going to test. By the way: the heavy construction work could be easily passed to a number of factories just responsible for creating your objects. These factories are easily testable too as the only assertion made would be is the returned object correctly configured.
Filed under OOD, OOP, PHP, Unit testing & eleven comments & no trackbacks
When it comes to reading I’m coming from a different corner: I read a lot of philosophical books from philosophers like Adorno, Marcuse, Marx before I really started reading tech books. These books are hard to read, especially the works of the Frankfurt School are notorious for their specific language which is sometimes hard to decipher. Tech books are exactly the opposite: while there are entertaining technical writers with a good style a lot use a pretty common and dry vocabulary – which is a good thing. The thing is, you don’t really need to read tech books.
Novels, philosophical – and more general humanistic – works are much harder. They often transport semantics in metaphors you don’t get when just reading. You have to read a sentence more than once to get it. But when you read a book about Design Patterns, your favourite book on PHP or something similar non-algorithm related you can just scan the book for news, read and understand the code samples and go on, page per page. Scan through the page, take notes but just note what’s new to you. If it is a reference, mark the important parts with stickers. Ignore the rest, remember, don’t read, just scan.
Additionally technical books tend to have a foreword and a foreword for the second edition and a forward for the third edition and a lot of testimonials attesting how good this book is (hey, I already purchased it, don’t sell it to me again). So the real content starts at page 40. Excluding white pages the book that was 400 pages long might shrink to 300 pages. If you need 30 seconds per page that means you can read the book in two and a half hours. And 30 seconds per page a a pessimistic estimation. With this technique it is possible to read a technical book in a day without stress and totally relaxed in a week. That means you could read 52 tech books a year. I’m lame, I just read scanned around 20 last year.
Filed under Books, Frankfurt School, PHP, Reading, Retraining, Technology & three comments & no trackbacks