Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • ⚠ Copy pasted the code is forbidden; to share functionality use functions.

  • All Groovy source code (“element” folders) should be auto-formatted by IDEA, see /wiki/spaces/LEARN/pages/2651979915.
    Note: logic.json should be excluded! It is formatted by Packaging Tool.

  • Always use curly brackets for if, for, while , e.g.:

    Code Block
    if (isCondition) {
      return null
    }
  • Reformatting of big amount of old code should be done within a separate commit, otherwise it is almost impossible to validate the merge request.

  • Follow the Recommended Logic Structure. Try to keep all input elements in the beginning of the logic.

  • Use out.SomeElement instead of (deprecated) api.getElement("SomeElement").

  • Use input.SomeInputName instead of (deprecated) api.input("SomeInputName").

  • Avoid api.local, api.global where possible. Using them in functions is forbidden except for caching. For small amount of data, use a dedicated element – this will help you trace the logic more easily. Big data cause a slowdown in line item logics.

  • Use field names in filters or use api.namedEntities() if possible.

  • Use real data type when declaring the variable instead of def. Mandatory use in functions – both parameters and the return type.

  • Prevent api.isSyntaxCheck Issues by having the AbortSyntaxCheck element in the logic.

  • Keep elements/functions small and simple. Shorter methods are always better than big ones. Try to break bigger element code / function code into smaller pieces.

  • Where to place functions?
    1. In the element – if used only once.
    2. In the Library element – if used twice or more, but only within the same logic.
    3. In Groovy Library – if used between logics.

  • Use Input Builders – mandatory for configurators and header logics, but recommended also for ordinary logics.

  • Use @Field constants (no use for fields, table names, configurator names in customer projects). Mandatory use for important values used in conditions or repeatedly used constant Strings or used in Accelerators.

  • Use api.findLookupTableValues("TableName") instead of api.find("MLTVx", ...) = you will get all rows.

  • Use consistently one approach for adding items to a list, do not mix various approaches. It is recommended to use List << value rather than List.add(value)(unless you need nullsafe operator).

  • Use the same approach for accessing a List item, do not mix various approaches. Use eitherlist[index] or list?.getAt(index). Not list.get(index).

  • Use the same approach for accessing Map values, do not mix various approaches. It is recommended to use Map.key rather than Map[key] or Map.get(key) unless there are spaces in 'key'.

  • BigDecimal should be the most commonly used data type for amount or percentage variables (never use floats for amounts or percentages). Use BigDecimal constants (e.g. 0.0 instead of 0) so you can rely it will be a BigDecimal.

  • If casting is needed, e.g. ?.toBigDecimal() for amounts, do this at the first occurrence of the variable.

  • Utilize Groovy conditions for IF statements that check if a List is not empty and not null, String is not empty and not null or value is not 0 and not null. Instead:

    Code Block
    List rows = ...
    if (rows != null && rows.size() > 0) {
        ...
    }
  • write simply:

    Code Block
    List rows = ...
    if (rows) {
        ...
    }
  • Use closures (collect, collectEntries, each, eachWithIndex, find, findAll, first, last, max, min, inject, sort, etc.) whenever applicable.
    Note: For better performance, use the sortBy parameter in api.find() rather than the sort() closure.

  • E.g. instead of for LOOP:

    Code Block
    for (item in items) {
        ...
    }

    use

    Code Block
    items.each { item ->
       ...
    }
  • Instead of FOR loop:

    Code Block
    def list 
    for (item in items) {
        list.add(x)
    }

    use collect:

    Code Block
    items.collect { item ->
       x
    }
  • Instead of FOR loop:

    Code Block
    def map 
    for (item in items) {
        map.put(x, y)
    }

    use collectEntries:

    Code Block
    items.collectEntries { item ->
       [(x) : y ]
    }
  • Use "find" (resp. "query") prefix for names of functions that query Master Data tables (resp. Analytics Data Sources / Datamarts). Do not mix data querying and calculation in the functions.

  • Use the library element alias when calling multiple Groovy library functions in an element or function: def CurrencyUtils = libs.MainLib.CurrencyUtils

  • Casting: instead of def xxx = out.Cost as BigDecimal or ?.toBigDecimal move the cast to the return of the element.

  • For performance reasons, avoid returning big data in an element. Remember: in Groovy, the expression on the last line is the value returned!

  • Initialize Map directly. E.g. instead of

    Code Block
    def map = [:]
    map["key1"] = "value1"
    map["key2"] = "value2"
    map["key3"] = "value3"

    directly use (and following auto-format):

    Code Block
    def map = [
      key1: "value1"
      key2: "value2"
      key3: "value3"
    ]
  • Analogically, initialize List directly. E.g. instead of

    Code Block
    def list = []
    list << "value1"
    list << "value2"
    list << "value3"

    directly use (and following auto-format):

    Code Block
    def list = [
        "value1",
        "value2",
        "value3"
    ]
  • For assignments based on IF

    Code Block
    def result
    if (condition) {
      result = x
    } else {
      result = y
    }

    directly use:

    Code Block
    def result = condition ? x : y

    or for longer x, y expressions:

    Code Block
    def result = condition 
        ? x
        : y
  • Split suuuupeeeeeerlooooong lines. If the function has many parameters, put a group of parameters on a separate line.

  • Dot not commit commented code and api.trace in GIT. Avoid api.log unless it is really needed for the PROD run.

  • Resolve the TODOs.