从这段代码开始:
new Person("ET").WithAge(88)
如何重构:
new Person("ET", 88)
需要执行哪些重构序列才能完成转换?
为什么呢?因为可能有数百个,我不想通过手动操作来引入错误。
你会说流利界面的缺点是它们不容易被重构吗?
注意:我想自动执行此操作而无需手动输入代码。
答案 0 :(得分:4)
也许最简单的重构方法是将名称“WithAge”更改为“InitAge”,将InitAge
设为私有,然后从构造函数中调用它。然后更新new Person(string).WithAge(int)
的所有引用以使用新的构造函数。
如果WithAge
是一行代码,您只需将代码移动到新构造函数中,然后完全取消InitAge
,除非使用其他方法提供额外的可读性。
进行良好的单元测试将隔离引入错误的位置,如果是的话。
答案 1 :(得分:3)
假设WithAge是Person上返回Person的方法,那么
之类的东西Person(string name, int age)
{
this.name = name;
this.WithAge(age);
}
或者更一般化:
Person(SomeType originalParameter, FluentParamType fluentParameter)
{
//Original constructor stuff
this.FluentMethod(fluentParameter);
}
然后如果您不想要它,请将FluentMethod设为私有,或者如果您想允许两种方式保持公开。
答案 2 :(得分:2)
如果这是C#(理想情况下你会用语言标记问题),Person类需要这个构造函数:
public Person(string name, int age)
: this(name) { WithAge(age); }
然后在适当的时候更改所有客户端代码以调用此新构造函数,您需要找到所有出现的模式:
new Person(x1).WithAge(x2)
其中x1和x2是表达式,并将其替换为:
new Person(x1, x2)
如果除了WithAge之外还有其他修饰方法,它可能会变得更复杂。例如:
new Person(x1).WithHair(x2).WithAge(x3)
也许你想要成为:
new Person(x1, x3).WithHair(x2)
这完全取决于您是否有一个IDE,可以让您定义类似语言的搜索/替换模式。通过简单的文本搜索和替换,您可以获得很长的解决方案,并结合重放一系列按键的宏。
你会说流利的缺点吗? 接口是他们不容易的 重构?
不是特别 - IDE中的重构功能要么设计得足够灵活,要么能够创造性地发明新的重构,要么它们在某些常见情况下都是硬编码的。我更喜欢将常见案例定义为我可以改变以发明新案例的例子。
答案 3 :(得分:1)
我对这种事情没有任何实际经验,但是如果我处于你的情况,那么我要去的地方将是custom Eclipse refactorings(或等同于Refactor!Pro for .Net if那是你正在使用的。)
基本上你想要的是匹配和替换,除了你的正则表达式应该匹配抽象语法树而不是纯文本。这就是自动重构的原因。
此重构的一个风险是目标版本不如原始版本精确。考虑:
class Person { public Person(String name, int age); public Person(String name, int numberOfChildren); }
没有办法告诉哪个构造函数对Person.WithAge的链接调用应替换为。
因此,在允许您继续之前,对此的自动支持必须检查这种歧义。如果已经有一个带有目标参数的构造函数,则中止重构。
除此之外,它看起来非常简单。为新构造函数提供以下内容:
public Person(String name, int age) { this(name); withAge(age); }
然后您可以安全地用新的。
替换原始呼叫(还有一个微妙的额外风险,因为在构造函数中调用withAge,即在部分构造的对象上,与在构造函数之后调用它不完全相同。如果你有一个继承链和如果withAge做了一件非常重要的事情。但那就是你的单元测试的目的......)
答案 4 :(得分:0)
为旧代码编写单元测试。
重新测试,直到测试再次通过。