Wednesday, September 11, 2013

Prototype web app using Dart M5

I just completed porting of a sample app DartExpenseServer project associated with chap 14 of 'Dart in Action' to Dart M5.
Although I started this as porting effort to Dart M5,  I ended up rewriting whole code.
The reason was the original sample app was not fully functional and not well designed as a realistic database application.

DartExpenseServer_v1.tar.gz

This sample project will be useful to start writing realistic web app.
It demonstrates basic idioms to write client/server side web application.
Namely the basic patterns of HttpRequest in client side, and HttpServer/HttpClient in server side as well as new bidirectional asynchronous WebSocket based communication method.
Also this covers basic CRUD operations over CouchDB through HttpClient in Dart. The adaptor class was made into a generic class so that it can be used to access different entity classes.

  • supporting CRUD operation in browser client app.
    Original sample did not support delete operation. and Also the entity id handling was unrealistic hack. This was fixed by using CouchDB's id generation feature.
  • supporting websocket which allows to push an event to multiple connected clients as well as asynchronous calling(by sending message) to server.
    this feature is used to updating the number of currently connected clients to all clients from server, and synchronizing list item changes to other browsers (web clients).
    this is actually using HttpClient to update the change to server, and server use websocket to the changes to all other browsers.

    But this type of communication mechanism is not almighty. sometime we want to receive message from server after sending message. For this purpose, we can use HttpClient as explained in next item.
  • HTTPClient usage for create/update/delete/read operations.
    The original Sample code was using persistent id created in a client side and used websocket to communicate with server for saving an object in database. this may be OK  to simplify code, but it is not realistic solution.
    If we want to insert(save) a new row in  a database, that db may generates the id, and we need the id in the client side.
    In such a case, websocket based message passing is not effective way. Since the websocket listener in client side has no knowledge over which object was saved in database. it may just receive this id, and it needs to find the  saved object in client side memory. but unless client side maintains local ids for the temporarily transient objects, it will be impossible to find such object.
    In this case, we should use HttpClient instead of websocket.
  • CouchDB access using server side HttpClient, this supports CRUD operations.
    there are not much good source of information for how to use CouchAPI from http level, I needed to several trials and errors and need to find some trick to achieve CRUD operation.
  • supporting both Dartulium and JS execution. (JS was not working before)
    Since Dart has a bug for handling Element.html, I need to find workaround to have the same result on both clients.
  • Since there were many layer and several problems, debugging were not easy.In particular, logging info by print function from client and server side cleared other side of output, so essentially there are very few info remained the terminal.
    So I switched to use logging library of Dart. This is also mandatory practice in Dart app.
Todo list
There are still a few things to be done even this level of app.

  • some common library dart file should be properly packaged.
  • Although this need not be done for this sample app, but it will be interesting to use Polymer for making GUI. This will be an another project.
  • CouchDB is a bit special DB, it is sort of cloud type DB. It is interesting to replace this with PostgresSQL. there is a driver for Dart now. 
  • When we write a code using websocket, code for sending message/receiving messages are splitted in client and server side. and it will become difficult to maintain  them  consistent.
    Since Dart support same language in both server/client, the nature is better than other approach using totally separate language on each sides. For instance, these websocket message names should be defined as constants in shared files. There may be more approach for this.

Since there are so many change in Dart, this application needed a lot of change.

  • Big change of HttpRequest, HttpClient etc.
  • difficulty to understand/use CouchDB through REst API(associated with choice for put/post/get, and handling of responseText etc) 
  • bugs in Dart(setter bug, Element.html bug) and some design  pattern of modeling and websocket.)
  • no logging lib feature original code.
Some of these issues came from the obviously early state of language development.

Interesting aspects of Dart is the new way to write asynchronous program.
Future is quite powerful idiom.
Also the new Stream library in M5 support more seems less use of Future.
If you compare the original DartExpenseServer code with the new Stream based code, you will see the difference.
In new version we don't need to use Completer class(almost).

I will describe these issues in separate posts.

No comments:

Post a Comment