我教高中生编程.这个学期我们正在做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岁,但在他前面有一个充满希望的未来.他是那些只是“得到它”的学生之一.我不希望他发展不好的做法.
感谢您的时间和意见.
解决方法
>保持一致
为什么不调用Recur(n1,n2 = – 1,n3 * = n1)?为什么n3的处理方式不同?在查看/保留代码时,这可能会造成混淆.
>不要做不必要或多余的工作
在Recur(n1,n2 – 1,n3 * = n1)之后是否曾经使用过n3?没有?那么为什么浪费时间来分配一个从未使用过的值呢?
>不改变方法参数被认为是好习惯(除非它们通过引用传递).为什么?因为它使调试和理解代码的工作方式更加困难;在方法执行时使初始条件变异使得跟踪可能的错误,优化,改进等变得更加困难.
所有这一切,我避免这种模式,因为我有非常糟糕的记忆:
var i = 0; Foo(i += 1); Bar(i);
什么传递给Foo?它是0还是1?我永远不会记得,我每次都要查一查.有可能无论谁审阅此代码都会遇到同样的问题.这些聪明的技巧不会使代码更快或更好地工作,并且它避免了总共一个代码行……不值得.