请访问http://news.ycombinator.com/item?id=4037794进行更多讨论。我有一个相对简单的开发任务,但是每次尝试攻击时,我都会结束不断上升的深层思考-它如何扩展未来,第二代客户将需要什么,它会如何影响“非功能性”方面(例如性能,授权...),如何最好地设计才能允许改变...

我记得自己有一阵子,更年轻,也许更渴望。那时我当时不会想到的“我”-他会继续写一些东西,然后重写,然后再次重写(再一次……)。今天的“我”更加犹豫,更加谨慎。

我发现今天坐下来规划和指导他人如何做事情比真正自己去做要容易得多-而不是因为我不喜欢编码-相反,我喜欢! -但是因为每次我坐在键盘上时,我都会到那个烦人的地方。

这是错误的吗?

公平公开-过去我是一名开发人员,今天的职务是“系统架构师”。祝你好运,弄清楚它的意思-但这就是标题。


哇。老实说,我没想到这个问题会引起如此多的答复。我会尝试将其总结。会伤害您”)。
完成给定任务的经验过多。
没有专注于重要的事情。
经验不足(并意识到这一点)。

解决方案(与原因不匹配):


先进行测试。
开始编码(+为好玩)
一个要扔掉(+一个API要扔掉)。
设置时间限制。
剥去绒毛,随身携带。
编写灵活的代码(与“一个扔掉”相反,不是吗?)。

多亏了每个人-我认为这里的主要好处是意识到我并不孤单。实际上,我已经开始编码了,有些太大的事情自然就消失了。当/如果它发生变化-我将尝试遵循。

评论

时间压力可以帮助您停止过度思考。

YAGNI

喝2杯啤酒..

第二系统效应,有人吗?

您的问题不是“了解太多”,而是分析太多。您现在不必太在意性能,将来的功能等,如果客户为您提供了一个很难实现的新功能,这并不是世界即将结束

#1 楼

考虑这些事情绝对是件好事,但不要让它阻止您的进步。

一种非常有效的方法(特别是在迭代开发中)是一种简单的解决方案,然后在以后进行必要的重构。这样可以使代码尽可能简单,并避免过度设计。您正在考虑的大多数性能或体系结构更改可能根本就不是必需的,因此在正式需要它们之前,不要费心编写它们。例如,在探查器告诉您应该提高性能之前,请不要担心性能。

您可以做的一件事是帮助您调整在编写代码之前对思考某事物的时间进行严格限制。在大多数情况下,如果您想一想,编写代码,意识到错误,然后通过重构来解决,那么代码的结果就会更好。

这里有一个平衡点。您不应该只急于工作,不考虑后果,而且也不要尝试过度设计您的代码。

评论


正式名称:YAGNI。

– Mark Ransom
2012年5月29日19:30

#2 楼

Wikipedia在软件中将其命名为“ Analysis paralysis”。秘诀是坚持敏捷方法。这意味着任何活动或个人行为比试图建立惯例或政策具有更大的价值。团队中的每个贡献者都是有价值的,无论该人的能力是否符合建筑理想。在敏捷中,个人(例如自我)是第一位的,政策是最后一位。无论您和团队感到多么不完美和效率低下,请停止思考,开始行动。也许第一个行动可能是取消不合适的政策。

#3 楼

40年前,弗雷德·布鲁克斯(Fred Brooks)写道:“写一个扔掉,不管怎么说,你会的。”
什么都没有改变.....

评论


曾经的Jeff Atwood说:“第1版很烂,但还是要释放它”。 codinghorror.com/blog/2009/12/…

–艾伦B
2012年5月29日9:27



任何版本都是如此:)

– Nemanja Trifunovic
2012年5月29日下午13:21

@AlanB,这是我记忆中的另一个编码恐怖帖子。

– Benjol
2012年5月30日8:42



#4 楼


这是错误的吗?这是自然的演变,还是我让自己陷入了车辙?


这要视情况而定。这通常是开发人员走上的第一步。意识到所有这些,YAGNI
落在一些务实的中间地带,在这里容易的东西被拍打在一起,而容易改变的东西则经过了足够的工程设计,以使其易于使用/改变。

如果停留在第2位,那只是发情了。

评论


+1当您开始过度设计“ Hello World”时,您会发现自己处于第2位的车辙。

–说话
2012年5月29日9:00

@Spoike-或Fizzbuzz。 la,企业级Fizzbuzz!

– CraigTP
2012年5月29日10:05



4.意识到3也是错误的,并且只关心满足业务需求而不是技术需求。普遍的业务需求是,一切都会不断变化,无论大小变化。实施细节将与底线驱动程序保持一致,并将在需要时尽快解决。及时开发。

