Conectividade fraca

NB : Este é um rascunho de dois novos capítulos do meu livro sobre API Design. O texto contém referências aos capítulos anteriores.







Conectividade forte e problemas relacionados



Nas seções anteriores, tentamos fornecer regras e princípios teóricos e ilustrá-los com exemplos práticos. No entanto, compreender os princípios de criação de uma API resiliente a mudanças requer mais prática do que qualquer outra coisa. O conhecimento de onde "jogar a palha" é, sob muitos aspectos, "o filho de erros difíceis". Você não pode prever tudo - mas pode desenvolver o nível necessário de intuição técnica.







Portanto, nesta seção, procederemos da seguinte forma: pegar nosso modelo de API da seção anterior e verificar a estabilidade em todos os pontos possíveis - conduziremos algumas "análises variacionais" de nossas interfaces. Ainda mais especificamente, abordaremos cada entidade com a pergunta "e se?" - e se precisarmos fornecer aos parceiros a capacidade de escrever sua própria implementação independente dessa parte da lógica.







O primeiro ponto importante a se prestar atenção: estamos falando especificamente sobre as opções para a implementação da lógica do produto . Não sobre as opções de implementação da entidade : as alterações na API são feitas principalmente para possibilitar fazer algo que não estava previsto no design original - algo útil. Seus clientes não irão reimplementar interfaces assim.







Esta consideração introduz certas restrições que nos permitem não variar cegamente as interfaces (afinal, existem um número infinito de tais opções, e prover para todas elas é um trabalho de Sísifo): precisamos entender, antes de tudo, porque é certo mudanças são necessárias e, a partir daqui, já entenderemos como devem ser introduzidas.







O segundo ponto importante é que muitas das soluções que permitem essa variação já estão integradas ao design da API. Cobrimos alguns deles (por exemplo, a questão de determinar a prontidão) com mais detalhes nos capítulos anteriores, e alguns deram sem comentários - é hora de explicar por que essas decisões foram tomadas.







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);
  )
}
      
      








Este é um rascunho de dois novos capítulos na próxima seção Compatibilidade com versões anteriores do meu livro sobre desenvolvimento de API. O trabalho é feito no Github . A versão em inglês do mesmo capítulo é publicada na mídia . Eu ficaria muito grato se você pudesse compartilhar no reddit - eu mesmo não posso de acordo com a política da plataforma.








All Articles