DEV Community

Discussion on: Non isomorphic C++ refactoring

Collapse
 
dmerejkowsky profile image
Dimitri Merejkowsky • Edited

That's a good point. For instance with:

class Safe {

void dust() {
    std::cout << "Removing dust from the safe" << std::endl;
  }
}

int main() {
  Safe safe;
  safe.open(combination, key);
  safe.putDocuments(documents);
  safe.dust();
}

You will get:

Opening door
Putting passport in safe
Putting ID card in safe
Removing dust from the safe
Closing door

Which is probably not want you want. That's the issue with contrived examples :)

We can make it work by having:

  • Get rid of Door destructor
  • Add an explicit .close() method in the Safe class though
  • Store the state of the safe inside a member of the class
  • Ensure the safe is closed in the destructor.

I'll update the article, thanks.

Collapse
 
dwd profile image
Dave Cridland

I'd make safe.open(...) return a Door as a guard. Maybe:

class Door {
  bool m_open = false;
  Safe & m_safe;
  public:
    Door(Door && door) : m_open(door.m_open), m_safe(door.m_safe) {
      door.m_open = false;
    }
    Door(Safe & safe) : m_safe(safe) {}
    void opened() {
      m_open = true;
    }
    ~Door() {
      if (m_open) safe.close(*this);
    }
};

class Safe {
  // ...
  Door open( ... ) {
    Door door(*this);
    // Do the open;
    door.opened();
    return std::move(door);
  }
  // ...
};

But I am addicted to RAII, it must be said.