83
How to build customizable multitenant web applications Stephan Hochdörfer, bitExpert AG "Building an application so customizable it's the last application you'll ever need to build" Harrie Verveer

How to build customizable multitenant web applications - PHPBNL11

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: How to build customizable multitenant web applications - PHPBNL11

How to build customizable multitenant web applications

Stephan Hochdörfer, bitExpert AG

"Building an application so customizable it's the last

application you'll ever need to build"

Harrie Verveer

Page 2: How to build customizable multitenant web applications - PHPBNL11

About me

Stephan Hochdörfer, bitExpert AG

Department Manager Research Labs

enjoying PHP since 1999

[email protected]

@shochdoerfer

Page 3: How to build customizable multitenant web applications - PHPBNL11

Single Tenancy

Page 4: How to build customizable multitenant web applications - PHPBNL11

Developer vs. Businessman

Page 5: How to build customizable multitenant web applications - PHPBNL11

Single Tenancy – more customers

Page 6: How to build customizable multitenant web applications - PHPBNL11

Single Tenancy – even more customers

Page 7: How to build customizable multitenant web applications - PHPBNL11

Where will this lead to?

Page 8: How to build customizable multitenant web applications - PHPBNL11

Maintenance nightmare!

Page 9: How to build customizable multitenant web applications - PHPBNL11

Single Tenancy

Tenant 1

Application

Database

Hardware

Page 10: How to build customizable multitenant web applications - PHPBNL11

Single Tenancy

Tenant 2

Application

Database

Hardware

Tenant 1

Application

Database

Hardware

Tenant 3

Application

Database

Hardware

Page 11: How to build customizable multitenant web applications - PHPBNL11

Multi Tenancy

Tenant 2Tenant 1

Application

Database

Hardware

Tenant 3

Page 12: How to build customizable multitenant web applications - PHPBNL11

What should be customizable?

Page 13: How to build customizable multitenant web applications - PHPBNL11

What should be customizable?

Tenant 2Tenant 1

Application

Database

Hardware

Tenant 3

Page 14: How to build customizable multitenant web applications - PHPBNL11

What should be customizable?

Tenant 2Tenant 1

Application

Database

Hardware

Tenant 3

Page 15: How to build customizable multitenant web applications - PHPBNL11

How to skin an application?

Frontend | Branding

Page 16: How to build customizable multitenant web applications - PHPBNL11

How to skin an application?

Application | Frontend

Remember:It`s a web application!

Page 17: How to build customizable multitenant web applications - PHPBNL11

How to skin an application?

Application | Frontend

HTML

Page 18: How to build customizable multitenant web applications - PHPBNL11

How to skin an application?

Application | Frontend

HTML + CSS

Page 19: How to build customizable multitenant web applications - PHPBNL11

Application | Frontend

Page 20: How to build customizable multitenant web applications - PHPBNL11

Application | Frontend

Page 21: How to build customizable multitenant web applications - PHPBNL11

Application | Frontend

Page 22: How to build customizable multitenant web applications - PHPBNL11

How to customize?

Application | Frontend

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>My App</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="css/styles/myapp.css" /></head><body></body></html>

Page 23: How to build customizable multitenant web applications - PHPBNL11

How to customize?

Application | Frontend

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>My App</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="css/styles/<?php echo$tenant ?>.css" /></head><body></body></html>

Page 24: How to build customizable multitenant web applications - PHPBNL11

How to customize?

Application | Frontend

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>My App</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="css/styles/myapp.css" /> <link rel="stylesheet" type="text/css" href="css/styles/<?php echo $tenant ?>.css" /></head><body></body></html>

Page 25: How to build customizable multitenant web applications - PHPBNL11

Feature driven CSS

Application | Frontend

Wait, there`s more...

Page 26: How to build customizable multitenant web applications - PHPBNL11

Feature driven CSS

Application | Frontend

display: none

Page 27: How to build customizable multitenant web applications - PHPBNL11

Application | Frontend

Next level...

Page 28: How to build customizable multitenant web applications - PHPBNL11

Menubar generation

Application | Backend

<?php

if($user->hasEnabled(Module::ORDERMANAGEMENT)){ if($user->canAccess(OrderManagement::LIST_ORDERS)) {

$this->renderLink(OrderManagement::LIST_ORDERS); }

if($user->canAccess(OrderManagement::ADD_ORDER)) {

$this->renderLink(OrderManagement::ADD_ORDER); }

if($user->canAccess(OrderManagement::CANCEL_ORDER)) {

$this->renderLink(OrderManagement::CANCEL_ORDER); }}

Page 29: How to build customizable multitenant web applications - PHPBNL11

Menubar generation

Application | Backend

<?php

if($tenant->hasModule(Module::ORDERMANAGEMENT){ if($user->hasEnabled(Module::ORDERMANAGEMENT)) {

if($user->canAccess(OrderManagement::LIST_ORDERS)){ $this->renderLink(OrderManagement::LIST_ORDERS);}

if($user->canAccess(OrderManagement::ADD_ORDER)){ $this->renderLink(OrderManagement::ADD_ORDER);}

}}

Page 30: How to build customizable multitenant web applications - PHPBNL11

Menubar generation

Application | Backend

Modularize!

Page 31: How to build customizable multitenant web applications - PHPBNL11

Menubar generation

Application | Backend

Module 2Module 1

Application core

Module 3

register at start up

Page 32: How to build customizable multitenant web applications - PHPBNL11

Menubar generation

Application | Backend

Module 2Module 1

Application core

Module 3

register at start up

Configuration for tenant 1

Page 33: How to build customizable multitenant web applications - PHPBNL11

Menubar generation

Application | Backend

Module 2Module 1

Application core

Module 3

register at start up

Configuration for tenant 2

Page 34: How to build customizable multitenant web applications - PHPBNL11

Optimize workflows

Application | Backend

<?php

if('CC' == $paymentType){ // handle credit card payment}else if('COD' == $paymentType){ // handle cash on delivery payment}

Page 35: How to build customizable multitenant web applications - PHPBNL11

Optimize workflows

Application | Backend

<?php

if('CC' == $paymentType){ // handle credit card payment for some tenants! if(in_array($tenant->getName(), array('tenant1', 'tenant2')) {

// insert logic here... }}else if('COD' == $paymentType){ // handle cash on delivery payment for some tenants! if(in_array($tenant->getName(), array('tenant3')) {

// insert logic here... }}

Page 36: How to build customizable multitenant web applications - PHPBNL11

Optimize workflows

Application | Backend

Decouple functionality!

Page 37: How to build customizable multitenant web applications - PHPBNL11

Optimize workflows

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType);

$payment->execute($order);

Page 38: How to build customizable multitenant web applications - PHPBNL11

Optimize workflows

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType, $tenant);

$payment->execute($order);

Page 39: How to build customizable multitenant web applications - PHPBNL11

Optimize workflows

Application | Backend

How to add custom logic?

Page 40: How to build customizable multitenant web applications - PHPBNL11

Custom logic - Subclassing?

Application | Backend

AbstractPayment

CCPayment

CCPaymentTenant 1

CCPaymentTenant 2

Page 41: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

Any alternatives?

Page 42: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

Let`s add hooks...

Page 43: How to build customizable multitenant web applications - PHPBNL11

Custom logic - Hooks

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType, $tenant);

if($this->paymentPreProcessor instanceof IPaymentPreProcessor) { $this->paymentPreProcessor->run($payment, $tenant, $order);}

$payment->execute($order);

if($this->paymentPostProcessor instanceof IPaymentPostProcessor) { $this->paymentPostProcessor->run($payment, $tenant, $order);}

Page 44: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

How to set the dependencies?

Page 45: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

Inject the dependencies!

Page 46: How to build customizable multitenant web applications - PHPBNL11

Custom logic – Dependency Injection

Application | Backend

<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.bitexpert.de/schema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.bitexpert.de/schema/

http://www.bitexpert.de/schema/bitFramework-beans.xsd">

<bean id="MyApp.Service.Order" class="MyApp\Service\Order.php"></bean>

<bean id="Tenant1.Service.Order" class="MyApp\Service\Order.php"><property name="paymentPreProcessor"

ref="Tentant1.Payment.PaymentValidation" /></bean>

<bean id="Tenant2.Service.Order" class="MyApp\Service\Order.php"><property name="paymentPreProcessor"

ref="Tentant2.Payment.StrictValidation" /><property name="paymentPostProcessor"

ref="Tentant2.Payment.PushOrderToSAP" /></bean>

</beans>

Page 47: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

Any improvements?

Page 48: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType, $tenant);

if($this->paymentPreProcessor instanceof IPaymentPreProcessor) { $this->paymentPreProcessor->run($payment, $tenant, $order);}

$payment->execute($order);

if($this->paymentPostProcessor instanceof IPaymentPostProcessor) { $this->paymentPostProcessor->run($payment, $tenant, $order);}

Page 49: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType, $tenant);

if($this->paymentPreProcessor instanceof IPaymentPreProcessor) { $this->paymentPreProcessor->run($payment, $tenant, $order);}

$payment->execute($order);

if($this->paymentPostProcessor instanceof IPaymentPostProcessor) { $this->paymentPostProcessor->run($payment, $tenant, $order);}

Page 50: How to build customizable multitenant web applications - PHPBNL11

Custom logic

Application | Backend

Aspect-oriented programming

Page 51: How to build customizable multitenant web applications - PHPBNL11

Custom logic – Aspects for the masses!

Application | Backend

/** * @aspect */class CustomPaymentProcessingAspect {

/** * @around MyApp\Service\Order->processPayment */public function customFilter(\AOP\JoinPointInterface $joinPoint) {

// @TODO: implement pre-processing logic// ...

$result = $joinPoint->getAdviceChain()->proceed($joinPoint);

// @TODO: implement post-processing logic// ...

return $result;}

}

Page 52: How to build customizable multitenant web applications - PHPBNL11

Custom logic - Result

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType, $tenant);

$payment->execute($order);

Page 53: How to build customizable multitenant web applications - PHPBNL11

Application | Backend

Next level...

Page 54: How to build customizable multitenant web applications - PHPBNL11

Database – Where to store the data?

Database

Page 55: How to build customizable multitenant web applications - PHPBNL11

Database – Where to store the data?

Database

We need to store data for a tenant!

Page 56: How to build customizable multitenant web applications - PHPBNL11

Database – Where to store the data?

Database

Database per Tenant?

Page 57: How to build customizable multitenant web applications - PHPBNL11

Database – Where to store the data?

Database

Database per Tenant?

Schema per Tenant?

Page 58: How to build customizable multitenant web applications - PHPBNL11

Database – Where to store the data?

Database

Database per Tenant?

Schema per Tenant?

Tenant Id per Row?

Page 59: How to build customizable multitenant web applications - PHPBNL11

Database – How to access the data?

Database

ORM dynamic statements

vs.

Page 60: How to build customizable multitenant web applications - PHPBNL11

What`s beyond?

Generalize you should!

Page 61: How to build customizable multitenant web applications - PHPBNL11

Multi Tenancy

What`s beyond?

Software system family

Page 62: How to build customizable multitenant web applications - PHPBNL11

No single solution!

What`s beyond?

Page 63: How to build customizable multitenant web applications - PHPBNL11

A factory for mass production!

What`s beyond?

Page 64: How to build customizable multitenant web applications - PHPBNL11

Multi Tenancy – Single Instance

Tenant 2Tenant 1

Application

Database

Hardware

Tenant 3

What`s beyond?

Page 65: How to build customizable multitenant web applications - PHPBNL11

Multi Tenancy – Multi Instance

Tenant 2Tenant 1

Application

Database

Hardware

Tenant 3

What`s beyond?

Page 66: How to build customizable multitenant web applications - PHPBNL11

Generative Programming

ConfigurationConfiguration

Implementationcomponents

Implementationcomponents

Generatorapplication

Generatorapplication

ProductProductGenerator

Generator

1 ... n

What`s beyond?

Page 67: How to build customizable multitenant web applications - PHPBNL11

Generative Programming

ConfigurationConfiguration

Implementationcomponents

Implementationcomponents

Generatorapplication

Generatorapplication

Tenant 1Tenant 1

GeneratorGenerator

Tenant xTenant x

What`s beyond?

Page 68: How to build customizable multitenant web applications - PHPBNL11

Generative Programming - Goal

What`s beyond?

Create an optimized application!

Page 69: How to build customizable multitenant web applications - PHPBNL11

Generative Programming - Goal

What`s beyond?

Create an optimized applicationfor one tenant!

Page 70: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

Reduce application complexity

Page 71: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

FileFrm FILEOrderService_php5 { private String PreProcessor = ""; private String PostProcessor = "";

public FILEOrderService_php5() {setFilename("Order.php5");setRelativePath("/classes/MyApp/Service");

}

private void assign() {BEGINCONTENT()<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType, $tenant);

<!{PreProcessor}!>$payment->execute($order);<!{PostProcessor}!>ENDCONTENT() }}

Page 72: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

FileFrm FILEOrderService_php5 { [...]

private void configure() {if(this.getConfiguration().hasFeature('PreProcessor')) { PreProcessor = this.getPreProcessorContent(

this.getConfiguration.getTenant() );}

if(this.getConfiguration().hasFeature('PostProcessor')) { PostProcessor = this.getPostProcessorContent(

this.getConfiguration.getTenant() );}

}}

Page 73: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

Application | Backend

Example:Preprocessor:Postprocessor:

Output:

Page 74: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

Application | Backend

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType);

$payment->execute($order);

Example:Preprocessor:Postprocessor:

Output:

Page 75: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

Application | Backend

Example:Preprocessor: $this->paymentPreProcessor->run($payment, $tenant, $order);

Postprocessor:

Output:

Page 76: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

Application | Backend

Example:Preprocessor: $this->paymentPreProcessor->run($payment, $tenant, $order);

Postprocessor:

Output:

<?php

$paymentType = 'CC'; // set via request$payment = PaymentFactory::create($paymentType);

$this->paymentPreProcessor->run($payment, $tenant, $order);

$payment->execute($order);

Page 77: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

Reduce maintenance support

Page 78: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

FeatureImplementation

component

Page 79: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

Feature

Implementationcomponent

Page 80: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – Bonus points

What`s beyond?

Feature

Implementationcomponent

Customer

Page 81: How to build customizable multitenant web applications - PHPBNL11

Generative Programming – The book

What`s beyond?

Page 82: How to build customizable multitenant web applications - PHPBNL11

http://joind.in/2497

Page 83: How to build customizable multitenant web applications - PHPBNL11

Flickr Creditshttp://www.flickr.com/photos/andresrueda/3452940751/

http://www.flickr.com/photos/andresrueda/3455410635/