Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Expression language Symfony live

Expression language Symfony live

Hussein Abbas

April 10, 2016
Tweet

Other Decks in Programming

Transcript

  1. COIFFARD Xavier ABBAS Hussein
    Expression
    language

    @

    Sell Secure

    View Slide

  2. Hussein ABBAS
    Ingénieur d’études et développement
    @habbas92
    L’accent est Libanais
    Xavier Coiffard
    Lead Developer SELL SECURE
    @angezanetti
    http://angezanetti.com
    About us

    View Slide

  3. COIFFARD Xavier ABBAS Hussein
    SellSecure ?

    View Slide

  4. Sell Secure
    ● Lutte contre la fraude à la CB sur les stores e-
    commerce

    ● Start up !

    ● 4 dev / 4 analystes / 15 enqueteurs / 2 bizdev

    ● MVP ftw!

    View Slide

  5. Sell Secure

    View Slide

  6. ● Analyser des centaines de datas

    ● Déclencher un traitement statistique

    ● Scorer une transaction: Go/Nogo livraison
    Un moteur de règle ?

    View Slide

  7. COIFFARD Xavier ABBAS Hussein
    Historique !

    View Slide

  8. Task force
    TAAASSK FORCE

    View Slide

  9. Un choix constestable…
    ● Choix de Ruler contestable

    ● Coder vite vite

    ● Plus personne après 100 jours

    View Slide

  10. View Slide

  11. ● Dette technique

    ● Construire à chaque fois le même objet (temps de
    traitement énorme)

    ● Petit projet opensource
    Problématiques techniques

    View Slide

  12. Problématiques métiers
    ● Compléxité des règles demandées par le métier qui
    explose

    ● Les métiers écrivent du JSON dans la BDD….

    View Slide

  13. COIFFARD Xavier ABBAS Hussein
    Et ça marche ?

    View Slide

  14. Un OR et un AND ?… !

    View Slide

  15. ·Petit projet Open Source (pas
    maintenu, en version bêta)

    View Slide

  16. Des alternatives ?

    View Slide

  17. hallelujah !

    View Slide

  18. COIFFARD Xavier ABBAS Hussein
    Expression

    Language

    View Slide

  19. ● Component Symfony symfony/expression-language
    ● Evaluer/Compiler des expressions
    ● Basé sur l’expression syntaxe de twig
    ● Simple à mettre en place
    Expression langage

    View Slide

  20. Exemple
    class Order
    {
    public $amount;
    }
    $order = new Order();
    $order->amount = 150;

    View Slide

  21. Exemple
    class Order
    {
    public $amount;
    }
    $order = new Order();
    $order->amount = 150;
    $language->evaluate(
    ‘order.amount in 100..200',
    array(
    'order' => $order,
    )
    );

    View Slide

  22. COIFFARD Xavier ABBAS Hussein
    Ok,

    mais en vrai ?

    View Slide

  23. Est-ce la bonne solution?
    ● Répond à nos besoins

    ● Valider par les métiers

    ● Extensible

    View Slide

  24. public function rulesTreatment($rules, $context, $isbref)

    {

    foreach ($rules as $expression) {

    try {

    $return

    = $this->expressionLanguage->evaluate(

    $expression,

    $context

    );
    if ($return === true) {
    //On déclenche la règle
    }

    } catch (SyntaxError $e) {

    }

    }

    }
    Implémentation

    View Slide

  25. Surcharge du composant
    class ExpressionLanguage extends BaseExpressionLanguage

    {

    /**

    * @param GetListElementsFunction $elementsList ;the object

    * @param ParserCacheInterface|null $parser

    * @param array $providers

    */

    public function __construct(

    GetListElementsFunction $elementsList,

    ParserCacheInterface $parser = null,

    array $providers = array()

    ) {

    // prepend the default provider to let users override it easily

    array_unshift($providers, $elementsList);


    parent::__construct($parser, $providers);

    }

    }

    View Slide

  26. COIFFARD Xavier ABBAS Hussein
    Avant / Après:

    View Slide

  27. [

    {

    "type": "group",

    "logical": "and",

    "children": [

    {

    "type": "condition",

    "variable": "var1",

    "operator": "lists-NotIn",

    "parameter": [

    "2"

    ]

    },

    {

    "type": "condition",

    "variable": "var2",

    "operator": "lists-NotIn",

    "parameter": [

    "3"

    ]

    },

    {

    "type": "condition",

    "variable": "var3",

    "operator": "lists-NotIn",

    "parameter": [

    "4"

    ]

    },

    {

    "type": "condition",

    "variable": "var4",

    "operator": "lists-NotIn",

    "parameter": [

    "5"

    ]

    },

    {

    "type": "condition",

    "variable": "var5",

    "operator": "lists-NotIn",

    "parameter": [

    "6"

    ]

    },

    {

    "type": "condition",

    "variable": "var6",

    "operator": "lists-NotIn",

    "parameter": [

    "15"

    ]

    }

    ]

    }

    ]
    var1 not in getListElement(2)

    and var2 not in getListElement(3)

    and var3 not in getListElement(4)

    and var4 not in getListElement(5)

    and var5 not in getListElement(6)

    and var6 not in getListElement(15)
    Les règles:

    View Slide



  28. namespace WS\RESTBundle\Services\jsonBuilder;


    use Symfony\Component\DependencyInjection\ContainerInterface as Container;

    use Ruler\RuleBuilder;


    /**

    * Class InsertRulesObjectDB

    *

    * @category Treatment_Standard_Data

    * @package WS\RESTBundle\Services\jsonBuilder

    * @author deploiement 

    * @license copyright SellSecure

    * @version Release: <2.0>

    * @link www.sellsecure.com

    */

    class InsertRulesObjectDB

    {

    private $_container;

    private $_connexion;

    private $_tableTransaction;

    private $_arrayDecisionRuler;

    private $_arrayRulesScoreRuler;


    /**

    * Method constructor

    *

    * @param connexion $connexion :connection to database

    * @param Container $container :container object

    */

    public function __construct($connexion, Container $container)

    {

    $this->_container = $container;

    $this->_connexion = $connexion;

    $this->_tableTransaction

    = $this->_container->getParameter('ISB_TRANSACTIONS');

    }



    /**

    * Insert rules object into DB

    *

    * @return void

    */

    public function insertObjectDB()

    {

    $rules = $this->getRulesFromDB();

    $this->rulesTreatment($rules);

    $this->insertRuleObjectDB($this->_arrayDecisionRuler);

    $this->insertRuleObjectDB($this->_arrayRulesScoreRuler);

    }



    /**

    * Get all rules from the DB

    *

    * @return Array

    */

    public function getRulesFromDB()

    {

    $sql = 'Select *

    FROM ' . $this->_tableTransaction . '.REGLES

    WHERE version = :version

    AND actif = :actif';


    $queryFlux = $this->_connexion->prepare($sql);

    $queryFlux->bindValue("version", 0);

    $queryFlux->bindValue("actif", 1);

    $queryFlux->execute();

    $rules = $queryFlux->fetchAll();


    return $rules;

    }



    /**

    * Separate the rules in 2 categories, for simple rules & decision

    *

    * @param Array $rules :the Array of the rules

    *

    * @return void

    */

    public function rulesTreatment($rules)

    {

    $arrayJsonRuler = array();

    $arrayDecisionRuler = array();

    foreach ($rules as $rule) {

    if ($rule['UTILISATION_SCORE'] == 1) {

    $arrayJsonRuler[]

    = $this->returnArrayRuler(

    $rule['JSON'],

    $rule['EMPLACEMENT'],

    $rule['NOM'],

    $rule['ID'],

    $rule['MOTIF'],

    $rule['SCORE']

    );

    } elseif ($rule['UTILISATION_SCORE'] == 2) {

    $arrayDecisionRuler[]

    = $this->returnArrayRuler(

    $rule['JSON'],

    $rule['EMPLACEMENT'],

    $rule['NOM'],

    $rule['ID'],

    $rule['MOTIF'],

    $rule['SCORE']

    );

    }

    }

    $this->_arrayRulesScoreRuler = $arrayJsonRuler;

    $this->_arrayDecisionRuler = $arrayDecisionRuler;

    }


    /**

    * Insert the object of rules into DB

    *

    * @param Array $rules :the json of rules to insert the object

    *

    * @return void;

    */

    public function insertRuleObjectDB($rules)

    {

    $jsonToRuleBuilder

    = $this->_container->get('JsonToRulerBuilder');


    foreach ($rules as $rule) {

    $ruleBuilder = new RuleBuilder();

    $parameters

    = $jsonToRuleBuilder->jsonToRuleBuilder(

    $rule,

    $ruleBuilder

    );



    $serializeRules = serialize($rule);

    $encodeRules = base64_encode($serializeRules);


    $serializeParameters = serialize($parameters);

    $encodeParameters = (base64_encode($serializeParameters));


    $sql = "DECLARE

    vClobVal varchar2(32767) := '$encodeParameters';

    vClobVal1 varchar2(32767) := '$encodeRules';

    begin ";


    $sql .= "UPDATE "

    . $this->_tableTransaction

    . ".REGLES SET PARAMETERS = vClobVal,

    RULES = vClobVal1 WHERE ID = '"

    . utf8_decode($rule[0]['id']) . "'; end;";



    $query = $this->_connexion->prepare($sql);

    $query->execute();

    }

    }



    /**

    * Convert the rules into an array

    *

    * @param string $json_ruler :the rule to convert

    * @param string $emplacement :the emplacement of the rule

    * @param string $name :the name of the rule

    * @param string $id :the name of the rule

    * @param string $motif :the motif of the rule

    * @param string $score :the score of the rule

    *

    * @return Array

    */

    public function returnArrayRuler(

    $json_ruler,

    $emplacement = '',

    $name = '',

    $id = '',

    $motif = '',

    $score = ''

    ) {

    $jsonInfosRule

    = ',"emplacement":"'

    . $emplacement

    . '","nom":"'

    . $name

    . '","id":"'

    . $id

    . '","motif":"'

    . $motif

    . '","score":"'

    . $score . '"}]';

    $jsonRuler = substr($json_ruler, 0, -2) . $jsonInfosRule;

    $objectRuler = json_decode($jsonRuler);

    $arrayRuler = json_decode(json_encode($objectRuler), true);


    return $arrayRuler;

    }

    }

    Plus de 450 lignes de codes 15 lignes de code
    Le code :
    public function rulesTreatment($rules, $context, $isbref)

    {

    foreach ($rules as $expression) {

    try {

    $return

    = $this->expressionLanguage->evaluate(

    $expression,

    $context

    );
    if ($return === true) {
    //On déclenche la règle
    }

    } catch (SyntaxError $e) {

    }

    }

    }

    View Slide

  29. temps en ms
    0
    200
    400
    600
    800
    Avant Après
    ms
    ms
    Les perfs :

    View Slide

  30. One more thing…

    View Slide

  31. COIFFARD Xavier ABBAS Hussein
    DEMOOO !

    View Slide

  32. Bilan !
    ● Ca va vite !

    ● Le métier est content

    ● To be continued…

    View Slide

  33. COIFFARD Xavier ABBAS Hussein
    Questions ?

    View Slide