这是我对Stackoverflow的第一个问题,尽管我多年来一直是消费者。如果我违反规则,请原谅我。那肯定不是我的意图。我已经严格审查了规则并相信我处于可接受的范围内。但是,如果它们存在,我会要求您指出使用错误,以便将来可以更加合规。
我教高中生编程。本学期我们正在做C#。上周我们正在研究递归。我分配了几个可以通过递归解决的经典问题,其中一个是求幂。
我的一个学生提交了以下代码作为使用递归取幂的解决方案(他确实允许我在此处发布)。方法调用中的任务给了我很多的意思,但当我告诉他这是不好的做法时,他抗议说“它有效”,对他“有意义”,他“一直都这样做” ”
static void Recur(int n1, int n2, int n3)
{
if (n2 > 0)
{
Recur(n1, n2 - 1, n3 *= n1); // this is the line in question
}
else
{
Console.WriteLine("The number calculated recursively is: {0}", n3);
}
}
我很难想出一些具体的东西来告诉我的学生为什么在方法调用中进行分配通常是不好的做法,除了1)意外副作用的可能性,以及2)难度维护。
我已经在线搜索了我可以构建的关于这个问题的每一个短语,但是空洞地出现了。我确实看到了罗伯特·C·马丁的一本名为“清洁代码”的书,我并不拥有。
我与学生的关系有点像父母的关系。除非我能用独立的资料证明,否则他们有时候不会把大量的股票放在我所说的内容中。如果我可以指出一个关于将分配放入方法调用的明确声明,我的学生将更倾向于停止这种烦人的习惯。
这种用法是否会困扰其他人?我是否希望他改变他一直做事的方式?他已经15岁了,但在他前面有一个充满希望的未来。他是那些只是“得到它”的学生之一。我不希望他发展不良做法。
感谢您的时间和意见。
答案 0 :(得分:3)
在发布的代码中有很多可以改进的东西:
保持一致
为什么没有通话Recur(n1, n2 =- 1, n3 *= n1)
?为什么n3
的处理方式不同?在审查/保留代码时,这可能会造成混淆。
不要做不必要或多余的工作
n3
之后Recur(n1, n2 - 1, n3 *= n1)
曾被使用过吗?没有?那么为什么要浪费时间来分配一个从未使用过的值呢?
考虑到不改变方法参数的好习惯(当然,除非它们通过引用传递)。为什么?因为它使调试和理解代码的工作方式更加困难;在方法执行时使初始条件变异使得跟踪可能的错误,优化,改进等更加困难。
所有这一切,我避免这种模式,因为我的记忆非常糟糕:
var i = 0;
Foo(i += 1);
Bar(i);
传递给Foo
的内容是什么?它是0
还是1
?我永远不会记得,我每次都要查一查。很可能无论谁审阅这些代码都会遇到同样的问题。这些巧妙的技巧不会使代码更快或更好地工作,并且它避免了总共一个代码行......不值得。
答案 1 :(得分:0)
错误的代码是这一个:n3 *= n1
您的学生没有看到任何问题,因为方法参数不是final
。只需定义它们final
,您就会发现代码的这种平衡会导致编译错误。
为什么要使用final
?因为这可以确保方法参数不会用于方法内的任何其他目的。这使得代码不易出错,更可靠。将一个变量用于一个目的使得代码更易于被其他人理解,这在业界很重要。
正如其他人已经指出的那样,为n3赋值是没有意义的,因为在代码中没有使用变量n3。
他的声明“这对他来说有意义”表明他并不关注现实生活中的软件开发 - 从小公司到谷歌或Facebook。其中一个要求是代码应该是可维护的。这种代码的和平不是。
关于“在他前面有一个充满希望的未来”:你怎么知道的?他赢得了任何编程竞赛吗?他“一直做到这一点”的论点相当薄弱。问他为什么这么做?给他一个关于代码质量的小研究。可能这将有助于他了解软件开发。