By using a comprehensive feature-filled framework we can build software fast. On the other hand, by decoupling our applications we can build sofware that is independent of our framework and infrastructure choices, and therefore longer lasting.
We can't do both, is one approach always right?
In this talk we'll look at different decoupling techniques, what problems they solve, and when they make sense. We will learn some concrete techniques to discover where we should be investing in decoupling, and when we should let the framework maintainers do the work for us.
11. Problems with dependencies
4 Changes to Car mean changes to Dispatcher
4 Can't reuse Dispatcher with new vehicles
12. interface Vehicle
{
public function goTo($destination);
}
class TaxiDispatcher {
function dispatch (Vehicle $vehicle, $destination)
{
$this->chargeCustomer();
$vehicle->goTo($destination);
}
}
13.
14.
15.
16.
17. Benefits of abstraction
4 Now we only need to rewrite Dispatcher and Car
when Vehicle changes
4 Vehicle can be very stable; it's just an interface
4 Can make new transportation types that implement
Vehicle
18. Defining abstractions
4 Start with the abstraction, not the detail
4 Contract should be a simple as possible
4 Contract should focus on resposibilities
4 Hide details of underlying APIs
19. Example - upgrade eligibility
Bad abstraction:
interface HttpClient
{
public function getData : array ($url, $parameters);
}
20. Example - upgrade eligibility
Better abstraction:
interface UpgradeEligibilityChecker
{
public function getContractId : int ($phoneNumber);
public function isEligibleForUpgrade : bool ($contractId);
}
21. Example - upgrade eligibility
Best abstraction:
interface UpgradeEligibilityChecker
{
public function isEligibleForUpgrade : bool ($phoneNumber);
}
22. Or, get on the bus
4 Migrate actions from method calls to objects
4 Depend on a bus rather than depending on contracts
4 Don't know anything about what handles the action
24. Commands
Use case / service style:
$invoiceApprover->approveInvoice(1234);
Command style:
$commandBus->dispatch(
new ApproveInvoice(1234);
);
25. Advantages of decoupling via
abstractions
4 Cleaner APIs
4 Swappable components
4 Separation of concerns
4 Easier to test
4 No 'ripple effect' around changes
26. Disadvantages of decoupling via
abstractions
4 Makes execution flow harder to follow
4 Adds more complexity (more files in codebase)
4 Cognitive cost of thinking of good abstractions
27. Architectural boundaries
4 Abstractions are going to change when the use cases
change
4 Interfaces are more tightly coupled to code that
uses them
4 Interfaces 'belong' in the same architectural
boundary as the code that uses them.
32. Highly coupled frameworks
Some frameworks let you go really quickly by coupling
directly to them.
You probably won't be able to reuse your code without
considerable effort.
4 Drupal
4 Magento
4 Wordpress
33. More coupled framworks
Some frameworks let you go faster when you adopt their
conventions.
You can reuse your code with a fair amount of additional
effort.
4 Laravel
4 Symfony1
4 CakePHP
34. More decoupled frameworks
Some frameworks encourage decoupling so your code is
more reusable.
You will go a little slower because you need to explicitly
configure things
4 Symfony 2
4 Zend Framework 2
35. Very decoupled frameworks
Some frameworks are extremely decoupled so code is
almost entirely reusable.
You almost have to construct the entire framework
yourself from components - this can be hard!
4 D.I.Y.
4 Zend Expressive
47. Organizations which design
systems ... are constrained to
produce designs which are copies
of the communication structures
of these organizations
1
Melvin Conway, 1967
48. Context mapping
4 Identify subdomains
4 Identify which are:
4 Core subdomains
4 Supporting subdomains
4 Generic subdomains
4 Mirror the structure in your architecture