The main goal of the Null Object Pattern is to ensure that a usable object is provided to the client. So 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 am thinking of is that GetObject() still returns an object, a NULL Object or otherwise. I like the idea of not checking for null repeatedly and trusting that the object sent back is usable, but why wouldn't I just do that in the first implementation?
Is the advantage of the Null Object pattern just a slight increase in trust to clean up code? With the second implementation, is it not still a good practice to check that it is not null before calling A.Method()?
You're correct that, if you're sure you're never returning nulls, just skip the null check before calling the method in your first implementation. Likewise, if you do need to do something special in the case that UseA() needs to do something differently on a null object, that you need to explicitly check for a null object anyway. However, what null object pattern really helps with is those situations where it doesn't really matter.
Take, for example, most observer patterns. If you implement your observer pattern as a member of your class for which there can only be one observer, and want to announce to the observer that your class did something, it doesn't matter to the class whether the observer is null or not.
This is also illustrated with empty container classes, which are essentially the null object pattern: Instead of returning a null container from a query, you simply return an empty container. For things like iterating through all entries of a container, it often won't matter whether it's empty or not, so getting rid of the need of a null check makes the code more maintainable/more readable. However, if you want to populate a view of your data set, you still need to explicitly show a different "No entries." that checks for an empty container.
Edit for clarity
One problem is only looking at it from the call site. Like most design patterns, this needs to encompass both sides to be fully utilized. Consider:
public PossiblyNull GetSomethingNull()
{
if (someBadSituation())
return null;
else
return SomehowProduceSomething();
}
vs
public PossiblyEmpty GetSomethingEmpty()
{
if (someBadSituation())
return StaticEmptySomething();
else
return ProdueSomethingYay();
}
Now, your call code, instead of looking like
public void DoSomethingWithChild(Foo foo)
{
if (foo != null)
{
PossiblyNull bar = foo.GetSomething();
if (bar != null)
bar.DoSomething();
}
}
it can be
public void DoSomethingWithChild(Foo foo)
{
if (foo != null)
foo.GetSomething().DoSomething();
}
With the second implementation, is it
not still a good practice to check
that it is not null before calling
A.Method()?
No. If you know that m_A is not null, then the check is superfluous; it's an example of paranoid coding. What harm does it do? It complicates your code - unnecessarily; it makes it harder to read, harder to debug.
Related
I use a monitoring class Progress. In a lot of functions, I update the progress if given. The progress variable is optional and given by pointer that could be null. A lot of part of my code look like this:
void do_the_job(Progress* progress)
{
do_part_1();
if((bool)progress)
progress->set(0.25f);
do_part_2();
if((bool)progress)
progress->set(1.0f);
}
Before creating it myself, I'm looking for a kind of smart pointer checking for me if it's null and ignoring the call if null. Somthing that could be used like this:
void do_the_job(boost::could_be_null_ptr<Progress> progress)
{
do_part_1();
progress->set(0.25f); // ignored if null
do_part_2();
progress->set(1.0f); // ignored if null
}
For compatibility reason, I don't use C++11 or >C++11. Please, only solutions working with C++03.
The function should not have to bother with a null pointer so design the Progress such that it can be used like this:
void do_the_job(XProgress& progress)
{
do_part_1();
progress.set(0.25f);
do_part_2();
progress.set(1.0f);
}
Getting there is simple:
struct XProgress {
std::shared_ptr<Progress> instance;
void set(float x) {
if (instance) instance->set(x);
}
};
In any case you need some instance on which you can call set, so there is no way to avoid reimplementing Progesss interface.
Sorry, missed the "only C++03". If you cannot use shared_ptr use the memory mangagment mechanism of your chioce. Perhaps a raw pointer that gets deleted in XProgress destructor is fine if you disable copying.
I need to check if my object Course is in a safe empty state.
Here is my failed attempt:
const bool Course::isEmpty() const {
if (Course() == nullptr) {
return true;
}
else {
return false;
}
}
Constructors:
Course::Course() {
courseTitle_ = new char[21]; // name
courseTitle_ = '\0';
credits_ = 0;//qtyNeeded
studyLoad_ = 0;//quantity
strcpy(courseCode_, "");//sku
}
Course::Course(const char* courseCode, const char* courseTitle, int credits , int studyLoad ) {
strcpy(courseCode_, courseCode);
courseTitle_ = new char[21];
strcpy(courseTitle_, courseTitle);
studyLoad_ = studyLoad;
credits_ = credits;
}
Apprently, Doing course() == nullptr is not truly checking if the object is in safe empty state, also checking individual variables if they are set to 0 will not work in my program. i need to check if the entire object was set to a safe empty state.
Edit: Some of you are asking what my empty() function is suppose to use. There is a tester that is suppose to test if my isEmpty() works well.
bool isEmptyTest0() {
// empty test
sict::Course c0;
return c0.isEmpty();
}
bool isEmptyTest1() {
// empty test
sict::Course c0("", "title", 3, 3);
return c0.isEmpty();
}
bool isEmptyTest2() {
// empty test
sict::Course c0("code", "", 3, 3);
return c0.isEmpty();
}
bool isEmptyTest3() {
// empty test
sict::Course c0("code", "title", -1, 3);
return c0.isEmpty();
}
bool isEmptyTest4() {
// empty test
sict::Course c0("code", "title", 3, -1);
return c0.isEmpty();
}
bool regularInitTest() {
// regular
sict::Course c5("OOP244", "Object-Oriented Programming in C++", 1, 4);
return (!c5.isEmpty()
&& !strcmp("OOP244", c5.getCourseCode())
&& !strcmp("Object-Oriented Programming in C++", c5.getCourseTitle())
&& (c5.getCredits() == 1)
&& c5.getStudyLoad() == 4
);
}
Note that in regularInitTest() my assignment operators work fine, but it never passes !c5.isEmpty() because it fails. Hopefully i explained it correctly.
Most probably here is what you should do to make the tests pass.
In the 2nd (4-argument) constructor, do some checking of the input, e.g. check if credits is positive. Do check all arguments for all possible errors you can imagine, including those in isEmptyTest0..4. If there is an error, initialize the object the same way as the 1st (0-argument) constructor does. If there is no error, initialize the data members from the arguments.
Here is how to implement the isEmpty method: it should return true iff all the data members of the object have the empty/zero/default value, as initialized by the 1st (0-argument) constructor.
The notion safe empty state in itself still doesn't make sense, but the concept the professor is trying to teach does make sense. I'll try to summarize my understanding here. Constructors can receive invalid arguments, based on which it's not possible to initialize a meaningful and valid object. The programmer should add code for error checking and handling everywhere in the program, including constructors. There are multiple approaches to do input validation and error handling in constructors, e.g. 1. throwing an exception; 2. aborting the entire program with an error message; 3. initializing the object to a special, invalid state; 4. initializing the object to a special, empty state. (This is also an option, but it's strongly disrecommended: 5. keep some data members of the object uninitialized.) Each of these approaches have pros and cons. In this assignment, the professor wants you to implement #4. See the 2nd paragraph in my answer how to do it.
When the professor asks for a safe empty state, he most probably means that you should be doing input validation in the constructor, and in case of an error doing #4 rather than #5.
I agree with pts that safe empty state is ill-defined.
The missing principle, it seems to me after reading the comments, is Resource Acquisition Is Initialization (RAII). A constructor is a transaction, in a way: you get either
a valid object, or
an exception.
Valid here is defined by the class. Usually it means that the passed parameters were incorporated into the object, and all required resources were successfully allocated and/or found.
Aborting the program is rarely an option, and returning an error (from a constructor) never is. Constructing an invalid object is usually done only in environments where exceptions are prohibited.
There is a special case: the default constructor. Sometimes it's desirable to "make an empty" thing that will be fully initialized later.
Consider std::string. It can be constructed with a value, and throws an exception if memory cannot be allocated. Or it can be constructed without a value, and later assigned one. Your class could be similar, in which case safe empty just means a state that the user would be happy to destroy when calling the "init" function. You don't have to test every member variable; you just have to check something that will be true only for a completely initialized object.
Then there's the question of "is valid". An "empty" object can be "initialized", but it can't be used. It's not "valid" for use until fully initialized, whether at construction, or via the 2-step with a default constructor and a subsequent "init".
There is a widely accepted idiom for testing whether an object is "is valid" or not: a user-defined conversion to void *:
...
public:
operator void*() { return is_valid()? this : nullptr; }
...
where is_valid() may be a private function. With that in place, the user can test his instantiated object thus:
class A;
A foo();
...
if (!foo) { foo.open(...); }
I know I haven't answered your question, exactly. I hope I've provided some background that makes it easier for your to answer it yourself.
In my code I have an if-else block condition like this:
public String method (Info info) {
if (info.isSomeBooleanCondition) {
return "someString";
}
else if (info.isSomeOtherCondition) {
return "someOtherString";
}
else if (info.anotherCondition) {
return "anotherStringAgain";
}
else if (lastCondition) {
return "string ...";
}
else return "lastButNotLeastString";
}
Each conditional branch returns a String.
Since if-else statements are difficult to read, test and maintain, how can I replace?
I was thinking to use Chain Of Responsability Pattern, is it right in this case?
Is there any other elegant way that I can do that?
I am left to assume that your code does not exist in the Info class as it is passed in an referenced for all but that last condition. My first instinct would be to make String OtherClass.method(Info) into String Info.method() and have it return the appropriate string.
Next, I would take a look at the conditions. Are they really conditions or can they be mapped to a table. Whenever I see code performing a lookup, such as this, I tend to fall back on attempting to fit into a dictionary or map so I can perform a lookup for the value.
If you are left with conditions that must be checked then I would begin thinking about lambdas, delegates or custom interface. A series of if..then across the same type could easily be represented. Next, you would collect them and execute accordingly. IMO, this would make the if..then bunch much clearer. It is more code by is secondary at this point.
interface IInfoCheck
{
bool TryCheck(Info info, out string);
}
public OtherClass()
{
// Setup checks
CheckerCollection.add(new IInfoCheck{
public String check(out result) {
// check code
}
});
}
public String method(Info info) {
foreach (IInfoCheck ic in CheckerCollection)
{
String result = null;
if (ic.TryCheck(out result))
{
return result;
}
}
}
The problem statement does not fit into an ideal chain of responsibility scenario because it is either/or kind or conditions which look 'chained' but is actually 'not'. Reason - one processes all the chain-links in the chain of responsibility pattern irrespective of what happened in the previous links, i.e. no chain-links are skipped(although you can configure which chain links to process and which not - but still the execution of a chain-link is not dependent on the outcome of a previous chain-link). However, in this if-else-if* scenario - once an if statement condition matches, the further conditions are not evaluated.
I have thought of an alternative design which achieves the above without if-else, but it is lengthier but at the same time more flexible.
Lets say we have a FunctionalInterface IfElseReplacer which takes 'info' as input and gives 'String' output.
public Interface IfElseReplacer(){
public String executeCondition(Info);
}
Then the above conditions can be re-phrased as lambda expressions would look like -
"(Info info) -> info.someCondition ? someString"
"(Info info) -> info.anotherCondition ? someOtherString"
and so on...
Then we need a processConditons method to process these Lambdas- it could be a default method in ifElseReplacer -
default String processConditions(List<IfElseReplacer> ifElseReplacerList, Info info){
String strToReturn="lastButNotLeastString";
for(IfElseReplacer ifElseRep:ifElseReplacerList){
strToReturn=ifElseRep.executeCondition(info);
if(!"lastButNotLeastString".equals(strToReturn)){
break;//if strToReturn's value changes i.e. executeCondition returns a String valueother than "lastButNotLeastString" then exit the for loop
}
return strToReturn;
}
What remains now is to (I am skipping the code for this - please let me know if you need it then will write this also) -
From wherever the if-else conditions need to be checked there -
Create an array of lambda expressions as explained above assigning them to IfElseReplacer interfaces while adding them to a list of type IfElseReplacer.
Pass this list to the default method processConditions() along with an instance of Info.
Default method would return the String value which we would be same as the result of if-else-if* block given in the problem statement.
I'd simply factor out the returns:
return
info.isSomeBooleanCondition ? "someString" :
info.isSomeOtherCondition ? "someOtherString" :
info.anotherCondition ? "anotherStringAgain" :
lastCondition ? "string ..." :
"lastButNotLeastString"
;
From the limited information about the problem, and the code given, it looks like this a case of type-switching. The default solution would be to use a inheritance for that:
class Info {
public abstract String method();
};
class BooleanCondition extends Info {
public String method() {
return "something";
};
class SomeOther extends Info {
public String getString() {
return "somethingElse";
};
Patterns which are interesting in this case are Decorator, Strategy and Template Method. Chain of Responsibility has another focus. Each element in the chain implement logic to process some commands. When chained, an object forwards the command if it cannot process it. This implements a loosly coupled structure to process commands where no central dispatch is needed.
If computing the string on the conditions is an operation, and from the name of the class I am guessing that it is probably an expression tree, you should look at the Visitor pattern.
I'm currently learning C++ and practicing my Knowledge by implementing an simple AddressBook Application. I started with an Entry class and an AddressBook class which implements a STL Map to access the entries by the last names of the persons. Now I arrived at the following code:
Entry AddressBook::get_by_last_name(string last_name){
if(this->addr_map.count(last_name) != 0){
//What can I do here?
} else {
return addr_map[last_name];
}
In Scripting Languages I would just return something like -1, Error Message(A List in Python) to indicate that the Function failed. I don't want throw an exception, because it's part of the application logic. The Calling Class should be able to react to the request by printing something on the console or opening a Message Box. Now I thought about implementing the Scripting Languae Approach in C++ by introducing some kind of an Invalid State to the Class Entry. But isn't that bad practice in C++? Could it be that my whole class design is just not appropriate? I appreciate any help. Please keep in mind that I'm still learning C++.
Some quick notes about your code:
if(this->addr_map.count(last_name) != 0){
//What can I do here?
You probably wanted it the other way:
if(this->addr_map.count(last_name) == 0){
//handle error
But your real problem lies here:
return addr_map[last_name];
Two things to note here:
The operator[] for map can do 2 things: If the element exists, it returns it; If the element doesn't exist, it creaets a new (key,value) pair with the specified key and value's default constructor. Probably not what you wanted. However, if your if statement from before would have been the right way, then the latter would never happen because we would knowthe key exists before hand.
In calling count() before, you effectively tell map to try and find the element. By calling operator[], you are telling map to find it again. So, you're doing twice the work to retrieve a single value.
A better (faster) way to do this involves iterators, and the find method:
YourMap::iterator it = addr_map.find(last_name); //find the element (once)
if (it == addr_map.end()) //element not found
{
//handle error
}
return *it.second; //return element
Now, back to the problem at hand. What to do if last_name is not found?
As other answers noted:
Simplest solution would be to return a pointer (NULL if not found)
Use boost::optional.
Simply return the YourMap::iterator but it seems that you are trying to "hide" the map from the user of AddressBook so that's probably a bad idea.
throw an exception. But wait, now you'll have to first check that calling this method is 'safe' (or handle the exception when appropriate). This check requires a boolean method like lastNameExists which would have to be called before calling get_by_last_name. Of course then we'er back to square 1. We're performing 2 find operations to retrieve a single value. It's safe, but if you're doing A LOT of calls to get_by_last_name then this is potentially a good place to optimize with a different solution (besides, arguably the exception is not very constructive: What's wrong with searching for something that isn't there, huh?).
Create a dummy member for Entryindicating that is not a real Entry but that is very poor design (unmanageable, counter intuitive, wasteful - you name it).
As you can see, the first 2 solutions are by far preferable.
One dead-simple option is to change the return type to Entry* (or const Entry*) and then return either the address of the Entry if found, or NULL if not.
If you use Boost, you could return a boost::optional<Entry>, in which case your success code would be the same, but on not-found you'd say return boost::none. This is fancier, but does about the same thing as using a pointer return type.
Throwing an exception is definitely the 'correct' C++ thing to do, based on your function return type.
You might want a function like this to help you, though:
bool AddressBook::lastNameExists(const string &last_name)
{
return addr_map.count(last_name) > 0;
}
Note that your current code returns the entry 'by value' so modifying the returned entry won't update the map. Not sure if this is by accident or design...
Other answers have given various approaches, most of them valid. I didn't see this one yet:
You could add a second parameter with a default value:
Entry AddressBook::get_by_last_name(string last_name, const Entry& default_value){
if(this->addr_map.count(last_name) == 0){
return default_value;
} else {
return addr_map[last_name];
}
In this particular instance, there might not be a sensible default value for a non-existing last name, but in many situations there is.
In C++ you have several ways of signalling that an issue happened in your function.
You can return a special value which the calling code will recognize as an invalid value. This can be a NULL pointer if the function should return a pointer, or a negative value if your function returns an index in an array, or, in the case of a custom class (e.g. your Entry class) you can define a special Entry::invalid value or something similar that can be detected by the calling function.
Your calling code could look like
if ( entryInstance->get_by_last_name("foobar") != Entry::invalid)
{
// here goes the code for the case where the name is valid
} else {
// here goes the code for the case where the name is invalid
}
On the other hand you can use the C++ exceptions mechanism and make your function throw an exception. For this youcan create your own exception class (or use one defined in the standard library, deriving from std::exception). Your function will throw the exception and your calling code will have to catch it with a try...catch statement.
try
{
entryInstance->get_by_last_name("foobar")
}
catch (Exception e)
{
// here goes the code for the case where the name is invalid
}
// here goes the code for the case where the name is valid
Apart from the fact that you could have more than one entry per surname.
Eliminate the getter, and you've solved the problem, or at least shifted it elsewhere.
Tell the AddressBook to display people with given surnames. If there aren't any it can do nothing.
AddressBookRenderer renderer;
AddressBook contacts;
contacts.renderSurnames("smith", renderer);
contacts.renderCompletions("sm", renderer);
//etc
You can do what std::map (and the other containers do).
You return an iterator from your search function.
If the search does not find a value that is useful return an iterator to end().
class AddressBook
{
typedef <Your Container Type> Container;
public:
typedef Container::iterator iterator;
iterator get_by_last_name(std::string const& lastName) {return addr_map.find[lastName];}
iterator end() {return addr_map.end();}
};
Your address book is a container like object.
Not finding an item in a search is likely to happen but it does not have enough context to incorporate error handling code (As the address book could be used from lots of places and each place would have different error handling ideas).
So you must move the test for not found state out of your address book.
just like "Python" we return a marker. In C++ this is usually an iterator to end() which the calling code can check and take the appropriate action.
AddressBook& ab = getAddressBookRef();
AddressBook::iterator find = ab.get_by_last_name("cpp_hobbyist");
if (find != ab.end())
{
Entity& person *find; // Here you have a reference to your entity.
// you can now manipulate as you want.
}
else
{
// Display appropriate error message
}
I've stumbled across this great post about validating parameters in C#, and now I wonder how to implement something similar in C++. The main thing I like about this stuff is that is does not cost anything until the first validation fails, as the Begin() function returns null, and the other functions check for this.
Obviously, I can achieve something similar in C++ using Validate* v = 0; IsNotNull(v, ...).IsInRange(v, ...) and have each of them pass on the v pointer, plus return a proxy object for which I duplicate all functions.
Now I wonder whether there is a similar way to achieve this without temporary objects, until the first validation fails. Though I'd guess that allocating something like a std::vector on the stack should be for free (is this actually true? I'd suspect an empty vector does no allocations on the heap, right?)
Other than the fact that C++ does not have extension methods (which prevents being able to add in new validations as easily) it should be too hard.
class Validation
{
vector<string> *errors;
void AddError(const string &error)
{
if (errors == NULL) errors = new vector<string>();
errors->push_back(error);
}
public:
Validation() : errors(NULL) {}
~Validation() { delete errors; }
const Validation &operator=(const Validation &rhs)
{
if (errors == NULL && rhs.errors == NULL) return *this;
if (rhs.errors == NULL)
{
delete errors;
errors = NULL;
return *this;
}
vector<string> *temp = new vector<string>(*rhs.errors);
std::swap(temp, errors);
}
void Check()
{
if (errors)
throw exception();
}
template <typename T>
Validation &IsNotNull(T *value)
{
if (value == NULL) AddError("Cannot be null!");
return *this;
}
template <typename T, typename S>
Validation &IsLessThan(T valueToCheck, S maxValue)
{
if (valueToCheck < maxValue) AddError("Value is too big!");
return *this;
}
// etc..
};
class Validate
{
public:
static Validation Begin() { return Validation(); }
};
Use..
Validate::Begin().IsNotNull(somePointer).IsLessThan(4, 30).Check();
Can't say much to the rest of the question, but I did want to point out this:
Though I'd guess that allocating
something like a std::vector on the
stack should be for free (is this
actually true? I'd suspect an empty
vector does no allocations on the
heap, right?)
No. You still have to allocate any other variables in the vector (such as storage for length) and I believe that it's up to the implementation if they pre-allocate any room for vector elements upon construction. Either way, you are allocating SOMETHING, and while it may not be much allocation is never "free", regardless of taking place on the stack or heap.
That being said, I would imagine that the time taken to do such things will be so minimal that it will only really matter if you are doing it many many times over in quick succession.
I recommend to get a look into Boost.Exception, which provides basically the same functionality (adding arbitrary detailed exception-information to a single exception-object).
Of course you'll need to write some utility methods so you can get the interface you want. But beware: Dereferencing a null-pointer in C++ results in undefined behavior, and null-references must not even exist. So you cannot return a null-pointer in a way as your linked example uses null-references in C# extension methods.
For the zero-cost thing: A simple stack-allocation is quite cheap, and a boost::exception object does not do any heap-allocation itself, but only if you attach any error_info<> objects to it. So it is not exactly zero cost, but nearly as cheap as it can get (one vtable-ptr for the exception-object, plus sizeof(intrusive_ptr<>)).
Therefore this should be the last part where one tries to optimize further...
Re the linked article: Apparently, the overhaead of creating objects in C# is so great that function calls are free in comparison.
I'd personally propose a syntax like
Validate().ISNOTNULL(src).ISNOTNULL(dst);
Validate() contructs a temporary object which is basically just a std::list of problems. Empty lists are quite cheap (no nodes, size=0). ~Validate will throw if the list is not empty. If profiling shows even this is too expensive, then you just change the std::list to a hand-rolled list. Remember, a pointer is an object too. You're not saving an object just by sticking to the unfortunate syntax of a raw pointer. Conversely, the overhead of wrapping a raw pointer with a nice syntax is purely a compile-time price.
PS. ISNOTNULL(x) would be a #define for IsNotNull(x,#x) - similar to how assert() prints out the failed condition, without having to repeat it.