–user7519
2012年5月30日,1:15



#5 楼

我一直想牢记的一件事是说:“未来不再是过去。”

有了一定的经验,就很容易相信您可以预测未来未来,但你不能。可以轻松想象将来的客户/用户/任何人想要的功能,但这并不意味着他们会立即想要它们。这也并不意味着他们会希望他们超越其他一些相互矛盾的功能。因此,您确实确实需要限制今天花费的时间来规划未来。您特别需要限制您花多少时间在今天建造只会在将来使用的东西。比现在建立对该功能的支持要难得多?通常,答案是未来的工作量大约是现在的两倍甚至两倍。在那种情况下,因为我无法预测未来,所以现在不构建它没有问题。如果答案达到10倍甚至更多,那么我将开始询问人们认为在未来一两年内我们将需要这个答案的可能性。即使那样,除非达成广泛共识,否则我只会将自己限制在确保没有必要撤销我们今天正在做的事情以实现将来的目标。

例如,我参与了一些项目,其中我们花费了大量时间来抽象出我们后来将Hibernate用作数据访问这一事实。 (我从未见过基于Hibernate构建的项目停止使用它,因此一开始就很浪费时间,但是我们将其搁置一旁。)即使有合理的可能性,我们以后可能想要更改,因为我们还使用了数据访问对象模式,它比从一开始就更容易构建灵活性,以便在需要时同时更改Hibernate和在需要时同时进行更改。面对现在这样的情况,我会推迟拥有这种灵活性,直到我们真正需要它为止。超过两到三年的架构问题,因为技术变化如此之快。您可能正在考虑构建的功能可能会在两三年内以开源形式免费提供。几乎可以肯定,成本效益分析将发生变化。几个月后,下一轮变革将带来什么。真的,这是您最好的选择。

评论


在我们当前的代码库中,过早的泛化是造成大多数背叛的原因。

– Benjol
2012年5月30日8:35



#6 楼

这是我个人消除疯狂设计的过程,这些设计(在第一个版本中)最终可能变得不切实际,并且从业务角度来看会破坏项目。


确定震中:思考作为热狗摊位的项目,震中将是热狗。您可以从摊位上拿走其他所有香料/调味料/蔬菜,但仍然可以出售热狗。您的软件的主要目的是什么?隔离其他所有附加项和/或附加值,并首先关注震中。稍后”注释。如果做得好并考虑其实际用途,您将得到相同的设计,但会按路线图进行优先排序。 / essential / pure / universal(有时甚至无需删除功能也可以实现)。当您无法进一步简化它时,请开始将可能自己存在并有目的的元素去耦。最后,如果您仍然有一些脂肪,则可以将其切断。

将“库代码”与“生产代码”分开:总是存在无法重用的代码,但它总是给设计增加噪音。此代码是包含业务规则的代码。您会发现,有时某些业务规则比健壮的设计更容易,更快捷地更改(极其重要)。您将找到可以依靠的代码,并为客户将来更改或重新实现所需的代码。您将希望将它们尽可能地分开。

顺便说一句,第0步是:“疯狂设计”。这有助于我将其从系统中脱颖而出,并经常发现新的含义,隐藏的要求甚至是新兴功能。

我从Rework中获得了1和2。

#7 楼

编写测试。测试全部通过后,您就完成了:在过度设计的史诗阶段之前,而且肯定不会在不久之后。对正在编写的代码进行一系列测试,将为您提供一个独立,公正的观察者,告诉您何时可以停止。

评论


(不是我的不赞成意见)您什么时候停止编写测试?您只是将问题放在间接级别的后面。

– MSalters
2012年5月28日在22:11

@MSalters我认为Graham指的是TDD,您在代码之前编写了一组测试。然后,编写使这些测试通过的最简单的代码。然后您重构。遵循此技术可能会阻止您过度思考初始开发,因为您的目标是使测试通过而不是编写完美的代码。

–奥莱西
2012年5月28日23:47

测试永远不能证明没有错误。仅仅因为您的吐司通过并不意味着您就完成了。您的测试充其量只能显示出,程序可能输入的统计意义的非常小子样本会产生您认为应该的输出。甚至还不能证明程序是正确的。无论如何,编写测试并不能帮助您构建可扩展且可维护的解决方案。

– Old Pro
2012年5月29日在1:40



@OldPro测试是一种手段,而不是目的。它们鼓励良好的设计和集中的工作流程,并且具有适度减少错误的副作用。一般来说。不总是。

