Global functions. Good Practice?

I have "discovered' the ability in MC to build functions outside a class and to call them from within a class.
Obviously they can't access any class variables, which I overcome by reading Storage values (very sparingly) , and that's OK as I'm using then to manage views.
The upside is that the code is simpler as I can call them directly from anywhere in my code.

My question is: Is this "good practice" and if not why not?

  • Seems to me that would be considered a coding style, and there is no right or wrong coding style. It's what works for you and lets you manage your project. There at least used to be some global naming issues with number of objects/variables/enums. Not sure if that ever got fixed. I'm all for anything that makes code simpler and easier for YOU to read and maintain.
  • Something like a distance function might be universal (something that can be used by many classes). That would be something that would reasonable to be global.

    Storage is real slow. It is intended to allow information to be preserved across multiple runs of an app.

    It might not be a good design to pass information around through storage while a program is running.

    If you use an object (a particular instance of a class) and keep references to the object the different places it's used, you can share data and call the functions that deal with the data with one "name" (reference).
  • Using globals in general can cause a small hit due to scope, as global is the last as scope is checked outwards.

    For data, if you set up a class for "data", you can pass that class to make data accessible elsewhere. Same way you can pass the view to a delegate. I would not use Application.Storage to pass data between classes.

  • I agree with the all points above, especially the advice to not use Storage to pass data around at run-time.

    If you're worried about maintainability, scope and naming conflicts, you could always put all your global functions (and global variables, if you must have them) in a module. Your code will get slightly bigger, but it'll be slightly faster, and you get some of the advantages of classes with less of the overhead.

    If these functions are used to manage views, then what they're doing is global to the app, anyway. Not too different from how you call WatchUi.popView() and pushView() without an object instance. (WatchUi is a module). When we write Monkey C apps, we are calling static module functions all the time, so the API itself is designed to expose functions that exist outside of classes.
  • Thanks everyone for your input. Here's what I take from your responses:
    • Don't pass Storage variables around the app. Yes, I understand that it's slow, so I don't do it very often and will probably go back and tidy it up.
    • Coming from previously strict OO languages like java and VB, I was surprised to have the ability to use global functions and was just checking that it's OK to use them.
    • There's a lot I don't understand about MC, including the concept of modules, as I just don't understand the nuances of:
      When we write Monkey C apps, we are calling static module functions all the time, so the API itself is designed to expose functions that exist outside of classes.


  • TL;DR Modules are just a way of organizing your code, like namespaces in Java. Calling a function in a module like System.println() isn't too different from calling a hypothetical global function like system_println(). In both cases, you didn't need an object instance to make the call. Furthermore, you could've also used static functions in a class, in both Java and Monkey C, and that has a similar effect as using a global function (you don't need an object instance.)

    ---

    Yes, in Java, everything has to be in a class. However, you can still have static methods in a class, which don't require an object instance to be called, so you still have the same effect as a global function/variable which can be called from anywhere without requiring an object instance. You could even do this in Monkey C, if you wanted to.

    To explain the point of my comment you quoted:

    A module in Monkey C is like a namespace for classes and functions/variables not contained in classes. Think of a Monkey C module as a Java package or namespace, except it can contain functions, variables and classes..

    For example, we often call a function named System.println() for debugging. As you may have noticed, there is no need to instantiate a class before calling this function. Similarly, we call functions named WatchUi.popView() and WatchUi.PushView(). Or Application.getApp().

    These could've all been written as strictly global functions: e.g. println(), popView(), pushView() and getApp(). Indeed, this is how things were done in very old languages/APIs such as C and the C standard library.

    In modern languages, we use namespaces, packages and modules to avoid name collision (e.g. when using two different libraries) and to organize our code better for reuse/sharing/documentation/etc.

    For practical purposes, I am saying that you could create a module called ManageView (or something) and put your view management functions in there. If you have any state variables specific to these functions, you can put them in the same module.

    The Monkey C Programmer's Guide mentions the practice of putting static methods in a module:
    https://developer.garmin.com/connect...uide/monkey-c/
    Monkey C modules serve a similar purpose as Java packages, but unlike packages, modules can contain variables and functions. It is common for static methods to exist in the module as opposed to a particular class.


    Pros of using modules:
    - Better organization of code (keep related items together)
    - Avoids the global lookup performance penalty mentioned above. (Although you can also use the "$" operator to avoid that penalty. e.g. If I have a global function called "myFunction()", I can call it using "$.myFunction()" which indicates that it's global)
    - Easier to share and reuse code. (Only the module name needs to be unique.) In older languages, or when the use of modules/namespaces/whatever is not desired, this is often accomplished by adding some kind of unique prefix to the name. e.g. Instead of putting a function in a module like System.println(), you might have a global function named system_println().
    - Arguably cleaner coding style

    Cons of using modules:
    - Slight overhead in amount of memory consumed by code (both for the module definition and for the module calls)

    If you're just writing code for yourself that you'll never share or reuse, then there's no need for modules. But I think it's just cleaner. Personally for some apps I do have global functions that were originally in a module which I later got rid of to save memory for CIQ1 devices. When I wanted to reuse those functions it was a bit of a pain. (I had to write another class to "wrap" those functions in a nice, reusable way).
  • Using globals in general can cause a small hit due to scope, as global is the last as scope is checked outwards.

    Don't forget you can access globals directly using $.variable to avoid scope delays. I normally do this when using globals.
  • Wrote a small windows tool some years ago to check a single source code file for the optimal using of variables. You may give it a try to see if everything is green for your project. :)
  • Don't forget you can access globals directly using $.variable to avoid scope delays. I normally do this when using globals.

    I always wondered about the purpose of the $. I will try it to get some performance boost.

  • You may give it a try to see if everything is green for your project. :)


    Would be great, but I have been seduced away from M$ to Mac. Any chance of the code to port across to Mac/Unix?