rOpenGov / fmi

Finnish Meteorological Institute open data API R client
Other
10 stars 7 forks source link

Is there a need for more conventional API for the package? #14

Open jlehtoma opened 7 years ago

jlehtoma commented 7 years ago

Currently fmi's architecture (as well as rwfs's) is very object-oriented (OO). Implementation is done using R's R6 object system. While this does bring all the benefits of OO in the code architecture (inheritance, encapsulation etc), it does produce a rather un-idiomatic interface to users. Consider creating and using the FMIWFSClient:

library(fmi)
request <- fmi:: FMIWFSRequest$new(apiKey=apiKey)
request$setParameters(request="getFeature",
                      storedquery_id="fmi::observations::weather::daily::timevaluepair",
                      starttime="2014-01-01T00:00:00Z",
                      endtime="2014-01-01T00:00:00Z",
                      bbox="19.09,59.3,31.59,70.13",
                      parameters="rrday,snow,tday,tmin,tmax")

client <- fmi::FMIWFSClient$new(request=request)
layers <- client$listLayers()
response <- client$getLayer(layer=layers[1], parameters=list(splitListFields=TRUE))

For anyone coming from proper OO languages, this (object methods access) is intuitive. For anyone only accustomed to R, this may be confusing. More idiomatic (i.e. functional programming) API would look something like this:

library(fmi)
request <- fmi::wfs_request(apiKey = apiKey)
request <- fmi::set_parameters(request = "getFeature",
                               storedquery_id = "fmi::observations::weather::daily::timevaluepair",
                               starttime = "2014-01-01T00:00:00Z",
                               endtime = "2014-01-01T00:00:00Z",
                               bbox = "19.09,59.3,31.59,70.13",
                               parameters = "rrday,snow,tday,tmin,tmax")
client <- fmi::wfs_client(request = request)
layers <- fmi::list_layers(client)
respones <- fmi::get_layer(layer = layers[1],  parameters = list(splitListFields = TRUE))

Not a high priority IMHO since the current implementation works, but worth considering. The latter API could be implemented on top of the current architecture without the need to re-write everything.

Opinions? @torsti @antagomir @muuankarski

torsti commented 7 years ago

Hmm, could we somehow have a session function to set the API key and provide a set of convenience functions to retrieve and list data and hide how that is done?

Implementation-wise thinking of requests and clients makes sense, but does the user really have to interact with request and client objects, whether function based or R6?

Not really strong opinions either way, though...

jlehtoma commented 7 years ago

Hmm, could we somehow have a session function to set the API key and provide a set of convenience functions to retrieve and list data and hide how that is done?

Implementation-wise thinking of requests and clients makes sense, but does the user really have to interact with request and client objects, whether function based or R6?

request and client objects are pretty standard patterns in lower level programming, but you're right, regular user doesn't really need to be concerned with these. I guess we could equally well provide a high-level API like this:

fmi::api_session(apiKey = apiKey)
weather <- fmi::get_weather_data(starttime = "2014-01-01T00:00:00Z",
                                 endtime = "2014-01-01T00:00:00Z",
                                 bbox = "19.09,59.3,31.59,70.13")
wind <- fmi::get_wind_data(starttime = "2014-01-01T00:00:00Z",
                           endtime = "2014-01-01T00:00:00Z",
                           bbox = "19.09,59.3,31.59,70.13")
...

and hide the implementation under the hood.

ouzor commented 7 years ago

I've also thought about this and considered it only as limitation in my knowledge :) But I think hiding the client / request stuff would be good for a typical R user.

On Wed, Sep 7, 2016 at 11:46 AM, Joona Lehtomäki notifications@github.com wrote:

Hmm, could we somehow have a session function to set the API key and provide a set of convenience functions to retrieve and list data and hide how that is done?

Implementation-wise thinking of requests and clients makes sense, but does the user really have to interact with request and client objects, whether function based or R6?

request and client objects are pretty standard patterns in lower level programming, but you're right, regular user doesn't really need to be concerned with these. I guess we could equally well provide a high-level API like this:

fmi::api_session(apiKey = apiKey)weather <- fmi::get_weather_data(starttime = "2014-01-01T00:00:00Z", endtime = "2014-01-01T00:00:00Z", bbox = "19.09,59.3,31.59,70.13")wind <- fmi::get_wind_data(starttime = "2014-01-01T00:00:00Z", endtime = "2014-01-01T00:00:00Z", bbox = "19.09,59.3,31.59,70.13")...

and hide the implementation under the hood.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rOpenGov/fmi/issues/14#issuecomment-245215867, or mute the thread https://github.com/notifications/unsubscribe-auth/ABK-iv52LHW-F7vWvetlindxlQVsCmcHks5qnnoCgaJpZM4J2pNn .

jlehtoma commented 7 years ago

Started working on this in architecture/new-api-branch, see e.g. api.R

jlehtoma commented 7 years ago

Branch architecture/new-api-branch is now merged to master in 0.2.0. Future developments should be based on the new API design, discussion can continue in this thread so I'm keeping it open for the time being.

jlehtoma commented 6 years ago

On a second thought, I probably prefer just re-writing the whole thing. I opened a new issue #30