“Develop something useful in under 100 lines of code” contest-Improved version

My article here was well received. Various people pointing out several flaws in the application. Some of these points that were discussed were:

a. Should the application use decimal instead of double since it is a financial application?
Answer: The application has been changed to use decimals to calculate the monthly payment amount, Interest amount, total interest amount. However based on the article here, “the results when computed in doubles are going to be off by a few billionths of a penny one way or the other”. I therefore believe that I need to find a actual use case where using a decimal produced a result that was more correct than using a decimal.

b. The application will not behave correctly when the “loan Date” is passed with a “DateTime.MaxValue” value.
Answer: This has been fixed and a unit test case added for the same.

c. The application needs to consider business rules related to “loan date” and “Loan Period in years”
Answer: This has been fixed and two unit test cases added for the same.

d. What advantages will the system get if the return type of the Get function is a “IList” instead of a “List”?
Answer: This has been fixed in the application. The advantages that we get is that the AmortizationSchedule.Get and IAmortizationSchedule.Get signature does not need to change when the internals of the AmortizationSchedule.Get method is changed to return a collection that implements a IList (example return a Array instead of a List collection).

e. How will you optimize the creation of a the List class on line 30? Will it make sense to pass the created object from the client application if the creation of the list instance is expensive?
Answer: If the List creation is an expensive operation then we can consider using the Object pooling design pattern in the application.
The Object pool design pattern is a creational design pattern that can improve performance when working with classes that are slow to instantiate. Rather than constructing new objects, reusable objects are retrieved from, and released to, a pool as required.
An example implementation is listed here.

f. Will the application need to take care of multiple processes creating “Amortization Schedule”? If yes then how will you change the application?
Answer: It was decided that the application does not need to change to take care of multiple processes creating the “Amortization Schedule”.

g. Why was the “IAmortizationSchedule” interface created? It is not used anywhere in the application
Answer: This is true, the “IAmortizationSchedule” interface is not used in the application but I always create an interface because it helps later down the road when I need to write unit tests by mock the various parts of the application.

h. Is there a possibility that the “toThePowerOfVariable” variable on line 22 will become 1? What happens on line 23 if the “toThePowerOfVariable” variable becomes 1?
Answer: It was decided that there is no possibility of the “toThePowerOfVariable” variable on line 22 becoming 1. If the “toThePowerOfVariable” variable becomes 1, no “DivideByZeroException or other exception will occur.

Here is the changed application:

