Committed to Code

Mediboard is an open source Healthcare Information System based on web technologies.

Deployed in either a public or private healthcare center, Mediboard handles all its patient files as well as most workflows and plannings of its activity.

Code Analysis


Recent Highlights

Anon32

Large commit — Fnc : Ajout possibilité de choisir le répertoir...

More than 1000 lines of source code were added or removed in this commit.

In commit /p/mediboard/commits/177458469 by kgrisel on 2012-05-07 (16 days ago)

Avatar

Large commit — Ref: Renommage de fichiers dans dPhospi Erg: Di...

More than 1000 lines of source code were added or removed in this commit.

In commit /p/mediboard/commits/177065121 by flaviencrochard on 2012-05-04 (19 days ago)

Avatar

Large commit — fnc: Ajout des schémas de la version 2.4 de l'e...

More than 1000 lines of source code were added or removed in this commit.

In commit /p/mediboard/commits/175182351 by Yohann Poiron (Using name ‘lryo’) on 2012-04-20 (about 1 month ago)

Anon32

Large commit — Fnc: Ajout de la version PHP des scripts Shell ...

More than 1000 lines of source code were added or removed in this commit.

In commit /p/mediboard/commits/175182326 by kgrisel on 2012-04-19 (about 1 month ago)

Anon32

Large commit — ref : separation en 2 classes de CSmartyDP

More than 1000 lines of source code were added or removed in this commit.

In commit /p/mediboard/commits/175182315 by charlyecho on 2012-04-18 (about 1 month ago)

See all highlights…


News

Connectathon 2012

Openxtrem participe pour la première fois au Connectathon, qui cette année se déroule à Bern en Suisse.

Cet évènement qui se déroule chaque année, est le point d'orgue pour tout travail d'intégration d'IHE d'un système.


Assignations compactes vs. complexité cyclomatique

Voici un beau fragment de code regroupant trois séries d'assignations qui mériteraient d'être refactorées, dans la double optique d'être plus compact et lisible, afin d'en faire ressortir la logique plus clairement.

function ... [More] updateFormFields() {
parent::updateFormFields();
 
$this->codes_ccam = strtoupper($this->codes_ccam);
if ($this->codes_ccam) {
$this->_codes_ccam = explode("|", $this->codes_ccam);
}
else {
$this->_codes_ccam = array();
}
 
$this->_hour_op = substr($this->temp_operation, 0, 2));
$this->_min_op = substr($this->temp_operation, 3, 2));
 
if ($this->libelle_sejour) {
$this->_view = $this->libelle_sejour;
}
elseif ($this->libelle) {
$this->_view = $this->libelle;
}
else {
$this->_view = $this->codes_ccam;
}
}

Opérateur ternaire

Un cas typique d'opérateur ternaire manquant :

$this->codes_ccam = strtoupper($this->codes_ccam);
if ($this->codes_ccam) {
$this->_codes_ccam = explode("|", $this->codes_ccam);
}
else {
$this->_codes_ccam = array();
}

Au delà de la syntaxe qui est plus compacte, cela permet de mettre en évidence que la condition n'a pour but que de faire varier l'affectation, et non de créer une branche cyclomatique nouvelle, avec tout un — possible — tas d'opérations impératives.

$this->_codes_ccam = this->codes_ccam ?
explode("|", strtoupper($this->codes_ccam)) :
array();

list + explode vs. substr

Ici on veut séparer les composantes HH et MM d'une variable de type ISO TIME HH:MM.

$this->_hour_op = substr($this->temp_operation, 0, 2));
$this->_min_op = substr($this->temp_operation, 3, 2));

Si la syntaxe de substr() est très puissante et son exécution rapide, utiliser explode() permet de mieux mettre en évidence la séparation des composantes, tout en étant plus compact.

En outre, la syntaxe est beaucoup plus robuste si par malheur les composantes n'ont qu'un chiffre, ce qui arrive potentiellement lorsque la valeur ne vient pas de directement des données de Mediboard, par exemple 8:20 au lieu de 08:20. Ce comportement pad proof est celui de la plupart des systèmes compatibles avec ISO 8601, comme par exemple MySQL ou PHP

list($this->_hour_op, $this->_min_op) = explode(":", $this->temp_operation);

Valeurs par défaut en série

Enfin, ce dernier fragment montre un cas typique de valeurs par défaut en série, ou valeurs prioritaires, que l'on cherche pour la première d'entre elles qui n'évalue pas à false — cad null ou la chaine vide dans la plupart de cas.

if ($this->libelle_sejour) {
$this->_view = $this->libelle_sejour;
}
elseif ($this->libelle) {
$this->_view = $this->libelle;
}
else {
$this->_view = $this->codes_ccam;
}

