DOA

A New Architecture for Building Better Frameworks


At its core, software is about exchanging, storing, and processing information. DOA (Data Oriented Approach) therefore focuses on clearly and simply defining and modifying what information a system should display, share, transform, and store.

It happens that there's already a programming concept that handles these tasks very efficiently: classes and objects from the object-oriented programming paradigm. DOA simply complements conventional objects with the necessary information to make them automatically managed by interface and storage components. These modified objects are called elements. Thus, defining or modifying a system only involves defining or modifying these elements and making them available to the automated fundamental components that will use them.

Development and changes are faster because we leverage encapsulation to our advantage and unify all information about a single concept in each element-type class (and therefore in a single file). Other software development paradigms fragment and repeat this information across multiple files, views, migrations, routes, models, etc., which become difficult to understand, create, manage, and update. For example, adding a new field in DOA takes just one line in one file, while in other frameworks it might require modifying multiple files.

MVC

DOA

The main implications are:

- Many of the most common changes in software development, such as adding, removing, or modifying fields, involve modifying only one point in one file. This dramatically simplifies and speeds up creating and modifying systems

- DOA elements remain objects and maintain their encapsulation, abstraction, inheritance, and polymorphism characteristics. That is, they maintain their advantages: modularity, reusability, maintainability, ease of modeling real-world problems, and scalability. Additionally, for those already familiar with object-oriented programming, the learning curve is minimal.

- Interface and storage objects can work with any element. This takes interoperability and reusability to trans-systemic levels. The classes for storing data in MySQL, Oracle, Mongo, Coach, Excel, etc., and the classes for presenting them with HTML, XML, Windows Forms, Qt, SwiftUI, etc., can be transparently and "instantly" used with elements from any system. Thanks to this, changing the interface and/or storage technology is almost immediate.

Metadata

The key to DOA is providing interface and storage classes with the necessary information to do their work automatically. This is achieved by adding that information to elements and data.

SC_Element

All classes derived from SC_Element have methods to obtain the following information:

*: automatically derived from the class name, but customizable if needed.

Additionally, objects derived from SC_Element have built-in permission and relationship systems.

SD_Data

All classes derived from SD_Data have methods and attributes to register and provide the following information:

*: Automatically derived from the attribute name, but customizable if needed.

**: Automatically provided by the elements.

Structure and syntax

DOA was created to simplify information management in an application. The main way to do this is by concentrating everything related to a dataset in Element-type classes, seeking a balance between brevity and clarity. Therefore, most of the information needed to manage an element is specified in its constructor, and much of it is implicit in the class itself or the data syntax. For example:

class AE_File extends SC_Element { .. . function construct() { $this->id = new SD_AutoIncrementId(); $this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL'); $this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S'); }

These lines tell the framework that elements of type AE_File:

- Should be stored in the AE_File table:

class AE_File extends SC_Element {

- Have id, user, type, file, and description.

$this->id = new SD_AutoIncrementId(); $this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL'); $this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S');

- The id, user, type, file, and description in the database and for the system are called id, user, type, file, and description.

$this->id = new SD_AutoIncrementId(); $this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL'); $this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S');

- The id, user, type, file, and description in the interface and for the user are called id, User, Type, File, and Description.

$this->id = new SD_AutoIncrementId(); $this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL'); $this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S');

- Only the user and type should be displayed in lists.

$this->id = new SD_AutoIncrementId(); $this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL'); $this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S');

- The user, type, file, and description should be displayed in the search form.

$this->id = new SD_AutoIncrementId(); $this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL'); $this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S');

- And the respective classes SD_AutoIncrementId, SD_ElementContainerDropBox, SD_ElementContainer, AD_File, SD_Text; imply the data type and that all data except the ID should be displayed in views, creation forms, and update forms. Each class also indicates how they should be displayed in each situation.

The standard constructor signature for data is:

public function __construct( $label=null, $flags=null, $val=null, $filterCriteria=null )

Label: Indicates how the data will be displayed to users in the interface.

Flags: Indicate when the data will be used.

The first letter of the following English actions is used:

Each SD_Data subclass already has these values predefined, but they can be altered with a character string in the constructor. If a lowercase letter is used, that data type is disabled for that action; if an uppercase letter is used, it is enabled.

The predefined strings for our example would be:

vcUslRFe - for SD_AutoIncrementId.

and

VCUslrFe - for the rest, which is why to appear in the search box, S was sent; and L for user and type to appear in lists.

