Sometimes you find a use case that has a simple and elegant solution in a particular programming language. It might come from a question in conversation, or a requirement in a project on the table. The nature of elegance in code defies firm definition, but as a famous Jurist once said, "I can't define it, but I do know what I like."
One characteristic I usually find in what most observers might call "elegant code" is brevity. Fewer lines of code mean fewer places for a software fault to lurk. DataWeave certainly lends itself to brevity, even nearly to the point of compulsion.
Recently, a student of mine raised a question after doing one of the standard exercises in the MuleSoft Developer series using DataWeave. His question surfaced a typical use case for an API.
We had just finished a Walkthrough that has us observe how to filter the elements of an Object given a list of desired fields.
His idea was to allow a query parameter that listed the fields being requested. If an API interface enumerates the fields that may be requested, the input can be easily validated.
Once we walked through the idea, we ended with a single line of code that completely handled the task. Follow our logic, and see if you find the outcome to be elegant, or simply brief.
The invitation offered an opportunity for everyone in the class to fine tune their understanding of DataWeave, so we began with this understanding from the RAML:
#%RAML 1.0title: Flight Info Selectorversion: 1.0.0
/records:description: Flight record(s) masked to selected fields onlyget:queryParameters:element:description: |Parameter may appear one or more times with each request.Any of the fields named here may be requestedenum:- price- flightCode- availableSeats- planeType- departureDate- origination- airlineName- destinationresponses:...
This implies that we might submit our request as:
When such a request is received by an API with its interface generated by APIKit, the router will validate any inputs named "element" for membership in the enumeration. Or to say it more simply, the input validation can be built into the interface from just this much of the API specification.
Now let's do a better job of articulating the use case:
%dw 2.0
output application/json
/*
* Use case: My API consumer will be presenting me with a
* collection (ie. array) of queryParameters that name
* the subset of fields needed to satisfy the request.
*
* We must dynamically calculate the fieldMask and apply it to the
* Object we return.
*/
So let's start with a view of the model object. This is the structure we need to mask before presenting it in our response.
//model object
var ogObject = {
"price": 750.0,
"flightCode": "A134DS",
"availableSeats": 40,
"planeType": "BOEING 777",
"departureDate": "Apr 11, 2018",
"origination": "MUA",
"airlineName": "Delta",
"destination": "LAX"
}
An array with the full set of field names (or Object keys) can be had easily enough.
// fieldSet - ie. pluck $$
var allFields = [
"price",
"flightCode",
"availableSeats",
"planeType",
"departureDate",
"origination",
"airlineName",
"destination"
]
To set up an experiment that will allow us to create our approach, we could use simulated input.
//simulated input
var message_attributes_queryParams_FIELDS = [
"price",
// "departureDate",
"origination",
"destination"
]
var message_attributes_queryParams_FIELDS = attributes.queryParams.*element
//model object
var ogObject = {
"price": 750.0,
"flightCode": "A134DS",
"availableSeats": 40,
"planeType": "BOEING 777",
"departureDate": "Apr 11, 2018",
"origination": "MUA",
"airlineName": "Delta",
"destination": "LAX"
}
ogObject -- ["price","planeType"]
(ogObject pluck $$) -- message_attributes_queryParams_FIELDS
ogObject -- ((ogObject pluck $$) -- message_attributes_queryParams_FIELDS)
No comments:
Post a Comment