APPLICATION FRAMEWORKS IN THE REAL WORLD
Apostolis Bekiaris, Independent Software Consultant/Architect, Greece, Athens,
apostolis.bekiaris@gmail.com
Introduction
A real life framework allows a software developer to concentrate on business problems at hand without being distracted by the general activities of application development. DevExpress XAF is one of the leading frameworks in the market at the moment.
1. Advantages of using XAF
Typical Line of Business (LOB) application consists of Data Management, Validation, Analysis, Reporting, Scheduling, Localization, and Security system. Here is a traditional pattern that one has to follow to implement above mentioned system:
1. Create a domain model and use a data retrieval technique to connect it with data
2. Use advanced controls like grid, pivoting, layout, scheduling etc to render the data and allow the end user to interact with them
3. Bind your domain model with the user interface
4. Provide a layered and modularized architecture
5. Build a sophisticated configuration engine that can change the behavior of the application as the needs are changing is mandatory as well.
6. Apply a robust Security System
When using XAF [1] you don’t have to worry for any of the above, as they come as part of the package allowing a developer to concentrate on business model. A huge knowledge base along with hundreds of code samples, provided by DevExpress will also give a boost start to any scenario. Given the fact that XAF is a framework it also defines the architecture that should be used for your application, making things even easier for you. XAF is built on a standard three tier architecture (Fig. 1, left) and uses the MVC pattern (Fig. 1, right).
Fig. 1 XAF three-tier architecture (left) and MVC design pattern (right)
2. Disadvantages of XAF
XAF [1] is a multiplatform framework which, for the moment, targets windows and web applications. To do so it was essential to define a common layer between platforms. That led in introducing different components than the ones we used to work with in traditional development. For example instead of classic Forms (Windows, Web) you now work with Frames. As we move towards a platform specific environment, Frames change to WinWindows or WebWindows
9
accordingly ending up with classic Forms (Windows, Web). This set up is expected to produce a steep learning curve but the gains in productivity are well worth it.
2.1. Need for expansion
It is impossible for a framework to cover all scenarios. However the decoupling achieved through the MVC pattern and the event based programming that is used throughout XAF makes it one of the most extensible frameworks out there.
DevExpress has been targeting developers with their excellent suite for many years now. XAF on the other hand lives on the edges of the developer - business world. The DevExpress policy is to put all its effort in order to make a very extensible core and let us apply our business point of view by extending their framework.
2.2. Declarative development
Over time business needs changing, so your application has to adapt to those changes as well. Xaf Model was introduced for that reason. By extracting metadata from model-enabled classes, all parts of an application are described using *.xafml files (Fig. 2, left).
Ц1 MySoluthon
E-^} ActionDesign Е--Д BOModel E-[^ Creatableltems В-Д OetailViewItems S-1^ ImageSources Е”У Localization S--^ Navigationltems S-® Options B-H Views
Misc
У Company
У Copyright
^ Description
<=® Id Application
Logo ExpressAppLogo
PreferredLanguage (User language)
У ProtectedContentText Protected Content
У Subtitle
У Title MySolutton
У VersionFormat Version {0},{1},{2}
У WebSite
©
Mode type: DevExpress.ExpressApp.Model.IModelApplication
Properties of the Application node provide general information on the current application.
Fig. 2 The multi-layer structure of the Application Model (left) and Model Editor (right)
The structure of the model is based on a very sophisticated system that in its core creates dynamic classes and binds them to a state of the art Model Editor Component (fig4) by combining interfaces. Extending the XAF model is as easy as designing a new interface, decorating it with metadata and registering to the core system. Then when the application starts it will read the model and create all application parts at runtime. Basing the modelon interfaces is therefore what gives the user tremendous control to further extend that procedure.
3. What is eXpand Framework [2]
Being there when Xaf was born and already having years of experience has made it very easy for our team to understand how to apply the best practices and design useful and abstract modules. But we were not satisfied with having that knowledge hidden from the public. Given our experience and also gathering as much knowledge and ideas from the great minds out there, we have managed to design 51 well architectured and tested assemblies. In the next paragraphs you will read more about them
3.1. Taming the model beast
A XAF application is described over the XAF Model (Fig. 2, right) and persists the model into *.xafml files, so the most obvious business requirements raised instantaneously are:
• How to persist that model in a database
• How to control the model construction from each layers
• How to connect the model with other artifacts
• How to create more runtime layers
• How to conditionally load model layers
10
• How to save cookies in model layers
• How to allow power end user design the layout for all users and propagate those changes to all other users
• How to combine layers at runtime
To fulfill the above requirements eXpand introduces the ModelDifference module.
Fig. 3 Persistent Model Domain
In Fig. 3 you see a set of xxxDifferentObject business classes each one of which has the ability to persist a model layer in the database. By overriding XAF model loading process we can load each model layer that is stored on those objects. So all of the above requirements are now merely a matter of handling persistent objects by using the built-in XAF api. The requirements could be extended very easily to support more neat features like e.g. a multitenant system.
3.2. Pushing Development to the runtime
Models can now be created, loaded, unloaded, combined at runtime making very clear the need to simply map all the features to the model. By using the powerful model editor exposed by the ModelDifference module for each model layer, power users can develop declaratively at runtime (Fig. 4).
It seemed of primary importance to give the end users power to create runtime members. That proved an easy task, by deriving from the IModelMember interface. When a model member of that type is created a Xaf Type system was used to create the member at runtime.
The next step was to allow runtime calculable members and runtime orphan collection members. This was accomplished by deriving from the interface that is used for runtime members.
Fig. 4 Runtime Members Interface diagram
3.3. Runtime persistent assemblies - Creating a new World
A Xaf default model is created by reading all assemblies, indentifying the business classes and from them and their metadata constructing views and other parts of the model (Fig. 2, left). Thinking of that fact it can be understood that Xaf does not allow for a creation of new business
11
classes at runtime. To overcome that limitation eXpand mapped the structure of an assembly to a persistent domain like the following (Fig. 5):
Fig. 5 Diagram of a persistent assembly
When the application starts Xaf will automatically create a UI for the above domain, so that the end user can fill up the data (assembly names/class and property names/attributes etc) and an eXpand code generation/template engine will create assemblies based on that. By using .NET CodeDom namespace eXpand will compile the generated code, giving also scripting control over the compiled code. We named that powerful module that instantly persists and creates assemblies WorldCreator.
3.4. Retrieving data from external data sources
A common requirement for a business application is to be able to retrieve data from external data sources.
3.4.1. Multiple database connection
• In an ORM language this entails the need to map external database tables into
business classes. Designing a Mapping engine that would extract database schemata and
create business classes (С#) would be a solution to that requirement.
• Business application needs are towards a mechanism that can notify the system which database our mapped classes have to query. This was accomplised by implementing multi datastore assembly level attributes. Those tell expand framework in which datastore should persist business objects under a given namespace. Then a DataStoreManager requests the datastore level attributes and queries the datastores accordingly. After that eXpand could redirect queries for objects under a given namespace to different datastores.
• In eXpand world this means that we target the runtime. The structure of a persistent assembly along with the template engine was already implemented from our WorldCreator module. Using it we could create dynamic assemblies by extracting the schema of the database and use the familiar ORM technology to create business classes that represent that schema. As a final step we could apply the multi data store mechanism to the namespace of the dynamic assembly and allow XAF to connect to any legacy database at runtime! All of
12
the above are done transparently to the end user by the form of wizards - UI that XAF generate automatically.
3.4.2. IO mechanism
Up to this point it should be clear that by using XAF automatic data representation we can map any type of behavior. XPO which is the ORM that XAF is using although it supports serialization, remoting, web services etc. it does not provide any direct means of controling objects serialization. Apparently we had to define a type of serialization graph model Fig. 6 (left) and serialize our objects in a plain form as shown in Fig. 6 (right).
|5erializedObj ects>
<SerializedObject type=’,Person”>
<Property type=,,simple1' nane=1,oid” isKey=1,true”>880af229</Property>
<Property type^simple1' name^'Naine" isK.ey=’,true’,>Apostolis<,/Property> <Property type="object” nane=’,Address” isKey=”false">
<SerializedObjectRef type=”Address” £trategy=”SerializeAsObject" /> </Property>
<Property type="collection” nane=”PhoneNijinbers" isKey=’,false1,>
<SerializedObjectRef type =” Phone Mu iriber” strategy="SerializeAsValue”> <Key nane=”Phone”>0030 6946067340</Key>
</SerializedObjectRef>
</Property>
</SerializedObject>
<SerializedObject type=”Address”>
</SerializedObj ect> </SerializedObjects|
Fig. 6 IO Domain diagram (left) and XML serialization sample (right)
For the figure above XAF is going to create a UI. Then the end user can choose which type he wishes to export by setting the TypeToSerialize property. eXpand based on that value is going to search the current application domain and find all types that have a direct or indirect relation to it. For each property of each one of them ClassInfoGraphNode objects will be created. As can be seen in the diagram for each property the Serialization strategy can be defined. Object key definition, which by default corresponds to a database key, can also be set to point to another (non-key) field by modifying ClassInfoGraphNode's Key property. Having defined how a serialization graph can be controlled at runtime, we then used XAF types info system to enumerate through all types/properties of the graph and create an xml document. Importing process is much simpler because no graph is required, all configuration is part of the export. Thus, when importing we simply load everything that was defined in the xml document.
3.5. Applying Design Patterns
After familiarizing oneself with the declarative programming established by XAF it becomes clear that the same design patterns that stand for traditional programming can be applied by using the model editor graphical interface. And a business application is a perfect environment for such an application, for example if one wants to extend the behavior of his views with a set of attributes, by applying fundamental programming principles it is necessary to group them in a class similar to the next figure. We have group Attribute1,Attribute2 under IModelMyCustomClass and extend Customer_DetailView over that class (Fig. 7).
public override void ExtendModellnterfaces(ModellnterfaceExtenders extenders) { base,ExtendModelInterfaces(extenders) j
extenders.Add<IModelDetailVieWj IModelDetailViewExtension>()j
}
public interface IModeU-lyCustomCLassiIModelNode { string Attributel { getj setj } string Attribute2 { getj setj }
>
public interface IModelDetailViewExtension : IModelNode {
1,‘lodelFlyCustornCLass CustomCLass { getj setj }
>
Fig. 7 Applying Design Patterns
Having some IOC experience it can lead us further than that, since the design described above gives the control to the view and you want to create a class set some attributes and apply it to multiple views. Extending the application node (IModelApplication) instead of the detail view node (IModelDetailView) and adding some more contexts will make it far more flexible. Such
13
brainstorming has led eXpand framework to design an abstact architecture that can be used to map any behavior to the model. Part of that architecture is shown on Fig. 8.
Fig. 8 Logic Rule System Diagram
| Model.DesignedDiffb.xafml - eXpressApp Framework Model Editor
H t* Language j (Default language)
13d
Loaded Modules Show Unusable Nodes
DetailViewItems FilterDatBStoreSystemTables ImageSources Localization MasterDetail M ode lA rtrfa ctSta te 0 0 CoodrBorHlActioaState 00 ExecutionContextsGroup j- 0 FrameTemplateContextsGroup 00 Rules_______________________________
ы____________________
0 ViewContextsGroup 00 ConditionalControllerState ModulesList Haviga tfonltem s Options Validation
И
FI
Behavtbii
AcbonState
EmptyCriteria
FrameTemplateContext
FrameTemplateContextGroup
IsRootView
Nesting
NormalCriteria
View
ViewContextGroup
ViewType
Data
Any
City ='Paris'
ConditioralSaveDelete_Detailtfiew
$ Actionld Delete
9|t ExeaitfonContextGmup ConditionalSaveDelete
ф Modeklfass Customer
Module
| ConditionalDetailView } [Щ Creatableltems ^ DetailViewItems | FilterDatBStoreSystemTables f ImageSources | Localization | MasterDetail
p ExeeutionCoritextsGroup p FrameTemplateContextsGroup 30 Rules
DMDCustomer_Orders
0
ModelArtifactState
Apply conditional logic to the artifacts of your model (Controllers, Actions). It means that you can enable, disable, hide, execute etc. at many contexts or combination of them.
: :-0 ViewContextsGroup
ModelArtifactState
30 ModulesList
31 Havigatnnltems (+}Ф Options [+}•■*/ Validation
MasterDetail
Enables conditional master detail functionality over your list views. It operates at any level!!
EmptyCriteria
FrameTemplateContext All
FrameTemplateContextGroup
IsRootView
Nesting Any
NormalCriteria 1=1
View
ViewContextGroup
ViewType Any
$ ChitdLisWiew $ CoftectionMember $ ExecutjonContsxtCroup Default aflt ModefUass
9 Model.DesignedDiffsLxafnil - eXpressApp Framework Model Editor
UjjS Language | [Default language)
1й
Loaded Modules Show Unusable Nodes
ЭШ FeatureCenter
ActionDesign
00 AdditionalViewControls i ©0 ExecutionContextsGroup : i""0 FrameTemplateContextsGroup
I 00 Rules
I ;....ЯВШЯЙВЯИДВДМ1
........0 Conditional View Controls Posi...
: : :-0 Conditional View Controls Posi...
: : : - 0 Header Action Button Viewltem
: : : 0 Header Conditional Control A,,,
: ; ; - 0 Header Conditional DetailViews
: ; ;-0 Header Conditional Foreign K...
: : :-0 Header Conditional Save And ...
: : :-0 Header Conditional View Cont...
: : 0 Header Connection Info Status
: : 0 Header Continent Filter
; ! !-0 Header Controlling DetailView...
: ; ;-0 Header Controlling ListView S...
: : : - 0 Header Disable Edit Detail View
: : :-0 Header Disable Full Text For,,,
: : : 0 Header Do Not Load When N,,,
: : : - 0 Header Exception Handling
; ! :-0 Header Existent Assembly Ma...
........0 Header Existent Assembly Ru...
: : : -0 Header Expand Able Members
i : :■"0 Header External Aoolication D...
Appearance
BackColor Fonts tyle ForeColor Height
Behavior
EmptyCriteria
FrameTemplateContext
FrameTemplateContextGroup
IsRootView1
Nesting
NormalCriteria
NotUseSameType
Position
View
ViewContextGroup
ViewType
Data
1=1
All
Any
Orders.Count>7
False
Bottom
ConditionalControlAndMessageJJstView
ф CoatrofType NotAvaliablelnThisPlatform
ф DecoratorType NotAvaliablelnThisPlatform
$ ExecufjonContcxtGroup CondibonalControlAndMessage Message
MessageProperty ConditionalControlAndMessage
ф ModefCfass Customer
AdditionalViewControlsProvider
Place any Win or Web control on any given position in any XAF view and control its visibility, text decoration, font,height, width
etc using conditional model rules
Fig. 9 The architecture which is used extensively from eXpand
Parts 1-2 of the diagram (Fig. 8) shows a set of rule interfaces. They describe how various parts of the system can be connected. For example IConditionalLogicRule describes the connection with an instance of an object when Criteria attributes are evaluated or ILogicRule.TypeInfo describes the connection with a specific type. Part 3 shows a set of interfaces that are responsible for connecting a rule with a context. For example the IModelViewContexts can associate a rule with
14
a list of Views. Looking at the IModelExecutionContext can provide a clear example. XAF is based on an MVC pattern which means that there is a Controller class responsible for connecting the Model with the View. The controller exposes the system events. What has been done is create a base controller and subscribe to all system events. Then when an event is raised the XAF model is queried for all rules that have that event in their IModelExecutionContexts list and for the rules found we execute the controllers registered for these. We have named the module that provides that architecture Logic Module.
3.6. More Abstraction
A XAF application can be controlled - ruled in at least 4 different ways. Developing with metadata (Fig. 2, left), declarative development though model, code development with the Rule systems provided (XAF has a Validation, ConditionalEditor, ConditionalAppeareance and eXpand the abstract Logic Module) and also the system behavior can be changed by applying security permissions. From parti of Fig. 8 one can see that interfaces are not Model depended (they are not named IModelxxx). This provides enough abstraction to implement the same interfaces in attributes (metadata) so that the model can be created but also we can implement permissions with them. Furthermore since there are base controllers which work with rule interfaces and we want to support rule creation with code instead of having to deal with model, permissions or rules it is possible to create a class adapter that implements the same interfaces and transform our model, attribute and permissions to that. That architecture is used extensively from eXpand to design various modules like shown on Fig. 9. (Note the common attributes and structure defined by the logic module).
Conclusions
Due to page limitations it has been impossible to cover further issues that may arise. The goal of this article has been to present a personal point of view and experience on how a real world application should behave. Describing our work with such functional tools allows for a better collaboration between us, and most importantly it can hopefully create a bridge with the business community.
References
1. DevExpress eXpressApp Framework (XAF), http://www.devexpress.com/xaf/
2. eXpand Framework is first open source project based on DevExpress eXpressApp Framework (XAF), http://www.expandframework.com
PROTOTYPE OF NONENAVIGATION OBJECT QUERY LANGUAGE SYNTAX REPRESENTED AS XML-DOCUMENTS
Pavel P. Oleynik, Ph.D., System Architect, JSC Aston, Russia, Rostov-on-Don, xsl@list.ru
Extensible Markup Language (XML) is used to represent semistructured data, i.e. such as information, the structure of which is either unknown or will experience profound changes in the future [1]. Due to its flexibility, visibility and the existence of a large number of supporting technologies, the language is applied in the various tiers of the information system (on a DBMS server, a client application, an application server). The problem of representing the syntax of a query language (QL) to the data (e.g., SQL, OQL, etc.) is one of the challenges that appears while saving the information the structure of which is unknown a priori. The declaration of such a QL in the form of XML-documents allows to unify the process of data manipulation, which in this case does not depend on a specific data source (a file system, RDBMS, OODBMS, etc.), and allows to replicate this solution for various hardware-software platforms. Thus, there appears an opportunity to perform XML-queries in a heterogeneous environment by creating a mechanism of mapping syntax structures of this language on a specific QL, supported by the data source (SQL, OQL).
15