–菲尔
2012年5月29日在2:58



测试有助于定义项目的范围和权限。不管您使用TDD还是其他方式,@ Graham都在想这样的想法:先拒绝测试,然后执行直到满足这些测试。

– Preet Sangha
2012年5月29日下午5:24

#8 楼

当您年轻时,您不会看到风险(可能是初级政治人物感到恐惧的原因),但是随着年龄的增长,糟糕的经历会在每次机会中使您瘫痪(可能是高级政治人物停滞的原因)。采用Occam的剃须刀引导方法-寻求需求最少的解决方案,然后从那里发展。

#9 楼

编写和设计软件时,真正需要记住的只有两件事:可维护性和正确性。正确性是最重要的短期方法,可以通过测试轻松地证明。

可维护性将在以后的开发中提供帮助,但更难确定。对UI一无所知),一旦我对它的可行性感到满意。如果我等待太久,将无法维护。如果我从分离的层开始,那么我似乎无法入门,因为我陷入了UI需要了解的关于模型的知识。

#10 楼

当我陷入这种情况时,我发现顽固地想象我是使用假设程序来完成一些琐碎事情的最终用户是有帮助的。然后,我尝试着眼于支持这些操作所需的编程入口点,并尽可能地忽略系统的其他方面。从这里通常可以构建完成系统功能的(小清单)“提示列表”,并编写一些不切实际的代码来开始实现该功能。完成该练习后,我通常会开始工作,并且系统的其余部分将变得更加清晰。这一切都是关于切入点的-所有软件中绝大多数的切入点都是最终用户使用程序进行的初始操作。

#11 楼

我认为您正在执行的任务对您来说太简单了。

几年前,您面临的挑战是编写可以完成给定任务的代码。这就是让您全神贯注的地方。现在,您的思想(您的经验等)正在更加有效地工作,并且完成同一任务仅需要以前所需的一部分精力。这就是为什么您会陷入那种深思熟虑的漩涡。您的思想正在为日常工作辩护,为挑战而战。

我认为您应该考虑改变工作。也许您应该学习一种新的编程语言。

#12 楼

15年前,我遇到了同样的问题。我想编写完美,可重用,通用的....代码,使解决方案变得比必需的复杂得多。今天,我将其视为镀金。对我有很大帮助的是一位同事的建议:


如果您有什么想法可以改善功能,使其更加通用,请将该想法写下一个单独的文本文件中“ ideas.txt”,但不要立即执行。
继续执行紧迫的任务。
六个月后,查看您的“ ideas.txt”并分析其中哪些更改真正使专案。


#13 楼

这只是分析而瘫痪。它发生在许多领域的许多人中。
您可以突破它。一个健身论坛,很多时候人们发布有关不同套路的信息,试图为他们找到最合适的套路。因此,我们告诉他们只是开始训练并按照自己的意愿进行工作。您想变得更强壮,做一些力量练习,然后随手调整一些东西。最初,程序必须运行,然后必须接受输入等。
您的挑战是让事情易于稍后更新和重构,但是代码一定不要比执行手头的任务复杂。 br />
请记住,将来可以重构代码以满足新的优先级。您无法预先预测所有指标,因此请勿尝试。

仅用于下一个任务的代码。
代码简单而又好,因此在需要时可以很容易地进行重构。
确保程序可以正常工作。
重复。

#14 楼

由于您正在“卡住”过多思考可能的最终用户用例场景,因此,如果要发布API并希望您不认识的人会使用该API,则需要考虑一些事项。一旦发布了API,即使您后来意识到您的第一个发行版有多糟糕,您也必须继续支持它,或者您必须破坏针对您编写的每个人(可能是您所不知道的)的代码,从而有可能疏远他们所有未来的时间。

标准解决方案是发布该API,并规定API可以随时以任何方式更改,直到您了解用户的需求以及API使用者正在做什么。

我认为这是您自己的解决方案。只写一些做一两件事的小事,也许做就好,让自己明白自己做的任何事情将来都会改变。

当您开始时,不可能一事无成,或者在某些情况下甚至一无所获,因为设计确实是一次发现之旅。它是最后出现的,不是要做的第一件事。

您不能立即设计一个API,也不必将其破坏给消费者。你明白为什么。同样,您不能编写软件,也不必抛弃所有软件并以新方法重新开始。

我不认为您遇到了问题,因为您不小心已经演变为缺乏创造力,生产力或期望的事物。我认为您的标准很高,却无意间将其不适用于您的情况,这是每个人都认为的普遍错误。

经验永远不会对您不利,除非您成为一个愤世嫉俗的万事通,万事俱备的公司,而且听起来确实与您的情况相反。

