agile data presentation 3 - cambridge

69

Upload: romans-malinovskis

Post on 16-Apr-2017

111 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Agile data   presentation 3 - cambridge
Page 2: Agile data   presentation 3 - cambridge

WARNINGThis presentation may contain:

‣ Alternattive opinions‣ Mention of phrase "new framework"‣ Mention of paid services and/or software‣ Out-of PHP concepts (Java, Scala, Ruby)

Page 3: Agile data   presentation 3 - cambridge

Love and Hatebetween ORM

andQuery

Builders

Page 4: Agile data   presentation 3 - cambridge

Myself‣ Love Web Apps‣ 25 years of

coding‣ Entrepreneur‣ I buy Software

My PHP Startup

‣ Helps developers

‣ Open-source‣ PHP in

Enterprise‣ Code Sharing

About Me

Page 5: Agile data   presentation 3 - cambridge

Query‣ Control‣ Advanced

Features‣ Multi-Record

ORM‣ 10+ tables‣ SoftDelete,

Audit‣ Domain Model

Database Interaction Today

Page 6: Agile data   presentation 3 - cambridge

MapperEntity Query

ORM: How it should work

Database

Business LogicORM

Page 7: Agile data   presentation 3 - cambridge

MapperEntity SQL Query

The Reality

SQL Database

Business LogicORM

no ORM

Page 8: Agile data   presentation 3 - cambridge

SQL Query

Why Bother…

SQL Database

Business Logic no ORM

Page 9: Agile data   presentation 3 - cambridge

Love Compatibility

Page 10: Agile data   presentation 3 - cambridge
Page 11: Agile data   presentation 3 - cambridge

Query Builder‣ Query‣ Conditions‣ Statements‣ Expressions

ORM‣ Entity‣ Property‣ Operations

(C.R.U.D.)

What do we work with?

Page 12: Agile data   presentation 3 - cambridge

Love CompatibilityEntity Property Operations

Query ❤️

Condition

Statements

Expression

ORM Components

Que

ry C

ompo

nent

s

Page 13: Agile data   presentation 3 - cambridge

Love CompatibilityEntity Property Operations

Query ❤️ 😔 😔

Condition

Statements

Expression

ORM Components

Que

ry C

ompo

nent

s

Page 14: Agile data   presentation 3 - cambridge

Love CompatibilityEntity Property Operations

Query ❤️ 😔 😔

Condition 😐 ❤️

Statements

Expression

ORM Components

Que

ry C

ompo

nent

s

Page 15: Agile data   presentation 3 - cambridge

Love CompatibilityEntity Property Operations

Query ❤️ 😔 😔

Condition 😐 😔 ❤️

Statements

Expression

ORM Components

Que

ry C

ompo

nent

s

Page 16: Agile data   presentation 3 - cambridge

Love CompatibilityEntity Property Operations

Query ❤️ 😔 😔

Condition 😐 😔 ❤️

Statements 💀 💀 💀

Expression

ORM Components

Que

ry C

ompo

nent

s

Page 17: Agile data   presentation 3 - cambridge

Love CompatibilityEntity Property Operations

Query ❤️ 😔 😔

Condition 😐 😔 ❤️

Statements 💀 💀 💀

Expression 💀 💀 💀

ORM Components

Que

ry C

ompo

nent

s

Page 18: Agile data   presentation 3 - cambridge

Reimagine a better data access framework. With fresh

start.

Agile Data

Page 19: Agile data   presentation 3 - cambridge

Agile DataEntity Property Operations

Query

Condition

Statements

Expression

ORM Components

Que

ry C

ompo

nent

s

Page 20: Agile data   presentation 3 - cambridge

Properties

/** @Column(type="datetime", name="posted_at") */private $postedAt;

protected $casts = [ 'is_admin' => 'boolean',];

public function setFirstNameAttribute($value){ $this->attributes['first_name'] = strtolower($value);}

Page 21: Agile data   presentation 3 - cambridge

Fields in Agile Data

$book->addField('total_cost', ['type'=>'money']);

Like properties, but smarter.

Page 22: Agile data   presentation 3 - cambridge

Property‣ Handy and

Native‣ No type‣ No logic‣ No meta-info

Field‣ Array-access‣ Type enforcing‣ Extensible logic‣ Meta-info

Fields

Page 23: Agile data   presentation 3 - cambridge

Fields

class Document extends \atk4\data\Model{ public $table = 'document'; function init() { parent::init(); $this->addField('ref_no', ['type'=>'string']); $this->addField('date', ['type'=>'date']); $this->addField('type', ['enum'=>['invoice','payment']]); $this->hasOne('contact_id', new Contact()); $this->addField('is_archived', ['type'=>'boolean']); }}

Page 24: Agile data   presentation 3 - cambridge

Generic UI

$form = new ui\Form();$form->setModel(new smbo\Model_Job($db));

