Saturday 17 December 2011

question on Stack Overflow recently gave me an opportunity to give an overview of the approach I am adopting in my personal system development project.  My answer, including a summary of the original question is reproduced here. 
"So my question is, has someone already done this work and found (or even half found) a structured way to extrapolate an appropriate metaphor or heuristic for a set of given programming problems?"
I may have the start of an answer to your query. This consists of multiple levels of abstraction; descriptions of multiple domains; and the application of "modelling" techniques in a particular way - really rather different from what is normally done in modelling. The overall approach is, I believe, what you are seeking - it gives metaphors that are operated on, and then translated into the actual result. It is based on a number of published approaches, and relies heavily on some of these approaches and methods. 


What follows is subject to these caveats: 
  1. This is very much "work in progress". 
  2. I have been on the receiving end of derogatory comments that I am an "architecture astronaut", with the consequent implication that I am out of touch with the nitty-gritty of real system development. This is one of the reasons this is work in progress - my current project is designed to validate this concept, and demonstrate that it has real utility. In order to do this I need to develop a system of sufficient scale and complexity, using my approach, that would normally be out of reach of an individual developer. I am only part way through such proof of concept development. 
  3. While the concepts I describe are derived from consideration of complex problem domains (sonar contact tracking system, and chip design systems), my examples relate to a simpler domain - basically an information system, constrained by a rules system. The rules base includes not only rules about the domain, but also rules about the applicability of other rules. I suspect, from your question, that I am coming to it from the opposite direction to you. You ask for a way to extrapolate an appropriate metaphor or heuristic for a set of given programming problems - which to me implies starting with the programming problems. My impetus has been from the analysis side - trying to find and formulate ways of describing a proposed system so that it can be implemented as a real system. 
  4. When I use the words "model" and "modelling" I mean modelling as described below. This description is somewhat different from common usage of these terms. 
The three main constituents needed for this approach are: 


Multiple domains 
My definition of a domain is wider than that normally adopted: A domain is a separate real, hypothetical, or abstract world inhabited by a distinct set of objects and phenomena that behave according to rules and policies characteristic of the domain. In problem analysis.the domain is a useful unit of consideration when developing complex systems. Under this definition, there are multiple domains for consideration within a system, Often when developers refer to a domain, they mean the problem (or application) domain (referred to hereafter as P). However for this approach, any aspect of the system, or system development is a potential subject for modelling. This includes the system architecture (A); system production artefacts (code, make scripts, database schemas, etc) (C); DBA functions; etc. To approach P via metaphor requires development of several such domains - relating to the metaphor and transformations from the metaphor to a model of the real world, or to the code realisation of the real world in the developed system. When multiple such models are developed, they are all developed to the same degree of scope and precision. 


Multiple levels of abstraction 
To describing a problem and system, one models not only P, but also models appropriate higher levels of abstraction. Thus the metaphor chosen to describe P is modeled (M). In a similar way, the formalism of A (F) is modeled, and if deemed necessary the transformation process between P and C using A (R). So one abstracts the problem domain; abstracts the abstraction and so on. The application of multiple models is similar to colour separations - they lie on top of each other, and the system has to meet all the descriptions (the "complete picture") of all the layers. Again this differs from common ways of modelling which tend to meet such multiple requirements by elaborating the original model to take in the different constraints. This has particular implications when all of the architecture domains are effectively applied to all the elements of all the problem domains. 


Modelling 
What I mean by modelling differs from more usual approaches to modelling in the following respects:

  • The subject matter of the model is highly likely to be different from domain to domain. This contrasts with modelling where initial models are elaborations of other models. 
  • Indeed, one test of the validity of a model is that it represents an extreme version of the DRY principles - if something is defined in more than one place, it indicates a deficiency in the model. This extends to all domains under consideration, so the way the system is built is defined only in one place. 
  • A domain, once modeled, is likely to be fairly static. The higher the level of abstraction, the less likely it is to change. 
  • The scope of a model is likely to be much narrower, and much deeper than those conventionally developed. There are likely to be fewer objects within a particular domain than in conventional modelling; but these models must be complete and there are tests which give some indication of the completeness of the model (obviously, one can never prove that a system description is complete). 
  • P is described in terms defined by M. The model might be expressed as diagrams, OO representations, mathematical formulae, or whatever is appropriate for the domain M

The following example, derived from my proof of concept project, may give some flesh to my descriptions above. I list some of my domains, together with candidate contents of the domain models. 

  • P [Vehicles, units, movements, exhaustion, speed...] 
  • P1 [Rules, applicability, states, priorities...] (a subsidiary problem domain) 
  • M [Object types, attributes, relationships, domains...] 
  • A [Events, tables, columns, database domains, classes...] 
  • F [Persistence mechanism, processing,.....] 
  • C [Database schemas, source code, SQL scripts, build scripts,....] 
  • R [Formalisms, transforms, mappings...] 
The sources for this answer are many and varied, but do rely heavily on works by: 
Michael Jackson on structured programming; system analysis; and problem domain descriptions. 
The Shlaer-Mellor method of system development by transformation rather than elaboration. The Kennedy-Carter method consultancy.

Saturday 12 November 2011

System generated and managed user input forms

Most of my system work so far has been purely architectural - establishing the way the system is to be constructed, and the overall structure of the system.  This work has led to a style of programming that separates out interfaces and their implementation. My system runs until it needs data from the user; at which point it runs an input form, and retrieve data from it. It was obviously going to be trivially easy to go from the architecture to implemention of a running system. This was a statement of the blindingly obvious that proved not to be so.

