Author Topic: Some ideas/questions on PersonalityManager.h/cpp  (Read 7700 times)

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5529
Some ideas/questions on PersonalityManager.h/cpp
« on: December 19, 2005, 12:00:09 pm »
When studying the code of the 2 mentioned files, several questions/remarks/ideas arised.

1) looking at the header : why the protected part, it seems they may be private. Stroustrup says that protected members are evil (protected method are less evil).
Argument pro : maybe somebody 'might' derive from it, but then it would be better to make the destructor virtual.
Several get functions are not const,m we'll see later why. Getters are adviced to be const methods. Derive interfaces, aggregation is advised for code reusion (inheritance is very strong coupling).

Below are some code lines from the cpp file
Code
void PersonalityManager::ReadPersonalities()
{
    m_Personalities.Clear();
    m_Personalities.Add(_("Full IDE (default)"));
}

const wxString& PersonalityManager::GetPersonality()
{
    static wxString pers;
    pers = m_CurrentPersonalityIdx > 0 && m_CurrentPersonalityIdx < (int)m_Personalities.GetCount()
            ? m_Personalities[m_CurrentPersonalityIdx]
            : wxT("default");
    return pers;
}

const wxArrayString& PersonalityManager::GetPersonalitiesList()
{
    return m_Personalities;
}

const wxString& PersonalityManager::GetPersonalitiesRoot()
{
    static wxString root = _T("/personalities");
    return root;
}

const wxString& PersonalityManager::GetPersonalityKey()
{
    static wxString key;
    key = m_CurrentPersonalityIdx <= 0
            ? wxT("") // default personality
            : GetPersonalitiesRoot() + _T("/") + GetPersonality();
    return key;
}

2) 3 different ways for getting in the text
 a) _("Full IDE (default)")
 b) wxT("default")
 c) _T("/personalities")
--> maybe it is better to make it consistent ? What is the preferred way of those 3 ?

3) GetPersonalitiesRoot() is not const :
 - why because it fills in a static (non const) variable --> bad : is like a global variable, but with some more scope restriction
 - Suggestion : use a static const in the class body
     static  const wxString root = _("/personalities");
 then we can make the Get const :
  const wxString& PersonalityManager::GetPersonalitiesRoot() const
  {
     return root;
  }
  -> note this can become a static method

4) GetPersonalityList : --> can be const method

5) GetPersonality method is not const
 a) is not consistent in the case no personalities : shoudl be again "Full IDE (default)", and that one should be present (added in the constructor) , so no need to create a static variable here, just return a const reference into the m_Personalities array --> const method
 b) besides even if a new value should be needed to created on the fly, it is better to construct it in the return statement , so the compiler can apply the 'optimize return value' idiom (see Meyers' books).
 c) in this case we could have worked with return by value (though wouldn't do it, since this is not a function called that often (startup))
 d) is not reentrant safe, say 2 CB instances nearly arrive at the same time in this function, and 1 looses cpu to the other just before the 'return pers;' line, then the other will override the value, and when cpu return to the first one, it's returning not the intended value !! (non const) Static's are evil !
I have the impression they were static so they live after the function return and one could return a reference to it. Maybe there are other good reasons, can't think of one at this moment, but hey, willing to learn anytime.

6) GetPersonalityKey is not const => nearly the same as in 5)
 - might be better to return in case the index <= 0 (should not happen ? Full Ide(default) ?) root/Full IDE (default)

7) maybe add : static const member :
  static const wxString m_Default = _T("Full IDE (default)");
 can then be used to return the default, or document that at index 0 , the default lives.


Cheers,
Lieven

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Some ideas/questions on PersonalityManager.h/cpp
« Reply #1 on: December 19, 2005, 12:51:09 pm »
Hi Lieven,

these are nice theoretical discussions but I 'd rather concentrate on writing code that works instead of writing the "perfect" code that passes the C++ conformity tests.

What I mean is that PersonalityManager is only used once on application startup. Really, it's quite useless after startup because the requested personality's configuration has already been loaded so whatever you do with PersonalityManager is futile :)
It used to be more powerful than that but no more...

Besides, since you seem to have put it under the microscope, haven't you noticed that its constructor/destructor is private? Effectively meaning you cannot inherit from it?  :roll:

EDIT: don't get this wrong, there are some places in the code that would do better with a better design. We 're working on it. It's just that PersonalityManager is not one of those places ;)
« Last Edit: December 19, 2005, 12:54:15 pm by mandrav »
Be patient!
This bug will be fixed soon...

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Some ideas/questions on PersonalityManager.h/cpp
« Reply #2 on: December 19, 2005, 12:53:16 pm »
1)
Technically, you are correct, but it does not matter at all. You cannot derive from PersonalityManager. Although private would be correct, and protected is not, it makes no difference.

2)
The code was written by different people at different times, such style differences happen. Functionally, it is identical.

3) to 7)  You can do const correctness because it helps optimization, or you can do const correctness for the sake of doing it. GetPersonality() is called exactly once during the entire lifetime of a Code::Blocks application. Const correctness helps the compiler do optimizations such as CSE elimination or invariant moves. What do you expect to be eleminated in this case? Clearly, there is no harm in making these funcitons const, but it does not help either.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Some ideas/questions on PersonalityManager.h/cpp
« Reply #3 on: December 19, 2005, 01:04:40 pm »
ad 1)

Even if you could derive from PersonalityManager, you would not want to make the destructor virtual, because this would cause you to pay the virtual function toll.

You need a virtual destructor if all three following conditions are met:
1. your class has at least one virtual function (this is not the case)
2. you derive from it and allocate an object of the derived class
3. you free the derived class object using a pointer of the base class' type (not possible for a manager)

In all other cases, you do not need one.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5529
Re: Some ideas/questions on PersonalityManager.h/cpp
« Reply #4 on: December 19, 2005, 01:10:34 pm »
Goals :
 - clearer interface : easier to understand, suppose someone needs this functionality, looks at the header (don't want to know the implementation) : then it's good to know which functions don't change the state -> const functions (well all gurus : Stroustroup, Sutter, Meyers, Alexandrescu, ... tell us to do it like that)
 - the static variables in the function can lead to problems in multi instance, problems not happening today, well we all know they gonna blow up in our face later ;-)
 - just trying to know for myself what to use : _T(), _(), wxT() ...

Special note : there is no criticism intended, I just wrote down the remarks/ideas that came to mind.
Why not be const correct ? There's no way not to do it, it just makes things clearer for users (users : people who need the functionality, today's code maintainer, tomoroows code maintainer ,...). We know what the code deos today, but when after 6 months we turn back to this code ...

Following up on the word from Bjarne, he even wished he'd never done protected members.

I agree on different styles, no need to sewat on stuff like where to put the "{" of a function, and all these kind of things.
Maybe it is just me : but I get the chills when I see statics, I had to fix too much multithreading/reantrance problems in my live from other people who were using statics and global variables.  :D

It were just my ideas on this matter.

Looking forward to the first CB developer days at some cool city, then we can discuss this over a beer  8)


Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5529
Re: Some ideas/questions on PersonalityManager.h/cpp
« Reply #5 on: December 19, 2005, 01:13:59 pm »
Thomas,

on your ad) .
Agreed, but we never know how someone might use this piece of code today, if we allow to derive from it.
Gurus also say : don't derive from full classes (eg classes dat don't have virtual functions), use aggreagation at that time.

But my point is , why make it protected, this is partially breaking the data hiding concept of OO. Why go half the way, if it is better to go all the way, loose coupling.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Some ideas/questions on PersonalityManager.h/cpp
« Reply #6 on: December 19, 2005, 01:47:25 pm »
- clearer interface : easier to understand, suppose someone needs this functionality, looks at the header
That will never happen. You have absolutely no reason to use PersonalityManager.
You don't know about personalities. There are no personalities. You have not seeeeeen anything.  8)

Quote
- the static variables in the function can lead to problems in multi instance
You do cannot have several instances within the same process.
Quote
Why not be const correct? [...] We know what the code deos today, but when after 6 months we turn back to this code ...
I know exactly what this particular code will do in 6 months. In one word: nothing. :)

Quote
- just trying to know for myself what to use : _T(), _(), wxT() ...
Code
#define _(s) wxGetTranslation(_T(s))

#ifdef UNICODE
  #define wxT(x) L ## x
#else
  #define wxT(x) x
#endif

#define _T(x) wxT(x)
So, you use _() if you want the text translated into another language. Otherwise, you use one of the others.
Please note that there are _U and _C macros too... the WiKi has a documentation on them.

(Edit: the last #define in my code is of course illegal, but I was too lazy to type that all again, you get the idea...)
« Last Edit: December 19, 2005, 01:50:47 pm by thomas »
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."