The API is composed of some classes (UserGroup, Namespace, General, Page...) and a MediaWiki class to access data.
Library architecture at the begining
The library is composed of a unique class: MediaWiki.
Synchronous or asynchronous?
Two choices are possible to develop the request management in the library: synchronous and asynchronous.
Synchronous way will lead us to use normal function call. But, since we expects the end of the function, the interface can freeze especially if there is a lot of latency. Moreover, this way will allow to not use signals.
Asynchronous way don’t block the interface because the application doesn’t wait the result of each request to execute the program. This method will lead us to use signals to access to the result.
On the one hand, use synchronous way will lead to use a QEventloop to avoid the freezing and a QNetworkAccessManager in synchronous mode. Otherwise, this way can involve the use of different threads in the application.
On the other hand, use asynchronous way will lead us to use signals and a QNetworkAccessManager in asynchronous mode.
To conclude, we choose the asynchronous one. Moreover, this method is the one used in the library architecture at the begining. But the asynchronous way give the problem of access to the result.
Get the request’s result
We can use three methods to get the result. First, we can develop accessors on each request classes. This way can cause risks of a call before the signal. This method use a synchronous call. A solution can be to specify this trouble in the documentation of the API.
The second method is to use a signal having the result as parameter. Use of signals, can meet the design pattern command. Indeed this pattern means that the query calls the action to perform, a slot, in the client. Also, this way respect the asynchronous semantic but the result is pass by value. The pass by value will be a trouble because it is something heavy. A possible problem will be that the copy is useless. A solution could be using pass by pointer, smart pointer or reference.
The last method consists in using a signal, like the previous way, which the result as parameter. This method respect the asynchronous semantic but the result is pass by reference. The problem is taht the visibility of errors by the slots is lesser.
To conclude, we choose to use two solutions. For the “attribute” classes, a good solution will be to use the first method. As for the “list” classes, the solution will be to use the second solution.
Develop Unique class vs multiple classes?
Two choices are possible to create the library: develop a unique class or multiple classes.
A unique class involves that all requests will be within. Another point is that there will be no memory management because only the destruction of the MediaWiki class would be sufficient to. Nevertheless, the presence of all requests hinders the code’s readability. Finally, use this way requires the application to handle a single request at a time.
Multiple classes will lead us to put one request in one class. This kind of development causes
an attentive memory management. On the other hand, this way improves the readability and especially allows to initiate some requests at a time.
Use a unique class means that all methods will be called in a normal way, for example for calling all pages we must do wiki->allpagesRequest(). We could find a way to allow the application to handle some requests but it will be quite difficult and take a lot of time. To improve the readability, we could put many comments in the code.
Use multiple classes leads us to pass a reference to a MediaWiki instance in the constructor of each classes. Finally, we have to define the objects life cycle therefore we will lead to manage the memory.
To conclude, we choose to use some classes because we think that calling many requests is important. Moreover, have a good quality code is a goal. This way is different from the development done at the begining. However, this method gives the problem of the objects life cycle and the memory management.
Objects life cycle
Technical contacts requirements
First, the technical contacts want a asynchronous interface: ”Even if you use a QEventLoop,you'll often need different threads in the application, and those can be a bitch. You can have a look at the current MediaWiki class to how those signals / slots should look like.”
Secondly, to call a request, the code should look like:
MediaWiki * mw = new MediaWiki(“mon_url”); mw->allpagesRequest(); connect(mw, SIGNAL(allpagesResult(QList<MediaWiki::Page>)), SLOT(allpagesProcess(QList<MediaWiki::Page>));
The MediaWiki class allows developers to call asynchronous request to access the MediaWiki data. For this, developers call a request like allpagesRequest() who send the request with the QNetworkAccessManager. To process the result, developers connect the signal allpagesResult() with his own slot. Because the class MediaWiki needs to emit signals, MediaWiki inherit QObject.
To avoid name conflicts with others libraries, we propose to define a namespace like silk::. mediawiki:: was a possibility but there will be a redundancy (mediawiki::MediaWiki).
For ensure the binary compatibility, we’ll use only a pointer to MediaWikiPrivate, which will contain attributes. In this case, modify the attributes doesn’t fail a class which uses MediaWiki.