echo $form->render();

Fastest imaginable way to build good looking data entry

form?

Page 25: Agile data   presentation 3 - cambridge

Generic UI

Page 26: Agile data   presentation 3 - cambridge

Expression

$client->addExpression( 'balance', 'coalesce([total_invoice]-[total_paid],0)');

Define custom SQL code for your field.

Page 27: Agile data   presentation 3 - cambridge

Aggregate Field

$client->hasMany('Order') ->addField('total_orders', [ 'field'=>'amount', 'aggregate'=>'sum' ]);

Express related model aggregate as sub-query.

Page 28: Agile data   presentation 3 - cambridge

Agile DataEntity Field Operations

Query ❤️

Condition ❤️

Statements ❤️

Expression ❤️

ORM Components

Que

ry C

ompo

nent

s

Page 29: Agile data   presentation 3 - cambridge

EntityClient

name address_id Order

titletotal_order

ExpressionSubQuery

hasManyhasOne

6 objects

Page 30: Agile data   presentation 3 - cambridge

Is this slow?6

objects 5 rows*

Page 31: Agile data   presentation 3 - cambridge

Object representing collection of records

Data Sets

Page 32: Agile data   presentation 3 - cambridge

Record Mapping

‣ Active Record and ORM map individual records

‣ Multiple records require Multiple objects in memory

Model_Client object

user type=client

user type=client

user type=client

user type=client user type=admin

user type=admin

table userModel_Client object

Page 33: Agile data   presentation 3 - cambridge

DataSet Mapping

‣ Agile Data works with DataSets

‣ Multiple records require Single objects in memory

Model_Client object

user type=client

user type=client

user type=client

user type=client user type=admin

user type=admin

table user

Page 34: Agile data   presentation 3 - cambridge

DataSet

Client Admin

User

Page 35: Agile data   presentation 3 - cambridge

Conditions

class Client extend User { function init() { parent::init();

$this->addCondition('type', 'client'); }}

Narrow the scope of accessible records

Page 36: Agile data   presentation 3 - cambridge

Conditions

$client = new Client($db);$client->load(12);$client['type'] = 'admin';$client->save(); // <== Exception

Prevent human error

Page 37: Agile data   presentation 3 - cambridge

Project

DataSet $m = new Project($db);

Page 38: Agile data   presentation 3 - cambridge

Project

$m = new Project($db);$m->addCondition( 'client_id', $c_id);

client=$c_id

Page 39: Agile data   presentation 3 - cambridge

Project

$m = new Project($db);$m->addCondition( 'client_id', $c_id);

$m->addCondition( 'is_cancelled', false);

client=1client=$c_id

is_cancelled = "N"

Page 40: Agile data   presentation 3 - cambridge

Conditions

$client = new Client($db);$client->load($_GET['user_id']);$project = $client->ref('Project');$project->insert($_POST);

Prevent human error

Page 41: Agile data   presentation 3 - cambridge

Conditions

$profitable_client = new Client($db);$profitable_client->addCondition($this->expr( '[income]>[expense]'));$data = $profitable_client->export();

Dynamically add expressions for reports.

Page 42: Agile data   presentation 3 - cambridge

Deep Traversal

foreach( $author->withID(20) ->ref('App') ->ref('Review') ->addCondition('rating', 1) as $bad_review ) {

$bad_review->sendApologyEmail(); }

Traverse without querying

Page 43: Agile data   presentation 3 - cambridge

QRM->Q.B.‣ Static scope‣ Limited

inheritance‣ Persistence layer

DataSet Model‣ Dynamic scope‣ Fully OOP‣ References infer

conditions‣ Domain layer

Model

Page 44: Agile data   presentation 3 - cambridge

Agile DataModel(DataSet) Field Operations

Query ❤️ ❤️

Condition ❤️ ❤️

Statements ❤️ ❤️

Expression ❤️ ❤️

ORM Components

Que

ry C

ompo

nent

s

Page 45: Agile data   presentation 3 - cambridge

ORM limit multi-record features and other database

capabilities.

N+1 problem

Page 46: Agile data   presentation 3 - cambridge

foreach (Client::all() as $client) { foreach($client->orders() as $order){ $sum += $order->amount; }}

N+1 problem

‣ 20 users in database

‣ 20 extra queries to fetch orders

Page 47: Agile data   presentation 3 - cambridge

foreach (Client::all() as $client) { foreach($client->orders() as $order){ $sum += $order->amount; }}

Memory Problem

‣ 20 users in database

‣ array of 20 objects

‣ other properties are also fetched

Page 48: Agile data   presentation 3 - cambridge

foreach (Client::all() as $client) { foreach($client->orders() as $order){ $sum += $order->amount; }}

Lazy-loading; ID Stuffing

‣ only load IDs

‣ trigger loading on property access

‣ select from `order` where user in (1,2,3,…)

