Programming Style Requirements

Software companies typically have programming style requirements to which their programmers must adhere. Many of these requirements have become industry standards. These requirements help to make the developed code more readable, portable, and maintainable. This appendix contains a short set (much shorter than what is typically found in industry) of programming style requirements for CIS 300. These requirements are consistent with Microsoft’s Naming Guidelines and de facto industry accepted practices. Other requirements are simplifications introduced due to the fact that this programming is for course assignments, rather than for distribution. All assignments in CIS 300 use the package KSU.CS.CodeAnalyzers to assist with meeting many of these requirements. This package will generate warnings when various style requirements are violated. All code submitted for grading is expected to follow these style requirements and to be free of warnings.

Subsections of Programming Style Requirements

General Formatting

All programming will be done using Microsoft Visual Studio® Community 2022. This integrated development environment (IDE) does a certain amount of formatting automatically. All code formatting should be consistent with what the IDE does automatically, including how it formats code stubs that it inserts. Specifically, all braces should occur on lines by themselves, vertically aligned so that matching braces occupy the same column. (An exception to this rule can be made when the braces enclose a single statement or a part of a statement, and they occur on the same line; however, if it is possible to omit the braces, as in an if statement, this is preferable to placing them on the same line.) Furthermore, blocks of code enclosed by braces should be indented one tab stop inside the braces.

Tip

An easy way to format a file consistently (after removing any syntax errors) is to select from the “Edit” menu, “Advanced -> Format Document”.

Warning

Don’t change the formatting defaults in the IDE.

Access Modifiers

C# provides 4 access modifiers for classes, fields, etc.: public, internal, protected, and private. For simplicity, however, we will not allow the use of the internal or protected access modifiers unless they are required by the compiler (for example, when overriding a protected method).

When classes, fields, etc., are declared, C# does not require that an access modifier be used. If the access modifier is omitted, a default accessibility level will be used. However, the default depends on where it is being declared. For example, the default accessibility level of a top-level type is internal, whereas the default accessibility level of a class member is private. In order to avoid confusion, we will require that access modifiers (i.e., public or private) be used on all declarations except where C# does not allow them (C# does not allow access modifiers for namespaces, members of interfaces or enumerations, or local variables within methods). In particular, note that when Visual Studio® automatically generates a class statement, it does not always supply an access modifier, or it may use internal. We require that the statement be changed to use public (C# does not allow private here).

In addition, fields within classes and structures should be declared private, unless they are also declared either const or readonly. If you want to make a variable accessible to outside code, you can instead do something like the following:

public double Force { get; set; }

Or if you want the outside code to be able to access it, but you don’t want it to change its value you can instead define it as:

public double Force { get; private set; }

In these examples, Force is not a field, but a property. It can be used like a field, but defining it as a property makes it more maintainable (see “Properties” for more details).

Warning

Don’t define a private property when a private field will accomplish the same thing - using a private field with the appropriate naming convention makes the code more readable.

For more information on access modifiers and accessibility levels, see the section on Accessibility Levels in the C# Reference.

Naming Conventions

The naming conventions described below use the following terminology:

  • Pascal case: Multiple words are joined without spaces, using capital letters at the beginning of each word. If acronyms of 3 or more letters are included, only the first letter of the acronym is capitalized. For example, AverageAge, ContextBoundObject, RgbCode.
  • Camel case: The same as pascal case, except the first letter is not capitalized. For example, averageAge, contextBoundObject, rgbCode.

Namespaces

In CIS 300 programming assignments, namespace names will typically be provided. They will use the form Ksu.Cis300.ProgramName, where each of the 3 components is in pascal case. For example:

namespace Ksu.Cis300.Spreadsheet
{

}

Classes, Structures, and Enumerations

Use pascal case. If the name begins with “I”, the following letter must not be capitalized, as this would look like an interface - see below. For an exception class, append the word “Exception”. Make your names descriptive nouns or noun phrases without abbreviations (common abbreviations like “Min” are allowed). For example:

public class AccountManager
{

}

Interfaces

Use the convention for a class name with a capital “I” preceding the first letter (which must also be capitalized). For example:

public interface IPriorityQueue
{

}

Methods

Use pascal case. Make your names descriptive without abbreviations (common abbreviations like “Min” are allowed). For example:

private void InitializeComponent()
{

}
Warning

Automatically-generated event handlers don’t follow this convention. For example, suppose you generate a Click event handler by double-clicking a Button named uxUpdate. The event handler generated will then be given a name of uxUpdate_Click. You will need to rename it to UpdateClick. Be sure to use Visual Studio’s Rename feature, as this name will also need to be changed in automatically-generated code that you normally won’t edit.

Properties

