These are chat archives for Ruhrpottpatriot/GW2.NET

24th
Sep 2016
Steven Liekens
@StevenLiekens
Sep 24 2016 12:22
I hope our code didn't put him off programming :D
I know I write bad code sometimes but I hope it's not bad enough to scare away beginners :D
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:06
I think it might have been my Haskell :smile:
But Haskell is... strange at first.
On a sidenote: I thought some more about HttpClient and came to the conclusion that directly implementing it will hinder us in the future
So I introduced two new layers
The first is the Connector class. This class offers three methods virtual Task<bool> Connect();, abstract Task<T> QueryAsync<T>(string query); and virtual Task Disconnect(). As you can see Connect(); and Disconnect() are virtual, so you don't have to implement them for connectors which don't support a persistent connection, such as HttpRequest against a REST api.
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:11
The second new layer is the AggregateRepositoty. This class takes n repositories and bundles them into one, much like the aggregate ResourceDictionary in WPF. A normal repository then only stores information about one particular url for the API. For example the ColourIdsRepository would query the v2/colors endpoint and nothing else.
The repository takes a Connector and a converter as usual, but it also exposes the string BuildQuery() method, which is passed to the connector to query stuff.
Currently it's a string, but I don't see why we couldn't change that to a completely new object which exposes the different query parameters the API offers.
This whole setup gives us the possibility to swap out the connecor for something different, e.g. a database connector for caching, or an SSH connector for stateful web connections.
Steven Liekens
@StevenLiekens
Sep 24 2016 15:22
you lost me lol
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:23
xD
Here's the order of execution:
  1. (optional) Connect with the connector class.
  2. Query the location defined by the Repository
  3. Convert the data into a useable format
  4. Return the data to the user
  5. (optional) Disconnect the connection
The AggregateRepository is the topmost layer of the application. This class offers methods and properties to query multiple underlying single repositories. E.g. the ColorAggregateRepository offers the user to query color ids and color objects via one repository. See HERE) for the idea.
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:30
Inside the AggregateRepository reside n single repositories, which each represent a single url endpoint of the GW2 api, such as /v2/colors or /v2/colors/{id}. A repository stores the path of the resource, how to query it and which additional parameters are valid (e.g. language).
The abstract Connector class is the objecto doing the heavy lifting. It opens and closes connections as well does data retrival. Each connector has to derive from the Connectorclass, with Connect and Disconnect being optional methods, since not every query has a persistent connection (REST calls for example can have the, but for security reasons they shouldn't have them).
The Connectorclass however can be anything besides simple http. It could be a file system connector, or a DB connector, too.
The user however only talks with the AggregateRepository or the Repositoryhe doesn't need to know how we make connections (aside from the connector class he gives us).
A bit more understandable?
Steven Liekens
@StevenLiekens
Sep 24 2016 15:37
I don't know how you want to control the lifetime of HTTP connections
isn't all of that stuff abstracted away?
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:38
yes that's the reason why the Connector class has Connectand Disconnectas optional methods
Steven Liekens
@StevenLiekens
Sep 24 2016 15:38
like even if you dispose HttpClient, the underlying connection is not closed until Windows decides it's no longer in use
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:38
because there are some connection lifetimes can't be controlled.
Steven Liekens
@StevenLiekens
Sep 24 2016 15:38
unless you use raw sockets :D
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:39
yeah
Steven Liekens
@StevenLiekens
Sep 24 2016 15:39
(which is one of my side projects)
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:39
which btw: was fun to program in University
we did it in C, but it was fun
writing your own webserver
Steven Liekens
@StevenLiekens
Sep 24 2016 15:40
mine's C# using streams to read/write HTTP messages
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:40
sounds nice, too.
but I introduced the additional layer of abstraction, because I don't want to be tied to the HttpClient class.
Steven Liekens
@StevenLiekens
Sep 24 2016 15:40
and TcpClient to provide the socket connections as streams
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:40
With that we can reuse the layout and only switch out the connector to implement caching
Steven Liekens
@StevenLiekens
Sep 24 2016 15:40
btw HttpClient is already an abstraction
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:40
i know
and strictly speaking you can access the FS by doing a get to a FS URI, but why should we do that?
btw: I want to make as many parts of the app side effect free
Steven Liekens
@StevenLiekens
Sep 24 2016 15:44
how many aren't right now?
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 15:44
the converters should be side effect free
but I'm not entirely sure about the repositories themselves
I need to look into that
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 16:23
question: Currently there are only two possible chars ({ or [) at the start of an api request, right? Or do we still have an endpoint with envelope?
Steven Liekens
@StevenLiekens
Sep 24 2016 16:25
huh
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 16:25
in V1 we had multiple endpoints who returned something like
"colors": { ... }
Steven Liekens
@StevenLiekens
Sep 24 2016 16:26
oh that
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 16:26
but in V2 we only get back
[{....}]
I need to know the first character, since I have to decide if we get back a collection or not
Steven Liekens
@StevenLiekens
Sep 24 2016 16:28
can't you use the endpoint url to decide that
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 16:29
i could, but I have a better idea
since I changed the layout, the connector does not need to know into which type we convert the data later on
and we have an X-Result-Count
also if I change the request url from e.g. v2/colors/{id} to v2/colors?ids={ids}, even if it's just one
I always get a collection back
so I just need to write a Slice object
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 22:06
This message was deleted
Robert Logiewa
@Ruhrpottpatriot
Sep 24 2016 22:12
Question: What do you think of a small DSL to describe queries? Here's the reason why:
Currently I have the ApiRequest class, which stores the resource's location and additional parameters. However we have many parameters which are only valid for a single node, e.g. signature, file_id and format are only valid for the render service. Of course we could add them to the ApiRequest object. However then we'd have many unused properties. We also could change the ApiRequest to only have the location and everything else is set via KeyValuePairs. But that'd mean passing around magic strings.
Your thoughts?