Page 49: Agile data   presentation 3 - cambridge

Action

$client = new Client($db);$sum = $client->ref('Order') ->action('fx', ['sum', 'amount']) ->execute();

Event from Domain Model to your database

Page 50: Agile data   presentation 3 - cambridge

Multi-record operations

$author->withID(20) ->ref('App') ->ref('Review') ->addCondition('rating', 1) ->action('delete') ->execute();

Delete all entries in data-set

Page 51: Agile data   presentation 3 - cambridge

Multi-record operations

$author->withID(20) ->ref('App') ->ref('Review') ->addCondition('rating', '<', 3) ->action('update') ->set('rating=rating+1') ->execute();

or just update rating

Page 52: Agile data   presentation 3 - cambridge

Aggregation

$q = $client->action('field', ['industry']);

$q->field('count(*)', 'c');$q->group('industry');

$data = $q->get();

Create any query around Model

Page 53: Agile data   presentation 3 - cambridge

Union

$q_inv = $client->ref('Invoice') ->action('field',['date','total']);

$q_pay = $client->ref('Payment') ->action('field',['date','paid']);

foreach($db->expr( 'select * from ([] UNION []) u1', $q_inv, $q_pay) as $row) { /// }

Prepare client statement

Page 54: Agile data   presentation 3 - cambridge

ORM‣ Emit query-

builder‣ Limited scope

support‣ SQL only‣ Fully Persistence

logic

Agile Actions‣ Emit DSQL‣ All conditions

applied‣ Extensible to

NoSQL‣ Domain model

support

Multi-record operations

Page 55: Agile data   presentation 3 - cambridge

Agile DataModel(DataSet) Field Operations

Query ❤️ ❤️ ❤️

Condition ❤️ ❤️ ❤️

Statements ❤️ ❤️ ❤️

Expression ❤️ ❤️ ❤️

ORM Components

Que

ry C

ompo

nent

s

Page 56: Agile data   presentation 3 - cambridge

Summary‣ ORM and Query Builders has a bumpy

relationship‣ Luckily there are other patterns‣ Consider query latency‣ Consider flexibility‣ Consider abstraction

Page 57: Agile data   presentation 3 - cambridge

Execute less queries

Design a beautiful API

Friendly with UIExtensions

Agile Data

Page 58: Agile data   presentation 3 - cambridge

Download

Page 59: Agile data   presentation 3 - cambridge

Result

Page 60: Agile data   presentation 3 - cambridge

Make UI better

Page 61: Agile data   presentation 3 - cambridge

git.io/ad

✓ Works in any framework / PHP app✓ Lightweight and Agile✓ Integrates with UI frameworks (like

ATK)✓ Commercial Support

Agile Data is Open-Source

Page 62: Agile data   presentation 3 - cambridge

Join my OSS project

‣ Agile Data v1.1.5git.io/ad

‣ Agile UI (developing)github.com/atk4/ui

My other topics‣ Agile Toolkit

Full-stack PHP UI

Page 63: Agile data   presentation 3 - cambridge

More examplesif there is time

Page 64: Agile data   presentation 3 - cambridge

Query into Field

$client->addExpression('last_sale', function($m){ return $m->refLink('Invoice') ->setLimit(1) ->setOrder('date desc') ->action('field',['total']); }, 'type'=>'money');

Convert Entity into Query then use inside Field / Expression.

Page 65: Agile data   presentation 3 - cambridge

Join on Expression

$invoice->hasOne('client_id', new Client()) ->addField('client_country_id', 'country_id');

$invoice->join('country', 'client_country_id') ->addFields([ 'country_short_code'=>'short_code', 'country_is_eu'=>'is_eu', 'country'=>'name' ]);

If you need country data inside your Invoice report, but country_id is defined through

Client.

Page 66: Agile data   presentation 3 - cambridge

Aliasing

Page 67: Agile data   presentation 3 - cambridge

Self-referencingclass Folder extends \atk4\data\Model{ public $table = 'folder'; public function init() { parent::init(); $this->addField('name');

$this->hasMany('SubFolder', [ new Folder(), 'their_field'=>'parent_id'] )->addField('count', [ 'aggregate'=>'count', 'field'=>$this->expr('*')] );

$this->hasOne('parent_id', new Folder()) ->addTitle(); }}

Page 68: Agile data   presentation 3 - cambridge

Unique Aliases

select `id`,`name`,

(select count(*) from `folder` `S` where `parent_id` = `folder`.`id`) `count`,

`folder`.`parent_id`,

(select `name` from `folder` `p` where `id` = `folder`.`parent_id`) `parent` from `folder`

Page 69: Agile data   presentation 3 - cambridge

✓ ACL, Audit, Undo, Logging, ..✓ File Management✓ Import/Export utility✓ RestAPI server

Commercial Extensions

git.io/ad