I've designed the below code for one of the requirement. I have to write different tests for the code and I would need feedback on where I can improve the design.
Requirement:
- Read the customer details from csv, calculate his average expenses on different items on yearly and write to csv again.
- Read the customer details from csv, calculate his total expenses on faimly and write to csv again.
As both the ExpenseCalculator uses CsvReaderWriter function, is it better to create the abstract class which implements csvReaderWriter functionality and derive from abstract class or is it better to use Interface?
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Expenses { get; set; }
// other details
}
public interface ICsvReaderWriter<T>
{
IEnumerable<T> ParseCsv(string filePath);
void WriteCsv(string filePath, IEnumerable<Customer> customers);
}
public class ReaderWriter : ICsvReaderWriter<Customer>
{
public IEnumerable<Customer> ParseCsv(string filePath)
{
throw new NotImplementedException();
}
public void WriteCsv(string filePath, IEnumerable<Customer> customers )
{
throw new NotImplementedException();
}
}
public interface IExpenseCalculator
{
void CalculateExpenses(string filePath);
}
public class ItemExpenseCalculator : IExpenseCalculator
{
private readonly ICsvReaderWriter<Customer> _csvReaderWriter;
public ItemExpenseCalculator(ICsvReaderWriter<Customer> csvReaderWriter)
{
this._csvReaderWriter = csvReaderWriter;
}
public void CalculateExpenses(string filePath)
{
var customers = _csvReaderWriter.ParseCsv(filePath);
// do manipulation
_csvReaderWriter.WriteCsv(filePath, customers);
}
}
public class FamilyExpenseCalculator: IExpenseCalculator
{
private readonly ICsvReaderWriter<Customer> _csvReaderWriter;
public FamilyExpenseCalculator(ICsvReaderWriter<Customer> csvReaderWriter)
{
this._csvReaderWriter = csvReaderWriter;
}
public void CalculateExpenses(string filePath)
{
var customers = _csvReaderWriter.ParseCsv(filePath);
// do manipulation
_csvReaderWriter.WriteCsv(filePath, customers);
}
}
public class Program
{
private void Main()
{
IExpenseCalculator itemExpenseCalculator = new ItemExpenseCalculator(new ReaderWriter());
itemExpenseCalculator.CalculateExpenses(@"D:\");
IExpenseCalculator familyExpenseCalculator = new FamilyExpenseCalculator(new ReaderWriter());
familyExpenseCalculator.CalculateExpenses(@"D:\");
}
}