Modèles métiers
Définition
Un modèle métier est un patron de conception utilisé pour respecter les règles de traitement propres à un métier. Ce modèle définit des tâches, où chaque tâche est précise et répond à la solution d'une demande métier.
Le Business Object (BO ou objet métier)
Un objet métier, plus connu sous l'acronyme BO, est une instance d'une classe métier. Comme vu dans la définition, le métier regroupe des traitements qui lui sont spécifiques et qui répondent à ses besoins.
Prenons par exemple la classe métier UserManagerBo
(les classes métiers avec AF sont toujours suffixées par Bo), qui consiste à gérer les utilisateurs de l'application. Cette classe proposerait alors les méthodes d'action suivantes :
addUserAction
: créer un nouvel utilisateur ;updateUserAction
: modifie les données d'un utilisateur ;deleteUserAction
: supprime un utilisateur ;getUserAction
: retourne les données d'un utilisateur ;getUsersAction
: retourne la liste des utilisateurs ;- ...
Remarquons que les méthodes d'action sont toujours suffixées par Action
. Cette pratique se retrouve souvent sur d'autres frameworks tels que Zend Framework, Symfony... La différence avec le framework Adventy, réside dans le nom de la classe. Cette dernière est suffixée par Bo
au lieu de Controller
.
Le Controller Remplacé par le BO
Le framework Adventy a automatisé la couche controller, et donc le développeur n'aura plus à créer de classes controllers, mais des classes métiers à la place.
Cette pratique est en réalité une stratégie technique pour :
- améliorer la productivité en développant moins de code ;
- avoir une meilleure qualité de code et visibilité du code ;
- réduire les anomalies.
Contrairement à la couche controller, la couche métier s'oriente vers la modularité et la réutilisabilité des BO, ce qui va faciliter par la même occasion le développement des tests unitaires (qui seront véritablement unitaires). Cette technique combinée avec l'AOP va apporter de l'élégance dans le code, mais aussi et surtout une ouverture vers un genre nouveau d'architecture. Ce sujet sera traité plus loin dans la documentation dans la partie Programmation Orientée Aspect.
Ce qu'il faut retenir avec le BO, c'est le développement orienté module métier. Chaque module est spécialisé, et ne traite qu'une seule tâche et une seule.
Le chemin et le nom d'une classe métier
Le nom d'une classe métier est dépendant de l'URI de la page dynamique à laquelle la classe est rattachée. Il prend le nom du dernier dossier de l'URI, et la dernière partie de l'URI désigne l'action.
Par exemple, si l'URI est /get-user
, alors nous aurons à définir les fichiers suivants :
- les propriétés de page (optionnelles) :
/application/meta/get-user.meta.php
- le corps de page :
/application/view/page/get-user.body.php
- le CSS de page (optionnel) :
/application/view/css/get-user.css.php
- le JS de page (optionnel) :
/application/view/js/get-user.js.php
- la classe métier :
/application/model/bo/IndexBo.class.php
qui doit implémenter la méthode actionpublic function getUserAction()
(optionnelle si page statique). Notons que le nom de classe métier (en upper camel case) est suffixé parBo
, et que l'action (en camel case) est suffixée parAction
. Dans cet exemple, le dossier racine des BO étant/application/model/bo/
, par défaut, il est assimilé au nom de dossierindex
, d'où le nom de la classeIndexBo
.
Un autre exemple où l'application de la règle sur le dernier nom de classe serait plus évidente. Soit l'URI /my-folder/get-user
, alors les fichiers à créer seraient :
- les propriétés de page (optionnelles) :
/application/meta/my-folder/get-user.meta.php
- le corps de page :
/application/view/page/my-folder/get-user.body.php
- le CSS de page (optionnel) :
/application/view/css/my-folder/get-user.css.php
- le JS de page (optionnel) :
/application/view/js/my-folder/get-user.js.php
- la classe métier :
/application/model/bo/MyFolderBo.class.php
, sans oublier l'implémentation de la méthode actionpublic function getUserAction()
(optionnelle si page statique).
Et voici un dernier exemple avec l'URI /my-folder/my-subfolder/get-user
:
- les propriétés de page (optionnelles) :
/application/meta/my-folder/my-subfolder/get-user.meta.php
- le corps de page :
/application/view/page/my-folder/my-subfolder/get-user.body.php
- le CSS de page (optionnel) :
/application/view/css/my-folder/my-subfolder/get-user.css.php
- le JS de page (optionnel) :
/application/view/js/my-folder/my-subfolder/get-user.js.php
- la classe métier :
/application/model/bo/my-folder/MySubfolderBo.class.php
avec l'implémentation de la méthode actionpublic function getUserAction()
(optionnelle si page statique).
La création d'une classe métier
Les classes métiers sont définies dans le dossier /application/model/bo/
. Le nom de la classe métier (en upper camel case) porte le nom du dernier dossier de l'URI, suffixé par Bo
, excepté si ce dossier est le dossier racine des BO. Dans ce cas, le nom de la classe métier est par défaut IndexBo
.
En respectant cette règle de nommage, il ne reste plus qu'à créer la classe métier dans le dossier souhaité. Si nous prenons un exemple plus concret avec l'URI /application/meta/my-manager/my-user/get-user.meta.php
, alors le fichier de la classe métier à créer sera /application/model/bo/my-manager/MyUserBo.class.php
.
Et voici son contenu :
<?php
namespace model\bo\myManager;
/**
* My business model class suffixed by Bo.
* @author xxx
* @version 0.1
* @package model.bo.my-manager
*/
class MyUserBo extends \org\adventy\model\bo\AbstractBo {
...
/**
* Display user data.
* @return void
* @uses /my-manager/my-user/get-user?userId=369
*/
public function getUserAction() {
//Retrieve parameters from $_GET and $_POST
$parameters = &$this->_parameters;
...
//Prepare user filter: set primary key
$filters = array('userId' => &$parameters['userId']);
//Retrieve user data: store result in view variable $this->userData
//xxxDs is a data source (ex: database)
$this->tuserData = $this->xxxDs->userDao->get($filters);
...
}
...
}
?>
Notons que la classe MyUserBo
étend la classe abstraite \org\adventy\model\bo\AbstractBo
.
Nous expliquerons ce qu'est une source de données (Data Source) dans la partie Accès aux données.
Les variables de vue
Dans l'exemple ci-dessus, la méthode MyUserBo::getUserAction
introduit 2 nouvelles notions :
- l'utilisation d'un DAO (
$this->xxxDs->userDao
), qui est un patron de conception permettant d'accéder aux données. Les DAO sont utilisées dans les BO. C'est un sujet qui sera abordé juste après les modèles métiers. - la création d'une variable de vue, ici
$this->userData
qui récupère les données de l'utilisateur ayant l'identifiantuserId=369
. Cette variable de vue peut également être récupérée depuis le tableau associatif des variables de vue$this->_viewData
de la façon suivante :$this->_viewData['userData']
.
Pour le framework Adventy, il faut savoir que les variables de vue sont assimilées à des attributs de portée public des classes BO. Le framework nomme les propriétés de classe selon leur portée, en utilisant la règle suivante :
- la
private
est préfixée par un double "_" (caractère de soulignement ou underscore), soit par exempleprivate $__myPrivate;
- la
protected
est préfixée par un simple "_". Par exempleprotected $_myProtected;
- la
public
n'a aucun préfixe. Par exemplepublic $myPublic;
Les variables de vue sont de type public, et ne devraient donc pas être préfixées par le caractère "_". Si cela devait arriver malgré tout, le nommage de ces variables devra être différents des noms d'attributs déjà réservés :
- _acceptEncoding
- _actionName
- _aop
- _boName
- _boPath
- _cleanFilter
- _dataSources
- _formData
- _i18n
- _metadata
- _parameters
- _request
- _requestType
- _response
- _templateFile
- _uri
- _viewData
- _viewPath
- _viewUri
Toutes les variables de vue sont stockées et peuvent être récupérées depuis le tableau associatif $this->_viewData
.
L'utilisation des variables de vue dans la vue
La vue /application/view/page/my-manager/my-user/get-user.body.php
peut accéder à toutes les propriétés et méthodes de la classe \org\adventy\request\PageRequest
, y compris les attributs créés dynamiquement depuis les méthodes d'action du BO. Ces attributs sont appelés variables de vue, et sont utilisés avec $this
pour faire référence à l'instance courante de la requête de page \org\adventy\request\PageRequest
.
Voici un exemple de contenu de la vue /application/view/page/my-manager/my-user/get-user.body.php
:
<?php
//Retrieve view variable
$userData = &$this->userData;
//Or $userData = &$this->_viewData['userData'];
?>
<table>
<tbody>
<tr>
<td>UserId</td>
<td><?= $userData['userId']?></td>
</tr>
<tr>
<td>First name</td>
<td><?= $userData['firstname']?></td>
</tr>
<tr>
<td>Last name</td>
<td><?= $userData['lastname']?></td>
</tr>
</tbody>
</table>
Les variables de vue sont :
- accessibles individuellement par
$this-><variableName>
(ex :$this->userData
) ; - ou récupérables depuis le tableau associatif
$this->_viewData
regroupant toutes les variables de vue (ex :$this->_viewData['userData']
).