当我变大时,我会记住一些图像。一种是与乐高玩。我将其放在一起并随意拆开。我开始做的可能不是我最终做的。我正在冲浪并为自己着迷,随着时间的流逝,我常常想到的就是完全在现场重新创建我的目标……这就是创造力。

另一幅图片是我听到的一个类比,描述了做真实的科学。您在黑暗的房间里摸索着可能没有的黑猫。仅当您将自己视为找不到那只猫的失败时,才会感到不安。没有其他方法可以找到黑猫。那是找到他们的唯一活动。其他一切就是已经拥有您正在寻找的东西的某种形式。

#15 楼

你不太了解;你还不够了解!而且您直到最近才意识到。

不要将您的设计选择视为必须获得“正确”的东西,因为没有“正确”的东西–存在许多“错误”的东西”,但也需要权衡取舍(在执行速度,完成编码任务的时间,可扩展性等方面)。如果您编写的代码构想很好,仍然会具有各种优点和缺点。

目标应该是了解当前和将来的使用和维护背景下的这些优点和缺点。

因此,不要回避深刻的想法,但要记住,要成为这种设计的主人,需要经验,而不仅仅是思想。进行思考,直到您对某个特定选择没有信心为止,然后实施您希望是最好的选择,尝试一下,并从中学习。

#16 楼

练习编码。提出练习或在线找到它们,并尝试尽快正确完成它们。当您加快速度时,请添加诸如可维护性和性能之类的注意事项。您会意识到,将不再投入生产的代码令人耳目一新,这可能会帮助您摆脱对编码的恐惧。

#17 楼

像10年前一样,在业余时间编码,减少烦恼,享受乐趣。在10年前。

#18 楼

不,您还不够了解。

丰富您的知识,例如通过这些简单的规则:


KISS:保持小巧简单。
YAGNI:您将不需要它。
越差越好:从可维护性的角度来讲,一些较差的解决方案实际上会更好。通过具有重构技能来为更改做好准备,但不要对代码中所有可能的更改进行编码。如果您发现随着时间的流逝,类或函数会变得太大,请对其进行更改。分而治之。使用界面,使用更多功能。如果您觉得划分过多(即某种程度上变得更奇特,但可读性较差),请撤消上一次更改。

总结:使代码足够灵活,但不能更多。相反,要使自己更加灵活,可以买一本有关重构的书。

#19 楼

有两件事:


认识很多还不够。您必须对什么值得实施有意见。我个人认为TDD是导致不良架构的拐杖。鉴于大量的民意对此不利,我可能是错的,但是我是否考虑过是否要在JavaScript中实现TDD并不是一个问题,因为调试从未使我感到头疼,嘿,数年后,这在开发社区中并不是第一次被大众认为是有缺陷的。因此,学习成为一个傲慢的人。至少在里面。您可能是错的,但至少是您致力于对自己有用的东西,而不是对可能不起作用的东西进行过思索。从宏开始。首先,您需要使用工具来完成应用程序所需的工作。这部分应该足够容易。然后从架构/接口问题开始。管道的连接方式和连接方式实际上应该只是脆弱的部分,而这一切您只需滑动一下即可更换即可。同样,有关如何完成工作的细节。正确包装后,即可轻松进行替换/编辑。


#20 楼


但是每次我尝试攻击它时,我都会陷入深刻的思绪中


没有错。您只注意到现在是时候改善您的流程了:在这种情况下,您是在思考过程。您已经注意到,因此您可以更改思考过程以保持正轨。

有很多解决方案,而我上面看到的最好的解决方案是设置时间限制。在开始之前,请确定要花多长时间(1小时?)来进行分析和思考。设置一个计时器。

然后,当计时器关闭时,开始编码。如果您发现自己考虑时间太久了,那就立即做出决定。那时您做出的决定都是正确的决定。您以后可以随时进行更改和改进。

此外,我们的环境也在不断变化。我们经常需要更新代码以处理新要求,新技术,新硬件,语言和系统更新等。

#21 楼

是的,这种编码恐怖甚至发生在我身上。
为小型应用程序详细编码。
但是当它是一个外包项目时,由于时间限制,它不会花费很多时间。
并且还可以与我觉得一群新人可以克服这个问题。

#22 楼


您还不够残酷


http://playswithfire.com/blog/2012/02/19/you-are-not-ruthless-enough/

编辑:本文的重点是开发时注意一些小细节,但我发现它有助于以无情的态度处理任何简单或复杂的任务,以便找到可能且公正的最有效解决方案完成工作。