nayef harb
nayef harb

Reputation: 753

Which is the better way of passing data to a Method

Let us say that we have 2 Classes Expense1 and Expense2. Which class implementation is preferred over the other, or which is considered closer to being object-oriented?

I always thought that doing Exp2.Calculate(1.5M,2) is more readable than exp1.Calculate() and using the properties of exp1 Class as the needed values for the calculate Method.

Expense1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Expense1
{
    public decimal ExpenseValue { get; set; }
    public int NumberOfItems { get; set; }
    private decimal result;

    public decimal Result
    {
        get
        {
            return this.NumberOfItems * this.ExpenseValue;
        }
    }

    public void Calculate()
    {
        this.result = this.ExpenseValue * this.NumberOfItems;
    }

    public void expense1()
    {
        this.ExpenseValue = 0;
        this.NumberOfItems = 0;
    }
}

Expense2

class Expense2
{
    public decimal Calculate(decimal expenseValue, int numberOfItems)
    {
        return expenseValue * numberOfItems;
    }
}

Implementation of both classes

class Program
{
    static void Main(string[] args)
    {

        Expense1 exp1 = new Expense1();
        exp1.NumberOfItems = 2;
        exp1.ExpenseValue = 1.5M ;
        exp1.Calculate();
        Console.WriteLine("Expense1:" + exp1.Result.ToString());

        Expense2 exp2 = new Expense2();
        string result = string.Empty;
        result = exp2.Calculate(1.5M,2).ToString();
        Console.WriteLine("Expense2:" + result);
        Console.ReadKey();
    }
}

Upvotes: 3

Views: 162

Answers (4)

3dd
3dd

Reputation: 2530

Expense2 is easier to read and understand what going on as it's evident from the call which parameters are used.

Expense1 could have various side effects as the caller might forget to set the variables used for calculating before he calls Calculate().

If you require access to the values that was used to calculate the result later, you can use something like this

public class Expense {
    public decimal ExpenseValue { get; private set; }
    public int NumberOfItems { get; private set; }
    public decimal Result { get; private set; }


    public decimal Calculate(decimal expenseValue, int numberOfItems) {
        ExpenseValue = expenseValue;
        NumberOfItems = numberOfItems;
        Result = ExpenseValue * NumberOfItems;

        return Result;
    }

    public Expense() {
        Calculate(0, 0);
    }
}

This will allow the internal state of Expense to stay consistent for the lifetime of the object, with the definition of how it's Calculated

Upvotes: 3

Swift
Swift

Reputation: 1881

It all depends on what you want to do, but a rule of thumb is use properties when they are really linked to the object, and pass what use need as parameters when they are external to the object.

A simple example, consider having Person as a class, one of its properties is birthday, so in this case you should do this

public class Person{
     public DateTime Birthday{get;set;}
     public int GetAge(){
          //some implementation
     }
}

another example, think of having a Cube object, and in this Cube object you have a method Intersect with another cube, in this case you should pass the second cube as parameter and not make it a property of Cube because it is something external.

public class Cube{
     public Cube Intersect(Cube other){
         //Do your logic here
     }
}

Upvotes: 1

sara
sara

Reputation: 3589

I don't like Expense1 one bit. I think properties with public get/set should generally be avoided since it provides no encapsulation. It's hardly even better than public fields (although it does give some room for guard clauses etc down the road).

Worse than that, however, is the Calculate() method imo. It takes no arguments but it still changes the internal state of the object. It is not clear how. At the same time, the field it writes to, result, isn't being returned by the property Result, that property does the same calculation again (if you have to do calculations, generally prefer a method over a property).

Finally, it is not necessary to initialize primitive types to their default value in the constructor, number types always get initialized to 0.

===

Expense2 is better, it is more clear what is happening. Method takes two well-named arguments and give a reasonable result straight away.

If this method is the only use-case of the class, however, I would consider renaming it since it does not represent an expense, it represents something close to an expense calculator.

Upvotes: 1

David Arno
David Arno

Reputation: 43254

Expense2.Calculate is deterministic (has the same result every time its called with the same parameters) and because it has no side effects (the parameters are served to it, rather than via properties) it is thread-safe too. Lastly, it is simpler and easier to read.

Expense1 is a classic OOP train-wreck with non-thread safe state, and no guarantee that Result will return the result of a thread's invocation of Calculate. Further, it is long-winded and complex to read and maintain.

I'd favour Expense2 over Expense1 every time. The only thing I'd change would be to make it static as there's no gain to having to create an instance of Expense2 to call Calculate.

Upvotes: 3

Related Questions