Zero checking a null object pattern

The main purpose of the Null Object pattern is to provide the client with a useful object. Therefore, we want to replace the following code ...

void Class::SetPrivateMemberA() { m_A = GetObject(); } void Class::UseA() { if (m_A != null) { m_A.Method(); } else { // assert or log the error } } 

... with this implementation:

 void Class::SetPrivateMemberA() { m_A = GetObject(); } void Class::UseA() { m_A.Method(); } 

The problem I'm thinking of is that GetObject () is still returning an object, a NULL object or otherwise. I like the idea of ​​not repeating the null check and trusting that the returned object can be used, but why don't I just do it in the first implementation?

Is the advantage of the Null Object template a slight increase in trust for clearing code? As for the second implementation, is it really not recommended to check that it is not null before calling A.Method ()?

+4
source share
2 answers

You are right that if you are sure that you never return zeros, just skip the zero check before calling the method in the first implementation. Similarly, if you need to do something special when UseA() needs to do something different on a null object, you still need to explicitly check the null object. However, which pattern of the null object really helps are situations in which it does not really matter.

Take, for example, most observer patterns. If you implement your observer pattern as a member of your class for which there can be only one observer, and want to tell the observer that your class has done something, it does not matter for the class whether the observer is null or not.

This is also illustrated by empty container classes, which are essentially a null object template. Instead of returning an empty container from the request, you simply return an empty container. For things like iterating through all container entries, it often doesn't matter if it is empty or not, so eliminating the need for zero checking makes the code more convenient and readable. However, if you want to fill out the view of your dataset, you still need to explicitly show different "No records". which checks an empty container.

Edit for clarity.

One problem is only to look at it from the call site. Like most design patterns, this should cover both sides, which should be fully utilized. Consider:

 public PossiblyNull GetSomethingNull() { if (someBadSituation()) return null; else return SomehowProduceSomething(); } 

against

 public PossiblyEmpty GetSomethingEmpty() { if (someBadSituation()) return StaticEmptySomething(); else return ProdueSomethingYay(); } 

Now your calling code instead of looking like

 public void DoSomethingWithChild(Foo foo) { if (foo != null) { PossiblyNull bar = foo.GetSomething(); if (bar != null) bar.DoSomething(); } } 

it could be

 public void DoSomethingWithChild(Foo foo) { if (foo != null) foo.GetSomething().DoSomething(); } 
+4
source

With the second implementation, is it still not good practice to verify that it is not null before calling A.Method ()?

Not. If you know that m_A is not null then checking is redundant; This is an example of paranoid coding. What harm is he doing? This complicates your code - unnecessarily; it makes reading difficult, more difficult to debug.

0
source

Source: https://habr.com/ru/post/1302927/


All Articles