Val: Allows setting an initial value.

Filter criteria: Determines how it will be read in DB searches.

Thanks to inheritance, all kinds of data variants can be generated, but in Simplon there are generally four types.

Generic data: Data that is directly reflected in the data store; by default appears in the view and in creation and update forms. Some of the types are: text, email, date, integer, number, and option selection. File and text in our example.

$this->file = new AD_File('File','S'); $this->description = new SD_Text('Description','S');

IDs: Fields to distinguish elements in the data store; there are auto-incremental, numeric, auto-generated string, and string. The auto-incremental is ideal for SQL DBs.

$this->id = new SD_AutoIncrementId();

Element containers: Option selectors, but where the selection is of other system elements. This allows, for example, Users to have Roles or in our example, files to have type and user.

$this->user = new SD_ElementContainerDropBox(new SE_User(),'User',null,'SL'); $this->type = new SD_ElementContainer(new AE_FileType(),'Type',null,'SL');

Complex data: Data composed of other data, so it generally doesn't appear in forms nor is it stored or read, although by changing its flags it's possible. This data allows us, for example, to show the full name by concatenating first and last names, calculate volume by multiplying length, width, and height, and calculate age from birth date.

$this->birthDate = new SD_Date('Birth date'); $this->age = new SD_TimeSince(['birthDate'],'Age','Years');

It's primarily for this data that the Fetch flag exists and that elements register in the data that is their parent element so they can access other parent data as in the example. This way we can, for example, assemble the full name from First and Last Names or show age from birth date.

Interface

Allowing users to give and obtain the information they seek in a simple and clear way is key to a system's success. To solve the challenge of generating a user interface from SimplonPHP Elements, it relies on rendering modules like SR_htmlJQuery and the objects that complement them: SI_Item and its subclasses. At the time of writing this documentation, only SR_htmlJQuery exists, but technically it's possible to generate interfaces for WPF, Qt, terminal, and even proprietary interfaces like SwiftUI simply by adding new rendering modules and interface items without modifying either the framework structure or system elements.

General Overview

When initializing, Simplon reads the main interface class to be used and prepares to load all corresponding interface items. Elements and data generate use interface items to generate their interface. Thus, if using the SR_htmlJQuery Renderer, when making the call to generate new items, it will be the items corresponding to htmlJQuery. For example:

class SC_Element extends SC_BaseObject { function showCreate(){ $content = new SI_VContainer(); $content->addItem(new SI_Title(static::$CreateMsg,4)); … .. .

In the method that shows an element's creation screen, it starts by creating a vertical container and then adding a title to it. By loading the SI_VContainer and SI_Title classes that correspond to the type of interface we want to show, we can change the interface type without having to modify elements or data.

NOTE: At the time of writing this documentation, given its WEB development origin in Simplon PHP, there are still some terms, functions, and code fragments in the interface items very linked to HTML, CSS, and JQuery. This will be removed for version 1.0. See RoadMap.

Permissions

An essential part of information management in a system is controlling who can view, modify, and/or register it. In Simplon, this is also managed in element classes through the $permissions array of each element, with the following structure:

'admin' => array('*'=>'allow'), 'user' => array( ''=>'accessibleWhen_CurrentUserId_=_user', 'View'=>array( ''=>'accessibleWhen_CurrentUserId_=_user', 'user'=>'fixed_CurrentUserId', ), 'Admin'=>array( 'user'=>'fixed_CurrentUserId', 'updateAction'=>'viwableWhen_user_=_CurrentUserId', 'deleteAction'=>'hide', ), 'Search…..

Each role is the key to an array of permissions for that element for the role.

'admin' => array('*'=>'allow'), 'user' => array( ''=>'accessibleWhen_CurrentUserId_=_user', 'View'=>array( ''=>'accessibleWhen_CurrentUserId_=_user', 'user'=>'fixed_CurrentUserId', ), 'Admin'=>array( 'user'=>'fixed_CurrentUserId', 'updateAction'=>'viwableWhen_user_=_CurrentUserId', 'deleteAction'=>'hide', ), 'Search…..

Each role's permission array is an array whose keys are wildcards, method families, or methods, and whose content contains the applicable rules for each Data (for that user and method/method family/element).

The possible wildcards are:

Method families are groups of functions related to specific operations in the system:

Methods generated in each class can be directly included by name in the permissions or in the instance's method family array copy.