Monkey C Coding Style Guide

I am about to release three Monkey C projects (as barrels), and was thinking that I should probably try to adhere to whatever generally accepted conventions exist. Plus, if any pull-requests are made, it would be good to be able to ensure that any code changes also adhere to accepted coding conventions. However, in an afternoon of perusing Garmin sample code, public repos, code posted in the forums, etc, I have found much variation in almost all aspects of coding convensions.

There has been a lot of activity with 's prettier-extension-monkeyc extension for Visual Studio Code, but I think it would do the Connect IQ / Monkey C community to put together some sort of style guide, in a collaborative fashion, probably building on some of the rules in Mark's extension. I'm thinking something like the Ruby Style Guide on GitHub. Obviously, like any project in any language, there is no need to adhere to the style (for example, I *detest* this obsession with lines ending at 80 chars) but I suspect it would be useful for any Monkey C programmer to have a style reference.

I am happy to take the lead but would like to gauge the interest of others in helping put an officially, unofficial style guide together.

  • I do like style guides, but honestly, with such a small user base I'm not sure if it's worth the effort.

  • With Monkey c, you can have "Style" variations based on the app type, so it could get confusing.  The samples in the SDK are pretty good to show somewhat different styles and ways to do things

  • With Monkey c, you can have "Style" variations based on the app type, so it could get confusing.

    I think you are confusing design patterns with coding style. A coding style (ie. coding conventions), if you look at any examples, is consistent regardless of platform or app type, and lays out rules/guidelines for writing code. Sometimes there is some crossover into patterns (we see some of this in the original style guide "The Elements of Programming Style") but I'm referring to coding style (spacing, indentation, variable naming, etc).

    While companies and/or projects sometimes override generally accepted styles with their own, I've always found that they are mostly based on the typical style.

  • I do like style guides, but honestly, with such a small user base I'm not sure if it's worth the effort.

    When the user base is small is *EXACTLY* the best time to put something like this together. There are fewer people to argue about the guidelines and and fewer projects (that might need retroactively changing).

    I've released source code that's been forked only once or twice, and likely never actually used by anyone else. But that's not a reason why it still shouldn't be released.

  • Maybe in another decade the base won't be so small...  Slight smile

    CIQ has been around 9+ years.

  • I'll just note that my extension basically uses prettier's built in javascript formatter, with some tweaks to handle the different syntax in MonkeyC. This means that it sticks with the Prettier philosophy that there is just one style, and there are very few configuration options. Pretty much the only things you can change are line length (which is a "soft" limit anyway), indent size, and whether to insert trailing commas in multiline arrays.

  • The size of the user base is irrelevant. When you answer a random post/question here on the forum, it applies (at the time) to only one person: the person who asked. Perhaps others will find the answer helpful but you don't know that.

    When I released the source code for my text picker, I spent a day cleaning up the code (it's still not great but it was even worse before, and it had to be extracted from the project it was built for) and I know of only two or three people who have used it. Maybe there's more, but it doesn't matter; I released it so people could make their apps better. It's about making it easier for the community as a whole to code stuff. Ignoring that Monkey C is specific to Garmin Connect IQ, a big part of why languages like Ruby and Python are popular is because of the community and the collective library of code. And most of that collective code is styled similarly and consistently, making use of the code that much easier.

    Finally, please not that I don't require replies here saying you're not interested; I'll assume that from not replying. But if you want to help, and make this a better community then I encourage you to reply.

  • The issue of readability and formatting isn't unique to Monkey C and everybody has their own opinion, so if you keep it clean and use meaningful names that would cover most of it.

    What isn't well documented are the costs of various code features. For example, class and global variables, arrays, dictionaries, double precision floats and double integers add a lot of invisible complexity to the resulting compiled bytecode. While these will go against what most would consider good style, they improve size and speed. Some guidance here includes:

    If you are going to use a class or global variable more than once, assign it to a local variable and then use that instead.

    If you are going to use a specific array element or dictionary key more than once, assign it to a local variable. Multi-dimensional arrays are nested objects, so try to reference only one dimension at a time if you can by assigning that dimension to a variable.

    If you are only going to call a function from one place, consider consolidating the code if the function is small.

    Some are less obvious, but it's safe to assume that the small processors in the Garmin devices share the weakness of all CPU's that division is harder than other math operations. Multiply by reciprocals where you can calculate them in advance and put them in the code, and divide only when you have no other option.

    public const PIx2 as Float = 6.2831853;
    public const PI_2 as Float = 1.5707963;
    public const PI_3 as Float = 1.0471976;
    public const PI_4 as Float = 0.78539816;

    If variables are only going to be used a few times in a function, consider reusing them when the value it contains isn't needed later on. They might need somewhat generic names to avoid confusion of there is more than a few.

    	public function getAge(defAge) as Number {
    		var age = UserProfile.getProfile();
    		if (age has :birthYear) {
    			age = age.birthYear;
    			age = (age != null) ? _currentYear - age : defAge; 
    			age = (age > 0 && age < 120) ? age : defAge; 
    		} else {
    			age = defAge;
    		}
    		return age;
    	}

    Don't be afraid to use lots of parentheses, the compiler can be easily confused by nested code. You may have to use more typing for variables than you would think you should need to for a supposedly duck typed language to reduce compiler warnings.

    Using "has" to verify that a certain operation is supported before you execute it will help with compatibility across devices. CIQ version alone isn't a guarantee that something will work at runtime. The compiler won't tell you as a rule.

    	public function initialize() {
    		_useLocalTime = (Time has :LocalMoment);
    		_hasBG = (System has :ServiceDelegate);
    
    		if (Application has :Storage) {
    			Storage.clearValues();
    		}
    

    This are the big ones that I can think of right away, others may add to this or disagree. I like some others don't mind offering suggestions to put in a guide, but if someone wanted to be a guide maintainer there would already be one.

  • I don't think that this is part of code styling but I think this is more important. Once in a while there's a list like this, the lucky ones pick it up, others have no idea about these things.

    BTW dbrobert I am still working on refactoring your code. The thing I sent in the PR were just the necessary changes to be able to compile and see it in action. Most things in the above list are still to be done Slight smile

  • I don't think that this is part of code styling but I think this is more important. Once in a while there's a list like this, the lucky ones pick it up, others have no idea about these things.

    I agree that some of these suggestions can be important, but I think that they are becoming less so as device memory and computing power increases. On the original iteration (in the era of the Fenix 3), it definitely was super important; if the onUpdate() method of your watch face was slow there was a noticeable lag when switching to/from the watch face in the widget carousel.

    That said, I think that suggestions such as these are good can be included into a style guide, perhaps in a section dedicated to smaller/faster code.

    The issue of readability and formatting isn't unique to Monkey C and everybody has their own opinion, so if you keep it clean and use meaningful names that would cover most of it.

    While I agree that these problems aren't unique to Monkey C, I disagree that it can be summed up with "keep it clean and meaningful". If that was the case, we wouldn't have style guides for every other language. The point of a style guide is to "guide" the programmer in a consistent manner.

    Take this code for an approximation of e, written in Ruby:

    estimate_e = ->(trials) { trials.times.map {1.0/trials.times.map {trials.times.map {rand(trials)==0}.count(true)==0}.count(true)}.sum }

    Is it valid and does it compile? For sure. But is it easily readable to the passing eye? Not even close. And yet it's potentially considered clean and uses meaningful names.

    But look, if anyone doesn't see the value of a style guide then I'm not going to try and make them drink from that river. But 99% of the developer world does see immense value in style guides, so much so that not having a style guide policy at the corporate level can be a deal breaker (as it implies, rightly or wrongly, an immature and less serious company/team).