Faiblesse de la connectivité

NB : Ceci est un brouillon de deux nouveaux chapitres de mon livre sur la conception d'API. Le texte contient des références aux chapitres précédents.







Connectivité forte et problÚmes connexes



Dans les sections prĂ©cĂ©dentes, nous avons essayĂ© de donner des rĂšgles et des principes thĂ©oriques et de les illustrer par des exemples pratiques. Cependant, comprendre les principes de la conception d'une API rĂ©siliente au changement nĂ©cessite plus de pratique qu'autre chose. Le fait de savoir oĂč «poser la paille» est Ă  bien des Ă©gards «le fils d'erreurs difficiles». Vous ne pouvez pas tout prĂ©voir - mais vous pouvez dĂ©velopper le niveau nĂ©cessaire d'intuition technique.







Par conséquent, dans cette section, nous procéderons comme suit: prenez notre modÚle d'API de la section précédente et vérifiez sa stabilité à chaque point possible - nous allons effectuer une «analyse variationnelle» de nos interfaces. Plus précisément encore, nous aborderons chaque entité avec la question "et si?" - et si nous devons fournir aux partenaires la possibilité d'écrire leur propre implémentation indépendante de ce morceau de logique.







Le premier point important auquel il faut prĂȘter attention: nous parlons spĂ©cifiquement des options pour la mise en Ɠuvre de la logique produit . Pas sur les options pour l'implĂ©mentation de l'entitĂ© : les changements dans l'API sont principalement faits pour permettre de faire quelque chose qui n'Ă©tait pas prĂ©vu par la conception originale - quelque chose d'utile. Vos clients ne rĂ©implĂ©menteront pas les interfaces comme ça.







Cette considĂ©ration introduit certaines restrictions qui nous permettent de ne pas varier aveuglĂ©ment les interfaces (aprĂšs tout, il existe un nombre infini de telles options, et les fournir toutes est un travail de Sisyphe): nous devons comprendre, tout d'abord, pourquoi certaines des changements sont nĂ©cessaires, et Ă  partir de lĂ , nous le sommes dĂ©jĂ , nous comprendrons comment ils doivent ĂȘtre introduits.







