TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Refactoring wars and how to avoid them: what is "simplicity" in programming?

46 pointsby MikeTaylorabout 15 years ago

14 comments

Chris_Newtonabout 15 years ago
We are far too willing to dismiss things as mere "personal preference" in this industry. There may be competing theories all supported by some empirical evidence and sound logic, but some claims are directly contradicted by hard data. Those claims are not just a personal preference for the best way to do things. They are measurably, objectively wrong, and failing to say so is just being nice because we don't want to criticise someone.<p>On the evidence I have found to date, I am coming around to the view that the style of writing many very short functions (say up to 5-6 lines) with little complexity in the logic (say just a single level of nesting) is one approach whose claimed superiority is directly contradicted by empirical data. For example, McConnell discussed the number-of-lines issue in <i>Code Complete</i> years ago, citing multiple studies. Anyone can find still more by investing a few minutes in Google Scholar searches.<p>Alas, that does not stop bloggers, consultants, trainers and book authors from advocating this programming style, even though it invariably results in the kind of incohesive "spread" that the article mentioned.
评论 #1225095 未加载
aaronblohowiakabout 15 years ago
this entire blog post reduces thusly: "hiding complexity with abstraction and encapsulation is not simplification, but further increases cognitive load as the abstractions must be undone to fully comprehend the function of the code." It is an interesting point, sure. I think the example as given makes his point fairly well.<p>The question becomes: when does hiding complexity improve your ability to reason about the code?<p>I agree with the author that this is ultimately a personal preference. One guideline that I appreciate is that your code should operate at a consistent level of abstraction. For instance, in the routine that defines the business logic, the details of the protocol used for persistence should be "somewhere else." This complicates tracing the execution of the program, but it makes understanding the intent of the business logic easier as there are less "implementation details" to ignore.
评论 #1224155 未加载
评论 #1224210 未加载
评论 #1224443 未加载
评论 #1224190 未加载
Khakiabout 15 years ago
Surely one long function is very much harder to test than several shorter ones? So in the context of unit-testing at least, testability is in harmony with Fowler's definition of simplicity. Seems like a nice goal to me.
评论 #1224137 未加载
评论 #1224132 未加载
sgoransonabout 15 years ago
Personally my brain has an easier time grasping {TaskA(); TaskB(); TaskC();} rather than a 750loc block of code. Yes, multiple source files are annoying, but there's plenty of tools out there to help (ctags and vim is enough for me).<p>But the more important reasons to strive for high cohesion/low coupling are: Future changes are generally easier when you have well defined blocks instead of a birds nest of code, unit testing practically writes itself, and you have a better chance at isolating a problem to a module if it's responsibilities are few and well defined.
fauigerzigerkabout 15 years ago
I think you are wrong. It's not just individual taste. What matters is how well functions are aligned with units of change and reuse.<p>Simplicity is having to think about a smaller number of items and dependencies when I want to change/extend/reuse code. If there are many functions and classes but I have to touch all of them whenever I want to make a typical modification, then it's worse than having everything in one function. Conversely, if a more granular design allows me to ignore most of the code and just change one simple function or even just parameterise it differently, that's simplicity.<p>But there is a snag. Even if the design aligns well with units of change and reuse, and I would have to make just one small change in one small function in order to have the desired effect, I don't necessarily know which of a large number of functions it is. I might not even know whether or not such a function exists. So I have to understand how everything works together in order to benefit from well designed code.<p>That leads me to the conclusion that better programmers who do understand the system and its interdependencies benefit from small units provided they align well with units of change and reuse. Bad programmers have to look at everything every time anyway, so they might find it easier to look at one large chunk of code.
daakusabout 15 years ago
I think the point is avoiding complexity until absolutely necessary. Splitting code and creating abstractions "because it will make doing X easier in the future" is often the wrong thing to do. The right thing imho is to split it when you need X now, not the future.
评论 #1224551 未加载
trunnellabout 15 years ago
The author's criticism of Fowler's refactoring:<p><i>But look at the cost: to understand how rentals are calculated, we now have to read six classes instead of one method... Fowler evidently finds it easier to read many small methods than a few larger ones; I find the opposite.</i><p>This raises the question, do we all have our own definition of good code?<p>Several books have tried to formalize what is good code (he mentions <i>Refactoring</i>, <i>Code Complete</i> also comes to mind). I enjoyed those books, but I'm often reminded of what my CS professor once told me: good code is a matter of taste.<p>In the example he cites from <i>Refactoring</i>, my taste is more like Fowler's. I think it's easier for bugs to hide in long methods than short ones. Plus, Fowler extracted some distinct concepts into their own classes-- things like prices. Price formulas are likely to change, so I say the cost of extracting that class is well worth it.<p>It seems to me that ultimately, Fowler and others are not claiming to have found the secret to "good code;" rather, they are trying to influence people's taste for what <i>they</i> consider good code.
drpabout 15 years ago
Fowler's book is about simplifying mainentance and testability, not (necessarily) simplifying the actual code. He doesn't even claim his techniques are the best way to start programs, hence the "Refactoring to" portion of the title. Also, it's specifically about object oriented design patterns so the examples aren't intended to apply to other paradigms.
digitallogicabout 15 years ago
From the first chapter of 'Refactoring': "Was it worth it? The gain is that if I change of the price's behavior, add new pricess, or add extra price dependent behavior, the will be much easier to make."<p>Massive functions start out as small and then large ones. If a business logic function has to grow every time there's a new rule that could live behind an abstraction, it's on the path to becoming massive.
barrkelabout 15 years ago
There's a spectrum with respect to abstraction. Too little, and you end up with a brittle blob of code where the multiplication of each axis of change and parameterization causes an explosion in state changes and maintenance costs. Too much, and you end up with too many indirections, lost performance, and an additive cost of change and parameterization in each axis that dwarfs the complexity of the underlying operation.<p>The happy middle is "just right", but it's hard to recognize or achieve without some experience of either extreme. And even then, the chosen point might be biased towards less abstraction for performance reasons or more abstraction for composability and reuse reasons. But really good use of abstractions (ideally including at the language level) ought to reduce the amount of compromise needed.
DanielRibeiroabout 15 years ago
Well, I like two definitions.<p>1: From the Agile Manifesto (<a href="http://agilemanifesto.org/principles.html" rel="nofollow">http://agilemanifesto.org/principles.html</a>):<p><i>Simplicity--the art of maximizing the amount of work not done--is essential.</i><p>2: From Kent Beck on Extreme Programming:<p><i>Simplicity is the most intensely intellectual of the XP values. To make a system simple enough to gracefully solve only today's problem is hard work. Yesterday's simple solution may be fine today, or it may look simplistic or complex. When you need to change to regain simplicity, you must find a way from where you are to where you want to be.</i><p>And a related one from Antoine de Saint-Exupery:<p><i>Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away</i>
yasonabout 15 years ago
Simplicity and good code is what we <i>seek</i> by practicing the art of programming. It's not meant to be an end.<p>The question of simplicity and good code is not a problem to solve but, rather, something that compels us to reach for more beautiful solutions to different problems — more beautiful than those we already know.<p>Suppose that Leonardo, after having painted "Mona Lisa", had concluded: "This is the most beautiful painting I can draw, therefore I'll just stick to the style and draw slight variations of her from now on because this is the most beautiful painting ever." He might have sought for something more, too.
chadaustinabout 15 years ago
I wish I had the "How do you stop people from refactoring too much?" problem. :)
评论 #1224640 未加载
johnwatson11218about 15 years ago
Does anyone know if there was ever a project to take a really complicated oo system and a unit test. You run the unit test with some aspectj stuff and produce one big method that does the same thing that all the objects and methods just did? Not as a replacement but rather as a tool to help you get the jist of something you don't really care about quickly?<p>Maybe even comment (or color code) the big method to show which objects it was ripped from?<p>Then maybe something to try and compress this big method and remove lines of code that are only picking out impls at runtime or doing reflection or something?