.. figure:: logo.png :align: center http://www.bardolph.org .. index:: projects .. _code_improvement: Improving and Making my Bardolph Code More Efficient ==================================================== *By Perry Piazza* *Hi. My name is Perry and I am helping Al with the Bardolph project. Articles that I write will cover my experiences with Bardolph.* My last article featured some short scripts that I wrote using Bardolph to create holiday light routines using a pair of LIFX multi-zone LED strips. The third and probably the most "complicated" of the three scripts made use of Bardolph's built-in random number function to randomize three variables #. the strip, #. the zone, and #. the hues (or "colors") that were "broadcast" to the strips. In my version of that script I was able to accomplish this using the assignment and randomization code below: .. code-block:: lightbulb assign zone_num [random 0 8] # 7 multi-LED-zones per strip assign strip_num [random 1 3] # 2 strips assign color_num [random 1 3] # 2 colors (for Christmas at least) These declarations sat within a repeat loop. Then, after these declarations and assignments in the code, two sets of nested if-else logic blocks followed. Coding this routine the way that I did ended up requiring four copies of the core light control code. The logic went something like this: set a random zone, and then light it with either hue 1 or hue 2 on either strip 1 or strip 2 based upon the random numbers returned above. This is where the four copies of the core light control code come in, since once a zone was chosen, I then needed specific code corresponding to strip1color1, strip1color2, strip2color1, and strip2color2. Yikes. Imagine if I needed three holiday colors. Al - who created Bardolph and is a software engineer - pointed out to me that the code could be simplified quite a bit. Again, the five-step process of illuminating and de-illuminating a random color and random strip is repeated four times inside a deeply nested if/else structure. This makes the script unnecessarily long and difficult to follow. Additionally, it introduces the risk of errors: if the programmer needed to change the brightness from 50 to 60 or change the ramp-up time, they would need to edit multiple lines in four separate blocks of code. Missing even one instance would result in inconsistent behavior—a common source of bugs. Al modified the script, which I'll share directly below and then make some comments about its efficiency: .. code-block:: lightbulb kelvin 2700 # how long it takes to brighten and darken assign ramp_time 0.4 assign wait_time ramp_time * 2 define set_strip_color with light_name color_hue zone_num begin hue color_hue saturation 100 brightness 50 set light_name zone zone_num duration ramp_time hue 0 saturation 0 brightness 0 set light_name duration ramp_time time wait_time end on "LS1" and "LS2" repeat 100 begin if [random 0 1] == 1 assign name "LS1" else assign name "LS2" assign color [random 0 1] * 120 assign zone_num [random 0 7] set_strip_color name color zone_num end off "LS1" and "LS2" This version of the script introduces a computer engineering concept called re-use. Re-use is the process of managing complexity in a program by encapsulating common behavior in a unit of code so that the logic does not have to be repeated. He primarily did this by adding a user-defined function (sometimes called a "procedure") named set_strip_color. set_strip_color is designed/defined to accept three parameters (note: the with keyword assigns the parameters). The first is "light_name" (e.g., which strip to target, LS1 or LS2), the second is "color_hue", the hue of the Christmas color (*e.g.*, 0 for red, 120 for green), and the third is "zone_num" (e.g. which zone on the strip to target). The function definition then contains the single, reusable instance of the 5-step process. Then, just one loop is needed - the repeat 100 code as it can randomize the parameters of the function within it. Also, a clever use of arithmetic is employed to set the hue: .. code_block:: lightbulb assign color [random 0 1] * 120 This shortcut makes it easier, if we had even more hues/colors, to broadcast (assuming you could mathematically derive the colors that you needed). Another clever use of arithmetic is employed intying wait_time to ramp_time. Both of these arithmetic shortcuts (and the function) are examples of procedural abstraction while, for obvious reasons, the assignment of a floating-point number 0.4 to ramp time is an example of simple data abstraction. A common, succinct definition often cited in textbooks comes from computer scientist John V. Guttag: "The essence of abstraction is preserving information that is relevant in a given context, and forgetting information that is irrelevant in that context." So when you are coding, try and think about where in your program you can employ abstraction in order to make it more efficient. This requires a little bit of creativity, but it is useful and fun.