-
Notifications
You must be signed in to change notification settings - Fork 79
Elaborate on API philosophy #134
Comments
@JaredReisinger this is excellent. Sorry I'm just now circling back to follow up.
Yup. Passing the URL to
Since path portion of the default URI template is hardcoded, I'd put the URL in the service that uses it, even though it might have the same URI parameters as templates in other services. So in this case, putting it in the Teams service makes sense to me.
Til now, we've put the pagination burden on the consumer. I'm intrigued by
You've aroused my curiosity. team := octokit.Teams(myTeamId) Would
It might be worth having it in both places, with descriptive language in the |
Looks like this library hasn't received all too much love recently. The questions about the overall design philosophy are indeed intriguing because the current API is a bit unwieldy to grasp. I'd be more than willing to suggest alternative an alternative API topology to this that might be a bit easier to grasp and more compatible with the polymorphism mechanics and related features that Go offers. I'll probably make a fork of this repository and refer back to this issue thread with updates. |
(Related to #119, #31, and maybe #32.)
I'd love to contribute to this project (for the team-related APIs in particular), but it feels like there's a change in the overall design philosophy, and it's not quite elaborated anywhere. In particular, I have questions in a couple of areas:
When/where do specific URLs get used?
There's some inconsistency as to whether URLs should be passed to the "service creator", with
One()
andAll()
taking no parameters, or the inverse with no parameters to the service creator, and Hyperlink/param arguments onOne()
andAll()
. As a case in point (return values omitted for clarity):I suspect this simply represents a transition in philosophy: (a) is the service pre-seeded or not, and (b) does it take a URL or Hyperlink/param? Regardless, only one of these patterns should be used, and it ought to be consistent across the package.
Where should multi-resource URLs live? Where should wrapper implementations live?
One of the Team-related APIs is "get a list of team members", which returns a
[]User
. Should the URL live in theusers.go
file, or inteams.go
(which I'm working on)? From the viewpoint of "it returns[]User
, and is just parameterized URL which eventually gets toUsers().All()
, you might say it belongs inusers.go
. But this conflicts with the structure of the GitHub documentation, and of the "natural" feel that it's a Team-related API that "just happens" to return users. If the project is also moving towards a friendlier style of API wrappers (likeTeams().GetMembers(nil, M{"id": 123})
), then since the wrapper likely lives in the "calling" service, the URL probably should as well.What about pagination?
Every service seems to have an
All()
method, but it really only returns one page of results, and doesn't navigate/enumerate theresult.NextPage
links. I can kind of understand why the methods that take a URL have to be a bit agnostic about this, but it seems like there's a significant use-case for "I want all of the chained repos/users/teams starting from a given URL". In fact, that was my first expectation when I saw theAll()
methods; it wasn't until I looked at the implementation that I understood they really only return one page of data, not "all" of it. (One might argue that instead of One/All, it should be One/Some/All or One/Page/All whereSome()
(orPage()
) returns a single page of data, andAll()
accumulates by following the NextPage links.)A more fluent-style API?
From a programmer-usability standpoint, it seems a little weird to delay knowledge of parameters to the very end of the chain. In the team/members example, if I'm performing several operations on a team, it feels weird to have to remember to pass all of the replacement values at the end. I'd rather be able to do something like:
or even:
With API wrappers, this is pretty straightforward—
GetMembers()
andCheckRepository()
have a*TeamService
as the receiver, and this have access to its properties—but it does impact the way that other values are passed in; perhaps instead of a genericoctokit.M
, the wrapper functions should take explicit parameters. (I think this makes discoverability much easier for developers new to the API.) Note that the underlying URLs are never passed; they are completely encapsulated by the wrapper methods.Should this be in
CONTRIBUTING.md
?Answers to these questions could live in
README.md
, but they are really targeted at folks wanting to contribute to the project, so perhaps it makes more sense to add them toCONTRIBUTING.md
.The text was updated successfully, but these errors were encountered: