mercoledì 29 settembre 2010

WhiteCat: scheduling tasks depending on role events

I spent a few hours making what seemed a little change to the WhiteCat code, but that soon resulted in a very complex and refactoring-based change: implementing a task scheduler driven by role events.
WhiteCat already publishes role events when a role is assumed or released, based on that and on the last change on role tasks, the idea is to allow an agent to schedule the execution of a role task as soon as the role is assumed by another agent or before the role is released by an agent. The scenario this change covers is that of asynchronous inter-agent collaboration: an agent can ask another agent to do something once it is ready to do it. To get it simple, consider a scenario where a person goes to work, and assume an employee role; thanks to the scheduling another agent is able to "ask" the former to perform a phone call as soon as it is at the office (i.e., as soon as it assumes the employee role). It is like when you say "call me when you are in office" to a friend of yours, or at the opposite "call me before you get home".
Now to get into details, the scheduler is fully configured thru Spring and an agent can specify to the scheduler to perform a task specific to a role by a specific agent or by the first agent that is going to assume/release such role. Of course, the event the task must be performed will be specified at the time of the scheduling, so an agent has the following choice for scheduling a task:
  • the task to schedule (of course)
  • an agent that must perform the task or any agent that is able to do the task (i.e., any agent that is going to assume/release the role the task belongs to)
  • when the task must be executed (after the role assumption or before the role release)
This allows for new dynamic and collaborative solutions in the agent/role modelling! The current implementation exploits AOP to deal with the event dispatching and the task schedulation. Several changes have been done to all the system, starting from the task execution, that now has a task return type that wraps the result of the execution and implements a simple "future reply" pattern, the event dispatching, that now allows for notification of all events no matter of which agent id they are related to, role descriptors and repository, that now are more powerful for inverse role lookup and so on. During the coding several problems have been fixed, and new tests have been added to the code base.
Of course, all the code is available thru the git repository.
Drawbacks of this implementation are present, of course: the scheduling is related to a single role instance, and this could be fixed in future releases since it is based on the role repository. Moreover, it could be interesting to implement a real "do it for me" mechanism, where the execution of the task is totally in charge of the agent running the role (i.e., a pure message based system).

martedì 28 settembre 2010

Il peso dell'esperienza...

Anni fa ho realizzato un progetto Java piuttosto complesso, e successivamente sono arrivato a fare un refactoring dello stesso progetto per sistemare le cose che nel frattempo avevo compreso meglio, o che semplicemente potevano essere fatte con pattern differenti. Ebbene, il peso dell'esperienza si fa sentire: il diagramma delle dipendenze dei package mostra un chiaro miglioramento (linearizzazione) fra le due soluzioni. Se la prima ("inesperta") mostrava un groviglio di interdipendenze, la seconda ("esperta") mostra una chiara separazione fra i vari componenti.

Risultato analogo per le dipendenze delle singole classi, dove si evidenzia un numero minore di "allacciamenti" e quindi di legami forti fra le varie classi. Personalmente non considero molto i diagrammi di dipendenza delle classi, non perché non siano importanti, ma perché tendono a fornire risultati facilmente fuorvianti. Infatti aumentando il numero delle classi riducendo contemporaneamente la complessità di ognuna di esse (quindi tenendo la complessità del progetto costante) si vengono ovviamente a creare un numero di dipendenze maggiori. Inutile dire che queste dipendenze non sono "cattive", ma sono naturalmente forzate dal design del progetto stesso. Basti pensare alla programmazione per interfacce, ove ogni classe avrà una dipendenza con una o piu' interfacce. Ad ogni modo di seguito riporto i diagrammi con la situazione di dipendenza reciproca fra classi nettamente migliorata.


Infine una curiosità: il progetto nella sua prima versione si basava su AspectJ, proprio per ridurne la complessità. La sua seconda versione non ha ancora introdotto tecniche AOP (piu' che altro per mia pigrizia). Ciò non significa che AOP non serva, ma semplicemente che AOP permette di gestire anche un cattivo design.