public class AmortizationSchedule: IAmortizationSchedule
{
    public IList<AmortizationScheduleRow> Get(double annualPercentageRate, 
        double loanAmount, int loanPeriodInYears, DateTime loanStartDate)
    {
        if (annualPercentageRate <= 0 || 
         loanAmount <= 0 || 
         loanPeriodInYears <= 0 || 
         loanStartDate <= DateTime.MinValue || 
         loanStartDate == DateTime.MaxValue)
        {
            throw new ArgumentException("Invalid arguments");
        }
        //If the code below does not throw an exception then 
        //the "loanStartDate" has been validated against the "loanPeriodInYears"
        DateTime addYears = loanStartDate.AddYears(loanPeriodInYears);
        
        #region Calculate monthly payment rounded to 2 digits
        const int NoOfMonthsInYear = 12;
        var loanPeriodInMonths = loanPeriodInYears * NoOfMonthsInYear;
        var effectiveInterestRateInDouble = annualPercentageRate / (NoOfMonthsInYear * 100);
        var toThePowerOfVariable = Math.Pow(1 + effectiveInterestRateInDouble, -loanPeriodInMonths);
        var monthlyPayment = (decimal) (loanAmount * (effectiveInterestRateInDouble / (1 - toThePowerOfVariable)));
        #endregion

        #region Calculate payment schedule based on monthly payment and loan start date
        //Initialize the collection(for performance) based on the 
        //no of elements that it is supposed to hold
        var amortizationSchedule = 
        new List<AmortizationScheduleRow>(loanPeriodInMonths);
        var currentMonthCounter = loanStartDate.AddMonths(1);
        var currentBalance = (decimal) loanAmount;
        decimal totalInterestAmount = 0;
        for (var counter = 0; counter < loanPeriodInMonths; counter++)
        {
            var interestAmount = (decimal) (effectiveInterestRateInDouble * (double) currentBalance);
            totalInterestAmount = (totalInterestAmount + interestAmount);
            var amortizationScheduleRow = new AmortizationScheduleRow
            {
                Date = currentMonthCounter,
                MonthlyPaymentAmount = monthlyPayment,
                InterestAmount = interestAmount,
                TotalInterestAmount = totalInterestAmount
            };
            amortizationSchedule.Add(amortizationScheduleRow);

            currentBalance = currentBalance - amortizationScheduleRow.GetPrincipalAmount();
            currentMonthCounter = currentMonthCounter.AddMonths(1);
        }
        #endregion
        return amortizationSchedule;
    }
}
public interface IAmortizationSchedule
{
    IList<AmortizationScheduleRow> Get(double annualPercentageRate, double loanAmount, 
        int loanPeriodInYears, DateTime loanStartDate);
}
public class AmortizationScheduleRow
{
    public decimal GetMonthlyPaymentAmount()
    {
        return Math.Round(MonthlyPaymentAmount, 2, MidpointRounding.AwayFromZero);
    }
    public decimal MonthlyPaymentAmount { private get; set; }
    public decimal GetInterestAmount()
    {
        return Math.Round(InterestAmount, 2, MidpointRounding.AwayFromZero);
    }
    public decimal InterestAmount { private get; set; }
    public decimal GetTotalInterestAmount()
    {
        return Math.Round(TotalInterestAmount, 2, MidpointRounding.AwayFromZero);
    }
    public decimal TotalInterestAmount { private get; set; }
    public decimal GetPrincipalAmount()
    {
        var principalAmount = MonthlyPaymentAmount - InterestAmount;
        return Math.Round(principalAmount, 2, MidpointRounding.AwayFromZero);
    }
    public string GetDate()
    {
        return Date.ToString("MMM yyyy");
    }
    public DateTime Date { private get; set; }
}
 [TestClass]
public class AmortizationScheduleTester
{
    const double annualPercentageRate = 3.5;
    const double loanAmount = 300000;
    const int loanPeriodInYears = 15;
    readonly DateTime loanStartDate = new DateTime(2016, 7, 1);
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest()
    {
        const int NoOfMonthsInYear = 12;
        var monthlyPaymentSchedule = new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
            loanPeriodInYears, loanStartDate);
        Assert.IsFalse(monthlyPaymentSchedule == null);
        Assert.IsFalse(monthlyPaymentSchedule.Count > 1);
        var secondMonthPaymentSchedule = monthlyPaymentSchedule[1];
        Assert.AreEqual(monthlyPaymentSchedule.Count, 15 * NoOfMonthsInYear);
        Assert.AreEqual(secondMonthPaymentSchedule.GetMonthlyPaymentAmount(), 
        (decimal) 2144.65);
        Assert.AreEqual(secondMonthPaymentSchedule.GetDate(), "Sep 2016");
        Assert.AreEqual(secondMonthPaymentSchedule.GetInterestAmount(), 
        (decimal) 871.30);
        Assert.AreEqual(secondMonthPaymentSchedule.GetTotalInterestAmount(), 
        (decimal) 1746.30);
        Assert.AreEqual(secondMonthPaymentSchedule.GetPrincipalAmount(), 
        (decimal) 1273.35);
    }
    [ExpectedException(typeof(ArgumentException))]
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest1()
    {
        new AmortizationSchedule().Get(0, loanAmount,
            loanPeriodInYears, loanStartDate);
    }
    [ExpectedException(typeof(ArgumentException))]
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest2()
    {
        new AmortizationSchedule().Get(annualPercentageRate, 0,
            loanPeriodInYears, loanStartDate);
    }
    [ExpectedException(typeof(ArgumentException))]
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest3()
    {
        new AmortizationSchedule().Get(annualPercentageRate, loanAmount, 0, loanStartDate);
    }
    [ExpectedException(typeof(ArgumentException))]
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest4()
    {
        new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
            loanPeriodInYears, DateTime.MinValue);
    }
    [ExpectedException(typeof(ArgumentException))]
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest5()
    {
        new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
            loanPeriodInYears, DateTime.MaxValue);
    }
    [ExpectedException(typeof(ArgumentOutOfRangeException))]
    [TestMethod]
    public void GetAmortizationScheduleExceptionTest6()
    {
        new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
            loanPeriodInYears, DateTime.MaxValue.AddYears(-1));
    }
}

Unit Test Project-Improved

Continue Reading

“Develop something useful in under 100 lines of code” contest.

One of my friends was recently asked to write the coolest/cleverest/most creative application in 100 lines of code or less. Any language could be used. It just needs to be creative, legible and easy enough to understand.

Here is my attempt. The program is a loan payment schedule calculator.
The formula to calculate loan payments is M = P * ( J / (1 – (1 + J) ^ -N)).
where
M = payment amount
P = principal, meaning the amount of money borrowed
J = effective interest rate. This is not the annual interest rate.
N = total number of payments
For more details see here .
I have also written several unit tests since I just do not like writing any code without unit tests. The actual code is just 30 lines and the remaining is all unit tests.
I have used the MidpointRounding.AwayFromZero enumeration to round a double to a number to two decimal points.


using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject
{
    public class AmortizationSchedule : IAmortizationSchedule
    {
        public List<AmortizationScheduleRow> Get(double annualPercentageRate,
             double loanAmount, int loanPeriodInYears, DateTime loanStartDate)
        {
            if (annualPercentageRate <= 0 || loanAmount <= 0 || loanPeriodInYears <= 0 ||
                loanStartDate <= DateTime.MinValue)
            {
                throw new ArgumentException("Invalid arguments");
            }

            #region Calculate monthly payment
            const int NoOfMonthsInYear = 12;
            var loanPeriodInMonths = loanPeriodInYears * NoOfMonthsInYear;
            var effectiveInterestRate = annualPercentageRate / (NoOfMonthsInYear * 100);
            var toThePowerOfVariable = Math.Pow(1 + effectiveInterestRate, -loanPeriodInMonths);
            var monthlyPayment = (loanAmount * (effectiveInterestRate / (1 - toThePowerOfVariable)));
            #endregion

            #region Calculate payment schedule based on monthly payment and loan start date
            var amortizationSchedule = new List<AmortizationScheduleRow>();
            var currentMonthCounter = loanStartDate.AddMonths(1);
            var currentBalance = loanAmount;
            double totalInterestAmount = 0;
            for (var counter = 0; counter < loanPeriodInMonths; counter++)
            {
                var interestAmount = effectiveInterestRate * currentBalance;
                totalInterestAmount = totalInterestAmount + interestAmount;
                var amortizationScheduleRow = new AmortizationScheduleRow
                {
                    Date = currentMonthCounter,
                    MonthlyPaymentAmount = monthlyPayment,
                    InterestAmount = interestAmount,
                    TotalInterestAmount = totalInterestAmount
                };
                amortizationSchedule.Add(amortizationScheduleRow);
                currentBalance = currentBalance - amortizationScheduleRow.GetPrincipalAmount();
                currentMonthCounter = currentMonthCounter.AddMonths(1);
            }
            #endregion
            return amortizationSchedule;
        }
    }
    public interface IAmortizationSchedule
    {
        List<AmortizationScheduleRow> Get(double annualPercentageRate, double loanAmount, int loanPeriodInYears, DateTime loanStartDate);
    }
    public class AmortizationScheduleRow
    {
        public double GetMonthlyPaymentAmount()
        {
            return Math.Round(MonthlyPaymentAmount, 2, MidpointRounding.AwayFromZero);
        }
        public double MonthlyPaymentAmount { private get; set; }
        public double GetInterestAmount()
        {
            return Math.Round(InterestAmount, 2, MidpointRounding.AwayFromZero);
        }
        public double InterestAmount { private get; set; }
        public double GetTotalInterestAmount()
        {
            return Math.Round(TotalInterestAmount, 2, MidpointRounding.AwayFromZero);
        }
        public double TotalInterestAmount { private get; set; }
        public double GetPrincipalAmount()
        {
            var principalAmount = MonthlyPaymentAmount - InterestAmount;
            return Math.Round(principalAmount, 2, MidpointRounding.AwayFromZero);
        }
        public string GetDate()
        {
            return Date.ToString("MMM yyyy");
        }
        public DateTime Date { private get; set; }
    }
    [TestClass]
    public class AmortizationScheduleTester
    {
        const double annualPercentageRate = 3.5;
        const double loanAmount = 300000;
        const int loanPeriodInYears = 15;
        readonly DateTime loanStartDate = new DateTime(2016, 7, 1);
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest()
        {
            const int NoOfMonthsInYear = 12;
            var monthlyPaymentSchedule = new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
                loanPeriodInYears, loanStartDate);
            var secondMonthPaymentSchedule = monthlyPaymentSchedule[1];
            Assert.AreEqual(monthlyPaymentSchedule.Count, 15 * NoOfMonthsInYear);
            Assert.AreEqual(secondMonthPaymentSchedule.GetMonthlyPaymentAmount(), 2144.65);
            Assert.AreEqual(secondMonthPaymentSchedule.GetDate(), "Sep 2016");
            Assert.AreEqual(secondMonthPaymentSchedule.GetInterestAmount(), 871.30);
            Assert.AreEqual(secondMonthPaymentSchedule.GetTotalInterestAmount(), 1746.30);
            Assert.AreEqual(secondMonthPaymentSchedule.GetPrincipalAmount(), 1273.35);
        }
        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest1()
        {
            new AmortizationSchedule().Get(0, loanAmount,
                loanPeriodInYears, loanStartDate);
        }

        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest2()
        {
            new AmortizationSchedule().Get(annualPercentageRate, 0,
                loanPeriodInYears, loanStartDate);
        }
        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest3()
        {
            new AmortizationSchedule().Get(annualPercentageRate, loanAmount, 0, loanStartDate);
        }
        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest4()
        {
            new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
                loanPeriodInYears, DateTime.MinValue);
        }
    }
}

