Ao comparar a estrutura REST [api] com um modelo OO, vejo essas semelhanças:
Ambos:
Os dados são orientados
- REST = Recursos
- OO = Objetos
Operação surround em torno de dados
- REST = surround VERBS (Get, Post, ...) em torno dos recursos
- OO = promove operação em torno de objetos por encapsulamento
No entanto, boas práticas de OO nem sempre permanecem nas APIs REST ao tentar aplicar o padrão de fachada, por exemplo: no REST, você não possui 1 controlador para manipular todas as solicitações E não oculta a complexidade interna do objeto.
Pelo contrário, o REST promove a publicação de recursos de todas as relações com um recurso e outro em pelo menos duas formas:
via relações de hierarquia de recursos (um contato do id 43 é composto por um endereço 453):
/api/contacts/43/addresses/453
via links em uma resposta json REST:
>> GET /api/contacts/43 << HTTP Response { id: 43, ... addresses: [{ id: 453, ... }], links: [{ favoriteAddress: { id: 453 } }] }
Voltando ao OO, o padrão de design da fachada respeita a Low Coupling
entre um objetoA e seu ' clienteB de objeto ' e High Cohesion
para esse objetoA e sua composição interna de objetos ( objetoC , objetoD ). Com a interface objectA , isso permite que um desenvolvedor limite o impacto no objeto B das mudanças internas do objeto A (no objeto C e no objeto D ), desde que a API do objeto A (operações) ainda seja respeitada.
No REST, os dados (recurso), as relações (links) e o comportamento (verbos) são explodidos em diferentes elementos e estão disponíveis para a web.
Jogando com o REST, eu sempre tenho impacto nas alterações de código entre meu cliente e servidor: porque eu tenho High Coupling
entre minhas Backbone.js
solicitações e Low Cohesion
entre recursos.
Eu nunca descobri como deixar meu Backbone.js javascript application
acordo com a descoberta de " recursos e recursos REST " promovida pelos links REST. Entendo que a WWW deve ser servida por vários servidores e que os elementos OO precisaram ser explodidos para serem atendidos por muitos hosts, mas para um cenário simples como "salvar" uma página que mostra um contato com seus endereços, Eu acabo com:
GET /api/contacts/43?embed=(addresses) [save button pressed] PUT /api/contacts/43 PUT /api/contacts/43/addresses/453
o que me levou a mover a responsabilidade transacional atômica da ação de salvar nos aplicativos dos navegadores (já que dois recursos podem ser endereçados separadamente).
Com isso em mente, se eu não puder simplificar meu desenvolvimento (os padrões de design do Facade não são aplicáveis) e se eu trouxer mais complexidade ao meu cliente (manipulando a economia de energia atômica), qual é o benefício de ser RESTful?
fonte
PUT /api/contacts/43
atualizações em cascata para objetos internos? Eu tinha muitas APIs projetadas assim (o URL mestre lê / cria / atualiza o "todo" e os sub-URLs atualizam as peças). Apenas certifique-se de não atualizar o endereço quando nenhuma alteração for necessária (por motivos de desempenho).Respostas:
Eu acho que os objetos são construídos apenas corretamente em torno de comportamentos coerentes e não em torno de dados. Vou provocar e dizer que os dados são quase irrelevantes no mundo orientado a objetos. De fato, é possível e, em algum momento, comum ter objetos que nunca retornam dados, por exemplo "log sinks" ou objetos que nunca retornam os dados que são transmitidos, por exemplo, se calculam propriedades estatísticas.
Não confundamos o PODS (que é pouco mais que estruturas) e os objetos reais que têm comportamentos (como a
Contacts
classe no seu exemplo) 1 .Os PODS são basicamente uma conveniência usada para conversar com repositórios e objetos de negócios. Eles permitem que o código seja do tipo seguro. Nem mais nem menos. Os objetos de negócios, por outro lado, fornecem comportamentos concretos , como validar seus dados, armazená-los ou usá-los para realizar um cálculo.
Portanto, comportamentos são o que usamos para medir a "coesão" 2 , e é fácil ver que no seu exemplo de objeto há alguma coesão, mesmo que você mostre apenas métodos para manipular contatos de nível superior e nenhum método para manipular endereços.
Em relação ao REST, você pode ver os serviços REST como repositórios de dados. A grande diferença com o design orientado a objetos é que existe (quase) apenas uma opção de design: você tem quatro métodos básicos (mais se contar
HEAD
, por exemplo) e, é claro, tem muita margem de manobra com os URIs, para que você possa fazer astuciosamente coisas como passar muitos IDs e recuperar uma estrutura maior. Não confunda os dados que eles passam com as operações que executam. Coesão e acoplamento são sobre código e não dados .Claramente, os serviços REST têm alta coesão (todas as formas de interagir com um recurso estão no mesmo lugar) e baixo acoplamento (todo repositório de recursos não requer conhecimento dos outros).
O fato básico permanece, no entanto, o REST é essencialmente um padrão de repositório único para seus dados. Isso tem consequências, porque é um paradigma construído em torno da fácil acessibilidade em um meio lento, onde há um alto custo para "chattiness": os clientes geralmente desejam executar o mínimo de operações possível, mas ao mesmo tempo recebem apenas os dados de que precisam . Isso determina a profundidade da árvore de dados que você enviará de volta.
No design (correto) orientado a objetos, qualquer aplicativo não trivial fará operações muito mais complexas, por exemplo, através da composição. Você pode ter métodos para realizar operações mais especializadas com os dados - o que deve ser assim, porque, embora o REST seja um protocolo de API, o OOD é usado para criar aplicativos inteiros para o usuário! É por isso que medir a coesão e o acoplamento é fundamental no OOD, mas quase insignificante no REST.
Agora, deveria estar óbvio que analisar o design de dados com conceitos de OO não é uma maneira confiável de medi-lo: é como comparar maçãs e laranjas!
De fato, os benefícios de ser RESTful são (principalmente) os descritos acima: é um bom padrão para APIs simples em um meio lento. É muito armazenável em cache e fragmentável. Possui controle refinado sobre chattiness, etc.
Espero que isso responda à sua pergunta (bastante multifacetada) :-)
1 Esse problema faz parte de um conjunto maior de problemas, conhecido como incompatibilidade de impedância objeto-relacional . Os proponentes das ORMs geralmente estão no campo que explora as semelhanças entre análise de dados e análise de comportamento, mas as ORMs foram criticadas ultimamente porque parecem não resolver realmente a incompatibilidade de impedância e são consideradas abstrações com vazamento .
2 http://en.wikipedia.org/wiki/Cohesion_(computer_science)
fonte
A resposta para "onde está o benefício de ser RESTful?" é cuidadosamente analisado e explicado aqui: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
A confusão nesta pergunta é que não se trata de características do REST e de como lidar com elas, mas assumindo que o design das URLs criadas para o seu sistema de exemplo tem algo a ver com ser RESTful. Afinal, o REST afirma que existem coisas chamadas recursos e um identificador deve ser fornecido para aqueles que precisam ser referenciados, mas não determina que, digamos, as entidades no seu modelo de ER devam ter 1 a 1 de correspondência com os URLs que você criou (nem que os URLs devem codificar a cardinalidade dos relacionamentos de ER no modelo).
No caso de contatos e endereços, você poderia ter definido um recurso que represente essas informações em conjunto como uma única unidade, mesmo que você queira extrair e salvar essas informações em, por exemplo, diferentes tabelas de banco de dados relacional, sempre que forem PUT ou POSTed .
fonte
Isso porque fachadas são um 'clamor'; você deve dar uma olhada em 'api abstraction' e 'api encadeamento'. A API é uma combinação de dois conjuntos de funcionalidades: E / S e gerenciamento de recursos. Localmente, a E / S é boa, mas dentro de uma arquitetura distribuída (por exemplo, proxy, porta da API, fila de mensagens etc.), a E / S é compartilhada e, portanto, os dados e a funcionalidade ficam duplicados e emaranhados. Isso leva a preocupações arquitetônicas transversais. Isso assola TODAS as APIs existentes.
A única maneira de resolver isso é abstrair a funcionalidade de E / S da API para um manipulador anterior / posterior (como um manipuladorIntercepter no Spring / Grails ou um filtro no Rails) para que a funcionalidade possa ser usada como uma mônada e compartilhada entre instâncias e externos ferramentas. Os dados para solicitação / resposta também precisam ser externalizados em um objeto para que possam ser compartilhados e recarregados também.
http://www.slideshare.net/bobdobbes/api-abstraction-api-chaining
fonte
Se você entende seu serviço REST ou, em geral, qualquer tipo de API, apenas como uma interface adicional exposta aos clientes para que eles possam programar seu (s) controlador (es) através dele, torna-se subitamente fácil. O serviço nada mais é do que uma camada adicional sobre sua lógica de negócios.
Em outras palavras, você não precisa dividir a lógica de negócios entre vários controladores, como fez na foto acima e, mais importante, não deveria. As estruturas de dados usadas para trocar dados não precisam corresponder às estruturas de dados usadas internamente; elas podem ser bem diferentes.
É de ponta e amplamente aceito que é uma má idéia colocar qualquer lógica de negócios no código da interface do usuário. Mas toda interface do usuário é apenas um tipo de interface (o I na interface do usuário) para controlar a lógica de negócios por trás. Consequentemente, parece óbvio que também é uma má idéia colocar qualquer lógica de negócios na camada de serviço REST ou qualquer outra camada de API.
Conceitualmente falando, não há muita diferença entre a interface do usuário e a API de serviço.
fonte