Take time to name the concepts of the system well, and find names that are related, this makes the system more familiar. Don't be hesitant to rename concepts, the better the connection to the world you know, the better your brain can work with it.
Ask for opinions from people who get their kicks from clean, simple solutions.
Only implement concepts needed by the current project (a desire for future proofing or generic systems make your design bloated).
I ask my customers why they need some feature. I try and get to the bottom of their request and identify the problem they are experiencing. This often lends itself to a simpler solution than I (or they) would think of.
Of course, if you know your clients' work habits and what problems they have to tackle, you can understand their problems much better from the get-go. And if you "know them" know them, then you understand their speech better. So, develop a close working relationship with your users. It's step zero of engineering.
This is a delicate balancing act: on the one hand you don't want something that takes too long to design and implement, on the other hand you don't want a hack that isn't complicated enough to deal with next week's problem, or even worse requires rewriting to adapt.
A couple of techniques I find helpful:
If something seems more complex than you would like then never sit down to implement it as soon as you have finished thinking about it. Find something else to do for the rest of the day. Numerous times I end up thinking of a different solution to an early part of the problem that removes a lot of the complexity later on.
In a similar vein have someone else you can bounce ideas off. Make sure you can explain to them why the complexity is justified!
If you are adding complexity because you think it will be justified in the future then try to establish when in the future you will use it. If you can't (realistically) imagine needing the complexity for a year or three then it probably isn't justifiable to pay for it now.
Talk to other programmers every step of the way. The more eyes there are on the design, the more likely an overcomplicated aspect is revealed early, before it becomes too ossified in the codebase.
Constantly ask yourself how you will use whatever you are currently working on. If the answer is that you're not sure, stop to rethink what you're doing.
I've found it useful to jot down thoughts about how to potentially simplify something I'm currently working on. That way, once I actually have it working, it's easier to go back and refactor or redo as necessary instead of messing with something that's not even functional yet.
Reduce the amount of data you're working with by serialising the task into a series of smaller tasks. Most people can only hold half a dozen (plus or minus) conditions in their head while coding, so make that the unit of implementation. Design for all the tasks you need to accomplish, but then ruthlessly hack the design so that you never have to play with more than half a dozen paths though the module.
This follows from Bendazo's post - simplify until it becomes easy.
It is inevitable once you have been a programmer that this will happen. If you seriously have unestimated the effort or hit a problem where your solution just doesn't work then stop coding and get talking to your project manager. I always like to take the solutions with me to the meeting, problem is A, you can do x which will take 3 days or we can try y which will take 6 days. Don't make the choice yourself.
Test first may help here, but it is not suitable for all situation. And it's not a panacea anyway.
Start small is another great idea. Do you really need to stuff all 10 design patterns into this thing? Try first to do it "stupid way". Doesn't quite cut it? Okay, do it "slightly less stupid way". Etc.
Get it reviewed. As someone else wrote, two pairs of eyes are better. Even better are two brains. Your mate may just see a room for simplification, or a problematic area you thought was fine just because you spend many hours hacking it.
Use lean language. Languages such as Java, or sometimes C++ sometimes seem to encourage nasty, convoluted solutions. Simple things tend to span over multiple lines of code, and you just need to use 3 external libraries and a big framework to manage it all. Consider using Python, Ruby, etc. - if not for your project, then for some private use. It can change your mindset to favor simplicity, and to be assured that simplicity is possible.
Using Test Driven Development and following Robert C. Martin's Three Rules of TDD:
You are not allowed to write any production code unless it is to make a failing unit test pass.
You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
In this way you are not likely to get much code that you don't need. You will always be focused on making one important thing work and won't ever get too far ahead of yourself in terms of complexity.
Read "Working Effectively With Legacy Code" by Michael C. Feathers.
The point is, if you have code that works, and you need to change the design, nothing works better than making your code unit testable, and breaking your code into smaller pieces.
I create a design etc., and then I look at it and try and remove (agressively) everything that doesn't seem to be needed. If it turns out I need it later when I am polishing the design I add it back in. I do this over several iterations, refining as I go along.
change your attitude, ask how you can make it so, that "it simply works" (convention over configuration could help there; or ask how Apple would do it)
practice (like jazz players -- jam with code, try Code Kata)
write same code multiple times, with different languages and after some time has passed
learn new languages with new concepts (if you use static language, learn dynamic one; if you use procedural language, learn functional one; ...) [one language per year is about right]
ask someone to review you code and actively ask how you can make your code simpler and more elegant (and then make it)
get years under your belt by doing above things (time helps active mind)
In my experience, designing for an overly general case tends to breed too much complexity.
Engineering culture encourages designs that make fewer assumptions about the environment; this is usually a good thing, but some people take it too far. For example, it might be nice if your car design doesn't assume a specific gravitational pull, nobody is actually going to drive your car on the moon, and if they did, it wouldn't work, because there is no oxygen to make the fuel burn.
The difficult part is that the guy who is developed the "works-on-any-planet" design is often regarded as clever, so you may have to work harder to argue that his design is too clever.
Understanding trade-offs, so you can make the decision between good assumptions and bad assumptions, will go a long way into avoiding a needlessly complicated design.
发布评论
评论(14)
花时间好好命名系统的概念,并找到相关的名称,这会让系统更加熟悉。 不要犹豫重新命名概念,与你所知道的世界联系得越好,你的大脑就能更好地处理它。
向那些喜欢干净、简单的解决方案的人征求意见。
仅实现当前项目所需的概念(对未来验证或通用系统的渴望会使您的设计变得臃肿)。
Take time to name the concepts of the system well, and find names that are related, this makes the system more familiar. Don't be hesitant to rename concepts, the better the connection to the world you know, the better your brain can work with it.
Ask for opinions from people who get their kicks from clean, simple solutions.
Only implement concepts needed by the current project (a desire for future proofing or generic systems make your design bloated).
我问我的客户为什么他们需要某些功能。 我尝试深入了解他们的请求并找出他们遇到的问题。 这通常会提供比我(或他们)想象的更简单的解决方案。
当然,如果您了解客户的工作习惯以及他们必须解决的问题,您从一开始就可以更好地理解他们的问题。 如果你“了解他们”,那么你就能更好地理解他们的讲话。 因此,与您的用户建立密切的工作关系。 这是工程的零步。
I ask my customers why they need some feature. I try and get to the bottom of their request and identify the problem they are experiencing. This often lends itself to a simpler solution than I (or they) would think of.
Of course, if you know your clients' work habits and what problems they have to tackle, you can understand their problems much better from the get-go. And if you "know them" know them, then you understand their speech better. So, develop a close working relationship with your users. It's step zero of engineering.
这是一个微妙的平衡行为:一方面你不想要一些需要太长时间来设计和实现的东西,另一方面你不想要一个不够复杂的黑客来处理下周的问题,或者更糟糕的是需要重写才能适应。
我发现一些有用的技巧:
如果某件事看起来比你想要的更复杂,那么在你思考完它之后,不要立即坐下来实施它。 在这一天剩下的时间里找点别的事情做。 很多次我最终都会为问题的早期部分考虑不同的解决方案,从而消除后来的许多复杂性。
同样,找一个可以与你交流想法的人。 确保您可以向他们解释为什么复杂性是合理的!
如果您增加复杂性是因为您认为将来是合理的,那么请尝试确定将来何时使用它。 如果您无法(现实地)想象一三年内需要这种复杂性,那么现在为此付费可能是不合理的。
This is a delicate balancing act: on the one hand you don't want something that takes too long to design and implement, on the other hand you don't want a hack that isn't complicated enough to deal with next week's problem, or even worse requires rewriting to adapt.
A couple of techniques I find helpful:
If something seems more complex than you would like then never sit down to implement it as soon as you have finished thinking about it. Find something else to do for the rest of the day. Numerous times I end up thinking of a different solution to an early part of the problem that removes a lot of the complexity later on.
In a similar vein have someone else you can bounce ideas off. Make sure you can explain to them why the complexity is justified!
If you are adding complexity because you think it will be justified in the future then try to establish when in the future you will use it. If you can't (realistically) imagine needing the complexity for a year or three then it probably isn't justifiable to pay for it now.
通过将任务序列化为一系列较小的任务,减少您正在处理的数据量。 大多数人在编码时只能在头脑中记住六个(加或减)条件,因此将其作为实现单元。 设计您需要完成的所有任务,然后无情地修改设计,这样您就不必在模块中使用超过六条路径。
这是从 Bendazo 的帖子中得出的——简化直到变得容易。
Reduce the amount of data you're working with by serialising the task into a series of smaller tasks. Most people can only hold half a dozen (plus or minus) conditions in their head while coding, so make that the unit of implementation. Design for all the tasks you need to accomplish, but then ruthlessly hack the design so that you never have to play with more than half a dozen paths though the module.
This follows from Bendazo's post - simplify until it becomes easy.
一旦你成为一名程序员,这种情况就会不可避免地发生。 如果您严重低估了工作量,或者遇到了解决方案不起作用的问题,那么请停止编码并与您的项目经理交谈。 我总是喜欢带着解决方案去参加会议,问题是A,你可以做x,这需要3天,或者我们可以尝试y,这将需要6天。 不要自己做选择。
It is inevitable once you have been a programmer that this will happen. If you seriously have unestimated the effort or hit a problem where your solution just doesn't work then stop coding and get talking to your project manager. I always like to take the solutions with me to the meeting, problem is A, you can do x which will take 3 days or we can try y which will take 6 days. Don't make the choice yourself.
先测试可能会有所帮助,但并不适合所有情况。 而且它无论如何也不是万能的。
从小事做起是另一个好主意。 你真的需要把所有 10 种设计模式都塞进这个东西里吗? 首先尝试用“愚蠢的方式”来做。 还不太切吗? 好吧,就用“稍微不那么愚蠢的方式”吧。 等等
对其进行审核。 正如其他人所写,两双眼睛更好。 更好的是有两个大脑。 你的伴侣可能只是看到了一个需要简化的空间,或者一个你认为很好的有问题的区域,只是因为你花了很多时间来破解它。
使用精益语言。诸如 Java 或 C++ 之类的语言有时似乎会鼓励令人讨厌、复杂的解决方案。 简单的事情往往会跨越多行代码,您只需要使用 3 个外部库和一个大框架来管理这一切。 考虑使用 Python、Ruby 等 - 如果不是为了您的项目,那么也可以用于一些私人用途。 它可以改变您的心态,偏向简单,并确保简单是可能的。
Test first may help here, but it is not suitable for all situation. And it's not a panacea anyway.
Start small is another great idea. Do you really need to stuff all 10 design patterns into this thing? Try first to do it "stupid way". Doesn't quite cut it? Okay, do it "slightly less stupid way". Etc.
Get it reviewed. As someone else wrote, two pairs of eyes are better. Even better are two brains. Your mate may just see a room for simplification, or a problematic area you thought was fine just because you spend many hours hacking it.
Use lean language. Languages such as Java, or sometimes C++ sometimes seem to encourage nasty, convoluted solutions. Simple things tend to span over multiple lines of code, and you just need to use 3 external libraries and a big framework to manage it all. Consider using Python, Ruby, etc. - if not for your project, then for some private use. It can change your mindset to favor simplicity, and to be assured that simplicity is possible.
使用测试驱动开发并遵循 Robert C. Martin 的 TDD 三规则:
通过这种方式,您不太可能获得太多不需要的代码。 你将始终专注于完成一件重要的事情,并且永远不会在复杂性方面超出自己太多。
Using Test Driven Development and following Robert C. Martin's Three Rules of TDD:
In this way you are not likely to get much code that you don't need. You will always be focused on making one important thing work and won't ever get too far ahead of yourself in terms of complexity.
阅读 Michael C. Feathers 所著的《有效处理遗留代码》。
关键是,如果您有有效的代码,并且需要更改设计,那么没有什么比使代码可进行单元测试并将代码分解为更小的部分更好的了。
Read "Working Effectively With Legacy Code" by Michael C. Feathers.
The point is, if you have code that works, and you need to change the design, nothing works better than making your code unit testable, and breaking your code into smaller pieces.
我创建一个设计等,然后查看它并尝试(积极地)删除所有似乎不需要的东西。 如果我稍后在完善设计时需要它,我会将其添加回来。我会进行多次迭代,并在进行过程中不断完善。
I create a design etc., and then I look at it and try and remove (agressively) everything that doesn't seem to be needed. If it turns out I need it later when I am polishing the design I add it back in. I do this over several iterations, refining as I go along.
如果测试太难,那么你的设计就太复杂了。 这是我使用的第一个指标。
If its too hard to test, your design is too complicated. That's the first metric I use.
这里有一些让设计变得更简单的想法:
Here are some ideas to get design more simpler:
根据我的经验,针对过于笼统的案例进行设计往往会产生过多的复杂性。
工程文化鼓励设计时减少对环境的假设; 这通常是一件好事,但有些人却太过分了。 例如,如果您的汽车设计没有假设特定的引力,那么可能会很好,实际上没有人会在月球上驾驶您的汽车,如果他们这样做了,它就行不通,因为没有氧气使燃料燃烧。
困难的部分是,开发“适用于任何星球”设计的人通常被认为是聪明的,因此您可能需要更加努力地证明他的设计太聪明。
了解权衡,以便您可以在好的假设和坏的假设之间做出决定,将大大有助于避免不必要的复杂设计。
In my experience, designing for an overly general case tends to breed too much complexity.
Engineering culture encourages designs that make fewer assumptions about the environment; this is usually a good thing, but some people take it too far. For example, it might be nice if your car design doesn't assume a specific gravitational pull, nobody is actually going to drive your car on the moon, and if they did, it wouldn't work, because there is no oxygen to make the fuel burn.
The difficult part is that the guy who is developed the "works-on-any-planet" design is often regarded as clever, so you may have to work harder to argue that his design is too clever.
Understanding trade-offs, so you can make the decision between good assumptions and bad assumptions, will go a long way into avoiding a needlessly complicated design.
让新人来看看。
Getting someone new to look at it.