My final implementation eventually proved simple, but the route to the solution was long and tortuous. I eventually investigated the Delphi concept of component ownership; the nature of Windows processing loop; the behaviour of modal forms; how to implement callback functions; and how to implement an interface based system controlling Delphi forms.

My initial approach was a naive, direct implementation of the architecture, The code illustrates that naive approach. The only problem is that it doesn't work! As explained by one of the answers I obtained from StackOverflow:
it doesn't allow the user to provide any input before it retrieves the content of TForm6.Edit1.Text. You basically say:
Create the form
Show it to the user
Immediately read whatever was set at designtime in the form's Edit1.Text
In addition, this basic formulation is not exactly what I wanted in terms of the architecture. The secondary form is called from the main form; I want it to be called from a unit rather than a form. It does not separate out the interfaces from the implementation in the manner I want, and if the example were to be scaled up, there would be a memory leak on each invocation of a new form.

So I started investigating and experimenting. My first exploration was the above question to StackOverflow. The preliminary response to this led me to investigating the use of modal forms rather than non-modal. I came to the conclusion that this was not an option - this has the side effect that a modal form blocks all keystrokes to the application, which blocks the application from creating new tasks. I did come up with a workaround to this particular problem. The use of modal forms also did not seem to meet my inferred requirements from the architecture I have derived.

My intended system
An grossly simplified overview of my overall system structure is:
A number of tasks can be run by the application. Each task applies a particular tool to an object. In order to obtain any needed user input the task may run one or more user interfaces (UI). These UIs are of varying complexity from a simple selection form to a multiple page wizard type interface taking a very substantial degree of information and user interaction. Each task needs the full information from its UI before it can proceed or complete. Each task may be sufficiently complex that the user may need to start another task before completing the first one, in order to get relevant information or provide updates to existing objects. The application does have its own UI, but this is minimal, providing a task/object selection only. All the work within the application is delegated to the individual tasks.

Example  
Using my example modules, one might wish to parse an XML version of a document concerning the Russian trip schedule. When selecting the document it is evident that the trip schedule needs editing. In order to correctly edit the trip schedule, the user needs to view the Moscow hotel booking.

I am currently programming one of the tasks, to prove that the overall structure is feasible, and to act as a template for subsequent development and code generation.

I am trying to produce the overall system in an extremely DRY (Don't Repeat Yourself) manner (perhaps I should call it ARID (Architectural Responsibilities In Design/Development)). As such I expect much of my eventual system to be described in domain specific languages, which I am also developing, and be produced by generators and templates which again form part of my overall development.

The UIs will be created, destroyed and managed by the task. In this respect, the manager is acting as a controller of the UI. The application needs to be able to run other tasks concurrently.

The above considerations have lead me adopt an programming approach based on interfaces, implemented by objects in Delphi - in particular, the UI as a Delphi interface, implemented by a TForm.

The point is still, though, that you have to allow the user a chance to provide input before you can retrieve it.

Other Approaches
As I continued to investigate I encountered other approaches. In no particular order they were:
  1. Use Show and have the form pass back information (via some mechanism like PostMessage or an event handler when the user clicks a button to let you know there's data to retrieve.
  2. Build reference counting into an enclosing TInterfacedObject object that includes the form.
  3. Build reference counting into a TForm descendant.
  4. Build each task as a separate process - which I understand is costly in terms of system resources and performance, on a Windows system.
  5. Have the implementation object be a wrapper to TForm and implement the event handlers for the TForm in the wrapper. Incorporate a delay loop function in the event handlers for all the relevant events.
  6. Use callback functions in the unit controlling the form.
  7. Use delegate as a keyword in the interface declaration.
Problems and obstacles
  1. Callbacks - the parameters of a callback function have to be derived from TObject rather than integers, booleans, interfaces, or other strucutured types.
  2. Callbacks - most of the resources I could find explaining callbacks used examples that had the callback function called from the code that initalized the callback. It took me a while to realise I had to split these two parts - set up the callback, run the form, and then call the callback function.
  3. Callbacks and Interface wrappers - I kept tripping over the the cyclic reference problem of Unit A needing to call Unit B which needed to call Unit A. This repeated in various ways as I experimented with callbacks.
  4. Interface wrappers - I hit an infinite regress: - if I seperated the form from its interface, then I needed a callback from the form; and if that was seperated out......
  5. Unit controller - trying to switch control of the form from another form to a unit shows that the controlling object needs to be derived from TComponent. This ensures that the TForm descendant is owned by something that will hook into the form management routines correctly.
  6. Windows processing loop - In order to use Delphi's implementation of the window's processing loop, all forms need to be ultimately owned by TApplication. This requires use of TApplication.CreateForm - either directly in Application; or indirectly via ownership by a TComponent, which is itself owned by Application (using TComponent.Create(Appliction)).
  7. TForm creation - the procedures used for communication with the form have to be  published rather than public - if they are only public the form will not display - for reasons I have not fully investigated.
My solution
My solution defines
  1. Two interfaces: IResult - defined to carry the required data from the form to UserInput; and     IUserInput - obtain user input from a form in an IResult. 
  2. Two creator functions - one for each Interface
  3. Implementation of the interfaces - one object for each interface, and one for the actual user input form.
Example code for this solution is attached. The example has not been extended to ensure that clean up is done correctly, and the form event that makes the information available is the closing of the form. In a real situation it would probably be a user triggered event.

The UserInput interface is a little odd since the sole property of the interface, UserInput, is a write only property - the intention being that property is filled by the user input; and implies that the appropriate setter needs to have been called before use is made of the interface. I am still not completely comfortable with this, though it does seem to be a solution to the issues I faced.