The earlier you start thinking about whether or not your design needs refactoring, the better. Refactor constantly, so it's never a large issue.
I've also found that the more I refactor early on, the better I've gotten about writing code more cleanly up front. I tend to create fewer large methods, and have fewer problems.
However, if you find yourself "refactoring" yourself into a corner, I'd expect that is more a matter of lack of initial design or lack of planning for the scope of use of a class. Try writing out how you want to use the class or framework before you start writing the code - it may help you avoid that issue. This is also I think one advantage to test driven design - it helps you force yourself to look at using your object before it's written.
Remember, refactoring technically should NEVER lock you into a corner - it's about reworking the internals without changing how a class is used. If your trapping yourself by refactoring, it means your initial design was flawed.
Chances are you'll find that, over time, this issue gets better and better. Your class and framework design will probably end up more flexible.
We have all heard of Premature Optimization, but what do you thing about Premature Refactoring? Is there any such thing in your opinion?
Yes, there is. Refactoring is a way of paying down technical debt that has accrued over the life of your development process. However, the mere accrual of technical debt is not necessarily a bad thing.
To see why, imagine that you are writing tax-return analysis software for the IRS. Suddenly, new regulations are introduced at the last minute which break several of your original assumptions. Although you designed well, your domain model has fundamentally shifted from under your feet in at least one important place. It's April 14th, and the project must go live tomorrow, come hell or high water. What do you do?
If you implement a nuts-and-bolts solution at the cost of some moderate technical debt, your system will become more rigid and less able to withstand another round of these changes. But the site can go live and proceed onward, and there will be no risk of delivering late; you're confident you can make the required changes.
On the other hand, if you take the time to refactor the solution so that it now supports the new design in more sophisticated and flexible way, you'll have no trouble adapting to future changes. But you run the risk of your company's flagship product running up against the clock; you're not sure if the redesign will take longer than today.
In this case, the first option is the better choice. Assuming you have little previous technical debt, it's worth it to take your lumps now and pay it down later. This is, of course, a business decision, and not a design one.
At the nuts and bolts end of design is the code itself. This final stage of the design comes in to existence as you code, it will at times be flawed, and you'll see that as the code evolves. If you refactor too early it makes it harder to change the flawed design.
For example, it's much easier to delete a single long function when you realise it's rubbish or going in the wrong direction than it is to delete a nice well-formed function and the functions it uses and the functions they use, etc., whilst ensuring you're not breaking something else that was part of the refactor.
It could be said that perhaps you should have spent more time designing, but a key element in an agile process is that coding is part of the design process and in most cases, having put some reasonable effort into design, it's better to just get on with it.
Edit In response to comments:-
Design isn't done until you've written code. We can't solve all problems in pre-coding design, the whole point behind Agile is that coding is problem solving. If the non-code design solved all problems up-front before coding there would be no need to re factor, we would simply convert the design to well factored code in one step.
Anyone remember the late 1980s and early 1990s structured design methods, the ones where you got all the problems solved in clever diagrams before you wrote a line of code?
Premature refactoring is refactoring without unit-tests. You are at that point simply not ready for a refactoring. First get some unit-tests and then start thinking about refactoring. Otherwise you will (might) hurt the project more than help.
I am a strong believer in constant refactoring. There is no reason to wait until some specific time to start refactoring.
Anytime you see something that should be done better, Refactor.
Just keep this in my mind. I know a developer (a pure genius) who refactors so much (he is so smart he can always find a better way) he never finishes a project.
I think any "1.0" project is susceptible to this kind of ... let's call it "iterative design". If you don't have a clear spec before you start designing you're objects, you'll likely think of many designs and approaches to problems.
So, I think overcoming this specific problem is to clearly design things before you start writing code.
There are a couple of promising solutions to this type of problem, depending on the situation.
If the problem is that you decide something can be optimized in a certain way and you extract a method or something and realize that because of that decision, you are forced to code everything else in a convoluted way, the problem is probably that you didn't think far enough in the design process. If there had been a well written and planned spec, you would have known about this problem ahead of time (unless you didn't read the spec, but that's another issue :) )
Depending on the situation, rapid prototyping can also address this problem, since you'll have a better idea of these implementation details when you start working on the real thing.
The reason why premature optimization is bad is that optimization usually leads to a worse design. Unlike refactoring, which leads to a better and cleaner design, if done thoughtful and right. What I learned to be useful for me to analyze the usefulness of a refactoring was first looking at our UML diagram to visualize the change and then writing the code-doc (e.g Javadoc) for the class first and adding stubs ahead of any real code. Of course experience help a lot with that, if in doubt, ask your favorite architect ;)
发布评论
评论(8)
我实际上认为相反。
你越早开始考虑你的设计是否需要重构越好。 不断重构,所以这从来都不是一个大问题。
我还发现,早期重构得越多,我就能更好地提前更清晰地编写代码。 我倾向于创建更少的大型方法,并且遇到的问题也更少。
但是,如果您发现自己“重构”自己陷入困境,我认为这更多是由于缺乏初始设计或缺乏对类的使用范围的规划的问题。 在开始编写代码之前尝试写出您想要如何使用类或框架 - 它可能会帮助您避免这个问题。 我认为这也是测试驱动设计的优点之一——它可以帮助您强迫自己在编写对象之前考虑如何使用它。
请记住,从技术上讲,重构永远不应该让您陷入困境——它是在不改变类的使用方式的情况下重新设计内部结构。 如果你因重构而陷入困境,这意味着你最初的设计是有缺陷的。
您很可能会发现,随着时间的推移,这个问题会变得越来越好。 您的类和框架设计最终可能会更加灵活。
I actually think the opposite.
The earlier you start thinking about whether or not your design needs refactoring, the better. Refactor constantly, so it's never a large issue.
I've also found that the more I refactor early on, the better I've gotten about writing code more cleanly up front. I tend to create fewer large methods, and have fewer problems.
However, if you find yourself "refactoring" yourself into a corner, I'd expect that is more a matter of lack of initial design or lack of planning for the scope of use of a class. Try writing out how you want to use the class or framework before you start writing the code - it may help you avoid that issue. This is also I think one advantage to test driven design - it helps you force yourself to look at using your object before it's written.
Remember, refactoring technically should NEVER lock you into a corner - it's about reworking the internals without changing how a class is used. If your trapping yourself by refactoring, it means your initial design was flawed.
Chances are you'll find that, over time, this issue gets better and better. Your class and framework design will probably end up more flexible.
就在这里。 重构是一种偿还开发过程中积累的技术债务的方法。 然而,仅仅增加技术债务并不一定是坏事。
要了解原因,请想象您正在为 IRS 编写纳税申报表分析软件。 突然,新的法规在最后一刻出台,打破了您最初的一些假设。 尽管您设计得很好,但您的领域模型至少在一个重要的地方已经从您的脚下发生了根本性的变化。 现在是 4 月 14 日,无论发生什么事,该项目都必须明天上线。 你做什么工作?
在这种情况下,第一个选项是更好的选择。 假设您之前几乎没有技术债务,那么现在就接受并稍后偿还是值得的。 当然,这是一项商业决策,而不是设计决策。
Yes, there is. Refactoring is a way of paying down technical debt that has accrued over the life of your development process. However, the mere accrual of technical debt is not necessarily a bad thing.
To see why, imagine that you are writing tax-return analysis software for the IRS. Suddenly, new regulations are introduced at the last minute which break several of your original assumptions. Although you designed well, your domain model has fundamentally shifted from under your feet in at least one important place. It's April 14th, and the project must go live tomorrow, come hell or high water. What do you do?
In this case, the first option is the better choice. Assuming you have little previous technical debt, it's worth it to take your lumps now and pay it down later. This is, of course, a business decision, and not a design one.
我认为重构可能太早了。
设计的具体细节是代码本身。 设计的最后阶段随着您的编码而存在,它有时会存在缺陷,随着代码的发展,您会看到这一点。 如果重构得太早,改变有缺陷的设计就会变得更加困难。
例如,当您意识到一个长函数是垃圾或方向错误时,删除它比删除一个格式良好的函数及其使用的函数和它们使用的函数等要容易得多,同时确保您不会破坏重构过程中的其他内容。
可以说,也许您应该花更多的时间进行设计,但是敏捷过程中的一个关键要素是编码是设计过程的一部分,并且在大多数情况下,在设计中投入了一些合理的努力后,最好继续前进用它。
编辑 对评论的回应:-
在编写代码之前,设计尚未完成。 我们无法解决预编码设计中的所有问题,敏捷背后的重点是编码就是解决问题。 如果非代码设计在编码之前预先解决了所有问题,则无需重新分解,我们只需一步将设计转换为分解良好的代码即可。
有人还记得 20 世纪 80 年代末和 90 年代初的结构化设计方法吗?在这种方法中,在编写一行代码之前,您就可以通过巧妙的图表解决所有问题?
I think it is possible to refactor too early.
At the nuts and bolts end of design is the code itself. This final stage of the design comes in to existence as you code, it will at times be flawed, and you'll see that as the code evolves. If you refactor too early it makes it harder to change the flawed design.
For example, it's much easier to delete a single long function when you realise it's rubbish or going in the wrong direction than it is to delete a nice well-formed function and the functions it uses and the functions they use, etc., whilst ensuring you're not breaking something else that was part of the refactor.
It could be said that perhaps you should have spent more time designing, but a key element in an agile process is that coding is part of the design process and in most cases, having put some reasonable effort into design, it's better to just get on with it.
Edit In response to comments:-
Design isn't done until you've written code. We can't solve all problems in pre-coding design, the whole point behind Agile is that coding is problem solving. If the non-code design solved all problems up-front before coding there would be no need to re factor, we would simply convert the design to well factored code in one step.
Anyone remember the late 1980s and early 1990s structured design methods, the ones where you got all the problems solved in clever diagrams before you wrote a line of code?
过早重构是没有单元测试的重构。此时您还没有准备好进行重构。 首先进行一些单元测试,然后开始考虑重构。 否则,你对项目的伤害将大于帮助。
Premature refactoring is refactoring without unit-tests. You are at that point simply not ready for a refactoring. First get some unit-tests and then start thinking about refactoring. Otherwise you will (might) hurt the project more than help.
我坚信不断重构。 没有理由等到某个特定时间才开始重构。
任何时候你看到一些应该做得更好的事情,重构。
请记住这一点。 我认识一个开发人员(一个纯粹的天才),他重构了很多(他很聪明,他总是能找到更好的方法),但他从未完成过一个项目。
I am a strong believer in constant refactoring. There is no reason to wait until some specific time to start refactoring.
Anytime you see something that should be done better, Refactor.
Just keep this in my mind. I know a developer (a pure genius) who refactors so much (he is so smart he can always find a better way) he never finishes a project.
我认为任何“1.0”项目都容易受到这种影响……我们称之为“迭代设计”。 如果在开始设计对象之前没有明确的规范,您可能会想到许多设计和解决问题的方法。
因此,我认为克服这个具体问题的方法是在开始编写代码之前明确设计事物。
I think any "1.0" project is susceptible to this kind of ... let's call it "iterative design". If you don't have a clear spec before you start designing you're objects, you'll likely think of many designs and approaches to problems.
So, I think overcoming this specific problem is to clearly design things before you start writing code.
根据具体情况,有一些有前途的解决方案可以解决此类问题。
如果问题是您决定可以以某种方式优化某些内容,并且您提取了一种方法或某些内容,并意识到由于该决定,您被迫以复杂的方式编写其他所有内容,那么问题可能是您没有这样做在设计过程中想得不够远。 如果有一个精心编写和计划的规范,您就会提前知道这个问题(除非您没有阅读规范,但那是另一个问题:))
根据具体情况,快速原型设计也可以解决这个问题,因为当您开始实际工作时,您会对这些实现细节有更好的了解。
There are a couple of promising solutions to this type of problem, depending on the situation.
If the problem is that you decide something can be optimized in a certain way and you extract a method or something and realize that because of that decision, you are forced to code everything else in a convoluted way, the problem is probably that you didn't think far enough in the design process. If there had been a well written and planned spec, you would have known about this problem ahead of time (unless you didn't read the spec, but that's another issue :) )
Depending on the situation, rapid prototyping can also address this problem, since you'll have a better idea of these implementation details when you start working on the real thing.
过早优化不好的原因是优化通常会导致更糟糕的设计。 与重构不同的是,如果考虑周全且正确的话,重构会带来更好、更简洁的设计。 我学到的对我分析重构有用性有用的方法是,首先查看我们的 UML 图以可视化更改,然后首先为类编写代码文档(例如 Javadoc),并在任何实际代码之前添加存根。 当然,经验对此有很大帮助,如果有疑问,请询问您最喜欢的建筑师;)
The reason why premature optimization is bad is that optimization usually leads to a worse design. Unlike refactoring, which leads to a better and cleaner design, if done thoughtful and right. What I learned to be useful for me to analyze the usefulness of a refactoring was first looking at our UML diagram to visualize the change and then writing the code-doc (e.g Javadoc) for the class first and adding stubs ahead of any real code. Of course experience help a lot with that, if in doubt, ask your favorite architect ;)