Question Performance question on a tool library

Hello,

I'm actually working on the education community

Basic OpenEdge Developer Learning Path and Certification Exam .​


Very good lesson by the way.
In this we learned that loading procedure in persistent allowed to save on performance because every time we called the procedure, she is already load in memory in contrary to just call the procedure.

I didn't done the part on OOP and will do it soon.
But with some experience on other programming langages it usually recommended to use class object.

On the side I'm building a big procedure library with many fonction for our use. And I would like to segment it and made it more easy to use.

What do you recommand?

Best Regards,

BobyIsProgress
 
On the side I'm building a big procedure library with many fonction for our use. And I would like to segment it and made it more easy to use.
Some more detail is required about the problems you are trying to solve.

What does "segment it" mean to you? It sounds like a solution that you envision to some problem. If so, what is that problem?

The same goes for "more easy to use"? Easier than what? What usability problems are you experiencing or envisioning?
 
I'm kind of old-school so I still create my libraries as persistent procedures that set themselves to be session super procedures, i.e.

Code:
session:add-super-procedure( this-procedure ).

when they are instantiated.

I have recently decided to take steps to explicitly ensure that only one copy of each such library is running. That is probably an indication of poor planning somewhere else in my code base but that's a topic for another time ;)

FUNCTIONs have to be declared with an "in super" but are otherwise simple to call. I have a dot-i with all of the function definitions in it. If you want to call them you just need to include that dot-i in your code. Not much different than using a C header file for similar purposes.

PROCEDUREs in such a library don't need any special syntax like "in super" or a handle. You just RUN them.

I suppose that I could group the procedures and functions in various ways but, in my case, there aren't enough of them that I feel like that would be much of a benefit. I am also fairly certain that most running sessions will end up loading most of the groupings I could come up with so it seems reasonable to just go ahead and load everything right away and for it to all be available. (I have not actually analyzed if that is true or not - it is just a gut feeling.)

So I have two main libraries/groups - functions that require a db connection and those that do not. I also have two smaller libraries that are specific to certain functions but, looking at them, they really could be merged into the others pretty easily. One of them is used quite a lot. The other would be an exception to my gut feel above, it is only used in one specific case (and, therefore, probably shouldn't even be a persistent library).

Could this all be OO?

Yes it could.

Would that be "better"?

Not obviously. At least it isn't obvious to me that it would any better.

If I were writing more OO ish code I might feel differently though.
 
Also... your title says "performance question"... but if you are asking something about performance I am failing to see it.
 
Some more detail is required about the problems you are trying to solve.

What does "segment it" mean to you? It sounds like a solution that you envision to some problem. If so, what is that problem?

The same goes for "more easy to use"? Easier than what? What usability problems are you experiencing or envisioning?
It's not that I have an issue to solve.

Performance is not the right word after reading your reply. Could be more like best-practice to implement tool library.
Today I have a big procedure file that generate popup-menu for browse, export tt in file, run some program to minimize the call, and many different things. So by segmenting it I mean I would like to create smaller procedure library to ease the code maintenance.

Thank you @TomBascom for your detailled explanation :)

Best Regards,
 
PROCEDUREs in such a library don't need any special syntax like "in super" or a handle. You just RUN them.
I shiver when seeing public procedures in library code, anything in library code should at least be a function that complains at compile time.

You probably have a good reason for these abominations?
 
I shiver when seeing public procedures in library code, anything in library code should at least be a function that complains at compile time.

You probably have a good reason for these abominations?
Quite harsh but I understand.

Why? The reason is simple I never received a proper formation on openedge and I'm currently following the courses on progress Education community. Has a self-made developper on progress, I learned by reading and observing code developp by the vendor of our ERP and so I replicate there way of code.

Now with more experience and more knowledge in progress and over languages I've doubt about the way I did it. This why I wrote this topic in the first place.
 
Quite harsh but I understand.
My reply was aimed at Tom's remark, Tom can handle harsh.

Using functions with an in super forward declaration prevents adding comments to code as to where you hope / expect it will run.

Code:
run foo ( 'bar' ). // foo is in the session super util library

Versus a central function declaration:

Code:
function foo logical ( character ) in super.

Which is then used as:

Code:
{ util/foo.i }

foo( 'bar' ).

The central function declaration can also serve as a central point of documentation:

Code:
// foo is a great way to do nothing
function foo 
   logical  // did foo do nothing?
   ( 
      bar as character // provide where you can get your beer
   ) in super.
 
@Stefan , I understand a bit why you would promote function instead of procedure. But how you do when you have to return more than one value with different data type .

For me this
Code:
DEF VAR myInput AS CHAR.
DEF VAR myCase AS INT.
DEF VAR outPut1 AS CHAR.
DEF VAR outPut2 AS DATE.
DEF VAR outPut3 AS DEC.

RUN myProc (INPUT myInput,INPUT myCase,OUTPUT outPut1,OUTPUT outPut2,OUTPUT outPut3) .

Is more readeable than this:

Code:
DEF VAR myInput AS CHAR.
DEF VAR myCase AS INT.
DEF VAR outPut1 AS CHAR.
DEF VAR outPut2 AS DATE.
DEF VAR outPut3 AS DEC.

DEV VAR list AS CHAR.

