Lately I have been talking with a lot of my mid-tier developers about how to structure the APIs in order to better accommodate the 2-way binding that AngularJS offers. We have been trying to decide whether or not the APIs should be very explicity with their definitions which would work better w/Angular but cause a little more work for the mid-tier or be more implicit and have extra logic in Angular to "massage" the data into a good Angular model.
Lets start with an example. Suppose we are talking about some sort of data backup service. The service allows you to backup data and retain the data for X number of years OR indefinitely. The UI has 2 elements to control this logic. There is a <select>
that allows the user to select whether or not they want to delete the data "Never" or "After" X years. If "Never" is selected then we hide the years input, but if "After" is selected, then we show the years input and allow them to input a number between 1-99.
Doing this I have introduced 2 different element controls, each controlling a different property on the $scope
model.
However, on the API my mid-tier guy wants to control all of this using a single property called "YearsRetention". If YearsRetention == 0
then that "implicitly" means that we want unlimited retention, but if it is set to anything> 0 then retention is set to that value.
So basically he wants to control the retention settings using this single value, which would force me to write some sort of transformation function in order to set values on the $scope to acheive the same effect in the UI. This transformation would have to happen on both incoming and outgoing data.
In the end, I want to know if the API should be defined implicitly (API sends a single value and Angular will then have to transform the data into usable view model) or explicitly (API sends all values needed to bind directly to the UI and reduces the need to transform the JSON)?
-
Sorry if it is kind of wordy.. it is hard to summarize my question in a concise manner. I can re-iterate on something if need beMatt Hintzke– Matt Hintzke2014年12月02日 20:21:50 +00:00Commented Dec 2, 2014 at 20:21
1 Answer 1
I think there are 2 bad ideas in the designs you describe.
- Defining the data structures based on UI convenience. This is a bad idea because you want your API to be clear, multipurpose (supporting different clients with different UIs potentially), and long-lived (API refactoring is operationally expensive). Instead, try to accurately and concisely represent your data in the purest, most accurate, most generalized form, and leave presentation issues such as formatting, truncation, localization, units of measure, page layout, etc to the UI.
- Overloading a single data field to express a concept that it doesn't naturally model by way of a "magic value". Assigning extra semantic meaning to the number zero is an example of this, and it's generally regarded as error prone and confusing and a leaky abstraction. Every client will have to encode the magic semantic that zero means forever. Of course, there's the glaring cognitive dissonance that the true meaning of zero would be "not at all". I'd model this as 2 fields, an enumeration called
retentionPeriod
allowing exactly 2 values: "PERMANENT" and "YEARS" and a separate field perhapsretentionValue
to store the integer representing the years. If you end up losing the argument with your back end developer, I'd at least argue that the magic value should be -1 meaning forever instead of 0. (I also thinknull
matches "not at all" more than "forever" which is why I think -1 is the least-bad of the bad magic options. There is some precedent out there for this, at least)
In your specific case I'd argue one of your UI drop-downs would control retentionPeriod
and the other would control retentionValue
. But my reasoning for this is not because it happens to pair up with your current UI implementation in a straightforward way (that's more of a happy coincidence), it's because it's a clearer representation of the data.
That said, in my experience this specific instance is fairly mild in it's badness. I'd be much more strongly concerned about incorrect choice of array vs object, vague or confusing naming, gigantic data structures, overly chatty APIs, etc.
5 Comments
null
instead of 0 or -1 to mean forever.