Using out
parameters in methods are usually a code smell with indicates that you want to
effectively return two results from a method. Out parameters are mostly introduced when developers realize the
need of an additional return value from an already existing method. The problem
with out parameters is that they
introduce the risk of side effects and are hard to debug.
You can use the Transform
out parameters refactoring to transform out parameters to a tuple in C#.
Later you can convert the tuple with a class or struct with
a static create method to enhance readability and maintainability.
For e.g., we can refactor the below given code
[TestMethod]
public void AddEmployeeReturnsTrueIfEmployeeWasSaved()
{
var employee = new Employee {Name = "Prajeesh
Prathap"};
var repository = new EmployeeRepository();
int employeeId = 0;
var success = repository.Add(employee, out employeeId);
Assert.IsTrue(success);
repository.RemoveAll();
}
public bool Add(Employee employee, out int employeeId)
{
employeeId = 0;
if (_employees.Any(x => x.Name == employee.Name)) return false;
employee.Id = _employees.Any() ?
_employees.Max(x => x.Id) + 1 : 1;
employeeId = employee.Id;
_employees.Add(employee);
return true;
}
Using the transform out parameters refactoring pattern to...
[TestMethod]
public void AddEmployeeReturnsTrueIfEmployeeWasSaved()
{
var employee = new Employee {Name = "Prajeesh
Prathap"};
var repository = new EmployeeRepository();
var add = repository.Add(employee);
var success = add.Item1;
Assert.IsTrue(success);
repository.RemoveAll();
}
public Tuple<bool, int> Add(Employee employee)
{
int employeeId = 0;
if (_employees.Any(x => x.Name == employee.Name)) return Tuple.Create(false, employeeId);
employee.Id = _employees.Any() ?
_employees.Max(x => x.Id) + 1 : 1;
employeeId = employee.Id;
_employees.Add(employee);
return Tuple.Create(true, employeeId);
}
Further improvement can be achieved by encapsulating the parameters
in a class as given below
public class AddOutput
{
public bool Result { get; set; }
public int Id { get; set; }
public static AddOutput Create(bool success, int id)
{
return new AddOutput {Result = success, Id = id};
}
}
public AddOutput Add(Employee employee)
{
int employeeId = 0;
if (_employees.Any(x => x.Name == employee.Name)) return AddOutput.Create(false, employeeId);
employee.Id = _employees.Any() ?
_employees.Max(x => x.Id) + 1 : 1;
employeeId = employee.Id;
_employees.Add(employee);
return AddOutput.Create(true, employeeId);
}
[TestMethod]
public void AddEmployeeReturnsTrueIfEmployeeWasSaved()
{
var employee = new Employee {Name = "Prajeesh
Prathap"};
var repository = new EmployeeRepository();
var add = repository.Add(employee);
var success = add.Result;
Assert.IsTrue(success);
repository.RemoveAll();
}