Use pascal case. Make your names descriptive without abbreviations (common abbreviations are allowed). For example:

public int Count { get; private set; }

Controls on Forms

Use camel case, and begin names with “ux” followed by a capital letter (this “ux” stands for “user experience”). Make your names descriptive of the functionality, not the type of control. For example, uxAccept, uxCustomerName.

Note

You will not typically declare these names in code, but will enter them in the Visual Studio® design window.

public Constants (const or readonly)

Use pascal case. Make your names descriptive. For example:

public const double GravitationalAcceleration = 9.80665;

private Fields

Use camel case with an underscore character preceding the first letter. For example:

private double _weight;

This applies to all private fields, including those defined as const or readonly.

Parameters and Local Variables Within Methods

Use camel case. For example, inString and outString in the following code:

public string ToMixedCase(string inString)
{
    string outString;
    // code here
    return outString;
}

Comments

Within each source code file that you edit, you will need to provide certain comments as documentation. Visual Studio® automatically generates some source code files that you will not need to modify — you don’t need to add comments to those files.

At the top of each file in which you provide code, add a comment of the following form:

/* filename.cs
 * Author: Name 
 */

where filename.cs is the name of the file, and Name is the name of the primary author. The primary author will either be you or, for files provided for you, the name of the original author of that file. Whenever you use someone else’s code, it is important that you give them credit for it. (To fail to do this is plagiarism.) Thus, if one of your source files was originally written by Rod Howell, leave his name as the author. If you have modified a file originally written by someone else, below the Author line, insert a line of the following form:

/*
 * Modified by: Your Name
 */

Prior to each class, structure, enumeration, field, property, and method, place a comment documenting its use. This comment should be delimited by /// on each line. When you type /// immediately above a class, structure, enumeration, field, property, or method, the IDE will automatically insert additional text to form a comment stub such as:

/// <summary>
/// 
/// </summary>

<summary> and </summary> are XML tags, which are understood by the IDE. Between these tags, you should insert a summary of the program component you are documenting, including any requirements that must be satisfied by the calling code in order for the method to work properly. For example:

/// <summary>
/// Indicates whether this structure is empty.
/// </summary>
private bool _isEmpty;

If the program component being documented is a method with at least one parameter and/or a non-void return type, additional XML tags will be generated by the IDE. For each parameter, <param> and </param> tags will be generated. You should insert a description of the use of that parameter between these tags. If the method has a non-void return type, <returns> and </returns> tags are generated. You should insert an explanation of the value being returned between these tags. For example:

/// <summary>
/// Computes the number of times a given string x
/// occurs within a given string y.
/// </summary>
/// <param name="x">The string being searched for.</param>
/// <param name="y">The string being searched.</param>
/// <returns>The number of occurrences of x in y.</returns>
private int Occurrences(string x, string y)
{

}
Note

You do not need to fill in <exception> tags - you may remove any that are generated automatically.

Visual Studio often generates warnings when it cannot verify that the value being assigned to a non-nullable variable is not null. In cases where you can determine that the value will not be null, you are allowed to remove the warning by inserting ! after the value. In such cases, prior to this line, insert a comment explaining why this value is not null. For example:

string line;
while (!input.EndOfStream)
{
    // Because input isn't at the end of the stream, ReadLine won't return null.
    line = input.ReadLine()!;
}

Comments should also be used within methods to explain anything that is not obvious from the code itself.

Prohibited Features

The following features of C# should not be used on assignments or quizzes unless otherwise stated:

  • The goto statement: It has been over 50 years since Dijkstra published “Go To Statement Considered Harmful” (Communications of the ACM, vol. 11 (1968), pp. 147-148). I am amazed that languages continue to include this statement.

  • The unsafe keyword: The name pretty much says it all.

  • The var keyword: There are very few contexts in which this is needed, and these contexts won’t occur in this class. For all other contexts, it makes the code less readable.

  • Virtual methods: These are useful in large-scale software development; however, they are overused. They will not be needed in the programming we will be doing. (However, virtual methods in the .NET class library may be overridden.)

  • Abbreviated constructor calls: Beginning with C# version 9.0, constructor calls are allowed to be abbreviated when the compiler can determine from the context the type of object that is being constructed. In such a case, the type name can be omitted from the new operator. For example, instead of writing:

    StringBuilder sb = new StringBuilder();

    we can write:

    StringBuilder sb = new();

    If the constructor takes parameters, they can be inserted between the parentheses. Such abbreviations are permitted - even encouraged - in cases like the above example, where the type being constructed is explicitly specified elsewhere in the same statement. However, if the type name is not explicitly specified elsewhere in the same statement, such abbreviations are prohibited, as they make the code harder to read.