How much work should my class constructor do?

I have a class representing a data stream that basically reads or writes to a file, but first the data is encrypted / decrypted, and there is also a main codec object that handles media access.

I'm trying to write this class in a RAII way, and I need a clean, nice, comfortable design.

My concern is that a lot of work is being done in the designer now. Before the object I / O procedures can be safely used, first of all, it is necessary to initialize the codec (this is not very demanding), but then the key is taken into account, and crypto and other things are initialized - this requires some analysis of the media, which take up quite a bit of computation.

Now I do all this in the constructor, which makes it take a lot of time. I am considering moving the crypto init material (most of the work) from ctor to a separate method (for example Stream::auth(key)), but again this will lead to some responsibility for the class user, since they need to be run auth()before they invoke any I / O operations. It also means that I will need to put a check in I / O calls to make sure it has been called auth().

Do you think a good design?

PS I read a similar question, but I really could not apply the answers to this case. They mostly look like "It depens" ...: - /

thank

+5
source share
4 answers

, , .

, - "" / "" , "" , .

, , . "", , . , RAII , , , . , .

, (, RAII , ). , .

. , ? , . ", " ", ", .

, , " , -", , , , .

, , .

, ? , . , , , "this", .

, , , .

+7

-, , auth, , , , .

, .

+2

, , :

: . , . , , , .


1

RAII. - , .

class SecureStream
{
public:
    SecureStream();
    void initialize(Stream&,const Key&) throw(InvalidKey,AlreadyInitialized);
    std::size_t get(      void*,std::size_t) throw(NotInitialized,IOError);
    std::size_t put(const void*,std::size_t) throw(NotInitialized,IOError);
};

Pros

  • , ""
  • , . , COM, (CoCreateObject() ). , builder .

  • . , . , , (, std::ostream).

2

RAII. , 100% (, stream.initialize(...); .

class SecureStream
{
public:
    SecureStream(Stream&,const Key&) throw(InvalidKey);
    std::size_t get(      void*,std::size_t) throw(IOError);
    std::size_t put(const void*,std::size_t) throw(IOError);
};

Pros

  • . .

  • .
  • . , № 1.

3

. , .initialize(...).

class SecureStream
{
public:
    SecureStream(Stream&,const Key&);
    std::size_t get(      void*,std::size_t) throw(InvalidKey,IOError);
    std::size_t put(const void*,std::size_t) throw(InvalidKey,IOError);
private:
    void initialize() throw(InvalidKey);
};

Pros

  • , # 1. (. ).

  • , , . .

, №1 , .

, . ? , , . , (, , ).

№ 3, №2.

, , , - - , , RAII.

+2

There is no hard and fast rule, but in general, it is better to avoid heavy constructors for two reasons that come to mind (perhaps others):

  • The procedure for creating a list of created objects can lead to subtle errors.
  • What to do with exceptions in the constructor? Will you need to handle partially created objects in your application?
-1
source

All Articles