我听说使用TDD开发的项目更容易重构,因为这种做法产生了一套全面的单元测试,如果任何更改破坏了代码,它将(希望)失败.然而,我所看到的所有这些例子都涉及重构实现 - 例如,用更高效的算法改变算法.
我发现重构架构在设计仍在制定的早期阶段更为常见.接口改变,添加和删除新类,甚至函数的行为可能会稍微改变(我认为我需要它来做这个,但它实际上需要这样做)等等......但是如果每个测试用例都紧密耦合对于这些不稳定的类,您每次更改设计时都不必不断地重写测试用例吗?
在TDD的什么情况下可以改变和删除测试用例?你怎么能确定改变测试用例不会破坏它们?此外,似乎必须同步一个全面的测试套件和不断变化的代码将是一个痛苦.我知道单元测试套件在维护期间可以提供很大的帮助,一旦软件构建完成,稳定并且运行正常,但是在游戏的后期TDD应该尽早提供帮助.
最后,关于TDD和/或重构的好书会解决这些问题吗?如果是这样,你会推荐哪一个?
我正在尝试重构一个超级脂肪模型,该模型有很多与状态和转换相关的ActsAsStateMachine代码,我希望将它重构为模块调用CallStates.
#in lib/CallStates.rb
module CallStates
module ClassMethods
aasm_column :status
aasm_state :state1
aasm_state :state2
aasm_state :state3
end
def self.included(base)
base.send(:include, AASM)
base.extend(ClassMethods)
end
end
Run Code Online (Sandbox Code Playgroud)
然后在模型中
include CallStates
Run Code Online (Sandbox Code Playgroud)
我的问题涉及如何将模块行为包含到模块中,以便单个模块可以包含在模型中.我已经尝试过class_eval也无济于事.感谢您对此事的任何深刻见解.
最近我发现自己在编码风格方面使用了R代码 - 多个作者和个人作者,他们并不严格遵守单一结构.有些任务我想比现在更好地自动化.
我正在寻找一种管理以下任务的工具(或多种工具) - 按照欲望的增加顺序列出,但也有点依赖于存在的怀疑主义.
基本格式.比如将"if(foo)"转换为"if(foo)"并在支撑位置和类似物方面实现一致性.
将"foo $ blah"转换为"foo [["blah"]]"以获取列表访问权限.理想情况下,它至少可以猜测一个对象是否真的是一个列表而不是data.frame并且只能转换列表.
将'='转换为'< - '.是的,这是一个简单的搜索和替换 - 但不是真的.工具(或regexp)需要具有语言感知能力,以便它知道转换"x = 5"而不是"foo(x = 5)".不仅简单地替换符号而且确保赋值运算符两侧的单个空格也是非常好的.
变量重命名,特别是跨功能和文件.例如,假设一个列表有一个元素"foo",我希望能够将它改为"foobar"一次,而不必在整个代码流中追踪该列表的每个用法.我想这将需要该工具能够进行整个控制流程,以便识别诸如在不同函数中作为另一个名称存在的列表之类的事物.
命名约定.我希望能够定义一些标准的命名约定(例如Google或其他)并让它识别所有函数,变量等并转换它们.请注意,这与列表元素之类的内容相关联.
随意列出基本的unix处理命令(例如sed),只要它真的足够智能,至少通常不会搞砸(例如将"foo(x = 5)"转换为"foo(x <-5)" ").
我猜测,如果这样的工具,我会听到它的一个完美的状态现在已经存在了,而且我也意识到,与如R语言,很难做一些这些类型的变化的自动的,但是人们可以做梦吧?有没有人对这些/所有这些有指针?
我正在浏览充满这样代码的代码库:
if let Some(i) = func1() {
if let Some(j) = func2(i) {
if let Some(k) = func3(j) {
if let Some(result) = func4(k) {
// Do something with result
} else {
println!("func 4 returned None");
}
} else {
println!("func 3 returned None");
}
} else {
println!("func 2 returned None");
}
} else {
println!("func 1 returned None");
}
Run Code Online (Sandbox Code Playgroud)
这是一个愚蠢的、简化的例子,但一般模式是:
Option.None)传递给下一个函数。Some,则返回的最终值将用于某些用途。None,则执行停止并记录某种错误 …现在,Visual Studio对C#的重构支持非常好(虽然不如我已经看到的一些Java IDE好一半),但我真的缺少C++支持.
我见过Refactor!我现在正在尝试,但也许你们其中一个人知道一个更好的工具或插件?
我们的代码很糟糕.实际上,让我澄清一下.我们的旧代码很糟糕.它很难调试,并且充满了很少人理解甚至记住的抽象概念.就在昨天,我花了一个小时在一个我工作了一年多的地方进行调试,发现自己在想,"哇,这真的很痛苦." 这不是任何人的错 - 我确信这一切最初都是完全合理的.最糟糕的部分通常是它只是工作...如果你不要求它做任何超出其舒适区域的事情.
我们的新代码非常好.我想我们在那里做了很多好事.它清晰,一致,(希望)可维护.我们有一台运行用于持续集成的Hudson服务器,我们已经开始使用单元测试套件了.问题是我们的管理层专注于编写新代码.没有时间给Old Code(甚至旧的新代码)提供它迫切需要的TLC.在任何特定时刻,我们的scrum积压(针对六个开发人员)有大约140个项目和大约十几个缺陷.这些数字并没有太大变化.我们正在以尽可能快的速度添加东西.
那么我该怎么做才能避免马德里调试会话在Old Code的深处陷入困境呢?每个sprint都充满了新的发展和showstopper缺陷.特别...
"替换条件与多态"只有在您正在为您选择切换/ if语句的对象类型时才是优雅的.作为一个例子,我有一个Web应用程序,它读取一个名为"action"的查询字符串参数.动作可以具有"视图","编辑","排序"等值.那么如何用多态实现呢?好吧,我可以创建一个名为BaseAction的抽象类,并从中派生ViewAction,EditAction和SortAction.但是,我不需要条件来决定实例化哪种类型的BaseAction?我不知道如何用多态完全替换条件.如果有的话,条件只会被推到链的顶端.
编辑:
public abstract class BaseAction
{
public abstract void doSomething();
}
public class ViewAction : BaseAction
{
public override void doSomething() { // perform a view action here... }
}
public class EditAction : BaseAction
{
public override void doSomething() { // perform an edit action here... }
}
public class SortAction : BaseAction
{
public override void doSomething() { // perform a sort action here... }
}
string action = "view"; // suppose user can pass either …Run Code Online (Sandbox Code Playgroud) 我熟悉在C#和Java中重构相当大的代码库,但Clojure是一个不同的野兽,特别是因为它:
鉴于上述情况,在Clojure中进行代码重构的最佳方法是什么?
我一直在寻找迭代字符串列表的最佳/最干净的方法,然后创建一个由换行符分隔的字符串(除了最后一行).像这样:
String 1
String 2
String 3
Run Code Online (Sandbox Code Playgroud)
我在这里写了两个循环,在字符串的末尾有一个换行符(我想避免)和另一个没有的换行符.这个不仅对我来说不是"干净".我认为有一种更简单的方法可以使逻辑几乎与在字符串末尾有一个新行的示例中一样简单.
List<string> errorMessages = new List<string>();
string messages = "";
//Adds newline to last string. Unwanted.
foreach(string msg in errorMessages)
{
messages += msg + "\n";
}
messages = "";
bool first = true;
//Avoids newline on last string
foreach (string msg in errorMessages)
{
if(first)
{
first = false;
messages = msg;
}
else
{
messages += "\n" + msg;
}
}
Run Code Online (Sandbox Code Playgroud)
也许这是一厢情愿的想法,但我认为这是一个足够普遍的事情,可以保证更好的方式来实现我的目标.
在Visual Studio中,有或没有扩展,有没有办法根据用法的顺序(它们在调用堆栈中的位置)自动对类中的私有方法进行排序?
例如,考虑以下类:
public class MyClass
{
public void MyMethod()
{
TestC();
}
private void TestA()
{
TestB();
}
private void TestB()
{
Console.WriteLine("Hello");
}
private void TestC()
{
TestA();
}
}
Run Code Online (Sandbox Code Playgroud)
这个类中的公共方法是MyMethod,它调用TestC哪个调用TestA哪个调用TestB.我想(自动)按此顺序对这些方法进行排序,以便类看起来像这样:
public class MyClass
{
public void MyMethod()
{
TestC();
}
private void TestC()
{
TestA();
}
private void TestA()
{
TestB();
}
private void TestB()
{
Console.WriteLine("Hello");
}
}
Run Code Online (Sandbox Code Playgroud)
我需要能够选择一个类,请求这样的方法排序,并让方法自动排序.即,我不想手动对这些方法进行排序.
我知道有一些细微差别.例如,可能存在从两个方法调用的私有方法,这两个方法在调用堆栈中处于两个不同的级别.我想在这种情况下考虑与公共方法的最小(调用堆栈)距离是有意义的.
更新:
这种以这种方式对方法进行分类的想法来自Robert C. Martin的清洁代码书.在第3章中,定义了Stepdown规则,该规则讨论了在低级函数之前出现更高级别的函数.
在google上快速搜索stepdown规则,我发现了一个netbeans插件:http://plugins.netbeans.org/plugin/58863/stepdownruleplugin …
refactoring ×10
c# ×2
c++ ×2
.net ×1
clojure ×1
conditional ×1
polymorphism ×1
r ×1
readability ×1
ruby ×1
rust ×1
scrum ×1
string ×1
tdd ×1
unit-testing ×1