昨晚,我写了大约200行蹩脚的perl代码,包括意大利面条代码,我无法调试的未定义变量,以及更多内容。最终,我把它放在PerlMonks上并等待。我认为这是最有帮助的回应:
超过200行意大利面条代码,输入解析在一个子中的其他所有内容中搅拌。难怪你在调试这只小狗时遇到了麻烦!一些提示可能有助于清理事物:
- 重构代码,将所有输入解析移出LHCC子,然后将解析后的数据传递给子。这使得您可以编写和调试sub,而无需将输入数据解析为正确的开始。
- 请勿使用goto
- 不要在if / elsif / else语句中使用空{} - 它们会模糊失败条件
- 不要重复代码块 - 使用sub。这包括大量的代码因长而无意义的错误消息而死亡的地方。使用sub并传递要包含在消息中的上下文。这将清理代码并帮助调试逻辑错误。
- 不要为不可能发生的事情编码(n%2只能是0或1)以避免混乱代码并模糊逻辑
- 在“早退出”循环旁边使用。这样可以避免嵌套代码并使其更易于理解。
- 使用前检查$ key(和die)。
- 为什么我的@StatementsKeys =键%语句;什么时候没有使用@StatementsKeys?
我会在适当的时候跟进一个有点版本的代码,但有很多行要删除,这需要一段时间! ;)
这对于Perl代码来说都是非常好的建议。但是我在实施他的建议和真正成为一个懒惰的编码器时遇到了问题。出于一些奇怪的原因,我无法实现他对我编程的所有内容的说法,我非常肯定你是如何学习真正好的编程的。我有2个问题:
首先,您将如何使这个快速脚本优化,更好,代码?我认为在看到这个优化后,我将能够开始使用我的代码更好的方向。顺便说一句,这不是上述消息中提到的代码。
ORIGINAL:
print "
Welcome to the Casio-Maxim Quadrilateral Identification\n
Algorithm. In order to identify said quadrilateral,\n
you must have the coordinates of all 4 vertices.\n
When you are ready to input your coordines, type\n
'ready.' Type 'quit' to exit the CMQIA.\n\n";
my $choice = <STDIN>;
if ($choice =~ /quit/i) {
if (!&Unit6()) {
return 0;
}
}
elsif ($choice =~ /ready/i) {
}
else {
print "\nCould not interpret, try again\n";
goto ORIGINAL;
}
print
"\nFor shape ABCD, in which point A has coordinates (X1, Y1), B has coordinates\n\n(X2, Y2), C has coordinates (X3, Y3), and D has coordinates (X4, Y4),\n\nX1 = ";
my $AX = <STDIN>;
chomp $AX;
if ($AX !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nY1 = ";
my $AY = <STDIN>;
chomp $AY;
if ($AY !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nX2 = ";
my $BX = <STDIN>;
chomp $BX;
if ($BX !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nY2 = ";
my $BY = <STDIN>;
chomp $BY;
if ($BY !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nX3 = ";
my $CX = <STDIN>;
chomp $CX;
if ($CX !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nY3 = ";
my $CY = <STDIN>;
chomp $CY;
if ($CY !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nX4 = ";
my $DX = <STDIN>;
chomp $DX;
if ($DX !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
print "\nY4 = ";
my $DY = <STDIN>;
chomp $DY;
if ($DY !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
goto ORIGINAL;
}
my $SAB = ($BX - $AX)**2 + ($BY - $AY)**2;
my $AB = sqrt($SAB);
my $SBC = ($CX - $BX)**2 + ($CY - $BY)**2;
my $BC = sqrt($SBC);
my $SCD = ($DX - $CX)**2 + ($DY - $CY)**2;
my $CD = sqrt($SCD);
my $SDA = ($AX - $DX)**2 + ($AY - $DY)**2;
my $DA = sqrt($SDA);
my $SAC = ($CX - $AX)**2 + ($CY - $AY)**2;
my $AC = sqrt($SAC);
my $SBD = ($DX - $BX)**2 + ($DY - $BY)**2;
my $BD = sqrt($SBD);
my $MAB = eval { ($BY - $AY) / { $BX - $AX } };
if ($@) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
goto ORIGINAL;
}
my $MBC = eval { ($CY - $BY) / { $CX - $BX } };
if ($@) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
goto ORIGINAL;
}
my $MCD = eval { ($DY - $CY) / { $DX - $CX } };
if ($@) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
goto ORIGINAL;
}
my $MDA = eval { ($AY - $DY) / { $AX - $DX } };
if ($@) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
goto ORIGINAL;
}
my $MAC = eval { ($CY - $AY) / { $CX - $AX } };
if ($@) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
goto ORIGINAL;
}
my $MBD = eval { ($DY - $BY) / { $DX - $BX } };
if ($@) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
goto ORIGINAL;
}
my $ShapeName;
if ($MAB == $MCD) {
if ($MBC == $MDA) {
if ((-1 / $MAB) == $MDA && (-1 / $MBC) == $MCD) {
if ($AB == $BC) {
$ShapeName = "square";
}
else {
$ShapeName = "rectangle";
}
}
else {
if ($AB == $BC) {
$ShapeName = "rhombus";
}
else {
$ShapeName = "parallelogram";
}
}
}
else {
if ($BC == $DA) {
$ShapeName = "isosceles trapezoid";
}
else {
$ShapeName = "trapezoid";
}
}
}
else {
if ($MBC == $MDA) {
if ($AB == $CD) {
$ShapeName = "isosceles trapezoid";
}
else {
$ShapeName = "trapezoid";
}
}
else {
if ((-1 / $MAC) == $MBD) {
$ShapeName = "kite";
}
else {
$ShapeName = "quadrilateral";
}
}
}
print "
Shape ABCD is a $ShapeName.\n
AB = $AB or the square root of ($SAB)\n
BC = $BC or the square root of ($SBC)\n
CD = $CD or the square root of ($SCD)\n
DA = $DA or the square root of ($SDA)\n
AC = $AC or the square root of ($SAC)\n
BD = $BD or the square root of ($SBD)\n
Slope of AB = $MAB\n
Slope of BC = $MBC\n
Slope of CD = $MCD\n
Slope of DA = $MDA\n
Slope of AC = $MAC\n
Slope of BD = $MBD\n";
goto ORIGINAL;
其次,如果我有一位导师来帮助我编码,那么我就不会只是继续发布PerlMonks和Stack Overflow了,但我可以去问我的导师。不幸的是,我已经失去了与我见过的最好的编码人员的联系,他总是帮我解决我的代码问题,我学校里没有人知道谁真的擅长Perl和Python-esque语言。找到我的代码导师的任何建议?
答案 0 :(得分:4)
首先,您使用标签和gotos来模拟正常的程序流控制语句。
非常极少数情况下,goto
语句适用于任何语言。向后跳Perl特别糟糕。在这种情况下,您可以简单地使用:
while (1) {
...
} else {
print "\nCould not interpret, try again\n";
continue;
}
...
}
让语言与你合作。
接下来,我希望您宣布自己的变量,是否还确保在文件顶部use strict;
,以便声明变量是有用的?
接下来,这部分代码重复了很多,只做了很小的改动:
my $AX = <STDIN>;
chomp $AX;
if ($AX !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n"; goto ORIGINAL;
}
你可以把它变成像这样的子:
sub parse_input {
my $coord = shift(_@);
chomp $coord;
if ($coord !~ /^-?\d+\.?\d*$/) {
print "\nMust be numeric value.\n";
return false;
}
return true;
}
然后这样称呼它:
my $AX = <STDIN>;
continue unless (parse_input($AX));
my $AY = <STDIN>;
continue unless (parse_input($AY));
my $BX = <STDIN>;
continue unless (parse_input($BX));
my $BY = <STDIN>;
continue unless (parse_input($BY));
my $CX = <STDIN>;
continue unless (parse_input($CX));
my $CY = <STDIN>;
continue unless (parse_input($CY));
my $DX = <STDIN>;
continue unless (parse_input($DX));
my $DY = <STDIN>;
continue unless (parse_input($DY));
接下来,您有许多重复的代码,如下所示:
my $SAB = ($BX-$AX)**2 + ($BY-$AY)**2;
my $AB = sqrt($SAB);
将其分解并使语言适合您。从那里找出错别字也很难,它很密集,难以阅读。
sub pyth {
my ($AX, $AY, $BX, $BY) = @_;
return sqrt(($BX-$AX)**2 + ($BY-$AY)**2);
}
并称之为:
my $AB = pyth($AX, $AY, $BX, $BY);
my $BC = pyth($BX, $BY, $CX, $CY);
等
接下来,您的斜率查找函数使用eval技巧捕获除以零。但是,我们可以直接检查。它更加清晰。
my $MAB = eval{($BY-$AY)/{$BX-$AX}}; if ($@) {print "\nUndefined or No Slope. Sorry, cannot compute.\n"; goto ORIGINAL;}
变为:
if ($BX-$AX == 0) {
print "\nUndefined or No Slope. Sorry, cannot compute.\n";
continue;
}
my $MAB = ($BY-$AY)/($BX-$AX);
当然,因为这是你重复一遍的代码的一部分,你应该把它放在一个子目录中。
一个好的经验法则是,如果你必须两次编写代码,它可能会保留,如果你重复了3次或更多次,或者它很长,你应该把它放在一个函数中。
接下来,您将需要处理斜率未定义的情况,因为它们仍然是有效的形状。
最后,加入一些注释,特别是在形状识别代码中,优先级并不是立即明显的,所以你首先要用简单的英语解释逻辑。