Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Opinion on this paradigm please
Forum Updated to NodeBB v4.3 + New Features

Opinion on this paradigm please

Scheduled Pinned Locked Moved C++ Gurus
9 Posts 7 Posters 3.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    GrahamL
    wrote on last edited by
    #1

    Hi
    I have just started working on a new project and have come across this class and I dont really like the paradigm@@ used to implement the getters and setters.
    Has anyone seen this method before?
    Is it good?
    is it bad?

    Header File:
    @
    class Tool
    {
    public:
    Tool();
    virtual ~Tool();

    bool setName(const std::string &name);
    bool setMechanicalSerialNumber(const std::string &serialNumber);
    
    bool getName(std::string &name) const;
    bool getMechanicalSerialNumber(std::string &serialNumber) const;
    
    void clearName();
    void clearMechanicalSerialNumber();
    
    virtual void clearAll() = 0;
    

    protected:

    private:
    std::string m_name;
    bool m_nameSet;

    std::string m_mechanicalSerialNumber;
    bool m_mechanicalSerialNumberSet;
    

    };
    @

    cpp file:
    @
    #include "Tool.h"

    Tool::Tool()
    : m_name("")
    , m_nameSet(false)
    , m_mechanicalSerialNumber("")
    , m_mechanicalSerialNumberSet(false)
    {
    }

    Tool::~Tool()
    {
    }

    bool Tool::setName(const std::string &name)
    {
    m_name = name;
    m_nameSet = true;
    return (m_nameSet);
    }
    bool Tool::setMechanicalSerialNumber(const std::string &serialNumber)
    {
    m_mechanicalSerialNumber = serialNumber;
    m_mechanicalSerialNumberSet = true;
    return (m_mechanicalSerialNumberSet);
    }

    bool Tool::getName(std::string &name) const
    {
    bool success = false;
    if (m_nameSet)
    {
    name = m_name;
    success = true;
    }
    return (success);
    }
    bool Tool::getMechanicalSerialNumber(std::string &serialNumber) const
    {
    bool success = false;
    if (m_mechanicalSerialNumberSet)
    {
    serialNumber = m_mechanicalSerialNumber;
    success = true;
    }
    return (success);
    }

    void Tool::clearName()
    {
    m_name = "";
    m_nameSet = false;
    }
    void Tool::clearMechanicalSerialNumber()
    {
    m_mechanicalSerialNumber = "";
    m_mechanicalSerialNumberSet = false;
    }

    void Tool::clearAll()
    {
    clearName();
    clearMechanicalSerialNumber();
    }

    @

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      Ke? I have not, but what does this have to do with this code? :)

      In my opinion, this is ugly and flawed code, but others may differ. A string is either empty or not. I see no point in the boolean variables. Also, a getter returning by parameter reference... doh.

      (Z(:^

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi, I have seen/used some variants of that paradigm when set/getting the data was done by putting/retrieving information from a device/remote service/etc... that could fail.

        But not for simple "container" classes like this, i'd rather test the returned value for null/empty/invalid value (Qt style).

        if setting a string fails then there is a much bigger problem at hand, the same applies for retrieving it.

        I also don't see (in this case) why is clearAll pure virtual, nothing else in the class is virtual so it doesn't make it a good candidate for inheritance. Anyone wanting to use it would have to inherit it, implement clearAll() by simply calling the default implementation. Not very good IMHO

        Just my 2 cents

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • T Offline
          T Offline
          tzander
          wrote on last edited by
          #4

          I've had discussions in the past about such an approach, in most cases it was made by people that learned the trade with C, not C++.

          People have told me often that they want to return stuff though an argument-ref because there may be more than one return variable.
          In all cases so far I've seen that the multiple arguments really belong together and should at minimum be in a struct, or even in a dedicated class.

          I've come to see the 'output argument' concept as an anti-pattern, where users of this apprach most likely need to create new classes to hold data instead of passing around individual parts that really belong together (like a string and its length).

          Back to your example;
          returning a bool to check if things went Ok when 99.999% of the time it will go Ok is not the best approach. I refer to Qts QString::toInt(*bool = 0); for a much better approach to solve this issue.

          1 Reply Last reply
          0
          • T Offline
            T Offline
            tzander
            wrote on last edited by
            #5

            Thinking about it more, your example is also a C-style separation of data that really should be grouped in a class.
            If you introduce a struct that holds a std::string and a bool you can simplify the class enormously.

            1 Reply Last reply
            0
            • O Offline
              O Offline
              ogoffart
              wrote on last edited by
              #6

              That would be something like boost::optional

              1 Reply Last reply
              0
              • L Offline
                L Offline
                lgeyer
                wrote on last edited by
                #7

                Avoid argument-ref wherever possible, for the simple reason that it almost always leads to bloated and somewhat ugly code.

                Just imagine you want to std::cout the name and the serial number:
                @
                void printArgumentRef(const Tool &tool)
                {
                QString name;
                if (tool.getName(name) == false)
                ...

                QString mechanicalSerialNumber;
                if (tool.getMechanicalSerialNumber(nechanicalSerialNumber) == false)
                    ...
                
                std::cout << name << mechanicalSerialNumber;
                

                }

                void printReturn(const Tool &tool)
                {
                std::cout << tool.getName() << tool.getMechanicalSerialNumber();
                }
                @
                (This is also one of the major drawbacks of streaming operators, as for example in QDataStream).

                Keep in mind that there is no longer a technical reason to use argument-ref. Any modern compiler has return-value optimization which eliminates the cost of the temporary and C++11 has move semantics built-in.

                In addition, I tend to agree that the state of data is part of the data itself (and should not, for instance, be split into a return value and a parameter as in your case). You'll find this paradigm in Qt all over as well someObject.isValid()). It is the code using the value beeing responsible for validation (std::cout.operator<<), not generating or simply passing the value (printArgumentRef()).

                boost::optional has already been mentioned. I want to add expected<T>, as introduced by Andrei Alexandrescu and presented on his talk on "Systematic Error Handling in C++":http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C at the C+B2012.

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  GrahamL
                  wrote on last edited by
                  #8

                  Thanks to everyone
                  Lots to think about

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    bipll
                    wrote on last edited by
                    #9

                    In Haskell, theres a standard Maybe type, defined as
                    @data Maybe a = Just a | Nothing@

                    Function
                    @isJust :: Maybe a -> Bool@

                    returns True, when parameter is not Nothing.
                    @fromJust :: Maybe a -> a@

                    extracts the value from parameter when it's a Just.
                    There can be numerous implementations of Maybe monad in C-family. Some libraries favour returning bool/int, where return value is the corresponding value of isJust; others return int, where 0 returned means everything's okay, and any other value suggests an error occured. Incapsulation of value and flag is more prefered. boost::optional has been mentioned above, I believe it's the same as Maybe, while any automatic pointer could do the trick as well, where NULL means Nothing and not NULL means Just something. In Qt, there's a QScopedPointer, in STL there's a std::shared_ptr. Default-constructed value would be Nothing.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved