UI Software Architecture - MVC + Code Generation?

  • Follow


Hi,

I have an architecture question for designing a suite of rich client
applications.  The synatx is Java although there is little specific to
the language - I consider this a software engineering dilema.

What do you think of my solution as follows?

My general requirement is to avoid hand crafting each gui application.
Many are similar with a subset of controls others are using but
following a simple form data entry layout.  There will be more complex
interactions between controls to be scripted.

I have a data/business layer which ultimately creates objects, here is
a simplified one as example - there are getter/setters per field

public class PatientObject {
    private String patientName;
    private Date birthDate;
    private int genderId;
    private int locationId;
}

I have a table which lists the gui controls in use for each app:

control_id addAction         width height Text
1          addLabel            200     20 Patient Name
2          addPatientName      200     20
3          addLabel            200     20 Birth Date
4          addBirthDate        100     20
5          addLabel            200     20 Sex
6          addGenderId         100     20
7          addLabel            200     20 Location
8          addLocationId       100     20

I have an auto generated Application which will dynamically build the
controls

public class MyApp extends JFrame {
     private AppController controller;

     private addControls(ControlList controls) {
         this.patient = p;
         Enumeration e1 = controls.elements();
         while (e1.hasMoreElements()) {
              ControlObject co = (ControlObject) e1.nextElement();
              if (co.getAddAction() == "addLabel") {
                   addLabel(co);
              } else if (co.getAddAction() == "addPatietName") {
                   addPatientName(co);
              } // repeats for all the unique controls in the
                // the table above
         }
     }

     private void addPatientName(ControlObject co) {
         JTextField textField = new JTextField();
         textField.setWidth(co.getWidth());
         textField.setHeight(co.getHeight());
         getCurrentContainer.add(textField);
     }

     private void addLocation(ControlObject co) {
         JList list = new JList((ListModel) controller.getLocations());
         list.setSize(200,60);
         getCurrentContainer().add(list);
     }
}

I guess the addControls should use reflection rather than generating a
large method - but I like the compile time check against the table by
auto generating the method name.

The controller has the lookup lists, each implementing ListModel to
directly update the application model and trigger additional
application logic.  That works ok.

The part I am not thrilled with is that I have to map back text fields
back to the data model

e.g. in AppController
   private PatientModel patient;
   public void saveData() {
      patient.setPatientName(myApp.getPatientName());
      ...
   }

Ideally I could have a model for *every* GUI control - but the
javax.swing.text.Document looks too heavy for my datamodel to implement
for every field - so it seems better to map the data.

Any other thoughts on this architecture?

thanks

Tim

0
Reply timasmith (248) 12/26/2005 4:51:33 AM

Responding to Timasmith...

> What do you think of my solution as follows?
> 
> My general requirement is to avoid hand crafting each gui application.

One way to do that is to use a commercial window builder.  B-)

If you are driven by some masochistic tendency and actually want to 
build the GUIs yourself, my advice would be to do it the same way the 
commercial window builders do it: abstract the overall GUI paradigm 
invariants and relegate detailed differences in GUI design to 
configuration data.  The paradigm for a GUI is Window/Control (as 
opposed to specific business notions like Patient).  One can abstract 
the paradigm in a subsystem where the business semantics only appears in 
the form of externally defined title and label strings.  One then 
provides a pure message interface to the business layer that interprets 
identity into the GUI Window/Control objects.  (Think: DTOs.)  That 
identity mapping can be provided in an external configuration file.

If one does that, then one can reuse the GUI subsystem as-is across 
applications by simply providing an application-specific configuration 
file and interface.  That's because the Window/Control abstractions 
don't depend on the specific applications and how one talks to the OS 
window manager doesn't change; the only things that change from one 
application to another are the Window objects instantiated, the Control 
objects instantiated, the relationships between them, and the data 
initialized into their attributes -- all of which one can synchronize to 
specific business contexts across the boundary via configuration data 
for identity embedded in the interface messages.

[BTW, the interface should reflect the business view of user 
communication needs.  So think: GoF Facade pattern where the Facade 
class' implementation does most of the identity mapping (using the 
configuration data via lookup tables) when dispatching to 
Windows/Controls.  Thus the Facade knows that a pile of data values in 
the message data packet maps to a specific Window object and the Value 
attributes of its associated Control objects.  IOW, the business logic 
sends monolithic Patient data and knows nothing about how that is broken 
up into multiple GUI objects.]


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions  -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH



0
Reply H 12/26/2005 3:22:18 PM


timasmith@hotmail.com wrote:
> 
> I have a table which lists the gui controls in use for each app:
> 
> control_id addAction         width height Text
> 1          addLabel            200     20 Patient Name
> 2          addPatientName      200     20
> 3          addLabel            200     20 Birth Date
> 4          addBirthDate        100     20
> 5          addLabel            200     20 Sex
> 6          addGenderId         100     20
> 7          addLabel            200     20 Location
> 8          addLocationId       100     20
> 

Hard coding the pixel width and height like that is probably a bad idea. 
A better idea would be to go for slightly higher level properties.

It might be worth reconsidering putting the description in a database. 
Would writing the code in code not be easier, both in terms of 
implementing and updating? It also allows you to break the rules in an 
emergency. At least start that way.

> Ideally I could have a model for *every* GUI control - but the
> javax.swing.text.Document looks too heavy for my datamodel to implement
> for every field - so it seems better to map the data.

PlainDocument should be fine. If you write your model in this way, it 
makes it trivial to put everything together.

You should be able to end up with model code like:

public class PatientModel {
     private final Document name = new PlainDocument();
     private final DateModel birthDate = new DefaultDateModel();
     ...
     public Document name() {
         return name;
     }
     public DateModel birthDate() {
         return birthDate;
     }
     ...
}

View building like:

     form
        .text("Patient name", model.name())
        .date("Birth date", model.birthDate())
        .gender("Sex", model.genderID())
        .location("Location", model.genderID())
     ;

And some infrastructure along the lines of:

public class DateModel extends AbstractSimpleModel<Date> {
     // Need to copy values due to terrible design of Data class.
     @Override
     public Date get() {
         return new Date(super.get().getTime());
     }
     @Override
     public void set(Date date) {
         super.set(new Date(date.getTime()));
     }
}

Tom Hawtin
-- 
Unemployed English Java programmer
http://jroller.com/page/tackline/
0
Reply Thomas 12/27/2005 11:11:09 AM

I implemented a similar idea that automatically maps the gui fields to the 
data model using reflection.  I created a data entry control for each data 
type, so the type declarations look something like:

public class Contact {
  public TextAttribute FirstName = new TextAttribute();
  public TextAttribute LastName = new TextAttribute();
  public FormattedTextAttribute WorkPhone = new 
FormattedTextAttribute("'(###')' ###-####");
  public FormattedTextAttribute HomePhone = new 
FormattedTextAttribute("'(###')' ###-####");
....

Each "Attribute" includes one or more editors that are automatically 
extracted by the application framework, so the entire default gui is 
generated automatically based on the data model.  You can see some examples 
of the guis that are generated:

http://www.mammothsoftware.com/groovy_plugins/groovy_plugins.htm

and

http://www.mammothsoftware.com/screenshots.htm

Regards,
Mike 


0
Reply Michael 12/30/2005 10:11:04 AM

3 Replies
95 Views

(page loaded in 0.069 seconds)

Similiar Articles:










7/22/2012 4:40:07 AM


Reply: