-
-
Save sdoward/77555de85d9b1529fec2a426dd857628 to your computer and use it in GitHub Desktop.
sealed class HomeCard { | |
data class Campaign(val campaignId: String, | |
val imageUrl: String, | |
val videoUrl: String?, | |
val mapUrl: String, | |
val title: String, | |
val progress: Int, | |
val footer: Footer) : HomeCard() | |
data class TheTable(val imageUrl: String, | |
val videoUrl: String?, | |
val title: String, | |
val subTitle: String, | |
val footer: Footer) : HomeCard() | |
data class Impact(val numberOfMeals: Long, | |
val numberOfUsers: Long) : HomeCard() | |
} | |
sealed class Footer { | |
data class Simple(val icon: String, | |
val text: String) : Footer() | |
data class Friends(val friends: List<String>) : Footer() | |
} |
{ | |
"homeCards": [ | |
{ | |
"type": "impact", | |
"numberOfMeals": "38,000,000", | |
"numberOfUsers": "26,000" | |
}, | |
{ | |
"type": "campaign", | |
"id": "syria", | |
"imageUrl": "www.sharethemeal/com/syria.jpg", | |
"videoUrl": "www.sharethemeal/com/syria.mp4", | |
"mapUrl": "www.sharethemeal/com/map.jpg", | |
"title": "Syria", | |
"progress": "15", | |
"footer": { | |
"type": "simple", | |
"icon": "www.sharethemeal/com/comeicon.jpg", | |
"text": "help children now" | |
} | |
}, | |
{ | |
"type": "theTable", | |
"videoUrl": "www.sharethemeal/com/syria.mp4", | |
"imageUrl": "www.sharethemeal.com/syria.jpg", | |
"title": "Subscribe for monthly etc", | |
"subTitle": "monthly giving", | |
"footer": { | |
"type": "friends", | |
"friends": ["Alex","Arun","Matthias"] | |
} | |
} | |
] | |
} |
@acorbi I would imagine that we wouldn't use it has a layoutId. Essentially it would only be used to parse the Json into the corresponding data type. Further down in the stack we would map that to correct layout. The kotlin data class does contain that value as well but it could be removed. I will update the gist to represent that.
@acorbi The more I think about it more I understand what you are Arun were talking about. I favour Aruns perspective, sorry :)
I think it would be beneficial for the backend to be UI agnostic as much as possible. For example...
Imagine the backend sends the a layoutId "campaign1". It would expect the client to render as per Petras designs. What do we do if we then want to change the designs. Such as show the donate button inside the card and change all of the colors. With the universal layoutId we would have to send a different layoutId from the backend, "campaign2" for example. It would depend on the client version to which id gets served. Without the id there are no backend changes required.
Another example...say we want to open our api to a partner or we make an Android tv app. Are the new clients expected to use the layoutId to render how the backend tells it to? The AndroidTv app would likely have to be served different id then the normal app. Not serving this allows the client to render how they want and gives more flexibility to the system
Like the basic concept. Clear, easy to parse and the setup should be quite easy to be implemented. Would prefer a type
over a global layoutId approach since the level of abstraction will potentially go crazy again. Mandatory values should be defined, if one of them is changing (future implementations) the model needs a new version, if stuff is added it should be optional (supported only in versions that parse the optionals). In this way it is quite easy to maintain the whole infrastructure, update the codebase and keep support for legacy.
Notes here:
friends
should be an array of string like ["Alex","Arun","Matthias"]
Not sure yet if we should pack the properties related to the type in a data
object or keeping them in the same level within the tree. Need to think about it a bit more, but would potentially go for a data part, which also opens up more flexibility for versioning.
@areisner I updated the json to represent the string array properly. I added some optionals into the data type (represented with ? in kotlin)
With regards to versioning, I was under the understanding that fields can always be added but never taken away. If this is the case then we would always stay under the same version. Removing fields and changing data structures would require a new version meaning a new endpoint.
With this in mind I am not sure how having an internal data
object could help. Can you elaborate how it opens up for flexibility?
Sure, there are in this way two options for potential versioning. Either custom data
objects as data
, datav2
or sth. or potentially a new endpoint, which is more clear in this way. ;)
Everything else seems to be fine.
I would also prefer API versioning as it allows for easier evolution and it's also a standard way to approach this.
hey everybody, so instead of having a universal layoutId
on all responses, you are advocating for a type
attribute which is unique in the context of each content type (HomeCards, NewsFeedItems, etc...) right?
If that is the case, that is fine for me. This naming convention can actually also be adopted by the design team while doing the mockups ( as in hey! how far are you guys implementing the support for homecards of the campaign
type ...)
I totally agree with not having anything related to how to display things in the backend responses.
The gist looks good to me, I'd just change the id
field to be campaignId
, since otherwise being in the root of a homeCard element seems to be its id. Also I'd like to avoid any use of theTable
as an identifier replacing it for just subscription
or something like that, since it's more generic and representative name and doesn't bind us to a name that potentially could change.
Finally I wonder what's the benefit of having different types of footers, or what does a friends
footer means. But we can discuss which types are needed there in the next meeting.
Some additional comments:
// general
- I'm advocating to keep more of the strings in the backend rather than loading them as part of the overall app localization, for better maintenance and for keeping the app localization slim
- I'm recommending to create re-usable structures to ease re-usability across endpoints
// overview homecard
- needs map image
- numbers should remain integers so the clients can use count-up anims
// campaign homecards
- need itemId when clicked on info-i for more info
- footers: version with commodity icons missing
- footers: version with friends should rather contain properties for images and formatted string (unless the backend wants to take care of Arabic plural concatenation of names and the like)
Following the suggestion I made about "universal layout ids": Instead of
type
we would pass something likelayoutId
which would have value such asHC_IMPACT
,HC_CAMPAIGN
orHC_THE_TABLE
.Not a big difference with
type
in this case, just that it has a more global scope....