Defensive, Offensive and Aggressive programming

Development stance

An approach to software development is guided by an underlying philosophy or mindset known as a “development stance,” which also influences the culture and decision-making of the team. It is more flexible and abstract, allowing for customization based on the requirements and context of the project.

Development method (methodology)

A development method is an organized and formalized collection of procedures, techniques, and equipment used in software development that provides a thorough, step-by-step plan for completing a project. It has clear rules and guidelines to ensure consistency and adherence to best practices, making it more prescriptive and strict.

Defensive programming

The concept of this approach is to develop code that can run properly even in unforeseen states, user inputs, etc. It means that the developer should anticipate different states and try to handle them to make the software continue properly. To make it happen, we should consider different terms:

  • Handle unexpected user inputs, data, etc. comprehensively.
  • Increase the code quality and reduce bugs through code review, static and dynamic analysis, etc.
  • Develop and run different levels of tests, such as test units, functional tests, etc., as much as possible.

It also helps to ensure any new revision can pass the last test, as it will pass the new tests. even the ones that should not happen. For instance, an empty list, or a null pointer, exceeding the expected length can lead to unexpected behaviour from the method, but in defense programming, we will go further and cover the internal errors as well, which might not be efficient.

But there is a paradox in this approach since we can not cover every possible state other than making the code more complicated, it demands more resources to be spent, such as money, time, and energy.

When to use Defensive programming

If you are interfacing directly with our world, especially hardware or any kind of communication or libraries that might have unforeseen behaviours you need to consider handling the exceptions that might happen because of timeout, failure, etc.

Handling the exceptions is not a good approach during the development process since the developer won’t be aware of the problem. The recommendation is to use the defensive approach for production rather than development. If there is any error or mistake, we need to know about it and fix it.

Pros
  • Make the critical systems more stable & reliable as they continue working
  • Cover even the not probable conditions
Cons
  • Hiding the errors and problems
  • It is hard to debug the code other than by logging any errors.
  • Make the code more complicated to cover all the states

Example

public class DefensiveProgramming {
    public static int divide(int numerator, int denominator) {
        if (denominator == 0) {
            System.out.println("Error: Division by zero is not allowed.");
            return -1; // Return an error code or throw an exception
        }
        return numerator / denominator;
    }

    public static void main(String[] args) {
        int result = divide(10, 0);
        if (result != -1) {
            System.out.println("Result: " + result);
        }
    }
}

Offensive programming

Offensive programming can be thought of as a branch of defensive programming with a different attitude. While defensive programming stresses handling all kinds of exceptions due to external and internal reasons, offensive programming emphasizes leaving internal reasons to rise and trying to catch the external source. So it divides the errors into two categories: acceptable and preventable

What is acceptable?
  • invalid (not proper) external inputs containing user inputs and other external sources
  • Hardware-related errors/failures
  • The system caused exceptions from system resources such as storage, network, and memory
What should be handled
  • Out of defined conditions, input values for the internal functions (range, length)
  • Undefined condition behaviours and return values
  • Invalid function input parameters

In simple terms, the offensive programming approach makes the errors bold and detectable.

Pros
  • Nice approach for the development process
  • Simpler code compared to defensive programming
  • No hiding the bugs
  • Force to deal with the bug dut to let it be revealed. We need to Fail Fast
Cons
  • Might influence the reputation because of the crashes
  • Make the system unstable
  • Can not be used in critical, real-time or safety-critical services and systems
  • It can’t be ignored by customers if they appear repeatedly

Note: For the system’s critical modules, services, and applications, it is vital to have minimal offensive programming and not rely on the proper input.

Note: We will cover input validation (such as user input, or external sources) later as an approach to secure the software but not to shut down the exceptions.

Example

public class OffensiveProgramming {
    public static int divide(int numerator, int denominator) {
        assert (denominator != 0) : "Denominator cannot be zero";
        return numerator / denominator;
    }

    public static void main(String[] args) {
        int result = divide(10, 0); // Will throw an AssertionError if assertions are enabled
        System.out.println("Result: " + result);
    }
}

Aggressive programming

In a time-critical project where delivery time plays a crucial role, we need to take another approach to make it possible to meet the deadline. It ought to only focus on the most important features and functionalities of software, rather than all aspects. It might happen once in the lifetime of the project to get a prototype ready. At this moment, we try to put as much effort into feature development as possible while having an appropriate plan for testing. Aggressive programming is an approach suited for these times. But after the delivery, we need to adjust the plan again to work on the other aspects skipped during the development. For instance, the way of communicating, modules, etc. might be changed while we have a plan to get back to normal development.

We can list out other kinds of programming, such as functional, object-oriented, etc. We tried to look at those programming approaches more directly relating to security; however, I cannot refute that a clean architecture, modularity, etc. can lead to having a better quality that affects security as well.

Best practice

To take the best approach, we need to combine different approaches: – In the development process, using offensive programming helps to find the bugs as soon as possible before delivering it to the customers – Having defensive programming for the inputs coming from the external source is needed, especially for hardware related inputs. For the released version, it’s better to report the bugs and errors silently. Then the product continues working while we get feedback from the logs and fix them for the new versions

Leave a Comment

Your email address will not be published. Required fields are marked *