Coding style 编写转换函数的最佳方法
假设我正在编写一个函数,在温度刻度之间进行转换。我想至少支持摄氏度、华氏度和开尔文。传递源比例和目标比例作为函数的单独参数,还是某种组合参数更好 示例1-单独的参数: 功能转换器温度(“摄氏度”、“华氏度”、22度) 示例2-组合参数: 功能转换器温度(“c-f”,22) 函数中的代码可能就是它的作用所在。有了两个参数,确定我们将要使用的公式的逻辑稍微复杂一些,但是一个参数不知怎么的感觉不正确Coding style 编写转换函数的最佳方法,coding-style,Coding Style,假设我正在编写一个函数,在温度刻度之间进行转换。我想至少支持摄氏度、华氏度和开尔文。传递源比例和目标比例作为函数的单独参数,还是某种组合参数更好 示例1-单独的参数: 功能转换器温度(“摄氏度”、“华氏度”、22度) 示例2-组合参数: 功能转换器温度(“c-f”,22) 函数中的代码可能就是它的作用所在。有了两个参数,确定我们将要使用的公式的逻辑稍微复杂一些,但是一个参数不知怎么的感觉不正确 想法?使用第一个选项,但不允许使用文本字符串(容易出错),而是使用常量值或枚举(如果您的语言支持),如
想法?使用第一个选项,但不允许使用文本字符串(容易出错),而是使用常量值或枚举(如果您的语言支持),如下所示:
convertTemperature (TempScale.CELSIUS, TempScale.FAHRENHEIT, 22)
我的投票是转换类型的两个参数,一个是值(如第一个示例中所示)。但是,我会使用枚举而不是字符串文字。如果您的语言允许,请使用枚举作为单元规范
我想说,里面的代码会更容易与两个。我将有一个包含预添加、多个和后添加的表,并对一个单元的项运行值,然后对另一个单元的项反向运行值。基本上将输入温度转换为内部的公共基值,然后输出到另一个单位。整个函数都是表驱动的。取决于要进行的转换次数。我可能会选择一个参数,作为枚举:考虑这个扩展版本的转换。< /P>
enum Conversion
{
CelsiusToFahrenheit,
FahrenheitToCelsius,
KilosToPounds
}
Convert(Conversion conversion, X from);
现在,您在调用点具有sane类型安全性—无法提供正确类型的参数,而这些参数会给出错误的运行时结果。考虑另一种选择。
enum Units
{
Pounds,
Kilos,
Celcius,
Farenheight
}
Convert(Unit from, Unit to, X fromAmount);
我可以打电话
Convert(Pounds, Celcius, 5, 10);
但是结果是没有意义的,你必须在运行时失败。是的,我知道你现在只讨论温度,但一般的概念仍然成立(我相信)。我会对温度类型进行枚举,并传入两个刻度参数。类似于(在c中):
公共温度(TemperatureTypeNum SourceTemp,
目标温度,
十进制温度)
{}
有几件事:
- 我会使用语法检查器或编译器可以检查的枚举类型,而不是可能键入错误的字符串。在伪PHP中: 定义('kCelsius',0);定义('kFarenheit',1);定义('kKelvin',2); $a=转换温度(22,克塞尔修斯,克法伦海特)
如果你正在为用户提供类似谷歌搜索框的东西,那么拥有像“c-f”这样的便捷快捷方式对他们来说很好。不过,在下面,我会在调用convertTemperature()之前将外部函数中的“c-f”转换为“摄氏度”和“华氏度” 将温度从一个刻度转换为另一个刻度的功能。
在我看来,将源标度和目标标度作为单独的参数传递更为自然。我绝对不想试图掌握第一个论点的格式。在写这样的设计时,我想自己,“如果我需要添加一个额外的单元,什么样的设计会使它最容易实现?”这样做,我得出结论,Enum最容易实现,原因如下: 1) 添加新值很容易。 2) 我避免做字符串比较 但是,如何编写转换方法?3p2是6。这意味着有6种不同的摄氏度、华氏度和开尔文的组合。如果我想添加一个新的温带格式“foo”呢?这意味着4p2,也就是12!再来两杯?5p2=20个组合。再来三个?6p2=30个组合
您可以很快看到,每次额外的修改都需要对代码进行越来越多的更改。因为这个原因,我不做直接转换!相反,我进行中间转换。我会选择一个温度,比如开尔文。最初,我会转换成开尔文。然后我将开尔文转换成所需的温度。是的,它确实会导致额外的计算。然而,它使代码的缩放变得更加容易。添加一个新的温度单位通常只会对代码进行两次新的修改。简单。如果使用第一种方法,您的函数将更加健壮。如果需要添加另一个比例,则需要再处理一个参数值。在第二种方法中,添加另一个比例意味着添加列表中已有比例的值,乘以2。(例如,要将K添加到C和F,必须添加K-C、K-F、C-K和C-F。) 构建程序的一种好方法是,首先将输入的任何内容转换为任意选择的中间刻度,然后从该中间刻度转换为输出刻度
更好的方法是为各种比例尺建立一个小的坡度和截距库,只需查找传入和传出比例尺的数字,然后在一个通用步骤中进行计算。取决于语言 通常,我会对枚举使用单独的参数 如果它是一种面向对象的语言,那么我建议使用一个temperature类,该类的温度按照您喜欢的方式存储在内部,然后使用函数以所需的任何单位输出: 摄氏温度();//返回temperatu
public void ConvertTemperature(TemperatureTypeEnum SourceTemp,
TemperatureTypeEnum TargetTemp,
decimal Temperature)
{}
interface ITemperature
{
CelciusTemperature ToCelcius();
FarenheitTemperature ToFarenheit();
}
struct FarenheitTemperature : ITemperature
{
public readonly int Value;
public FarenheitTemperature(int value)
{
this.Value = value;
}
public FarenheitTemperature ToFarenheit() { return this; }
public CelciusTemperature ToCelcius()
{
return new CelciusTemperature((this.Value - 32) * 5 / 9);
}
}
struct CelciusTemperature
{
public readonly int Value;
public CelciusTemperature(int value)
{
this.Value = value;
}
public CelciusTemperature ToCelcius() { return this; }
public FarenheitTemperature ToFarenheit()
{
return new FarenheitTemperature(this.Value * 9 / 5 + 32);
}
}
// Freezing
Debug.Assert(new FarenheitTemperature(32).ToCelcius().Equals(new CelciusTemperature(0)));
Debug.Assert(new CelciusTemperature(0).ToFarenheit().Equals(new FarenheitTemperature(32)));
// crossover
Debug.Assert(new FarenheitTemperature(-40).ToCelcius().Equals(new CelciusTemperature(-40)));
Debug.Assert(new CelciusTemperature(-40).ToFarenheit().Equals(new FarenheitTemperature(-40)));
CelciusTemperature theOutbackInAMidnightOilSong = new CelciusTemperature(45);
FarenheitTemperature x = theOutbackInAMidnightOilSong; // ERROR: Cannot implicitly convert type 'CelciusTemperature' to 'FarenheitTemperature'
float LinearConvert(float in, float scale, float add, bool invert);
public class Temperature
{
private double celcius;
public static Temperature FromFarenheit(double farenheit)
{
return new Temperature { Farhenheit = farenheit };
}
public static Temperature FromCelcius(double celcius)
{
return new Temperature { Celcius = celcius };
}
public static Temperature FromKelvin(double kelvin)
{
return new Temperature { Kelvin = kelvin };
}
private double kelvinToCelcius(double kelvin)
{
return 1; // insert formula here
}
private double celciusToKelvin(double celcius)
{
return 1; // insert formula here
}
private double farhenheitToCelcius(double farhenheit)
{
return 1; // insert formula here
}
private double celciusToFarenheit(double kelvin)
{
return 1; // insert formula here
}
public double Kelvin
{
get { return celciusToKelvin(celcius); }
set { celcius = kelvinToCelcius(value); }
}
public double Celcius
{
get { return celcius; }
set { celcius = value; }
}
public double Farhenheit
{
get { return celciusToFarenheit(celcius); }
set { celcius = farhenheitToCelcius(value); }
}
}
$ units 'tempF(-40)' tempC
-40
use Convert::Temperature;
my $c = new Convert::Temperature();
my $res = $c->from_fahr_to_cel('59');
double fahrtocel(double tempF){
return ((tempF-32)*(5/9));
}
double celtofahr(double tempC){
return ((9/5)*tempC + 32);
}
function Temperature($value, $input, $output)
{
$value = floatval($value);
if (isset($input, $output) === true)
{
switch ($input)
{
case 'K': $value = $value - 273.15; break; // Kelvin
case 'F': $value = ($value - 32) * (5 / 9); break; // Fahrenheit
case 'R': $value = ($value - 491.67) * (5 / 9); break; // Rankine
}
switch ($output)
{
case 'K': $value = $value + 273.15; break; // Kelvin
case 'F': $value = $value * (9 / 5) + 32; break; // Fahrenheit
case 'R': $value = ($value + 273.15) * (9 / 5); break; // Rankine
}
}
return $value;
}