list = myFunction(myInput,myCase) .
ASSIGN
    outPut1 = ENTRY(1,list)
    outPut2 = DATE(ENTRY(2,list))
    outPut3 = DEC(ENTRY(3,list)) .


I'm learning so it's possible I missed something in my statement.

Best Regards
 
@Stefan , I understand a bit why you would promote function instead of procedure. But how you do when you have to return more than one value with different data type .

Code:
DEF VAR myInput AS CHAR.
DEF VAR myCase AS INT.
DEF VAR outPut1 AS CHAR.
DEF VAR outPut2 AS DATE.
DEF VAR outPut3 AS DEC.

RUN myProc (INPUT myInput,INPUT myCase,OUTPUT outPut1,OUTPUT outPut2,OUTPUT outPut3) .
I would avoid concatenating various data types or various values in a single character (unless no other option). If doing so you need to be much more careful when serializing / deserializing the values, your decimal for example will silently break when the numeric format is European (decimal comma).

Fortunately, the parameters of a function, whose default is input, can also be input-output or output. When returning multiple values you may want to promote the main output as the return value, or a logical indicating failure / success.

Code:
myProc( myInput, myCase, output outPut1, output outPut2, output outPut3 ).

Code:
function myProc returns logical (
   myInput as char,
   myCase as int,
   output outPut1 as char,
   output outPut2 as date,
   output output3 as dec
):
   // do something
   return true.

end function.
 
First of all, these days I would never have one big procedure with everything in it. I would have a few that are split out based on function and use and only load the one(s) I want when needed. Otherwise you're carrying around a lot of bloat for no reason at all.

There are some distinct advantages to writing the code in OO. The biggest one for me is the compile time checking of parameters. This is similar to compile time checking of function definitions but doesn't need the same hoops for definitions.

Secondly, OO allows overloading of method definitions so the same method can be called with different parameter patterns. This makes things a lot easier when dealing with complex logic.

OO also allows you to create static classes that don't need instantiating. This can be very useful for simple things where you just want to quickly call some functionality to return a calculation or some such.

Proper OO programming also has principles baked into the paradigm around how to split out code into logical groupings too. 4 Principles of Object-Oriented Programming | Khalil Stemmler.
 
You beat me to it, James! I was just about to point out that biting the bullet and making the transition to OO would make most of these issues go away while providing a cleaner and more well-structured environment.
 
I would avoid concatenating various data types or various values in a single character (unless no other option). If doing so you need to be much more careful when serializing / deserializing the values, your decimal for example will silently break when the numeric format is European (decimal comma).

Fortunately, the parameters of a function, whose default is input, can also be input-output or output. When returning multiple values you may want to promote the main output as the return value, or a logical indicating failure / success.

Code:
myProc( myInput, myCase, output outPut1, output outPut2, output outPut3 ).

Code:
function myProc returns logical (
   myInput as char,
   myCase as int,
   output outPut1 as char,
   output outPut2 as date,
   output output3 as dec
):
   // do something
   return true.

end function.
I didn't know that . I will work with that.


First of all, these days I would never have one big procedure with everything in it. I would have a few that are split out based on function and use and only load the one(s) I want when needed. Otherwise you're carrying around a lot of bloat for no reason at all.

There are some distinct advantages to writing the code in OO. The biggest one for me is the compile time checking of parameters. This is similar to compile time checking of function definitions but doesn't need the same hoops for definitions.

Secondly, OO allows overloading of method definitions so the same method can be called with different parameter patterns. This makes things a lot easier when dealing with complex logic.

OO also allows you to create static classes that don't need instantiating. This can be very useful for simple things where you just want to quickly call some functionality to return a calculation or some such.

Proper OO programming also has principles baked into the paradigm around how to split out code into logical groupings too. 4 Principles of Object-Oriented Programming | Khalil Stemmler.
Thank you James :)
 
So I worked on it a lot and made a class to extract a sheet from an xlsx without using excel. So I did it.

But I have encountered one maybe issue if we can call that on OE10 (we are working to migrate to OE12 and I don't have the behaviour with PDOSE on OE11), could be more a lack of expertise from my side.

I created it with static method o ease the use in abl code for the other user.
But when working on it with the app builder, each time I do modification on the class and compile it the running program would work with an older version of the class. I add to close my entire OE session and restart it to work with the last version.
I checked with this Kb188557 but nothing was running.

Do you have some info on that ?

Best Regards,
 

Attachments

I am not sure, but I think the workings in Kb188557 do not work with static classes.

One option to try/fix is to have your class as a singleton class instead and doing that you should find you can pickup any modifications without having to restart the whole session:

 
If you are going to declare something static, you have to really want it to always be there ... and for it to remain "static", i.e., unchanging.
 
But when working on it with the app builder, each time I do modification on the class and compile it the running program would work with an older version of the class. I add to close my entire OE session and restart it to work with the last version.

This is because the static code is loaded once per session and you cannot unload or force a reload. When you are testing, I would strongly recommend that you use a separate session/shortcut. That way you know that you are working on the most recent code.

If you follow @Osborne 's suggestion and use instance methods (aka not STATIC) then you can just NEW the class every thime you need to test changes made to it.

Generally you should consider whether you need the methods to be static or not. A class like this - a 'helper' class - seems like a good candidate for stastic methods, but in general terms if you are using static methods just to avoid a NEW call here and there, or to have a single instance in memory, then there are better approaches.
 
Back
Top