Model acts as a central location to store data from ddic based on commands triggered by controller. It is crucial that only one instance of model exists through out the report execution ensuring all views and the controller itself access the same data. Because of this we don’t allow for a model instance to be created outside the model class. No class or report can’t create a model instance. But they can access a model static attribute (model=>instance) holding a model instance reference via a static model function (model=>get_instance). When called for the first time, model=>get_instance will create model=>instance as a model object and return it. Future calls will return model=>instance created in the beginning. This way, everytime model=>get_instance gets called it will return the same model instance. This design pattern is called a singleton. In ABAP you can set this behavior by making the instantiation type private under class properties window.
Custom data explorer is about:
- retrieving a table list based on table name and description: model->table_list
- selecting a table from the table list: model->current_table
- retrieving table fields:Â model->field_list
- generating a select where clause for the selected table: model->field_conditions
model->current_table is of type table_info
begin of table_info,
tabname type dd02t-tabname,
ddtext type dd02t-ddtext,
fulldescr type string, "combines tabname with ddtext
end of table_info .
At first glance it looks like we only need to perform a select statement on table ddo2t containing all the fields we need. But there are different table types within ddic and
only transparent ones (having the exact same structure with the underlying database table structure) can be reliable used on generating dynamic where clauses without raising exceptions (this comes from rfc FREE_SELECTIONS_DIALOG). Also, dd02t contains table description for each supported language. We can end up with a table list having the same
table twice, once with an english description, once with a german description. Taking the above into consideration we end up with something like:
select dd02l~tabname dd02t~ddtext into wa_re_tablist
from dd02l inner join dd02t on dd02t~tabname = dd02l~tabname
where dd02l~tabname like tabname and dd02t~ddtext like tabdescr and dd02t~ddlanguage = 'E' and dd02l~tabclass = 'TRANSP'.
Something similar is done for retrieving table fields, only this time we need fields with a valid inttype. Without a valid inttype rfc FREE_SELECTIONS_DIALOG won’t be able to display them in the begining. We also don’t want to display mandt table field, this one can’t be used in a user generated where clause and will raise an exception as well.
select * from dd03l into table re_flist where tabname = im_tabname and fieldname not in ('MANDT') and inttype <> ''.
The other methods within model are self-explanatory, don’t require further details.
Please keep in mind that model should not start to modify data in any way unless given instructions by the controller. Braking this rule will create lots of headache when troubleshooting your code. Instead of reviewing just controller code, you’ll have to review all views to see where model gets modified.
Taking the shortcut view-model instead of view-controller-model when modifying model data can be very appealing. It does have its uses in some cases but generally always update the model via controller, not directly from a view.
This post is part of Custom Data Explorer.