1.4-Software-Development-Principles

Principles for writing software

Introduction

There are two important principles that you must always remember and apply as you are writing software.

  1. KISS
  2. DRY

KISS

The acronym KISS stands for “Keep It Simple, Stupid” or “Keep It Small and Simple” (or some variation thereof) and is a design principle that emphasises that systems will function better when they are divided into simple tasks rather than one very complex one. The essence of KISS is avoiding unnecessary complexity.

The KISS principle in software engineering emphasises the value of simplicity in design and implementation. By keeping your code simple, responsible for only one thing and well-structured, it becomes more readable, maintainable and often more efficient. This foundational approach is extremely useful for beginning programmers and for learning good programming habits.

Measuring complexity

How do you know if your software has become too complex? One measurement is called “cyclomatic complexity”.

Cyclomatic complexity is a measurement in software engineering that is determined by the number of different paths your code can take. For instance a basic if-then-else statement always adds two paths. Even when there is no else! switch statements add a path for each option and one default path. And finally loops will multiply the complexity by the number of paths within the loop.

It’s not just about counting the number of statements, but more about how these statements interact with each other. It helps developers to recognise parts of the code that are difficult to maintain or test.

So in conclusion code with a high cyclomatic complexity is usually much more difficult to maintain. Such code requires a lot more tests to ensure that all possible paths (or branches) are covered. See also the lesson about unittests and branch coverage. The video talks about branch coverage from timestamp 13:00.

Plugins for IntelliJ

Open the settings window and go to plugins: Settings -> Plugins

If you install the CodeMetrics tool, from the marketplace, your code will from then on be annotated with “suggestions” like this:

CodeMetrics report

Everything below 5 is good. Anything above 15 may be worthy of refactoring. (Of the code already looks really simple to you, please ignore the plugin.)

DRY

The acronym DRY stands for “Don’t Repeat Yourself”. Once you have written a certain piece of code. That same piece of code or similar ones should not appear elsewhere in your program.

It is a fundamental principle in software design that says that you don’t want any, or at least a minimal amount, of repetitions in your code. The idea is that every piece of knowledge (data or logics) should be implemented only once. If there is a mistake in the way you solved this, there is only one location to update.

This also improves maintainability and avoids mistakes. It makes the code clearer and easier to understand.

Hier is een eenvoudig voorbeeld in Java om het DRY-principe te illustreren.

A Non-DRY Example (Insert joke here)

Let us imagine a program that does a set of calculations multiple times:

public class NonDryExample {
    public static void main(String[] args) {
        int num1 = 5;
        int num2 = 10;
        int som1 = num1 * 2 + num2 * 2;

        int num3 = 15;
        int num4 = 20;
        int som2 = num3 * 2 + num4 * 2;

        // More code that repeats the caclulationt...
    }
}

Clearly the same calculation (num * 2 + othernum * 2) is repeated multiple times. This violates the DRY principle.

A DRY Example

A better approach is to store this knowledge in a method that does the calculation:

public class DryExample {

    public static void main(String[] args) {
        int num1 = 5;
        int num2 = 10;
        int som1 = calcSum(num1, num2);

        int num3 = 15;
        int num4 = 20;
        int som2 = calcSum(num3, num4);

        // The same method can now be used for future calculations...
    }

    private static int calcSum(int a, int b) {
        return a * 2 + b * 2;
    }
}

In this example the way of doing the calculation is stored in the calcSum method, this single method is called multiple times. Every time you need to do this calculation, you simply run this method. In this case the code is not any shorter, but it is “cleaner”.

Additionally:

Another DRY example (based on knowledge)

The DRY principle is not only applicable to code-logic, it can also be applied to knowledge within an application. “Knowledge” can mean data, configuration or even documentation. Het core idea once again is to generate a single source of truth for each piece of information.

Let’s assume a simple situation where a Java class uses the same small piece of information in two places:

public class NonDryKnowledgeExample {
    public void displaySettings() {
        System.out.println("Maximum number of users: 100");
        // ... other settings
    }

    public void checkUserLimit() {
        if (currentUsers > 100) {
            System.out.println("User limit reached");
        }
        // ... other logic
    }
}

In this example you may notice that the of the value 100 (the maximum number of users) is expressed in two separate places. Any change to this value requires adapting your code in all of those locations. This is once again a really stupid example, but you can image how this can escalate.

How to improve?

A better way is to define this value is one single location and then refer to that instead. If you ever need to change this information, then there is one single location where you need to do that.

public class DryKnowledgeExample {
	// Define our information once.
    private static final int MAX_USERS = 100;

    public void displaySettings() {
		// Reference one.
        System.out.println("Maximum number of users: " + MAX_USERS);
        // ... other settings
    }

    public void checkUserLimit() {
		// Reference two.
        if (currentUsers > MAX_USERS) {
            System.out.println("User limit reached");
        }
        // ... other logic
    }
}

Conclusion

As you write more complex applications during this modules and the ones from year two, you will find more and more reasons to divide your knowledge in simple methods. It is our intention that this skill will continue to improve over the years as you interact with other developers which have learned other useful tips and tricks, or possibly very good reasons to sometimes break these rules.

For now this means that during the exam we will deduct points when you break these principles. So as you make the assignments for these modules keep track of duplicate pieces of code and try to rewrite them so that the same piece of code is used in both cases. (IntelliJ actually notes code duplication.)