3

I took a PHP test for NASA recently and thought I should have done better. I believe the issue is something I used to know about, but need a refresher in. I can't remember what it is called though. It is the concept that you have to check for null, empty, and edge-cases. No, it's not unit testing or anything like that. It is a programming technique involving conditionals, equality, and existence tests, and then handling error exceptions.

Does anyone know what the web-searchable, hash-taggable, technical term for this technique is?

  • 5
    Your description sounds somewhat contradictory. Checking for null references doesn't sound proactive at all to me, but purely reactive. Proactive would mean to never have null references in the first place. – Jörg W Mittag Jan 29 '21 at 10:18
  • @JörgWMittag I see. Perhaps proactive isn't the best word. It seems that @Glorfindel has found a more appropriate term with `defensive`. – Eric Hepperle - CodeSlayer2010 Jan 29 '21 at 10:30
  • 1
    I have edited the question and removed the word "proactive" trying to not lure opinionated answers. Hope it helps. – Laiv Jan 29 '21 at 10:35
  • Do you mean assertions? – Pieter B Jan 29 '21 at 12:12
  • 2
    Checking for nulls and edge cases is definitely not restricted to OOP, I took the freedom to edit the question accordingly; this does not seem to invalidate the current answer. – Doc Brown Jan 29 '21 at 15:01
  • It's called edge case testing – Cap Barracudas Jan 29 '21 at 15:24
  • Of course, the question arises about what you should if you encounter a NULL. See https://softwareengineering.stackexchange.com/questions/220444/should-we-always-write-defensive-null-check-in-code – fpmurphy Jan 29 '21 at 16:56
  • See also https://en.wikipedia.org/wiki/Off-by-one_error, which mentions "boundary conditions". – Erik Eidt Jan 29 '21 at 17:20
  • 3
    It can go by many different names, but these are all examples of needing to do input validation. – rwong Jan 30 '21 at 04:26
  • 2
    I agree that defensive programming is the right topic. I also agree that input validation covers what you mention. See also [fail-fast](https://en.wikipedia.org/wiki/Fail-fast), and contrast offensive programming and exception handling. You might also find [Circuit breaker design pattern](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) interesting. – Theraot Jan 31 '21 at 15:24
  • 1
    For a context shift, consider [Total functions (as understood in math and functional programming)](https://softwareengineering.stackexchange.com/q/334874/45814), which (along with restriction on recursion) must be defined for all possible inputs. – Theraot Jan 31 '21 at 15:24

3 Answers3

10

It's part of defensive programming, but that may encompass many other things:

Defensive programming is a form of defensive design intended to ensure the continuing function of a piece of software under unforeseen circumstances. Defensive programming practices are often used where high availability, safety, or security is needed.

Defensive programming is an approach to improve software and source code, in terms of:

  • General quality – reducing the number of software bugs and problems.
  • Making the source code comprehensible – the source code should be readable and understandable so it is approved in a code audit.
  • Making the software behave in a predictable manner despite unexpected inputs or user actions.

(source: Wikipedia)

Glorfindel
  • 3,137
  • 6
  • 25
  • 33
  • 2
    The OP is asking for a "proactive" approach though, whereas I would argue defensive programming is very much reactive. Proactive to me would mean making sure that you never have null references in the first place. Design-by-contract, static analysis, or choosing a different programming language would be more proactive, I think. – Jörg W Mittag Jan 29 '21 at 10:16
  • 3
    Like your comment under the question, I don't think that his and our definitions of the word 'proactive' coincide. – Glorfindel Jan 29 '21 at 10:23
  • 2
    @JörgWMittag I somehow agreed with Glorfindel. When you say reactive, what do you mean? What makes defensive programming or checking nulls to be a reactive approach? Because we have allowed nulls to happen due to a wrong decision or flawed design? – Laiv Jan 29 '21 at 10:27
  • @Glorfindel Yes, defensive programming seems like it could be the answer I'm looking for. Next I need to figure out where to get a refresher tutorial on these techniques. Do you think this would be part of a PHP debugging course? Or might it be more likely to be found as a PHP security course? I'm taking lots of LinkedIn Courses in whatever I find needs improvement. – Eric Hepperle - CodeSlayer2010 Jan 29 '21 at 10:34
  • 1
    @EricHepperle-CodeSlayer2010 I have no idea. I only use PHP when forced to, and I have some control over the input (and hence defensive programming is less necessary). But 'security' often covers things like SQL injection, XSS and other hacking tricks. – Glorfindel Jan 29 '21 at 10:43
  • 1
    @Laiv: A null reference is something that should not happen normally. If you have one, something has *already gone wrong*, but instead of making sure it doesn't go wrong, you are *reacting* to the problem by checking for a situation that shouldn't have happened in the first place. *Proactive* would be to make sure that the situation cannot happen. – Jörg W Mittag Jan 29 '21 at 10:45
  • Eric, remember that patterns are mean to solve programming language deficiencies. Sure defensive programming engloves some known design and patterns but ultimately, they will depend on the features of the language. As @JörgWMittag commented, some languages don't even allow nulls. For example, defensive programming will result in different techniques depending on whether I use Java or Kotlin. In any case, it takes a good understanding of the languages, overall of their weaknesses – Laiv Jan 29 '21 at 10:47
  • 2
    A defensive driver is someone who doesn't hang their personal safety on the assumption that others will operate their vehicles correctly. A defensive programmer is someone who doesn't hang the safety of their code on the assumption that other parts of the system will behave correctly. If you are assuming the caller won't pass you a null when they're not supposed to, you're doing it wrong. People make mistakes. If you program defensively, you prevent their mistakes from propagating to other parts of the system in an unpredictable way. – John Wu Jan 30 '21 at 06:51
  • @Jörg “A null reference should not normally happen”. With the right language support, like in Swift, null references are quite normal, impossible to use without checking, and references that shouldn’t be null cannot ever be null. – gnasher729 Jan 31 '21 at 12:35
  • 1
    I don't believe the phrase "defensive" applies here. To me, defensive applies to handling conditions that aren't expected/supposed to happen but sometimes do (e.g. in the driving analogy above, when other drivers drive badly). However, empty input and edge cases are 100% expected, must always be handled. In some situations, NULL is 100% expected too; it may not be the result of an error or allocation failure, but simply the way a function reports a negative result. I think "error checking" may be a better answer. TBH, I'm tempted to simply say "programming" is the real answer! – Stephen Warren Feb 01 '21 at 05:13
  • 1
    The Wikipedia article you quote from has serious issues and is flagged as such. Defensive design/programming is the wrong general term to use for input validation. Safe coding practice? – fpmurphy Feb 01 '21 at 06:21
  • 1
    @JörgWMittag: Defensive programming isn't reactive. Defensive programming revolves around defending yourself _before_ an "attack" happens. It's almost the textbook approach that preaches default blanket development practice, specifically, to pre-empt any issues that may occur further down the line (even though you may be able to prevent them today). It's one of the most proactive things you can do. Reactive means responding when the proverbial feces hits the fan - which is exactly the thing which defensive programming aims to prevent. Defensive programmers have feces-free fans, ideally. – Flater Feb 01 '21 at 16:39
3

If you are referring to a particular check, that is usually called a “guard condition”, if you are talking about using guard conditions that would be defensive programming.

Some languages have ways to embed particular types of such checks in the language, which is typically done through the type system. For instance C# allows you to create a variable where the type is a non-null string. Pascal allows you to declare a type where the underlying value is an integer between 18 and 120.

jmoreno
  • 10,640
  • 1
  • 31
  • 48
2

If a function argument can be null, but is never supposed to be null, you have three choices: a. You ignore this and whatever happens, happens. B. You check and if the pointer is null you report an error, throw an exception, kill the program, whatever seems most appropriate. C. You check and if the pointer is null you muddle through as best as you can. C. would likely be called “defensive programming”

You decide on a case-by-case basis what to do. Usually you look at it from a higher level where you decide “if this pointer, which should never be null, ends up being null, what’s the best thing to do”. During development the best would often be to fall into the debugger so the developer can figure out why the pointer is null and fix the problem. In production you need to decide intelligently what to do. In many situations it’s better for a program to crash than to give wrong results.

PS. In C++, a null reference is undefined behaviour. For example "int* p = NULL; int& r = *p;". Since it is undefined behaviour, checking that an int& reference that your function received is a null reference won't necessarily work. The compiler can say "null references are undefined behaviour, therefore there are no null references, therefore a check if (&r == NULL) is assumed to always fail". In Java, references to objects can be nil so you can check for it.

Xcode + Clang in C and C++ have an interesting feature: Since they don't know if a pointer argument is allowed to be a null pointer or not, they assume that the caller passed in a non-null pointer to avoid gazillions of warnings. But once you check whether it is null, the compiler assumes it can be null (or why would you have checked?) So

if (p == NULL) printf ("Error, p is null\n");
*p = 1; 

will give you a warning. Without the p == NULL check, no warning.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
  • 1
    *You check and if the pointer is null you muddle through as best as you can.* Honestly, I'd call that ***offensive*** programming - as in offensively bad programming. That's probably the worst thing you can do if you find an argument with a value it's never supposed to have. If `x` is never supposed to be null but you get a null value for `x`, by continuing you've just silently propagated a bug further along. That's how you wind up with systems that have nine 5's for reliability... – Andrew Henle Mar 21 '21 at 13:28
  • Andrew, this is where you post your alternative that i didn’t mention. So there’s a fighter pilot under attack, and a null pointer comes in. What would that fighter pilot want you to do? – gnasher729 Mar 21 '21 at 14:37
  • @gnasher729 As if any of us are writing jet fighter code. Yes, there are rare exceptions (also medical devices) where crashing is ugly. But too often programmers follow the [PHP Fractal of Bad Design](https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/) philosophy: "When faced with either doing something nonsensical or aborting with an error, it will do something nonsensical." – user949300 Mar 21 '21 at 15:03
  • @gnasher729 Replace "fighter pilot under attack" with "Boeing 737MAX right after takeoff" to get a better feel for the consequences of propagating a bug because you write code to low standards. You already covered the alternatives: you return an error or throw an exception. Ignoring the problem totally or trying to keep working despite an out-of-spec input not only allows the bug to continue to exist but expands its impact. How is that a good idea? – Andrew Henle Mar 21 '21 at 15:25