Le deuxiÚme point important est que la plupart des solutions qui permettent cette variation sont déjà intégrées à la conception de l'API. Nous avons abordé certains d'entre eux (par exemple, la question de la détermination de l'état de préparation) plus en détail dans les chapitres précédents, et certains ont donné sans commentaire - il est temps d'expliquer pourquoi ces décisions ont été prises.







NB: , ; ad hoc , . API ; , , .







, . ?







  • , «» ;
  • , .


. , ? , «»: , . , :







//   
POST /v1/recipes
{
  "id",
  "product_properties": {
    "name",
    "description",
    "default_value"
    //  , 
    //   
    

  },
  "execution_properties": {
    //  
    "program_id",
    //   
    "parameters"
  }
}
      
      





, , . , — .







, 11: . :







"product_properties": {
  // "l10n" —  
  //  "localization"
  "l10n" : [{
    "language_code": "en", 
    "country_code": "US", 
    "name", 
    "description" 
  }, /*     */ 
 ]
]
      
      





— default_volume



? , , , . , , , «300 », «10 ». :







  • , ;
  • , .


, API - — , API. , — . .







, , API . — name



description



? , . — /v1/search



, : search



?







— , UI . -, name



description



— , ( ) ( ). , API . , UI ? , , : name



— «-» , . -, , UI; -, . , , «», «» «» « » « ».







— UI ( ) , ( , , ). product_properties



, , .







, — . , , , () ( , ). API « », . , : . .









: , . — , (, , .. API) .







, . - , API, — , API . - API :







l10n.volume.format(value, language_code, country_code)
// l10n.formatVolume('300ml', 'en', 'UK') → '300 ml'
// l10n.formatVolume('300ml', 'en', 'US') → '10 fl oz'
      
      





API , , , . , , :







//    
//   
PUT /formatters/volume/ru
{
  "template": "{volume} "
}
//    
//      «»
PUT /formatters/volume/ru/US
{
  //     
  // ,   
  "value_preparation": {
    "action": "divide",
    "divisor": 30
  },
  "template": "{volume} ."
}
      
      





NB: , , , , , (, , ), (.. ). .







name



description



. , , (, , API) «». name



description



, UI. UI .







GET /v1/layouts/{layout_id}
{
  "id",
  //      ,
  //     
  // 
  "kind": "recipe_search",
  //    ,
  //     
  //   
  "properties": [{
    //    ,  `name`
    //      
    //     —
    //      `seach_title`
    "field": "search_title",
    "view": {
      //   ,
      //    
      "min_length": "5em",
      "max_length": "20em",
      "overflow": "ellipsis"
    }
  }, 
],
  //   
  "required": ["search_title", "search_description"]
}
      
      





, , . :







PUT /v1/recipes/{id}/properties/l10n/{lang}
{
  "search_title", "search_description"
}
      
      





:







POST /v1/layouts
{
  "properties"
}
→
{ "id", "properties" }
      
      





, UI , , .







— , — execution_properties



, , . :







POST /v1/recipes
{ "id" }
→
{ "id" }
      
      





, «» , . , , -, :







POST /v1/recipe-builder
{
  "id",
  //   
  "product_properties": {
    "default_volume",
    "l10n"
  },
  //  
  "execution_properties"
  //   
  "layouts": [{
    "id", "kind", "properties"
  }],
  //   
  "formatters": {
    "volume": [
      { "language_code", "template" },
      { "language_code", "country_code", "template" }
    ]
  },
  //  ,  
  //    
  //    
  

}
      
      





, — . , — , , - . , , , , : ( ), , 11.







POST /v1/recipes/custom
{
  //   :
  // ,    
  "namespace": "my-coffee-company",
  //   
  "id_component": "lungo-customato"
}
→
{
  "id": "my-coffee-company:lungo-customato"
}
      
      





, : , . , "common", . (, , , API .)









, . , API 9 «» « ». , program-matcher



:







GET /v1/recipes/{id}/run-data/{api_type}
→
{ /*   
       
        
       API */ }
      
      





:







  • API -;
  • API ;
  • API .


, — , , API -. , «», , «».







program_run_id



, . .







, , . API - API. , , -, API. API , - ?







, API : , () . API — , :







//   
// - 
PUT /partners/{id}/coffee-machines
{
  "coffee-machines": [{
    "id",
    

    "program_api": {
      "program_run_endpoint": {
        /* - 
              */
        "type": "rpc",
        "endpoint": <URL>,
        "format"
      },
      "program_state_endpoint",
      "program_stop_endpoint"
    }
  }, 
]
}
      
      





NB: API ( program_run_endpoint



, program_state_endpoint



, .)







API , , API . .







  1. (.. API), : , .
  2. : .


2 , 1. , , — , , . , , program_modify_endpoint



, ( , ). , , ( , ) .







- , . : , API , . , , , modify



API — , . , , , : , - , « ». , , , , , , , , , , , .







, , program_takeout_endpoint



. :







  • program_takeout_endpoint



    , program_modify_endpoint



    ;
  • program_modify_endpoint



    , program_takeout_endpoint



    .


, . , takeout



. - modify



, . , , — API , .







, API , . , , «» , , : , API -, . — , , — , , .







, . API « », .







? : , . ? - :







  • API , ; , : - - , , - ;
  • API , API ; , .


, , , : , . , « ».







:







  • , ;
  • : , .


, , (- ) . SDK :







/*   
       - */
registerProgramRunHandler(apiType, (program) => {
  //   
  //    
  let execution = initExecution(
);
  //   
  //  
  program.context.on('takeout_requested', () => {
    //    ,
    //  
    execution.prepareTakeout(() => {
        //      ,
        //   
        execution.context.emit('takeout_ready');
    });
  });

  return execution.context;
});
      
      





NB: HTTP API , GET /program-run/events



GET /partner/{id}/execution/events



, . , Apache Kafka Amazon SQS.







, , , , :







  • takeout



    takeout_requested



    /takeout_ready



    ;
  • , API , context



    , ;
  • , .


. API , . API : . ? , ; - ( !) , ( ).







, . , :







  • , API — ; , , ;
  • — , , , .


, — , - .







, , (, ) API, , . program



( , , ); execution



( , , API). , execution



- , - API, program



- , .







, . API, , , , . , UI. , SDK.









, , . , — . :







/*   
       - */
registerProgramRunHandler(apiType, (program) => {
  //   
  //    
  let execution = initExection(
);
  //   
  //  
  program.context.on('takeout_requested', () => {
    //    ,
    //  
    execution.prepareTakeout(() => {
      /*      ,
            ,  
             */
      // execution.context.emit('takeout_ready')
      program.context.set('takeout_ready');
      //    :
      // program.setTakeoutReady();
    });
  });
  //       
  //   - 
  // return execution.context;
}
      
      





, . : , . , , , , . .







, , , :







  • , , — ;
  • , , API . API , .


, API API , «» «-».







NB: . , — Redux. Redux :







execution.prepareTakeout(() => {
  //     
  //     ,
  //    
  //      
  dispatch(takeoutReady());
});
      
      





, , — , API, . ( -) , , : , , .







execution.prepareTakeout(() => {
  //     
  //     ,
  //    
  // 
  program.context.dispatch(takeoutReady());
});
      
      





//  program.context.dispatch
ProgramContext.dispatch = (action) => {
  // program.context   
  //  ,   
  // ,    
  globalContext.dispatch(
    //     
    //     
    //    
    // 
    this.generateAction(action);
  )
}
      
      








Ceci est un brouillon de deux nouveaux chapitres dans la prochaine section de compatibilitĂ© descendante de mon livre sur le dĂ©veloppement d'API. Le travail se fait sur Github . La version anglaise du mĂȘme chapitre est publiĂ©e sur support . Je vous serais reconnaissant si vous pouviez le partager sur reddit - je ne peux pas moi-mĂȘme selon la politique de la plate-forme.








All Articles