On aurait déjà pu compacter le code en utilisant un double opérateur ternaire, seulement la lisibilité n'est pas merveilleuse, surtout lorsqu'on a de nombreuses valeurs dans la série. Par ailleurs ce genre de logique est très fréquemment utilisée dans Mediboard, ainsi le framework fournit un opérateur qui permet de retourner la première valeur !false d'une série variatique.

$this->_view = CValue::first($this->libelle_sejour, $this->libelle, $this->codes_ccam);

Au total

Au total nous avons un code plus concis et plus clair donc plus maintenable.

function updateFormFields() {
parent::updateFormFields();
 
$this->_codes_ccam = this->codes_ccam ?
explode("|", strtoupper($this->codes_ccam)) :
array();
 
list($this->_hour_op, $this->_min_op) = explode(":", $this->temp_operation);
 
$this->_view = CValue::first($this->libelle_sejour, $this->libelle, $this->codes_ccam);
}

Nous avons vu également qu'il était légèrement plus robuste ! [Less]


Usage des classes CSS multiples pour simplifier le code

Voici un cas typique de code à simplifier. On souhaite ici avoir un affichage qui dépend du $vue, valant classique ou compacte, avant dans les deux cas, une base commune.

Le snippet côté template :
="wrapper_line{{if $vue == ... [More] 'compacte'}}_compacte{{/if}}">
...
>

Le code CSS concerné :
div.wrapper_line {
position: relative;
height: 2em;
margin-bottom: 8px;
}
 
div.wrapper_line_compacte {
position: relative;
height: 1.1em;
margin-bottom: 8px;
}

Plusieurs remarques :

les deux classes CSS sont très proches en contenu
le code n'est pas symétrique, car il n'y a pas de style spécifique pour la vue classique: elle se définie comme "non-compacte"
la condition Smarty qui concatène un mot dans la classe n'est pas très élégante

Traitons les deux premiers point en factorisant les styles avec des classes multiples. Cela évitera de propager des modifications sur les deux modes, ouvrira la voie à d'autre modes et rendra le différentiel plus explicite :

div.wrapper_line {
position: relative;
margin-bottom: 8px;
}
 
div.wrapper_line.classique {
height: 2em;
}
 
div.wrapper_line.compacte {
height: 1.1em;
}

Le troisième point est traité de facto par cette nouvelle structure :
="wrapper_line {{$vue}}">
...
> [Less]


Usage des classes CSS multiples pour simplifier le code

Voici un cas typique de code à simplifier. On souhaite ici avoir un affichage qui dépend du $vue, valant classique ou compacte, avant dans les deux cas, une base commune.

Le snippet côté template :
="wrapper_line{{if $vue == ... [More] 'compacte'}}_compacte{{/if}}">
...
>

Le code CSS concerné :
div.wrapper_line {
position: relative;
height: 2em;
margin-bottom: 8px;
}
 
div.wrapper_line_compacte {
position: relative;
height: 1.1em;
margin-bottom: 8px;
}

Plusieurs remarques :

les deux classes CSS sont très proches en contenu
le code n'est pas symétrique, car il n'y a pas de style spécifique pour la vue classique: elle se définie comme "non-compacte"
la condition Smarty qui concatène un mot dans la classe n'est pas très élégante

Traitons les deux premiers point en factorisant les styles avec des classes multiples. Cela évitera de propager des modifications sur les deux modes, ouvrira la voie à d'autre modes et rendra le différentiel plus explicite :

div.wrapper_line {
position: relative;
margin-bottom: 8px;
}
 
div.wrapper_line.classique {
height: 2em;
}
 
div.wrapper_line.compacte {
height: 1.1em;
}

Le troisième point est traité de facto par cette nouvelle structure :
="wrapper_line {{$vue}}">
...
> [Less]


Do add-edit-delete, and make it mulitple, the easy way

On a régulièrement besoin d'enregistrer une valeur donnée sur une collection d'objets.

Prenons l'exemple d'une vue qui permet d'annuler des séjours.
On construira classiquement un tableau avec un bouton d'annulation à la fin de ... [More] chaque ligne :

{{foreach from=$sejours item=_sejour}}
...
 

 

 

 
...
 

 
...
{{/foreach}}

Seulement on aimerait également avoir un bouton pour tout annuler, sans cliquer sur n boutons et encore moins en chainant des requêtes Ajax.

Voici comment transformer un do_aed classique : il suffit d'ajouter un champ dont le nom est celui de la clé avec un s final, et donc la valeur est une sérialisation des identifiants.

 

 

 

On pourra également laissé la valeur en blanc pour la remplir en Javascript, par exemple sur l'état de cases à cocher :

Le tout, bien entendu, sans avoir à coder de do_multiple_aed.php specifique.

Remarque: Les controlleurs multiples fonctionnent également en suppression. [Less]


Read all Mediboard articles…

Edit RSS feeds.