Now I know I'm a C++ noob. I looked at some of your new code and it just fills me with questions.
1) Why define DarwinetEngineProxy::shared_ptr as a pointer to type DarwinetEngineProxy?
I'm guessing that this is to hide the underlying type, but since the APIs on whatever object it may be have to be clearly defined and documented, what is so terrible about documenting the object's type too?
What's with the "this->"? I thought that by definition any member or function was automatically taken from the current instance "this" if no other instance was specified? What is the benefit of being so explicit?
3) Why don't you create child objects on construction and why don't you free it?
1) Why define DarwinetEngineProxy::shared_ptr as a pointer to type DarwinetEngineProxy?
Its about decoupling code dependencies. I will re-define the pointer to boost::shared_ptr and does not what to do this by search and replace. The client code just need to know that the class defines the type. It does not need to know what type it really is as long as it behaves as a pointer.
2) Why do this->function_call()?
It's about object creation synchronization and service layer design. The Code shows the object aggregation structure. The design implements a "just in time" creation of objects and removes the potential huzzle of calling an object that is not yet created. And the code creates just the instances actually used. Now I sympathize with your gut-feeling that this is overhead. But I use this design as a way to ensure the stability and the integrity of the code though future changes.
3) Why don't you create child objects on construction and why don't you free it?
I have not come round to implement the freeing mechanism yet. As of now we have only one application, view, domain and engine. So the client APP (The MIV Console) does not have to free them until the whole process dies. Further more, when I redefine the share_ptr to a boost::shared_ptr it will handle freeing when there are no longer any references to the instance. So the code does not have to handle that.
4) I don't like <iostream> :(
Well, I can sympathize with that. The code you see is really my "logging" design. I just output to bout at the end. printf and sprintf is really powerful and quite easy to read. But I still write 1. Create string + 2. send it somewhere approach as this tends to make refatcoring and debugging later on easier. I refrain from using sprintf if it is possible. It is really dangerous to use and I have cursed many hours looking for overwritten call stack dues to local sprintf's overwriting their out-buffer.
About code efficiency. Good compilers identifies temporaries and intermediate operations and replaces them with efficient code. Bit when it comes down to it, we all use a proven way to write code. I'd like us to welcome these differences as long as it does not compromise the final goal. Fo me it is, "The code should be written for the programmer. Then let the compiler make the most of if :)"
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Surely the calling code DOES need to know what the type is or it won't know what the APIs are, what functions can be called?
2)
I still don't get it. You must have instantiated the object to be able to call a function on it in which "this" is defined, surely? ANd even if there is some behind the scenes black magic, "this" is implicit so you still don't need to actually write it do you?
3)
I think your answer to this kind of answers 1). You're using the shared pointers to make memory management easier, so you don't need to explicitly track all objects and free them, it's all handled magically and automatically. Is that right?
I'm not really familiar with shared pointers like that. I very briefly bumped into a C++ garbage collection system over a decade ago and didn't like what I saw there. This looks nicer - if it works. I tend to be paranoid about such things if I didn't actually write them myself sometimes :)
I'll check it out, because it does seem a good idea, even unfamiliar with C++ as I am.
4)
When I say sprintf, I of course mean snprintf, barring only when you have dynamically malloc'ed the memory to the right size previously so snprintf is kinda unnecessary.
I take your point though.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Now I know I'm a C++ noob. I looked at some of your new code and it just fills me with questions.
1) Why define DarwinetEngineProxy::shared_ptr as a pointer to type DarwinetEngineProxy?
I'm guessing that this is to hide the underlying type, but since the APIs on whatever object it may be have to be clearly defined and documented, what is so terrible about documenting the object's type too?
2) Why do this->function_call()?
I see:
and:
What's with the "this->"? I thought that by definition any member or function was automatically taken from the current instance "this" if no other instance was specified? What is the benefit of being so explicit?
3) Why don't you create child objects on construction and why don't you free it?
DarwinetEngineProxy::DarwinetEngineProxy()
: m_pDarwinetDomainProxy(NULL)
So on construction of a DarwinetEngineProxy instance, m_pDarwinetDomainProxy is set to NULL, right? Why not simply instantiate it?
Subsequently this object is never freed. Surely it ought to be freed in the destructor?
4) I don't like <iostream> :(
Sorry, I know it's C++ and everyone uses it, but I never have liked the iostream constructors.
As far as I can tell, the code:
probably does 1 allocate and 3 re-allocates. Whereas:
does none and can be written more concisely as:
But I'm well aware I'm working on your project and its C++, so i guess I'll have to adapt. Somehow. :-)
Last edit: JX 2013-04-02
Its about decoupling code dependencies. I will re-define the pointer to boost::shared_ptr and does not what to do this by search and replace. The client code just need to know that the class defines the type. It does not need to know what type it really is as long as it behaves as a pointer.
It's about object creation synchronization and service layer design. The Code shows the object aggregation structure. The design implements a "just in time" creation of objects and removes the potential huzzle of calling an object that is not yet created. And the code creates just the instances actually used. Now I sympathize with your gut-feeling that this is overhead. But I use this design as a way to ensure the stability and the integrity of the code though future changes.
I have not come round to implement the freeing mechanism yet. As of now we have only one application, view, domain and engine. So the client APP (The MIV Console) does not have to free them until the whole process dies. Further more, when I redefine the share_ptr to a boost::shared_ptr it will handle freeing when there are no longer any references to the instance. So the code does not have to handle that.
Well, I can sympathize with that. The code you see is really my "logging" design. I just output to bout at the end. printf and sprintf is really powerful and quite easy to read. But I still write 1. Create string + 2. send it somewhere approach as this tends to make refatcoring and debugging later on easier. I refrain from using sprintf if it is possible. It is really dangerous to use and I have cursed many hours looking for overwritten call stack dues to local sprintf's overwriting their out-buffer.
About code efficiency. Good compilers identifies temporaries and intermediate operations and replaces them with efficient code. Bit when it comes down to it, we all use a proven way to write code. I'd like us to welcome these differences as long as it does not compromise the final goal. Fo me it is, "The code should be written for the programmer. Then let the compiler make the most of if :)"
1)
Surely the calling code DOES need to know what the type is or it won't know what the APIs are, what functions can be called?
2)
I still don't get it. You must have instantiated the object to be able to call a function on it in which "this" is defined, surely? ANd even if there is some behind the scenes black magic, "this" is implicit so you still don't need to actually write it do you?
3)
I think your answer to this kind of answers 1). You're using the shared pointers to make memory management easier, so you don't need to explicitly track all objects and free them, it's all handled magically and automatically. Is that right?
I'm not really familiar with shared pointers like that. I very briefly bumped into a C++ garbage collection system over a decade ago and didn't like what I saw there. This looks nicer - if it works. I tend to be paranoid about such things if I didn't actually write them myself sometimes :)
I'll check it out, because it does seem a good idea, even unfamiliar with C++ as I am.
4)
When I say sprintf, I of course mean snprintf, barring only when you have dynamically malloc'ed the memory to the right size previously so snprintf is kinda unnecessary.
I take your point though.