-
Notifications
You must be signed in to change notification settings - Fork 13
REST API as (formal) Object Model
| Main > Key Concepts > REST API as (formal) Object Model |
|---|
Before RESTful APIs became the industry standard, the representation and use of remote served Object Models (OMs) were naturally done by proxies.
Despite the fact of being just client-side dumb clones of those remote services, proxies reconstruct those served OMs as formal classes, with their properties and operations being responsible for contract description and enforcement.
Nowadays, these contracts are the OpenAPI Specifications published and versioned for each service and endpoint. Those should be the ultimate truth to rely on.
And for the sake of integration quality, one should put his/her trust less on compilers (for static compilation check on those typed contracts) and more on DevOps pipelines (for dynamic check by continuous integration tests).
So, instead of replicating back-end business abstraction as client code, Liquid promotes the use of such services in natura, the same way they are provided by remote server.

See the following code example using Liquid LightApi for accessing the remote API directly:
// Get the basket data and build an order draft based on it
var basket = await new LightAPI("BASKET").GetAsync<BasketVM>(basketId);
if (basket != null)
{
var orderDraft = await new LightApi("ORDER").PutAsync<OrderVM>("/draftfrombasket", basket);
}
The proxy version would be something like the following:
// Get the basket data and build an order draft based on it
var basket = await _basketService.GetById(basketId);
if (basket != null)
{
var orderDraft = await _orderService.GetOrderDraftFromBasket(basket);
}
...
/// <summary>
/// Proxy class for the Order API
/// </summary>
public class OrderApiClient : IOrderApiClient
{
private readonly HttpClient _apiClient;
private readonly ILogger<OrderApiClient> _logger;
private readonly UrlsConfig _urls;
public OrderApiClient(HttpClient httpClient, ILogger<OrderApiClient> logger, IOptions<UrlsConfig> config)
{
_apiClient = httpClient;
_logger = logger;
_urls = config.Value;
}
public async Task<OrderData> GetOrderDraftFromBasket(BasketData basket)
{
var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft();
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
var response = await _apiClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var ordersDraftResponse = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<OrderData>(ordersDraftResponse);
}
}
}
/// <summary>
/// Proxy class for the Basket API
/// </summary>
public class BasketApiClient : IBasketApiClient
{
...
}
Server proxy classes commonly used in Angular 2+ can also be spared by doing direct API calls with the Javascript version of Liquid LightApi.
Once again, quality comes from CI/CD/CT pipelines integrating them all.
Finally, of course one can continue using proxies (for remote services) into his/her code and still getting other general benefits from Liquid and even from its LightApi primitive.
But this prescribed way of doing it is believed the one that gives more simplicity and productivity to application development.