Maximo

Maximo

Come for answers, stay for best practices. All we're missing is you.

 View Only
  • 1.  Automation Scripts: Do/Don't, Performance & Code Styling.

    Posted Fri November 11, 2022 11:13 AM
    Hi All,

    Is there any documentation that consolidate all automation scripts coding recommendation (avoid performance degradation, avoid memory leaks, usability and supportability)?

    Thanks!

    ------------------------------
    Dianne Woodley
    ------------------------------



    #MaximoIntegrationandScripting
    #AssetandFacilitiesManagement
    #Maximo


  • 2.  RE: Automation Scripts: Do/Don't, Performance & Code Styling.

    Posted Mon November 14, 2022 09:59 AM

    Truthfully, it's a bit light but https://ibm-maximo-dev.github.io/maximo-autoscript-documentation/bestpractice/overview is where we intend to cover this. 

    I want to enhance this when I have time and create a series of blogs to go a bit deeper. For example, choosing the right launch point is critical but we only talk about a few examples of it here and there are a lot of examples of code that works but isn't optimized because the developer chose the wrong event.

    I'd also inform developers to avoid count() entirely over just minimizing it. There are very few circumstances where you need to know the actual count but don't need to process the data. Typically, I see developers using this to loop through records or determine if records exist. Both can be achieved without using count() which will always cause another database query. For example, if you want to determine if a record exists use set.notExist() instead. This will check the in-memory set first to see if we have any Mbos. If the set hasn't been initialized it will execute a query against dummy_table with an exist() statement instead. This allows the database to stop processing once 1 record is returned whereas the count requires every record to be returned from the query first. If you're trying to loop through records, start at 0 and iterate until your Mbo is null. 



    ------------------------------
    Steven Shull
    ------------------------------



  • 3.  RE: Automation Scripts: Do/Don't, Performance & Code Styling.

    Posted Tue November 15, 2022 02:28 AM
    Hi Steven,

    at first, many thanks for writing that down and publishing!

    This may be a bit offtopic from the question, but related to your answer.

    You write

    Starting from 7612, the following function will be added in the "service" variable that will allow you to check it easily:

    if service.isLoggingEnabled():
      service.log("count of mbos "+mboset.count())​
    I am currently looking at the ScriptService of TPAE7612 (IFIX026) and don't see that "isLoggingEnabled" function. Are you sure it is in it?

    You also write:

    You may want to do costly Object init scripts only when the object is initialized from the Main tab (UI) and not from the List tab. This is because in such cases, the following sample code bis helpful:

    from psdi.common.context import UIContext
    if UIContext.getCurrentContext() is not None and UIContext.isFromListTab()==False:
        ..costly initlization..​
    (Btw, there is an error in it, it should be "UIContext.getCurrentContext().isFromListTab()")

    Since there is service.webclientsession(), i do it this way so i don't need to import UIContext:
    if service.webclientsession() and service.webclientsession().getCurrentApp().onListTab():
        ... costly initialization...​

    Are there differences? What is the better way?

    Belonging to that, is there any way to stop processing if we are in a resultset in startcenter? I neither get a UIContext nor a WebClientSession.



    ------------------------------
    Andreas Brieke
    IT Service Management Consultant
    SVA System Vertrieb Alexander GmbH
    ------------------------------



  • 4.  RE: Automation Scripts: Do/Don't, Performance & Code Styling.

    Posted Tue November 15, 2022 08:37 AM

    I want to clarify that while I wrote some of the documentation on this wiki, by far the large majority of this documentation was written by Anamitra in his personal time including this page. The goal of the wiki was to make it easier to maintain with multiple contributors to ensure that we keep it current as we release new capabilities in the framework. 

    With that out of the way, the isLoggingEnabled() is not in the latest MAS release either. I'm not sure if that was something planned that ended up getting dropped from the release for some reason. What I would do instead is getting the logger like:
    logger=service.getLogger("maximo.script."+scriptName)

    Then from there you can call the various methods such as:
    if logger.isDebugEnabled():

    I personally prefer using the logger directly over utilizing the service variable logging functions. 


    On the UIContext, good catch. I'll submit a PR to update the example.

    We use the UIContext for service.webclientsession() so there's no difference between:
    UIContext.getCurrentContext().getWebClientSession()
    and
    service.webclientsession()

    There is technically a difference between UIContext.getCurrentContext().isFromListTab() and service.webclientsession().getCurrentApp().onListTab(). The UIContext stores some data such as the app name and whether it's on the list tab and we retrieve from that. When you call service.webclientsession().getCurrentApp() you're retrieving an AppInstance object which is part of our UI framework that you're interacting with. I'd expect the outcome to be identical and inconsequential from a performance perspective so either approach should be fine.

    Regarding start centers, I haven't tried to do anything here. I try to avoid initialize on the object entirely (only on the attributes). This way the logic is only invoked when the attribute is requested. I don't think we set anything special like we do when we're going through a table download but this would be good to investigate. 



    ------------------------------
    Steven Shull
    ------------------------------



  • 5.  RE: Automation Scripts: Do/Don't, Performance & Code Styling.

    Posted Tue November 15, 2022 10:40 AM
    Actively discourage the use of service.log() and of getting the plain "maximo.script" logger. For Mbo-based launch points, for example, you should use logger = mbo.getMboLogger(). For integration scripts, I suggest getting the maximo.integration.SCRIPTNAME logger.

    I discuss this more in my 'add implicit "log" variable to autoscripts...' enhancement request (MASM-I-850). Any extra votes would be appreciated!

    Among other things, joining me in my vendetta against using plain "maximo.script" will mean that setting the Log Level to DEBUG on your script will let you see every request for a variable's value, but setting the log output to DEBUG on maximo.service.SERVICENAME.OBJECTNAME, for example, will let you see the output you intentionally send from your script in the context in which it executes. It's win-win.

    On a different topic, a rule autoscripters should keep is that if they didn't get the MboSet from MXServer, then it is not up to them to save() or close() or even moveXXXX() on it. I have seen exceptions to this rule that do not interfere with the user experience or other processes, but those are exceptions. The advice against calling moveXXXX() is based on this MboSet might be showing in a table in the UI, and it's just best to avoid playing around with the current record pointer when it could impact the user.

    ------------------------------
    Blessings,
    Jason Uppenborn
    Sr. Technical Maximo Consultant
    Cohesive
    ------------------------------