Tuesday, August 23, 2005

Model

Newsgroups: borland.public.delphi.oodesign
From: "Joanna Carter \(TeamB\)"
Date: Wed, 28 Apr 2004 10:20:48 +0100
Local: Wed, Apr 28 2004 5:20 pm
Subject: Re: Who's watching who?


I have managed to determine that the Model is there essentially to provide a set of rules and validations for anything that may happen to the Value object it maintains.

e.g.

ICustomer = interface
function GetCode: string;
function GetName: string;
procedure SetCode(const Value string);
procedure SetName(const Value string);
end;

TCustomerModel = class
public
class function ValidateCustomer(const Customer: ICustomer): Boolean;
class function StoreCustomer(const Customer: ICustomer): Boolean;
class function DeleteCustomer(const Customer: ICustomer): Boolean;
...
public
constructor Create(const Customer: ICustomer);
function GetValue: ICustomer;
procedure SetValue(const Value: ICustomer);
end;

If someone changes the Value object held in the Model, then the Model notifies the View that the whole display is invalid.

If someone changes an attribute in the Value object, then the Attribute notifies the Value object that it has changed as well as notifying the edit view that is displaying it. Subsequently, the Value object notifies the form view in case there are other aspects of the form that need updating like buttons/menus that need enabling/disabling.

The Model seems to play very little part in mediating between the Value/View/Value; it is rather there as an extension of the Value object. This means that the basic description of, say, a Customer can remain the same, but the effects of handling a Customer can be modified in the Customer Model without affecting the Customer itself.

Newsgroups: borland.public.delphi.oodesign
From: "Joanna Carter \(TeamB\)"
Date: Tue, 4 May 2004 15:36:19 +0100
Local: Tues, May 4 2004 10:36 pm
Subject: Re: Who's watching who?

ICustomer = interface
...
end;

TCustomer = class(..., ICustomer)
// class (static) data and methods
...
// instance data and methods
...
end;

IMVPModel = interface
function GetCommandSet; ICommandSet;
function GetCurrentSelection: ISelection;
end;

TMVPModel = class(..., IMVPModel)
...
end;

TCustomerModel = class(TMVPModel)
// class (static) methods
class function Validate(const Customer: ICustomer; out Errors:
IErrorList): Boolean;
class function Store(const Customer: ICustomer): Boolean;
...
// instance data and methods
GetValue: ICustomer;
end;

Newsgroups: borland.public.delphi.oodesign
From: "Joanna Carter \(TeamB\)"
Date: Fri, 25 Feb 2005 13:15:01 -0000
Local: Fri, Feb 25 2005 9:15 pm
Subject: Re: MVP Questions


More correctly, The Model holds a Value which can be anything from a simple value type like Integer or string to a business object. The Value will have its own rules and logic; the Model can hold additional rules and logic where those rules extend the effects of the Value beyond the limits of the Value.

e.g.

SalesOrder
This is a valid Value and all the rules that pertain to internal handling of a Sales Order like totaling lines, discounts, etc are implemented in here.

SalesOrderModel
When a Sales Order is created/altered it also affects the Customer and Product classes; the code to govern the outside interactions resulting from, say, storing a Sales Order should be in a static method of the SalesOrderModel class

Newsgroups: borland.public.delphi.oodesign
From: "Joanna Carter \(TeamB\)"
Date: Tue, 16 Mar 2004 14:13:21 -0000
Local: Tues, Mar 16 2004 10:13 pm
Subject: Re: Hiding public elements

In the case of MVP, I use Interfaces to define business domain behaviours: Customer, Order, Invoice, etc.. This allows me to create classes that not only implement the business interface but that can also implement metadata and identity behaviours, not normally visible to the application programmer. This ability to treat an object in different ways, depending on the POV is possibly what I find most attractive about interfaces from a design perspective. The business classes may seem a bit like pure data classes, but, in fact, they also contain consequential effect and calculation code.

Now when it comes to the Model part of MVP, I have now improved how I see this working. This next bit may ramble, but see if you can make sense of it :-)

You need a Model to correlate the Value object, the Selection and the Command Set.

You need an instance of a Command Set within the Model which will make available appropriate Commands for an instance of the Value type, dependent on the User, Security, Scenario, etc..

The Command Set may need to see more than just the Value type (e.g. Customer) in order to build itself, and it is this need to see outside the Value type that I believe is beyond the remit of the standard Value type classes.

The Model can be said to represent a Use Case or Scenario; and the use of the Model allows the Scenario to change without necessarily changing the Value type.

Whereas, methods like Store and Delete definitely don't belong in the Value type, I do believe they are valid methods of the Model. But they should be class methods that take an instance of the Value type as parameter.

This allows the Model class to have 'command' methods which can be called from within the Command Set and that are related to and strictly typed to the Value type that the Model contains.

So you would have:

IOrder = interface
property Number: string;
Customer: ICustomer;
Lines: IOrderLineList;
...
end;

TOrder = class(TInterfacedObject, IOrder)
// implements IOrder
end;

TOrderModel = class
class procedure Store(const Order: IOrder);
class procedure Delete(const Order: IOrder);
class procedure DeleteLine(const Order: IOrderLine);
...
end;

Methods like Delete and Store have consequences, in that the Customer's balance will have to be adjusted as well as the Stock levels of the Products included in the Order Lines; it is these side effects that seem to fit very nicely in the use of the Model to enforce rules that apply not to an instance of a Value type but to the type itself.

In any case, feel free to pull apart this ramble :-))

Comments: Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?