SOLID MVC - thephp.cc fileProbably the widest quoted pattern in UI development is Model View...

Preview:

Citation preview

SOLID MVCStefan Priebsch | Bulgaria PHP Conference 2015

Stefan PriebschConsultant and coach. Helps teams to successfully develop software.

sharing experience

MVC ?

Controller

ModelView

Probably the widest quoted pattern in UI development is Model View Controller

(MVC) - it's also the most misquoted. I've lost count of the times I've seen

something described as MVC which turned out to be nothing like it.

http://martinfowler.com/eaaDev/uiArchs.html

"A Framework is no architecture"Ask your favourite search engine for more information

SOLID ?

[SOLID] stands for five basic principles of object-oriented programming and

design.

[...]

The principles, when applied together, intend to make it more likely that a

programmer will create a system that is easy to maintain and extend over time.

https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

SOLID• Single Responsibility Principle• Open/Closed Principle• Liskov Substitution Principle• Interface Segregation Principle• Dependency Inversion Principle

Single ResponsibilityThere should never be more than one reason for a class to change

Open/Closed PrincipleCode should be open for extensions, but closed for modifications

Liskov Substitution PrincipleIn short: inheritance sucks

Interface SegregationClients should not be forced to depend upon interfaces that they do not use

Dependency InversionA. High-level modules should not depend on low-level modules.

Both should depend on abstractions.

Dependency InversionB. Abstractions should not depend on details.

Details should depend on abstractions.

Infrastructure

Domain

Infrastructure

Domain

A

I

<?php

class FooController extends FrameworkController

{

public function indexAction()

{

...

}

public function createAction()

{

...

}

public function deleteAction()

{

...

}

...

}

<?php

class IndexController extends FrameworkController

{

public function indexAction()

{

...

}

}

class CreateController extends FrameworkController

{

public function createAction()

{

...

}

}

...

<?php

class IndexController extends FrameworkController

{

public function run()

{

...

}

}

class CreateController extends FrameworkController

{

public function run()

{

...

}

}

...

<?php

interface Controller

{

public function run();

}

<?php

class IndexController ...

{

public function process(HttpRequest $request)

{

...

}

}

class CreateController ...

{

public function process(HttpRequest $request)

{

...

}

}

...

<?php

interface Controller

{

public function process(HttpRequest $request);

}

<?php

class IndexController ...

{

public function process(HttpGetRequest $request)

{

...

}

}

class CreateController ...

{

public function process(HttpPostRequest $request)

{

...

}

}

...

<?php

interface Controller

{

public function process(HttpRequest $request);

}

<?php

class FrameworkController

{

protected function getRequest() {...}

protected function getFactory() {...}

protected function getServiceContainer() {...}

...

}

<?php

class MyController extends Framework_Controller

{

public function someAction()

{

global $templating;

global $router;

global $mailer;

// ...

}

}

<?php

class YourController extends FrameworkController

{

public function someAction()

{

// ...

... $this->retriveFromDiContainer('something') ...

// ...

}

}

<?php

class YourController extends FrameworkController

{

public function someAction()

{

// ...

... $this->retrieveSomethingFromDiContainer() ...

// ...

}

}

<?php

class YourController extends FrameworkController

{

private $something;

public function __construct(Something $something)

{

$this->something = $something;

}

public function someAction()

{

// ...

... $this->something->doStuff() ...

// ...

}

}

Dependency Disguise is an Antipattern

<?php

class YourCode

{

private $dependency;

public function __construct(

SomePartOfTheFramework $externalDependency

)

{

$this->dependency = $externalDependency;

}

// ...

}

<?php

class YourCode

{

private $dependency;

public function __construct(

SomePartOfTheFrameworkButItIsAnInterface $externalDependency

)

{

$this->dependency = $externalDependency;

}

// ...

}

<?php

class YourCode

{

private $dependency;

public function __construct(

InterfaceDefinedByFramework $externalDependency

)

{

$this->dependency = $externalDependency;

}

// ...

}

<?php

class YourCode

{

private $dependency;

public function __construct(

InterfaceDefinedByYou $internalDependency

)

{

$this->dependency = $internalDependency;

}

// ...

}

<?php

interface YourSomethingLoaderInterface

{

public function loadAllSomethings();

}

<?php

class YourLoader implements YourSomethingLoaderInterface

{

private $thing;

public function __construct(FrameworkLoaderMagicComponentThing $thing)

{

$this->thing = $thing;

}

public function loadAllSomethings()

{

... work with $this->thing ...

... and convert the result back to a SomethingCollection ...

}

}

Infrastructure

Domain

A

I

<?php

class SomethingModel

{

public function __construct(Session $session)

{

...

}

}

<?php

class SomethingModel

{

public function __construct(ApplicationState $applicationState)

{

...

}

}

<?php

class SomeController extends FrameworkController

{

public function indexAction()

{

...

$this->redirect(...);

}

}

<?php

class FooController extends FrameworkController

{

public function indexAction()

{

...

$view->setData(...);

}

}

Summary:MVC usually does not apply to your problem,

but makes it super-simple to write non-SOLID code.

Summary:You are responsible for the quality of your code.

Warning Signs:First, you decide which framework to use

Warning Signs:You put code into the framework

Warning Signs:You consider migrating from one framework to another

Warning Signs:Your methods do not fit on one screen

Warning Signs:You are unsure whether to put something into a controller, or into a model

Warning Signs:You have a hard time naming classes and methods

http://thePHP.cc

stefan@thePHP.cc

@spriebsch

sharing experience

Recommended