Coding Conventions in Rules

Edit: Fixed a couple of typos

I keep seeing confusion and a general slow down in an ability to help many users because they use interesting coding conventions. So I’m posting this as what I’ve seen as the most common conventions I’ve seen in use across openHAB in examples and tutorials here on the forum. Please comment below if you’ve seen something different or something I’ve missed.

Why does this matter? By following common coding conventions anyone who looks at a symbol in a program (e.g. a variable name) can instantly know the nature of that symbol just by the way the letters are arranged (e.g. if it’s all caps we know it’s a constant, if it starts with a capital we know it’s a Class or an Item, etc.).

It also helps in understanding the code. For example, consistent indentation helps visually show what blocks of code go together.

Term Description Example
meaningful A name/label that has meaning to you the human in the context of your home automation. “kitchen_light” is good, “zwave_node12” is not
title case Follow the English title conventions, capitalize all the words except for prepositions and articles, always capitalize the first letter. Master Bedroom Lamp
camel case Run the words together, capitalize the first letter of each word. It’s optional to capitalize the first letter of the first word. ThisIsCamelCase, thisIsAlsoCamelCase
snake case Replace the spaces and punctuation with underscores (_). Usually all upper or all lower case. this_is_snake_case
all caps Every letter is capitalized. ALLCAPS
all lower case Every letter is lower case lower
kebab case Like snake case except replace spaces and punctuation with dash (-). Usually all upper or all lower case. Not used here, included for completeness. this-is-kebab-case

Things

  • When given the choice always change the randomly generated portion of a Thing’s ID to something meaningful.

  • Use lower snake case.

  • Always give your Things a meaningful Label. This is the most prominent name you will see in the all parts of MainUI. Use title case.

Channels

  • Use lower snake case for the ID.

  • Use title case for the Label.

Items

  • Use camel case with the first letter capitalized for the Item name.

  • When using something like Design Pattern: Associated Items to break the Item name up, use snake case for the parts of the Item name but follow camel case for the parts of the name. For example MasterBedroomChromecast_PlayPause.

  • Make sure the name of the Item is meaningful.

  • The label should be title case and meaningful.

Rules

  • The Unique ID should be lower snake case.

  • The label should be meaningful and title case.

  • Put a high level explanation of the purpose of the rule in the description.

Triggers

  • Fill out the label and description with something meaningful. For example, replace the autogenerated content (e.g. “it is a date and time specified in an item” with “the date and time held by AlarmClock”).

  • Use title case for the label.

  • Use full sentences for the description.

Conditions

  • Same rules as for Triggers.

Actions

  • Same rules as for Triggers and Conditions for the label and description.

Script Actions/Script Conditions

  • First and foremost, follow the coding conventions for the language you’ve chosen to use. Except for Rules DSL and Blockly, each supported language has a published (sometimes more than one) style guide which you should follow. This will cover everything from how to name variables, indentation, etc. Most languages follow a similar coding style so much of below will be the same for all languages.

Rules DSL

Because Rules DSL doesn’t have a published style guide, here are some conventions that are in use.

  • Constants should be declared using val and be all caps.

  • Variables should be declared using var, start with a lower case and be camel case.

  • Functions should follow the same convention as variables, lower case first letter and camel case.

  • Class names and Items will always start with a capital and use camel case or sometimes snake case.

  • Use four spaces for indentation.

  • Always indent to denote each constant. There should be an indent for the next lines when you see any of the following symbols until you see the closing symbol. The closing symbol should be in the same column as the opening symbol so you can more easily match up the pair.

Opening Symbol Closing Symbol
then end
{ }
[ ]
  • Pay attention to the number of indentations. When you have four or five indents deep that’s a code smell. It doesn’t necessarily mean something is wrong but often it means there is a better way if you step back and think about it some more.

  • Lines that are really long can and should be broken up into multiple lines. I’m not going to provide a rule here as there are lots of ways to do this and I’ve not seen a consensus. Break them up in logical places (e.g. on the && or || in a conditional statement, put each argument to a function call on it’s own line, etc.) Some ideas:

    • indent the following lines
    • half indent the following lines (e.g. use two spaces instead of four)
    • line them up with each other (e.g. for arguments, line the next line up with the first argument to the function)
  • In Rules DSL, do not over specify the types of variables. Only force a type when you need to (e.g. now.plusSeconds() needs an int but Rules DSL likes to treat all numbers as Number so instead of declaring a variable or constant as int, wait until you call plusSeconds() and only then call intValue on the number.

  • The only time where you need to provide a type to a var or val declaration is when it’s initialized to null. In all other cases, refrain from specifying the type.

  • Where possible, use List streaming operations instead of for loops and while loops. They are faster and more powerful. See Design Pattern: Working with Groups in Rules for Rules DSL. Other languages will have their own conventions (e.g. Python has list comprehension).

  • This rule can apply to many languages. If you find yourself with a long list if if/else statements with each doing mostly the same thing only with slightly different values, see Design Pattern: How to Structure a Rule for a way to shorten the code and avoid hard to maintain nearly duplicated code.

Blockly

  • Follow the variable naming convention rules listed above. Beyond that, the structure of the graphical blocks themselves enforce a coding convention.

If I can think of a way to work it in, I’m considering adding this as a page or a section to the reworked rules docs I and @florian-h05 are working on. I’m not sure yet where it would fit but it should help everyone if most of us follow a common convention in our code. It is particularly troublesome when you can’t immediately tell the difference between an Item and a variable in a script.

15 Likes

It never occurred to me that these variations all have fun nicknames. This will likely be the best thing I learn today.

4 Likes

There’s always a name. :wink:

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.