7-1.임시 필드 Temporary Field
[ 2017-08.16 작성 ]
클래스는 일반적으로 모든 인스턴스 변수를 사용하기를 기대하기 때문에 임시 변수가 사용되는 것을 보기가 어려울 수 있습니다.
특정 상황에 따라 값이 변하게 되는 임시 변수는 코드를 이해하기 어렵게 만듭니다.
참고 사이트
http://blog.ploeh.dk/2015/09/18/temporary-field-code-smell/
[ sample source ]
public class Estimator
{
private readonly TimeSpan defaultEstimate ;
private IReadOnlyCollection < TimeSpan > durations ;
.....
.....
public TimeSpan CalculateEstimate ( IReadOnlyCollection < TimeSpan > durations )
{
.....
this . durations = durations ;
this . CalculateAverage ();
this . CalculateStandardDeviation ();
var margin = TimeSpan . FromTicks ( this . standardDeviation . Ticks * 3 );
return this . average + margin ;
}
private void CalculateAverage (){ // 임시 필드에 셋팅된 값(durations) 처리
.....
}
private void CalculateStandardDeviation (){ // 임시 필드에 셋팅된 값(durations) 처리
.....
}
....
위의 durations 임시변수와 평균계산, 표준편자 계산 메서드를 Class로 추출하여 사용하는 예제를 보게 됩니다.
아래의 코드와 같습니다.
[ 1. ] 해결책
public class Estimator // class
{
// private IReadOnlyCollection<TimeSpan> durations; <- 삭제
......
......
var stats = new DurationStatistics ( durations ); // 평균, 표준편차 계산
var margin = TimeSpan . FromTicks ( this . standardDeviation . Ticks * 3 );
return this . average + margin ;
......
......
private class DurationStatistics // public class안의 private class
{
private readonly IReadOnlyCollection < TimeSpan > durations ;
private readonly Lazy < TimeSpan > average ;
private readonly Lazy < TimeSpan > standardDeviation ;
public DurationStatistics ( IReadOnlyCollection < TimeSpan > durations )
{
if ( durations == null )
throw new ArgumentNullException ( nameof ( durations ));
if ( durations . Count == 0 )
throw new ArgumentException ( "Empty collection not allowed." , nameof ( durations ));
this . durations = durations ;
this . average = new Lazy < TimeSpan >( this . CalculateAverage );
this . standardDeviation = new Lazy < TimeSpan >( this . CalculateStandardDeviation );
}
public TimeSpan Average {.....}
public TimeSpan StandardDeviation {.....}
private TimeSpan CalculateAverage (){.....}
private TimeSpan CalculateStandardDeviation (){.....}
.....
.....
Estimator 클래스 안에 private 접근자 DurationStatistics 클래스는 중첩 된 클래스입니다.
하지만 임시 변수 durations에 값이 설정되고 공유하고 있는 코드를 제거할 수 있고 만약
공용 클래스로 만들어 재사용 가능한 개념을 도입한다면 전체 코드베이스가 향상될 수 있습니다.
[ 2. ] 해결책
public class Estimator
{
// private IReadOnlyCollection<TimeSpan> durations; <- 삭제
......
var average = CalculateAverage ( durations );
var standardDeviation = CalculateStandardDeviation ( durations , average );
var margin = TimeSpan . FromTicks ( standardDeviation . Ticks * 3 );
return average + margin ;
.....
.....
private static TimeSpan CalculateAverage ( IReadOnlyCollection < TimeSpan > durations )
{
.....
private static TimeSpan CalculateStandardDeviation ( IReadOnlyCollection < TimeSpan > durations , TimeSpan average )
{
.....
필요한 인수를 전달하는 방법도 좋은 해결책!