SlideShare a Scribd company logo
Modularity and
Layered Data Model
Attila Jenei
2014.
!
www.attilajenei.com
Modularity
Modularity
Our problems:
• Long development time
• Generic functionality in all projects
• Near identical operation of same features
• Hard maintainability
Modularity
What we need?
• Compatible components
• High reusability
• Exchangeable parts
• Configurable system
• Improved maintainability
High-level Modularity
We can
• Remove hard-coded class calls
• Turn Singletons into services
• Use dynamic table names for data layer
• Define keys for soft referencing
Soft References
Keys to
• Class names - simple “new”
• Factories - complex initialization
• Aliases - reusability
• Initializers - additional initialization
Soft References
Managers
• Handling references
• Lazy loading for performance and low-memory
profile
• Shared or own instances
• We can use cloning to prevent recurring
initializations
PHP Example
$user = new User;
!
// turns to
!
$user = clone $services->get(‘ModelUser’);
PHP Example
$path = Config::get(‘ViewPath’);
!
// turns to
!
$path = $services->get(‘MyConfig’)->get(‘ViewPath’);
Example Config
array(

‘invokables’ => array(

‘ModelUser’ => ‘ProjectModelUser’

),

‘factories’ => array(

‘ModelUserTable’ => function ($sm) {

return ProjectModelUserTable(

$sm->get(‘ModelUserTableGateway’));

},

‘ModelUserTableGateway’ => function ($sm) {

return ProjectModelUserTableGateway(

$sm->get(‘ZendDbAdapterAdapter’),

‘user’,

$sm->get(‘ModelUser’));

},

‘ZendDbAdapterAdapter’ => ‘ZendDbAdapterAdapterServiceFactory’,

),

);
A Simple Service Manager
public function get($name)

{

if (isset($this->instances[$name])

{

return $this->instances[$name];

}



if (isset($this->invokables[$name]))

{

$className = $this->invokables[$name];

if (class_exists($className))

{

$instance = new $className;

}

else

{

throw new Exception(‘Unknown class: ’ . $className);

} 

}
A Simple Service Manager
else

if (isset($this->factories[$name])

{

$factory = $this->factories[$name];

if ($factory instanceof FactoryInterface)

{

$factory = array($factory, ‘createService’);

}



if (is_callable($factory)

{

$instance = call_user_func($factory, $this, $name);

}

else

{

throw new Exception(‘Wrong factory: ’ . $name);

}

}
A Simple Service Manager
else

{

throw new Exception(‘Unknown key: ’ . $name);

}



if ($instance)

{

$this->instances[$name] = $instance;



return $instance;

}



throw new Exception(‘No instance: ’ . $name);

}
Data
&
Responsibility
Higher-level OOP
• Database engine independent
• Unknown “outside world”
• Focus (only) on own tasks
• An entity class holds the information and has its
related methods
Entity
• Represents the information
• ≠ database record
• Takes part in execution
Entity
An Object represents
a Database Record.
A Database Record stores
the information of an Object.
Example: CMS
• Page as entity
• Control flow
!
• Column as entity
• Display flow
Data Model
Layers
ENTITY Information
TABLE Entities
TABLE GATEWAY Database Interface
HYDRATOR Object - Information
Entity Class
abstract class Entity

{

protected $serviceLocator;

protected $storedPrimaryKey;

protected $table;



final public function getServiceLocator()

{

return $this->serviceLocator;

}



final public function getStoredPrimaryKey()

{

return $this->storedPrimaryKey;

}



final public function getTable()

{

return $this->table;

}
Entity Class
final public function setServiceLocator(Ser…ace $serviceLocator)

{

$this->serviceLocator = $serviceLocator;

return $this;

}



final public function setStoredPrimaryKey(array $storedPrimaryKey)

{

$this->storedPrimaryKey = $storedPrimaryKey;

return $this;

}



final public function setTable(Table $table)

{

$this->table = $table;

return $this;

}
Entity Class
public function delete()

{

if (!$this->storedPrimaryKey)

{

throw new Exception(‘Entity is not stored’);

}



$this->table->delete($this->storedPrimaryKey);

$this->storedPrimaryKey = array();



return $this;

}



abstract public function exchangeArray(array $data);
Entity Class
public function save()

{

$this->table->save($this);

$reloaded = $this->table->fetchAll($this->storedPrimaryKey)->current();



if ($reloaded)

{

$this->exchangeEntity($reloaded);

}

else

{

throw new Exception(‘Error on reload’);

}

}

}
Example: User Entity
class User extends Entity

{

protected $name;

protected $userID;



public function getName() {…}



public function getUserID() {…}



public function setName($name) {…}



public function setUserID($userID) {…}



.

.

.

Example: User Entity
public function exchangeArray(array $data)

{

$this->name = isset($data[‘name’]) ? $data[‘name’] : null;

$this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;

$this->storedPrimaryKey = array(‘userID’ => $this->userID);



return $this;

}



public function exchangeEntity(User $entity)

{

$this->name = $entity->name;

$this->userID = $entity->userID;

$this->storedPrimaryKey = $entity->storedPrimaryKey;



return $this;

}
Example: User Entity
public function exchangeArray(array $data)

{

$this->name = isset($data[‘name’]) ? $data[‘name’] : null;

$this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;

$this->storedPrimaryKey = array(‘userID’ => $this->userID);



return $this;

}



public function exchangeEntity(User $entity)

{

$this->name = $entity->name;

$this->userID = $entity->userID;

$this->storedPrimaryKey = $entity->storedPrimaryKey;



return $this;

}
Hydrator
Table Class
abstract class Table

{

protected $serviceLocator;

protected $tableGateway;



public function __construct(TableGateway $tableGateway)

{

$this->tableGateway = $tableGateway;

}



final public function getServiceLocator() {…}



final public function getTableGateway() {…}



final public function setServiceLocator(…tor) {…}



.

.

.
Table Class
public function delete($where)

{

$this->tableGateway->delete($where);



return $this;

}



final public function fetchAll($where = null)

{

return $this->tableGateway->select($where);

}

}
Example: User Table
class UserTable extends Table

{

public function save(User $entity)

{

$data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());



if ($entity->getStoredPrimaryKey())

{

$this->tableGateway->update($data, $entity->getStoredPrimaryKey());

}

else

{

$this->tableGateway->insert($data);

$data[‘userID’] = $this->tableGateway->getLastInsertValue();

}



$entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));

}
Example: User Table
class UserTable extends Table

{

public function save(User $entity)

{

$data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());



if ($entity->getStoredPrimaryKey())

{

$this->tableGateway->update($data, $entity->getStoredPrimaryKey());

}

else

{

$this->tableGateway->insert($data);

$data[‘userID’] = $this->tableGateway->getLastInsertValue();

}



$entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));

}
Hydrator
TableGateway Class
abstract class TableGateway extends AbstractTableGateway

{

protected $entityPrototype;

protected $serviceLocator;



public function __construct(Adapter $adapter, $table, $entityPrototype)

{

$this->adapter = $adapter;

$this->table = $table;

$this->entityPrototype = $entityPrototype;

$this->resultSetPrototype = new ResultSet;

$this->resultSetPrototype->setArrayObjectPrototype($entityPrototype);

$this->sql = new Sql($adapter, $table);

}



.

.

.
TableGateway Class
final public function getServiceLocator() {…}



final public function setServiceLocator(…) {…}



public function create()

{

return clone $this->entityPrototype;

}

}
AbstractTableGateway Class
Have to implement basic operations:
• select()
• insert()
• update()
• delete()
Example: User - Group
Relation
class User extends Entity

{

.

.

.



protected $group;



public function getGroup()

{

if (!is_object($this->group) && !empty($this->group))

{

$this->group = $this->serviceLocator->get(‘ModelGroupTable’)

->fetchAll(array(‘groupID’ => $this->group))->current();

}



return $this->group;

}
Example: User - Group
Relation
public function getGroupID()

{

return is_object($this->group) ? $this->group->getGroupID() : $this->group;

}
public function setGroup($group) {…}

}
Summary
• Modules - maintainability, reusability
• Network of simpler components - complex system
• Entity-based - focus on information
• Layered Data Model - thinnest database engine related
layer, more portability
http://www.attilajenei.com
www@attilajenei.com
Attila Jenei
2014.

More Related Content

PDF
Simplifying JavaScript Projects with ReactJS
PDF
Drupal Field API. Practical usage
PDF
Field api.From d7 to d8
PPTX
Drupal 8 migrate!
PDF
Drupal Render API
PDF
The State of Lithium
PPT
J query
PPTX
J query1
Simplifying JavaScript Projects with ReactJS
Drupal Field API. Practical usage
Field api.From d7 to d8
Drupal 8 migrate!
Drupal Render API
The State of Lithium
J query
J query1

What's hot (20)

PDF
Dependency Injection in Laravel
PDF
Mysql & Php
PDF
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
PDF
Lithium: The Framework for People Who Hate Frameworks
PPTX
Drupal II: The SQL
PDF
Dependency Injection with PHP and PHP 5.3
PDF
The Zen of Lithium
PDF
Drupal 8: Fields reborn
PDF
PHP Data Objects
KEY
Zf Zend Db by aida
PDF
CakeFest 2013 keynote
PDF
PHP 5.3 and Lithium: the most rad php framework
PDF
Dependency Injection
PDF
Database Design Patterns
PDF
The History of PHPersistence
KEY
Symfony2 Building on Alpha / Beta technology
PDF
Dependency Injection
PDF
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
PDF
Drupal 8: Forms
PDF
Dependency injection-zendcon-2010
Dependency Injection in Laravel
Mysql & Php
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Lithium: The Framework for People Who Hate Frameworks
Drupal II: The SQL
Dependency Injection with PHP and PHP 5.3
The Zen of Lithium
Drupal 8: Fields reborn
PHP Data Objects
Zf Zend Db by aida
CakeFest 2013 keynote
PHP 5.3 and Lithium: the most rad php framework
Dependency Injection
Database Design Patterns
The History of PHPersistence
Symfony2 Building on Alpha / Beta technology
Dependency Injection
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Drupal 8: Forms
Dependency injection-zendcon-2010
Ad

Viewers also liked (9)

PDF
iOS Home Screen Concept
PPT
Slides for language speech thought..
PPTX
Theories of Speech Perception
PDF
Game Engine Architecture
PPTX
Stochastic Screen-Space Reflections
PPTX
FrameGraph: Extensible Rendering Architecture in Frostbite
PPTX
4K Checkerboard in Battlefield 1 and Mass Effect Andromeda
PPTX
High Dynamic Range color grading and display in Frostbite
PPTX
Photogrammetry and Star Wars Battlefront
iOS Home Screen Concept
Slides for language speech thought..
Theories of Speech Perception
Game Engine Architecture
Stochastic Screen-Space Reflections
FrameGraph: Extensible Rendering Architecture in Frostbite
4K Checkerboard in Battlefield 1 and Mass Effect Andromeda
High Dynamic Range color grading and display in Frostbite
Photogrammetry and Star Wars Battlefront
Ad

Similar to Modularity and Layered Data Model (20)

PDF
Drupal 8 Services And Dependency Injection
PDF
Doctrine For Beginners
PDF
The IoC Hydra - Dutch PHP Conference 2016
PDF
PHP: 4 Design Patterns to Make Better Code
PDF
The IoC Hydra
PDF
Advanced symfony Techniques
PPTX
Taming that client side mess with Backbone.js
PPTX
Php on the desktop and php gtk2
PDF
Unittests für Dummies
PDF
Dependency Injection
PPT
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
PPTX
Resource Routing in ExpressionEngine
PDF
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
PDF
SPL: The Missing Link in Development
PDF
What is DDD and how could it help you
PDF
Staying Sane with Drupal NEPHP
PDF
Understanding backbonejs
PDF
Your Entity, Your Code
PDF
Your Entity, Your Code
PDF
How Kris Writes Symfony Apps
Drupal 8 Services And Dependency Injection
Doctrine For Beginners
The IoC Hydra - Dutch PHP Conference 2016
PHP: 4 Design Patterns to Make Better Code
The IoC Hydra
Advanced symfony Techniques
Taming that client side mess with Backbone.js
Php on the desktop and php gtk2
Unittests für Dummies
Dependency Injection
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
Resource Routing in ExpressionEngine
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
SPL: The Missing Link in Development
What is DDD and how could it help you
Staying Sane with Drupal NEPHP
Understanding backbonejs
Your Entity, Your Code
Your Entity, Your Code
How Kris Writes Symfony Apps

Recently uploaded (20)

PPTX
cloud_computing_Infrastucture_as_cloud_p
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Machine learning based COVID-19 study performance prediction
PDF
Mushroom cultivation and it's methods.pdf
PDF
Heart disease approach using modified random forest and particle swarm optimi...
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
August Patch Tuesday
PPTX
Spectroscopy.pptx food analysis technology
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Encapsulation theory and applications.pdf
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Machine Learning_overview_presentation.pptx
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
A Presentation on Artificial Intelligence
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Approach and Philosophy of On baking technology
cloud_computing_Infrastucture_as_cloud_p
Programs and apps: productivity, graphics, security and other tools
Unlocking AI with Model Context Protocol (MCP)
Machine learning based COVID-19 study performance prediction
Mushroom cultivation and it's methods.pdf
Heart disease approach using modified random forest and particle swarm optimi...
Digital-Transformation-Roadmap-for-Companies.pptx
August Patch Tuesday
Spectroscopy.pptx food analysis technology
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Encapsulation theory and applications.pdf
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
Reach Out and Touch Someone: Haptics and Empathic Computing
Machine Learning_overview_presentation.pptx
Univ-Connecticut-ChatGPT-Presentaion.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
A Presentation on Artificial Intelligence
Diabetes mellitus diagnosis method based random forest with bat algorithm
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Approach and Philosophy of On baking technology

Modularity and Layered Data Model

  • 1. Modularity and Layered Data Model Attila Jenei 2014. ! www.attilajenei.com
  • 3. Modularity Our problems: • Long development time • Generic functionality in all projects • Near identical operation of same features • Hard maintainability
  • 4. Modularity What we need? • Compatible components • High reusability • Exchangeable parts • Configurable system • Improved maintainability
  • 5. High-level Modularity We can • Remove hard-coded class calls • Turn Singletons into services • Use dynamic table names for data layer • Define keys for soft referencing
  • 6. Soft References Keys to • Class names - simple “new” • Factories - complex initialization • Aliases - reusability • Initializers - additional initialization
  • 7. Soft References Managers • Handling references • Lazy loading for performance and low-memory profile • Shared or own instances • We can use cloning to prevent recurring initializations
  • 8. PHP Example $user = new User; ! // turns to ! $user = clone $services->get(‘ModelUser’);
  • 9. PHP Example $path = Config::get(‘ViewPath’); ! // turns to ! $path = $services->get(‘MyConfig’)->get(‘ViewPath’);
  • 10. Example Config array(
 ‘invokables’ => array(
 ‘ModelUser’ => ‘ProjectModelUser’
 ),
 ‘factories’ => array(
 ‘ModelUserTable’ => function ($sm) {
 return ProjectModelUserTable(
 $sm->get(‘ModelUserTableGateway’));
 },
 ‘ModelUserTableGateway’ => function ($sm) {
 return ProjectModelUserTableGateway(
 $sm->get(‘ZendDbAdapterAdapter’),
 ‘user’,
 $sm->get(‘ModelUser’));
 },
 ‘ZendDbAdapterAdapter’ => ‘ZendDbAdapterAdapterServiceFactory’,
 ),
 );
  • 11. A Simple Service Manager public function get($name)
 {
 if (isset($this->instances[$name])
 {
 return $this->instances[$name];
 }
 
 if (isset($this->invokables[$name]))
 {
 $className = $this->invokables[$name];
 if (class_exists($className))
 {
 $instance = new $className;
 }
 else
 {
 throw new Exception(‘Unknown class: ’ . $className);
 } 
 }
  • 12. A Simple Service Manager else
 if (isset($this->factories[$name])
 {
 $factory = $this->factories[$name];
 if ($factory instanceof FactoryInterface)
 {
 $factory = array($factory, ‘createService’);
 }
 
 if (is_callable($factory)
 {
 $instance = call_user_func($factory, $this, $name);
 }
 else
 {
 throw new Exception(‘Wrong factory: ’ . $name);
 }
 }
  • 13. A Simple Service Manager else
 {
 throw new Exception(‘Unknown key: ’ . $name);
 }
 
 if ($instance)
 {
 $this->instances[$name] = $instance;
 
 return $instance;
 }
 
 throw new Exception(‘No instance: ’ . $name);
 }
  • 15. Higher-level OOP • Database engine independent • Unknown “outside world” • Focus (only) on own tasks • An entity class holds the information and has its related methods
  • 16. Entity • Represents the information • ≠ database record • Takes part in execution
  • 17. Entity An Object represents a Database Record. A Database Record stores the information of an Object.
  • 18. Example: CMS • Page as entity • Control flow ! • Column as entity • Display flow
  • 20. Layers ENTITY Information TABLE Entities TABLE GATEWAY Database Interface HYDRATOR Object - Information
  • 21. Entity Class abstract class Entity
 {
 protected $serviceLocator;
 protected $storedPrimaryKey;
 protected $table;
 
 final public function getServiceLocator()
 {
 return $this->serviceLocator;
 }
 
 final public function getStoredPrimaryKey()
 {
 return $this->storedPrimaryKey;
 }
 
 final public function getTable()
 {
 return $this->table;
 }
  • 22. Entity Class final public function setServiceLocator(Ser…ace $serviceLocator)
 {
 $this->serviceLocator = $serviceLocator;
 return $this;
 }
 
 final public function setStoredPrimaryKey(array $storedPrimaryKey)
 {
 $this->storedPrimaryKey = $storedPrimaryKey;
 return $this;
 }
 
 final public function setTable(Table $table)
 {
 $this->table = $table;
 return $this;
 }
  • 23. Entity Class public function delete()
 {
 if (!$this->storedPrimaryKey)
 {
 throw new Exception(‘Entity is not stored’);
 }
 
 $this->table->delete($this->storedPrimaryKey);
 $this->storedPrimaryKey = array();
 
 return $this;
 }
 
 abstract public function exchangeArray(array $data);
  • 24. Entity Class public function save()
 {
 $this->table->save($this);
 $reloaded = $this->table->fetchAll($this->storedPrimaryKey)->current();
 
 if ($reloaded)
 {
 $this->exchangeEntity($reloaded);
 }
 else
 {
 throw new Exception(‘Error on reload’);
 }
 }
 }
  • 25. Example: User Entity class User extends Entity
 {
 protected $name;
 protected $userID;
 
 public function getName() {…}
 
 public function getUserID() {…}
 
 public function setName($name) {…}
 
 public function setUserID($userID) {…}
 
 .
 .
 .

  • 26. Example: User Entity public function exchangeArray(array $data)
 {
 $this->name = isset($data[‘name’]) ? $data[‘name’] : null;
 $this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;
 $this->storedPrimaryKey = array(‘userID’ => $this->userID);
 
 return $this;
 }
 
 public function exchangeEntity(User $entity)
 {
 $this->name = $entity->name;
 $this->userID = $entity->userID;
 $this->storedPrimaryKey = $entity->storedPrimaryKey;
 
 return $this;
 }
  • 27. Example: User Entity public function exchangeArray(array $data)
 {
 $this->name = isset($data[‘name’]) ? $data[‘name’] : null;
 $this->userID = isset($data[‘userID’]) ? $data[‘userID’] : null;
 $this->storedPrimaryKey = array(‘userID’ => $this->userID);
 
 return $this;
 }
 
 public function exchangeEntity(User $entity)
 {
 $this->name = $entity->name;
 $this->userID = $entity->userID;
 $this->storedPrimaryKey = $entity->storedPrimaryKey;
 
 return $this;
 } Hydrator
  • 28. Table Class abstract class Table
 {
 protected $serviceLocator;
 protected $tableGateway;
 
 public function __construct(TableGateway $tableGateway)
 {
 $this->tableGateway = $tableGateway;
 }
 
 final public function getServiceLocator() {…}
 
 final public function getTableGateway() {…}
 
 final public function setServiceLocator(…tor) {…}
 
 .
 .
 .
  • 29. Table Class public function delete($where)
 {
 $this->tableGateway->delete($where);
 
 return $this;
 }
 
 final public function fetchAll($where = null)
 {
 return $this->tableGateway->select($where);
 }
 }
  • 30. Example: User Table class UserTable extends Table
 {
 public function save(User $entity)
 {
 $data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());
 
 if ($entity->getStoredPrimaryKey())
 {
 $this->tableGateway->update($data, $entity->getStoredPrimaryKey());
 }
 else
 {
 $this->tableGateway->insert($data);
 $data[‘userID’] = $this->tableGateway->getLastInsertValue();
 }
 
 $entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));
 }
  • 31. Example: User Table class UserTable extends Table
 {
 public function save(User $entity)
 {
 $data = array(‘userID’ => $entity->getUserID(), ‘name’ => $entity->getName());
 
 if ($entity->getStoredPrimaryKey())
 {
 $this->tableGateway->update($data, $entity->getStoredPrimaryKey());
 }
 else
 {
 $this->tableGateway->insert($data);
 $data[‘userID’] = $this->tableGateway->getLastInsertValue();
 }
 
 $entity->setStoredPrimaryKey(array(‘userID’ => $data[‘userID’]));
 } Hydrator
  • 32. TableGateway Class abstract class TableGateway extends AbstractTableGateway
 {
 protected $entityPrototype;
 protected $serviceLocator;
 
 public function __construct(Adapter $adapter, $table, $entityPrototype)
 {
 $this->adapter = $adapter;
 $this->table = $table;
 $this->entityPrototype = $entityPrototype;
 $this->resultSetPrototype = new ResultSet;
 $this->resultSetPrototype->setArrayObjectPrototype($entityPrototype);
 $this->sql = new Sql($adapter, $table);
 }
 
 .
 .
 .
  • 33. TableGateway Class final public function getServiceLocator() {…}
 
 final public function setServiceLocator(…) {…}
 
 public function create()
 {
 return clone $this->entityPrototype;
 }
 }
  • 34. AbstractTableGateway Class Have to implement basic operations: • select() • insert() • update() • delete()
  • 35. Example: User - Group Relation class User extends Entity
 {
 .
 .
 .
 
 protected $group;
 
 public function getGroup()
 {
 if (!is_object($this->group) && !empty($this->group))
 {
 $this->group = $this->serviceLocator->get(‘ModelGroupTable’)
 ->fetchAll(array(‘groupID’ => $this->group))->current();
 }
 
 return $this->group;
 }
  • 36. Example: User - Group Relation public function getGroupID()
 {
 return is_object($this->group) ? $this->group->getGroupID() : $this->group;
 } public function setGroup($group) {…}
 }
  • 37. Summary • Modules - maintainability, reusability • Network of simpler components - complex system • Entity-based - focus on information • Layered Data Model - thinnest database engine related layer, more portability