This seems to be trivial to me but I don’t know how to do it in Xojo.
I have this code in WebApp but I think it doesn’t matter if it was in DesktopApp.
Here is the code:
If mCurrentQuery.saved_query_id = 22 Then
mRepObj = New rep_022
ElseIf mCurrentQuery.saved_query_id = 137 Then
mRepObj = New rep_137
ElseIf mCurrentQuery.saved_query_id = 139 Then
mRepObj = New rep_139
ElseIf mCurrentQuery.saved_query_id = 141 Then
mRepObj = New rep_141
ElseIf mCurrentQuery.saved_query_id = 147 Then
mRepObj = New rep_147
ElseIf mCurrentQuery.saved_query_id = 175 Then
mRepObj = New rep_175
ElseIf mCurrentQuery.saved_query_id = 180 Then
mRepObj = New rep_180
ElseIf mCurrentQuery.saved_query_id = 179 Then
mRepObj = New rep_179
ElseIf mCurrentQuery.saved_query_id = 181 Then
mRepObj = New rep_181
ElseIf mCurrentQuery.saved_query_id = 182 Then
mRepObj = New rep_182
ElseIf mCurrentQuery.saved_query_id = 185 Then
mRepObj = New rep_185
ElseIf mCurrentQuery.saved_query_id = 187 Then
mRepObj = New rep_187
ElseIf mCurrentQuery.saved_query_id = 188 Then
mRepObj = New rep_188
ElseIf mCurrentQuery.saved_query_id = 190 Then
mRepObj = New rep_190
ElseIf mCurrentQuery.saved_query_id = 199 Then
mRepObj = New rep_199
ElseIf mCurrentQuery.saved_query_id = 202 Then
mRepObj = New rep_202
ElseIf mCurrentQuery.saved_query_id = 203 Then
mRepObj = New rep_203
ElseIf mCurrentQuery.saved_query_id = 204 Then
mRepObj = New rep_204
ElseIf mCurrentQuery.saved_query_id = 207 Then
mRepObj = New rep_207
ElseIf mCurrentQuery.saved_query_id = 209 Then
mRepObj = New rep_209
ElseIf mCurrentQuery.saved_query_id = 212 Then
mRepObj = New rep_212
ElseIf mCurrentQuery.saved_query_id = 213 Then
mRepObj = New rep_213
ElseIf mCurrentQuery.saved_query_id = 214 Then
mRepObj = New rep_214
ElseIf mCurrentQuery.saved_query_id = 215 Then
mRepObj = New rep_215
ElseIf mCurrentQuery.saved_query_id = 220 Then
mRepObj = New rep_220
ElseIf mCurrentQuery.saved_query_id = 228 Then
mRepObj = New rep_228
ElseIf mCurrentQuery.saved_query_id = 232 Then
mRepObj = New rep_232
ElseIf mCurrentQuery.saved_query_id = 233 Then
mRepObj = New rep_233
ElseIf mCurrentQuery.saved_query_id = 238 Then
mRepObj = New rep_238
ElseIf mCurrentQuery.saved_query_id = 239 Then
mRepObj = New rep_239
ElseIf mCurrentQuery.saved_query_id = 241 Then
mRepObj = New rep_241
ElseIf mCurrentQuery.saved_query_id = 242 Then
mRepObj = New rep_242
ElseIf mCurrentQuery.saved_query_id = 244 Then
mRepObj = New rep_244
ElseIf mCurrentQuery.saved_query_id = 246 Then
mRepObj = New rep_246
Else
mRepObj = Nil
End If
Basically I want to use redirection instead of explicit name of the class object.
Can someone please help me?
There is no direct support for this. You can make it easier through Introspection and a factory function, but at some point you have to register your classes somewhere.
Off the top of my head:
Sub Init()
Globals.Classes = new Dictionary
Globals.Classes.Value( 22 ) = new rep_022
Globals.Classes.Value( 137 ) = new rep_037
// etc.
End Sub
Function ClassFromID(id As Integer) As MyClass
var o as MyClass = Globals.Classes.Value( id )
// Use Introspection or some other method to create a new object
// from o and return it
End Function
This can be made more efficient in a number of ways, and has the advantage of cleaner code and a single place to register your classes, but nothing is going to get close to the performance of your IF statement, if that matters.
BTW, if you decide to stick with it, you can rewrite your IF as a SELECT CASE:
select case mCurrentQuery.saved_query_id
case 22
mRepObj = new rep_022
case 137
mRepObj = new rep_137
...
case else
raise new RuntimeException( "Unknown id" )
end select
where square bracket in the above would force the Xojo to evaluate the string as class object name (when programming in different language I would this approach at times).
btw, what is the limitation of number of cases in “CASE” statement?
I use “rep_” object to populate the WebListBox using DataSource.
The “rep_” stores the layout of the list and the corresponding queries (until I find a way to put the metadata into database itself). The app has several WebListBoxes used for displaying data, there is also report page that has several reports that get displayed in the same WebListBox only using different layout.
True, thare are different ways of doing things, but that is what it is, I am not going to change it now.
The question I’m getting at is, is there any fundamental difference (methods or properties) between the class rep_001 and rep_002 ?
If not, then there’s no reason to have separate classes; rather, you could simply define a single class, and then just keep an array of instances of them and reference them by index.
That would be possible of course to use array but my preference was to use object class:
easier to add/remove (code maintenance)
encapsulation
I would like to move the metadata into set of tables in the database at the appropriate time in the future, once in database the queries and layout could be pulled via single query using “id” in the where clause (aka reference them by index)
Well, it is as usual the “yes and no” answer I have.
I want eventually to move the metadata describing WebListBoxes including queries (make them build dynamically too) to the database out of the application.
At this point however, I was just hoping to refactor existing If/Else statement.
Well, as usual there are many ways to go about it. I would prefer storing raw data in relevant tables (normalized), then building queries dynamically before actually running them. At the same time I would separate application and user domains to facilitate customization of data output.
Object-oriented design and code encapsulation are good idea, but it’s also possible to get it wrong (by abstracting at the wrong level, or having an object model which doesn’t match the underlying data model).
I do a lot of database design, and whenever I see a pattern like this:
Person
EmailAddressField1
EmailAddressField2
EmailAddressField3
EmailAddressField4
[...]
it almost always means the model is incorrect and should be refactored. [In this case, if you have a large number of fields, they generally should be moved into a related table of their own (if you are using a SQL database) or put into an Array (if modeling the data in Xojo]
Your design, which isn’t using multiple fields but rather multiple classes is very very unusual!
I think you will regret this design and so I humbly offer advice to rethink it sooner, rather than later.
Edit to add:
Normalization is a very important idea in relational data design; but what I think you are describing here is basically the exact opposite of normalization.
Maybe, but I work with “live” legacy WebApp and I have to do my “scaffolding” when re-writing the code. This is simply an intermediary phase until I have all the reports and lists covered, hopefully until then Xojo engineers will also improve few more things pertaining to DataSource concept. Once there I will probably be able to move everything out of the object classes into database and eliminate the object classes altogether.
On the other hand I do understand why people took/take “shortcuts”. Proper relational database design requires thinking that one has to pay for and often decision makers have no desire to spend money on this. There are other reasons as well, of course.
Having said the above, at the end of the day the app (be it desktop or web) must be useful and profitable. If this is the case then everybody seems to be satisfied. Thanks for your coments and have a great weekend.