Download Solution

Continue Reading

Generate fibonacci series

Lately I have been reading up on interview related questions. One of the other favorite interview questions interviewers have is to “write a program to generate fibonacci set of series for a user defined input number”. In mathematics, the Fibonacci numbers are the numbers in the following integer sequence(Fibonacci sequence)
0,1,1,2,3,5,8,13,21,34,55,89,144………….
So if the user inputs 8 then the output should be
0,1,1,2,3,5,8,13.

Solution

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void GenerateFibonanciSeries()
        {
            var result = new StringHelper().GenerateFibonanciSeries(8);
            Assert.AreEqual(result[0], 0);
            Assert.AreEqual(result[1], 1);
            Assert.AreEqual(result[2], 1);
            Assert.AreEqual(result[3], 2);
            Assert.AreEqual(result[4], 3);
            Assert.AreEqual(result[5], 5);
            Assert.AreEqual(result[6], 8);
            Assert.AreEqual(result[7], 13);
        }
    }

    public class StringHelper
    {
         public List<long> GenerateFibonanciSeries(long numbersToGenerate)
        {
            if (numbersToGenerate <= 0)
            {
                throw new ArgumentException();
            }
            var result = new List<long>();
            long previousNumber = 0;
            long currentNumber = 1;
            result.Add(previousNumber);
            result.Add(currentNumber);
            for (int counter= 2; counter < numbersToGenerate; counter++)
            {
                long tempNumber = currentNumber + previousNumber;
                result.Add(tempNumber);
                previousNumber = currentNumber;
                currentNumber = tempNumber;                
            }
            return result;
        }
    }
}
Continue Reading

Is string same as its reversed string(i.e Is it a Palindrome)

Lately I have been reading up on interview related questions. One of the favorite interview questions interviewers have is to “write a program to check if a string is the same as its reversed string i.e check that a string is a Palindrone”. To make it more interesting, they ask to not use Array.Reverse.

Solution

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void IsStringSameAsItsReversedStringThatIsItIsAPalinDrome()
        {
            var result=new StringHelper().IsStringSameAsItsReversedStringThatIsItIsAPalinDrome("Anna");
            Assert.AreEqual(result, true);
        }
    }

    public class StringHelper
    {
         public bool IsStringSameAsItsReversedStringThatIsItIsAPalinDrome(string tempString)
        {
            if(String.IsNullOrEmpty(tempString))
            {
                throw new ArgumentException();
            }
            var tempStringLower= tempString.ToLower();
            var tempArray= tempStringLower.ToCharArray();
            var tempArray1 = Reverse(tempArray);
            var reversedString=new string(tempArray1);
            if (reversedString.Equals(tempStringLower))
                return true;
            return false;
        }
        //This function just reverses a array of characters.
        private char[] Reverse(char[] characters)
        {
            for(int counter=0; counter<characters.Length/2;counter++)
            {
                char character = characters[counter];
                characters[counter] = characters[characters.Length - counter -1];
                characters[characters.Length - counter - 1] = character;
            }
            return characters;
        }
    }
}
Continue Reading

Compute value of string that has numbers seperated by arithmetic operators.

One of my friends recently went to an interview to a very well known startup company. It is supposed to hire only the very best technical people in the industry.  One of the problems that he was asked to write a unit test was,

Suppose a string has numbers separated by arithmetic operators, how do you compute the value of it?

BTW, I personally feel that you are not really testing the knowledge of a person by asking such questions and expecting them to solve it in 6 minutes.

Solution

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Data;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var operator1= new Operator();
            int result = operator1.Maths("2+3");
            Assert.AreEqual(result, 5);
        }

        [TestMethod]
        public void TestMethod2()
        {
            var operator1 = new Operator();
            int result = operator1.Maths("2+3*4");
            Assert.AreEqual(result, 14);
        }
        [TestMethod]
        public void TestMethod3()
        {
            var operator1 = new Operator();
            int result = operator1.Maths("2+3*10/5");
            Assert.AreEqual(result, 8);
        }
    }

    public class Operator
    {
        public int Maths(string operation)
        {
            object result=new DataTable().Compute(operation, null);
            return Int32.Parse(result.ToString());
        }
    }
}
Continue Reading

Mock ASP.Net internals when unit testing ASP.Net MVC.

Problem:
ASP.NET MVC controller context depends on asp.net internals. How should these be mocked for unit tests?

Solution:

Here is a sample unit test class using MsTest and Moq which mocks HttpRequest and HttpResponse objects. Controller action get value from request and sets http header in response objects. Other http context objects could be mocked up in similar way.

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

[TestClass]
public class SampleControllerTest
{
    protected Mock<HttpContextBase> httpContextBaseMock;
    protected Mock<HttpRequestBase> httpRequestBaseMock;
    protected Mock<HttpResponseBase> httpResponseBaseMock;

    [TestInitialize]
    public void TestInitialize()
    {
        this.httpContextBaseMock = new Mock<HttpContextBase>();
        this.httpRequestBaseMock = new Mock<HttpRequestBase>();
        this.httpResponseBaseMock = new Mock<HttpResponseBase>();
        this.httpContextBaseMock.SetupGet(x => x.Request).Returns(
        this.httpRequestBaseMock.Object);
        this.httpContextBaseMock.SetupGet(x => x.Response).Returns(
        this.httpResponseBaseMock.Object);
    }

    protected SampleController SetupController()
    {
        var controller = new SampleController();
        var routeData = new RouteData();
        controller.ControllerContext = new ControllerContext(
        this.httpContextBaseMock.Object, routeData, controller);
        controller.Url = new UrlHelper(
        new RequestContext(this.httpContextBaseMock.Object, routeData), 
        new RouteCollection());
        return controller;
    }

    [TestMethod]
    public void IndexTest()
    {
        this.httpRequestBaseMock.Setup(x => x["x"]).Returns("1");
        this.httpResponseBaseMock.Setup(x => x.AddHeader("name", "value"));

        var controller = SetupController();
        var result = controller.Index();
        Assert.AreEqual("1", result.Content);

        this.httpRequestBaseMock.VerifyAll();
        this.httpResponseBaseMock.VerifyAll();
    }
}

public class SampleController : Controller
{
    public ContentResult Index()
    {
        var x = Request["x"];
        Response.AddHeader("name", "value");
        return Content(x);
    }
}
Continue Reading