Skip to content

Instantly share code, notes, and snippets.

@sdoward
Last active March 27, 2019 14:31
Show Gist options
  • Save sdoward/77555de85d9b1529fec2a426dd857628 to your computer and use it in GitHub Desktop.
Save sdoward/77555de85d9b1529fec2a426dd857628 to your computer and use it in GitHub Desktop.
HomeCard Api Response
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
Copy link

acorbi commented Mar 20, 2019

Following the suggestion I made about "universal layout ids": Instead of type we would pass something like layoutId which would have value such as HC_IMPACT, HC_CAMPAIGN or HC_THE_TABLE.

Not a big difference with type in this case, just that it has a more global scope....

@sdoward
Copy link
Author

sdoward commented Mar 20, 2019

@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.

@sdoward
Copy link
Author

sdoward commented Mar 20, 2019

@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

@AlfredReisner
Copy link

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.

@sdoward
Copy link
Author

sdoward commented Mar 25, 2019

@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?

@AlfredReisner
Copy link

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.

@esoxjem
Copy link

esoxjem commented Mar 25, 2019

I would also prefer API versioning as it allows for easier evolution and it's also a standard way to approach this.

@acorbi
Copy link

acorbi commented Mar 25, 2019

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 ...)

@dfigueroa87
Copy link

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.

@hellmund
Copy link

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment