Slicker Coding Style

Working Draft


William Lahti <fury@calyptos.com>


Introduction


The ability to understand code easily should not be a problem for a well-designed, well thought out code-base. Also it is to be expected that projects with badly-designed, “hacked” code-bases will be difficult to understand. This stems from the non-definition of naming conventions and a clear coding style in the project. Everyone has their own taste in naming, from private class variables to class names to settings dialogs to naming files. The same goes for coding styles. Because of this non-definition, the project's developers tend to follow their own rules when adding new classes, files, and user interfaces to the code-base. This is a very bad thing design-wise, and should be avoided, fixed, and stopped before widespread problems resulting from such bad design begin to culture.

Take a minute to analyze Slicker's naming conventions, including settings dialogs, class names, private class variables, function names, and file names. Naming is not uniform, resulting in confusion about the function of particular classes, cards, and most of the Slicker core itself. This document tries to resolve these problems by defining a clear, specific set of naming conventions that developers must follow when working with the Slicker code-base.


Taste


All developers have their own tastes in code formatting. So although some coding styles may be hard to understand for most developers, some may understand it much better than others. This can't be fixed, every developer is entitled to their own opinion. However, problems stem when code from the same code-base is formatted radically different from the rest. Problems stem when there are four or five different coding styles being used actively in development, especially when two developers with different coding styles are working on the same code. That is the reason this document is essential to the Slicker code-base and Slicker itself staying consistent and easy to understand.


Naming Conventions


When choosing naming conventions I looked for concise, descriptive, and logical ways of representing the function of the specific object, whether it is a class, function, et cetera. The most notable hard call was whether to call—for instance—a Hello World applet “HelloWorldCardApplet” or “HelloWorldCard”. Although “HelloWorldCard” was more concise and easier to type, “HelloWorldCardApplet” better suited the class's inheritance, because the Hello World applet would have been derived from “CardApplet”.

Some naming conventions did not have a logical reason behind their choosing, because there simply weren't non-decorative pros or cons about any of the possibilities. Such a convention was the class private variable policy. If someone can name a logical reason to choose any of the following naming styles than please contact me at the above address and plead your case.




Coding Styles


The only thing I could find to consider in choosing a coding style was readability and conciseness. A good style balances the extensive use of line breaks with class and logic. I hope I have achieved such a coding style, which is very similar to the Linux® kernel one. It is very specific to keep code as consistent as possible. If any developers or code-base reviewers should find code that violates this style, it should be corrected as soon as possible.


Definition of Naming Conventions


      1. Classes

        General

        • Classes should reflect their ancestors names as much as possible.

        • When classes are original (i.e., no ancestors), names should not resemble existing components of Slicker, KDE, or QT that are unrelated to it. It should instead resemble the component/card it serves.

        • Classes start with a capital letter, and each new word in the class name starts with a capital letter. The only exception to this rule is acronyms. For example if a GNOME panel compatibility system were to be added to the Slider, the name may be GNOMESliderApplet.

        Cards

        • Classes used to implement functionality in Slicker excluding applets and plugins are to be included in the C++ name space “Slicker”.

        • The class used to hold Dynamic Shared Object applets is to be called a CardApplet.

          1. Classes derived from CardApplet are to always end in CardApplet.

          2. Classes multi-derived from CardApplet and other classes may be named differently only if the class's function is radically different than the intention of CardApplet, for instance implementing a taskbar plugin that uses a card as it's user interface.

        • The class used to group custom tab drawing operations is to be called a TabDelegate.

          1. Classes derived from TabDelegate are to always end in TabDelegate. This includes multi-derived TabDelegates.

        • The class used to represent a Card's always-visible area used to manipulate the card's state and position is to be called a Tab.

          1. Subclassing the Tab is extremely discouraged. If what you wish to accomplish cannot be performed using the TabDelegate class, you should contact the Slicker development team with a profile of the operations that are not provided with TabDelegate.

        • The class used to represent a Card's content is to be called a Content.

          1. Classes derived from Content are to always end in Content. This includes multi-derived Contents.

        • The class used to represent the divider between a Card's Tab and it's Content widget is to be called a Separator and may not be subclassed.

        • The class used to provide positioning, expansion/hiding, and painter matrix transformations for cards is to be called EdgeWidget.

        • The class used to encapsulate the functionality of EdgeWidget, Tab, and TabDelegate is to be called a Card.

          1. Classes derived from Card are always to end with “Card”.

        • The class used to represent the optional CardApplet-configurable always-visible area directly below the tab is to be called a Tray.

        • The class used to represent a widget contained in a Tray is to be called a TrayWidget.

          1. Classes derived from TrayWidget are always to end with “TrayWidget”.

        Taskbar Plugins

        • The class used to define a taskbar plugin is to be called a TaskbarPlugin.

          1. Classes derived from TaskbarPlugin are to end with “TaskbarPlugin”.

          2. Classes that are multi-derived that include TaskbarPlugin may be named differently only if the class's functionality radically differs from the function of TaskbarPlugin.

        Slider Applets

        • The class used to define a Slider applet is to be called a SliderApplet.

          1. Classes derived from SliderApplets are to end with “SliderApplet”.

        ConfigModules

        • The class used to define a set of options and a settings dialog is to be called a ConfigModule.

          1. Classes derived from ConfigModule are always to end with “ConfigModule”.

          2. ConfigModules that relate to a CardApplet are always to end with “CardConfig.”

          Private/Protected Class Variables

        • Private/Protected Class Variables must always start with an underscore followed by a lowercase word. Succeeding words should be capitalized. Example: _privClassVar.

          QT Designer Classes

        • QT Designer Classes (user interfaces) must end with “UI”.

      1. Functions

        • Global functions are not allowed unless the task at hand is absolutely unattainable without them.

        • The first word in a function name must not be capitalized. The words following the first word must be capitalized. Acronyms may be capitalized only if they are not the first word in the function name. No underscores are permitted in function names.

        • Function arguments must never overshadow superceding variables. This means if there is a class variable named _redGinger then you cannot name a function argument _redGinger.

        • Function argument names start with a lowercase word, and subsequent words in the argument name are capitalized. Function arguments should never be a single letter. They should signify what they are used for.

      2. Settings Dialogs

        • Menu entries and push buttons that open a settings dialog should be labeled 'Preferences...'. A short description of what settings dialog is opened may be placed before 'Preferences'. Example: Slicker Preferences...

        • Titles of settings dialogs must include 'Preferences'. A short description of what the settings dialog controls may be placed before 'Preferences'.

      3. File names

        • C++ source files must end in “.cpp”.

        • C++ header files must end in “.h”.

        • QT Designer files must end in “.ui”.

        • C++ header files that define a class must be named after that class. If the header file contains multiple class definitions (discouraged) then it should be named after the most important one. If that cannot be established, it should be named using a generalization of the function of the class definitions contained.

        • C++ source files that implement classes must be named the same as the header file for that class, minus the “.h”. Example header: TaskbarView.h, Example source: TaskbarView.cpp.

        • The portion of the file name of QT Designer files before “.ui” must consist of the class the file contains.

        • Documentation/information for a certain directory and it's contents must be named “README”.

        • The directory that contains CardCore must be named “cardcore”.

        • The directory that contains the plugin loader, Slicker startup components and the Slicker class implementation must be named “slickercore”.

        • The directory that contains plugins and applets included with Slicker must be named “plugins”.

        • The directory that contains card applets included with Slicker must be named “cardapplets” and must be a subdirectory of “plugins”.

        • The directory that contains taskbar plugins included with Slicker must be named “taskbars” and must be a subdirectory of “taskbars”.

        • The directory that contains Slider applets included with Slicker must be named “sliderapplets”.



Coding Style


      1. When indenting use a single tab (per indent).

      2. Function definitions (including prototypes) must fit the following format:

          <type> <name>(<arguments>)[;]

          {

          <tab><line>

          <tab><line>

          ...

          }

          If the function has no arguments, “void” must be used in replacement of <arguments>.

          If the function has no-op (has no code), include only line 1 of the function format and replace “;” with “{ }”.

      3. Construct statements (if,while,for,etc.) must fit the following format:

          <construct> {

          <tab><line>

          <tab><line>

          ...

          }

          The code block may be replaced with a single line if there is a single line in the code block. The placement of the statement is up to the developer. It may be placed either directly after the <construct> on the same line or it may be on the following line and tabbed.

      4. Variable declaration follows the following format:

          <type> <name> [= <value>][, <name>[= <value>]...];

          If the line gets too long the developer has two choices:

          - Overflow the definition onto the next line, and give each new variable a new line.

          - Overflow the definition onto the next line, tab in and continue from the previous line.

      5. Class definitions follow the following format:

          class <name>[: [public|private] <ancestor>][;] {

          <tab><definition>[

          <tab><tab><continued definition>]

          <tab><definition>

          ...

          } [<instance>[, <instance]...];