Posts tagged ‘software engineering’

C++ is bad: structs aren’t the same as structs

Here’s a fun little problem. Suppose you’ve got a system that makes use of the following struct:

struct User {
  unsigned int user_id;
  unsigned short access_level;
  float account_balance;  // stored as US dollars
}

Your system is ridiculously well-tested, all the tests pass, everything works totally fine. I’ll be so bold as to say it’s (kinda) bug-free.

One day, you decide to add a new field to the User struct, a string called name. You recompile everything, and suddenly all kinds of tests fail! New users have all kinds of access levels, some have account balances in the billions while others have accounts worth negative billions. What happened, why, and how do you fix it (without removing name again)? Edit: and no, the code does not rely on brittle assumptions about the value of sizeof(User), nor does it break type safety and have unsafe casts or void*’s pointing into the middle of Users. That would be too easy.

The answers, and more →

Getters and Setters aren’t all they’re cracked up to be

Allen Holub, author of Holub On Patterns, has an interesting article on how if you use getters and setters, you’re probably doing it wrong.

His main claim is that getters and setters are a way of shoehorning procedural design into an object-oriented language, done by people who don’t really understand the difference between a C-style struct and a class. He mentions a course taught in the ’80s by Beck and Cunningham, in which they lament, “the most difficult problem in teaching object-oriented programming is getting the learner to give up the global knowledge of control that is possible with procedural programs, and rely on the local knowledge of objects to accomplish their tasks. Novice designs are littered with regressions to global thinking: gratuitous global variables, unnecessary pointers, and inappropriate reliance on the implementation of other objects.” Holub talks about the CRC design model, in which Classes have Responsibilities and Collaborators. The idea is that the interface to a class should be a list of actions the class can do (its responsibilities) for the other classes it works with (its collaborators). In particular, the interface should not be a list of what data the class can store/retrieve for strangers (which is what getters/setters really are). Under this model, he claims that nearly all getters/setters can be removed in favor of functions that do the work you wanted for you, rather than giving you the info you need to do the work yourself.

Examples, motivations, and discussion →

C++ is bad: inheritance is counterintuitive

In our latest installment of “why not to program in C++,” let’s take a look at a simple class hierarchy:

class Duck {
 public:
  Duck() {
    InitializeMigratoryRoute();
  }

  // Default behavior is nonmigratory; this is
  // overridden in the Mallard class.
  virtual void InitializeMigratoryRoute();
}

class Mallard : public Duck {
 public:
  Mallard();

  // Migrate south in the fall and north in the spring
  virtual void InitializeMigratoryRoute();
}

class DonaldDuck : public Duck {
 public:
  DonaldDuck() {
    outfit_.AddShirt(Outfit::Shirts::SAILOR);
    outfit_.AddHat(Outfit::Hats::SAILOR);
  }

 private:
  Outfit outfit_;
}

You can assume this code compiles and runs (i.e., the Outfit class is defined, it implements AddShirt(), both versions of InitializeMigratoryRoute() are defined, etc). I would say this looks like perfectly reasonable code: its intention is clear and straightforward, and any sane language should have no trouble implementing this. [1] However, we’re dealing with C++, which means there are always more problems, and in fact this code is not in the least alright. In particular, there are two major things wrong with it. Do you see what they are?

This code has two major problems. →

How to swap two integers in C++

Warning: this post got embarrassingly long. For the short version, read up through the paragraph that starts with “If you use.”

This is something that’s been bugging me for a while, and I’d like to lay it to rest. If you’ve done any work in C++, you’ve probably heard the riddle about how to swap two integers without using a temporary variable. The question is exactly what it sounds like: you have two integers (call them x and y), you want to swap their values, and you may or may not want to use a third, temporary variable while doing it. Here are some ways of swapping integers that I have actually seen in professional code written by professional coders:

Method Name Code
Method A
{  // Limit the scope of t
  int t = x;
  x = y;
  y = t;
}
Method B
x ^= y;
y ^= x;
x ^= y;
Method C
x ^= y ^= x ^= y;
Method D
x = x + y;
y = x - y;
x = x - y;
Method E
std::swap(x, y);


Which of these is the fastest way to swap integers? Which way is the fastest method that doesn’t require extra memory? When will you want to use a different method? What is the overall best method?

 

Try to come up with some answers before reading further.

 

When you’ve decided on your answers, let’s take a closer look. No, on second thought, this got really long. For those of you who don’t want to read all the way to the end, let me just get my main point out of the way. After that, we’ll take a closer look. If you don’t want to spoil the ending, skip the next paragraph.

If you use this link you will spoil the ending, so skip to the next paragraph after this one. →