Clean code attempt at ATM problem on codechef.com The problem asks you to take an integer (debit amount) and a double (credit or initial balance amount) and process the requested debit verifying that 1 it's a multiple of the minimum denomimation amount of $5 and that it's also smaller than the credit/balance.  If either is untrue, it is supposed to return the initial deposit amount otherwise it will return the new balance.

Full problem description

I have created 3 objects for this problem:


Transaction - This object reads in the two initial values given and then is used in ATM
ATM - Takes the transaction and applies them to the account and then displays the new balance.
Account - This object keeps track of the current account balance and updates the balance if the ATM passes it a value.


Limitations:

I understand that it can only process a single account, but that is more a limitation set by the problem description than it is me not accounting for multiple accounts.  Also no error is returned if the balance cannot be updated, but it is not a requirement.  I also understand I made a mountain out of a molehill with this problem as it can be solved by much less code.

In what ways can I improve this code other than the limitations mentioned?

#include &lt;istream&gt;
#include &lt;iostream&gt;
#include &lt;iomanip&gt;

class Account {
public:
    Account() 
        :   mBalance(0.0)
    {}

    void updateBalance(double transaction) {
        mBalance += transaction;
    }

    double getBalance() {
        return mBalance;
    }

private:
    double mBalance;
};

class Transaction {
public:
    Transaction() 
        :   mDebit(0)
        ,   mCredit(0.0)
    {}

    int getDebit() {
        return mDebit;
    }

    double getCredit() {
        return mCredit;
    }

    friend std::istream&amp; operator&gt;&gt;(std::istream&amp; input, Transaction&amp; transaction) {
        input &gt;&gt; transaction.mDebit;
        input &gt;&gt; transaction.mCredit;
        return input;
    }

private:
    int     mDebit;
    double  mCredit;
};

class ATM {
public:
    ATM() 
        :   mAccount()
        ,   mMinDenomination(5)
        ,   kWithdrawal_fee(0.50)
    {}

    void processTransaction(Transaction&amp; transaction) {
        credit(transaction);
        debit(transaction);
    }

    void displayBalance() { 
        std::cout &lt;&lt; mAccount.getBalance() &lt;&lt; '\n';
    }

private:
    Account             mAccount;
    int                 mMinDenomination;
    const double        kWithdrawal_fee;

    bool debit(Transaction&amp; transaction) {      
        if(isWithdrawable(transaction.getDebit())){         
            mAccount.updateBalance(-1*(transaction.getDebit() + kWithdrawal_fee));
            return true;
        }
        return false;
    }

    void credit(Transaction&amp; transaction) {
        if(transaction.getCredit() &gt; 0) {
            mAccount.updateBalance(transaction.getCredit()); 
        }
    }

    bool isWithdrawable(int transaction) {
        if(transaction % mMinDenomination == 0) {
            return mAccount.getBalance() &gt;= transaction + kWithdrawal_fee;
        }
        return false;
    }
};

int main() {
    std::iostream::sync_with_stdio(false);
    std::cout &lt;&lt; std::setprecision(2) &lt;&lt; std::fixed;

    Transaction transaction;
    ATM         atm;    

    std::cin &gt;&gt; transaction;    
    atm.processTransaction(transaction);
    atm.displayBalance();

    return 0;
}
This looks quite readable and easy to follow.  I just have a few things that have stuck out to me:


It would not be good to use a floating-point type for currency, and it's especially worse for a more accurate type like a double.  For instance, you can wind up with a value like 0.0001, which is not an ideal value to deal with.  Unfortunately, C++ doesn't have a standard library to deal with this, such as Java's BigDecimal.  You need an integer type for this, which avoids these problems.

Refer to this, this and this for more info.  There are already many resources on this very topic.
Your "getters" should be const as they're not supposed to modify data members:

int getSomeMember() const {
    return someMember;
}


mMinDenominations should also be const for the same reason.  Initializer lists do also allow initialization of const members (be aware that constructors cannot do this).

Moreover, consider redesigning this to avoid getters.  They (and also setters) are generally bad for encapsulation as they expose implementation details.  You may not even need them here, either.
You can replace displayBalance() with an overload of operator&lt;&lt;:

friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; out, ATM const&amp; obj) {
    return out &lt;&lt; obj.mAccount.getBalance() &lt;&lt; '\n';
}


Since mAccount is private, this will have to be defined within the class.  This will still work, even if you remove the getters.