Skip to content

Instantly share code, notes, and snippets.

@arlobelshee
Last active October 2, 2015 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arlobelshee/25a17ce7676b807c1dde to your computer and use it in GitHub Desktop.
Save arlobelshee/25a17ce7676b807c1dde to your computer and use it in GitHub Desktop.
Combine 2 methods into one with a discriminator variable
// Initial state for unifying two similar methods to use a discriminator variable.
//
// Includes 2 methods (Drive_WithFuelMonitoring and Drive_WithAverageSpeedCalculation)
// that are similar in intent and differ only in implementation. This may be a bug or
// may be intentional. We can't tell without asking the domain expert. So we want to
// unify them mechanistically.
//
// The history shows how.
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
namespace Blog_gists
{
public class Car
{
[NotNull] private readonly List<TravelSegment> drivingHistory = new List<TravelSegment>();
public Car()
{
Odometer = 0;
IsAtDestination = false;
}
public void Drive_WithFuelMonitoring(int speed, int distance)
{
for (var i = 0; i < distance; ++i)
{
DriveOneMile(speed);
}
FinishDriving();
FuelRemaining -= CalculateFuelConsumed(speed, distance);
Odometer += distance;
}
public void Drive_WithAverageSpeedCalculation(int speed, int distance)
{
for (var i = 0; i < distance; ++i)
{
DriveOneMile(speed);
}
FinishDriving();
Odometer += distance;
drivingHistory.Add(new TravelSegment(speed, distance));
}
public decimal? AverageSpeed
{
get
{
if (drivingHistory.Count == 0) return null;
var totalDriveTime = drivingHistory.Select(h => h.Distance/h.Speed).Sum();
return Odometer/totalDriveTime;
}
}
public void FillGasTank(decimal numGallons)
{
FuelRemaining += numGallons;
}
private void FinishDriving()
{
IsAtDestination = true;
}
public class TravelSegment
{
public decimal Speed;
public decimal Distance;
public TravelSegment(int speed, int distance)
{
Speed = speed;
Distance = distance;
}
}
private decimal CalculateFuelConsumed(int speed, int distance)
{
return 3;
}
private void DriveOneMile(int speed)
{
IsAtDestination = false;
}
public int Odometer { get; private set; }
public decimal FuelRemaining { get; private set; }
public bool IsAtDestination { get; private set; }
}
}
using FluentAssertions;
using NUnit.Framework;
namespace Blog_gists
{
[TestFixture]
public class CarsDrive
{
private const int Speed = 50;
private const int Distance = 100;
[Test]
public void DrivingWhileUpdatingFuelGuageShouldMoveTheCarAndRequireGas()
{
var testSubject = new Car();
testSubject.FillGasTank(12);
testSubject.Drive_WithFuelMonitoring(Speed, Distance);
testSubject.IsAtDestination.Should().BeTrue();
testSubject.Odometer.Should().Be(100);
testSubject.FuelRemaining.Should().Be(9);
testSubject.AverageSpeed.Should().NotHaveValue();
}
[Test]
public void DrivingWhileUpdatingMilageShouldMoveTheCarAndCalculateMilage()
{
var testSubject = new Car();
testSubject.FuelRemaining.Should().Be(0);
testSubject.Drive_WithAverageSpeedCalculation(Speed, Distance);
testSubject.IsAtDestination.Should().BeTrue();
testSubject.Odometer.Should().Be(100);
testSubject.FuelRemaining.Should().Be(0);
testSubject.AverageSpeed.Should().Be(50);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment