TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

The Wrong Aesthetic

101 点作者 urlwolf将近 15 年前

12 条评论

axiom将近 15 年前
I've always felt that most good programmers go through 3 stages.<p>Stage 1: Write very simple, naive code, no fancy design patterns, just kind of brute force everything.<p>Stage 2: Discover design pattens, and fancy obscure programming constructs. Use them <i>everywhere</i> regardless of whether it makes sense or makes the code easier to understand and maintain.<p>Stage 3: Realize the folly of stage 2, and enter a zen like state where one writes deceptively simple, clean code. Rarely, if ever, use any fancy constructs or design patterns (except where it actually makes sense to use them.)<p>For the novice programmer looking at someone else's code it's very very easy to confuse stages 1 and 3.
评论 #1427783 未加载
评论 #1427788 未加载
评论 #1427685 未加载
评论 #1428141 未加载
评论 #1430319 未加载
评论 #1428818 未加载
DougBTX将近 15 年前
I guess this is what he meant to write, programming language permitting:<p><pre><code> int Total() { return dice.Sum(die =&#62; die.FaceValue); }</code></pre>
评论 #1427845 未加载
评论 #1427745 未加载
评论 #1429255 未加载
评论 #1427760 未加载
评论 #1427789 未加载
评论 #1427798 未加载
jrockway将近 15 年前
I disagree. I like the second example, because it explains what it's trying to do -- accumulate, over +, the values of the dice from begin to end. Instead of dumbing down the algorithm for the machine, it uses the words in the problem domain to describe the problem. (Now, you could argue that C++ is messy because you are using a hammer to screw in a screw, and that's true. You could also argue that it's stupid to rewrite code in this new way when the old way works fine and the problem is so simple. Also a valid point.)<p>Oh, and I don't know Boost, but I guessed that the error was a missing _ before the 1. And after reading the linked article, it turned out that I was right. So it's not <i>that</i> hard to figure out.<p>I think the article makes sense if you consider its source. This is Zed Shaw, who has given up high-level languages in favor of C, at least for the purpose of blog posts. Of course he would prefer the "how the machine does it" version of the code to "how the programmer thinks of it" version that Boost (and presumably Ruby) prefer.<p>I think 50 years of programming has proven that approach wrong, but he is entitled to believe whatever he wants to believe. I take the opposite stance -- describe your problem as precisely as possible, and let an optimized library or language figure out how to get the computer to solve the problem quickly. You can do both, of course, but keep the two parts separated!
p3ll0n将近 15 年前
Great Post!<p>While a lot of factors go into determining whether a language is readable I have always felt the most obvious is familiarity. The human mind is very good at adaptation, and often it’s astonishing what we will perceive as "normal." Familiarity only comes from constant exposure, though, which means that languages with relatively simple syntax become familiar more quickly. Lisp is at one extreme, with only one syntactic construct. It’s very easy to become familiar with Lisp, although grasping the large Common Lisp standard library is another matter. I tend to agree with the author that C++ is a language at the other extreme. Most C++ coders I have encountered use only a relatively small subset of the C++ language. Worse yet, everyone uses a slightly different subset.<p>Of course, the biggest impact on readability comes not from the language, but from the developer. A poor developer can write illegible code in any language. A good developer? I’ve even seen well-written, readable Visual Basic code (once).
albertzeyer将近 15 年前
Such functional code in C++ doesn't need to be bad. Though I would have coded it a bit different:<p><pre><code> int Dice::total() const { return sum(dice.begin(), dice.end(), _1 -&#62;* &#38;Dice::faceValue()); } </code></pre> with:<p><pre><code> template&#60;typename T, typename Iter&#62; T sum(Iter begin, Iter end, function&#60;T (Iter)&#62; f = *_1) { if(begin != end) return sum(next(begin), end, f) + f(begin)); return 0; } </code></pre> This allows some more flexibility. For example, you could also provide other implementations of sum. You could also easily make your code threaded without changing the code of Dice::total (well, take this example a bit carefully -- of course it implies that faceValue() is threadsafe and also does only make sense if faceValue is expensive to call).<p>Summing up some numbers may be anyway not the best example for this because the naive implementation is really so short and trivial and in most cases enough.
评论 #1427831 未加载
iamwil将近 15 年前
I dunno. This reminds me of that post about "Say what you mean in javascript"<p><a href="http://news.ycombinator.com/item?id=1358753" rel="nofollow">http://news.ycombinator.com/item?id=1358753</a><p>Sometimes, things are confusing or are seemingly super weird depending on your background. While I haven't done C++ in years, I recognized that std::accumulate() was probably very much like Ruby's inject().<p>I suspect those that have seen map, inject, and their ilk wouldn't be so confused.<p>While you can argue that the 'average corporate programmer' wouldn't know what the hell it is, and you might be right. But if we stuck with that attitude, we'd still be using goto's liberally because the 'average corporate programmer' would find for loops weird and confusing.
评论 #1427727 未加载
sosorry将近 15 年前
I don't particularly understand what makes the second one more confusing than the first.<p>In particular, as a non-c programmer this: "(*i)-&#62;faceValue()" would be pretty confusing to me.<p>The first one in 'English':<p>"For each i starting at dice.begin(), while i is not equal to dice.end, incrementing i. Add to 'total' the face value of the thing that i is pointing to."<p>The second one in 'English': "Accumulate from dice.begin to dice.end, initializing the accumulator to 0, adding the face value of each die."<p>The first one might be idiomatic C++, but it doesn't seem to me that it would be idiomatic in any natural language.<p>(reduce #'+ (map 'list #'faceValue dice))<p>what is obvious depends on your background.
评论 #1428103 未加载
评论 #1428140 未加载
评论 #1428022 未加载
Bjoern将近 15 年前
Wish zed would have a date on the blogpost of when he posted that.
评论 #1428869 未加载
pbiggar将近 15 年前
This would have been fine with a BOOST_FOREACH. I find it hard to believe that he knows his way around boost:bind, but not BOOST_FOREACH.
评论 #1428340 未加载
benatkin将近 15 年前
Did anyone else notice the inconsistency without Zed's help?<p>Even if I hadn't, it still wouldn't have affected how I thought about the code. It's just a type error that would have been caught by the compiler.<p><a href="http://www.boost.org/doc/libs/1_43_0/boost/bind/placeholders.hpp" rel="nofollow">http://www.boost.org/doc/libs/1_43_0/boost/bind/placeholders...</a>
shin_lao将近 15 年前
So in other words the author isn't used to boost::bind and stl algorithms and complains that he doesn't understand code written with both?<p>First of all today you would rather use a lambda which is easier to understand.<p>The advantage of the second code is that it's generic and less error prone. You can't get the loop wrong. You can change the addition by any operation very easily, and the compiler will complain when you get things wrong.<p>fyi, the same code written with a lambda:<p><pre><code> int Dice::total() const { return std::accumulate( dice.begin(), dice.end(), 0, [&#38;](size_t v, const Die &#38; d) -&#62; size_t { return v + d.faceValue(); }); ); } </code></pre> For more information about why the second version is better, I advise the book "Elements of programming".<p>ps: the spelling error introduced by the author prevents the code from compiling, so the argument doesn't hold
评论 #1427793 未加载
评论 #1427800 未加载
评论 #1427852 未加载
edanm将近 15 年前
I suspect that some of the programmers who find the second version better are non-experienced. To them, the first version is <i>not</i> standard C++ code, so it looks as "ugly" as the second version. The second version is cooler (= harder to understand), so they prefer it.<p>Having said that, the second version written in a better language <i>is</i> pretty standard. It's mostly the limits of C++ which make the "functional" version look so bad, imo.