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

科技回声

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

GitHubTwitter

首页

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

资源链接

HackerNews API原版 HackerNewsNext.js

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

Tell, don't ask

216 点作者 djacobs将近 13 年前

23 条评论

bluesnowmonkey将近 13 年前
Example 3 adds a nonsense method, EmailUser#send_to_feed. What does that mean? Email users don't have feeds. If we're going to evangelize OO purity, let's do it right.<p><pre><code> class Post def created user.post_created(self) end def send_to_feed(feed) feed.send(contents) end end class TwitterUser def post_created(post) post.send_to_feed(twitter) end end class EmailUser def post_created(post) # no-op. end end </code></pre> The post merely tells its user that it was created. Then the user can decide to do something else. All users know about posts, but only TwitterUser knows about feeds.<p>Honestly though, if I saw the not-so-good code, I'd leave it alone. It takes a pretty big justification to double the code for the same features.
评论 #4268524 未加载
评论 #4268439 未加载
评论 #4268451 未加载
djacobs将近 13 年前
For me, this technique is bigger than objects or encapsulation. It's about reusing existing "branch points" that a language gives you (whether it is polymorphism, method dispatch, namespacing) instead of explicit conditionals at a level higher than the language. My general take is that explicit conditionals in a high-level language are a smell. Sometimes they're necessary, but if you tell yourself that they mostly aren't, you tend to end up with cleaner code.<p>I'm not saying it's possible to avoid conditionals completely, but this article gives several good examples of where it's possible. Someone should put together a similar set of examples in a functional language.
评论 #4268323 未加载
评论 #4268554 未加载
评论 #4268257 未加载
评论 #4268338 未加载
afrenchcoder将近 13 年前
all of those examples look horrible, make debugging harder and implies strong code coupling.<p>example 1, we're mixing data with UI labels. How do you handle localization ? by coupling your localization code with your user data/behavior ?<p>example 2 : you're simply coupling the system_monitor with the alarm, while in the worst case, the alarm should be linked to the system_monitor. Now if you want to add a "report_to_government_agency" method, you'd add that inside the code of every single one of your monitors (knowing that you don't want to report a broken light, but it might be a good idea for a melting nuclear core) ? Note that I'm not saying that the first code is good, it's just as bad... Also, the method becomes very poorly named (I want to know if the sensor went back to normal, but every time I query "check_for_overheating", it just rings the alarm and doesn't give me any info back ???)<p>example 3 is just a poor usage of pseudo inheritance (and an abuse of duck typing). you create a new type of user for every messaging service again ? and if a user uses more than one messaging service, you just create a type for every combination ? Not very scalable nor readable, IMO.<p>The last example is just as bad. useless inheritance, senseless object. the definition of street_name is wrong. the doc will be around "Street name returns a street name or an error message if there's no street name defined" How do you know if there's no street name, now ?<p>All those examples basically make all extension harder. They're everything that's wrong with OO. an object is not about one structure that contains data and does everything that can be done with it. An object is about giving organized access to pertinent data and/or pertinent behavior and (potentially) allowing to change them.
fusiongyro将近 13 年前
This is a great little refresher. I recently inherited a codebase of about 3500 lines, 2500 of which are in one class. Not OO.<p>Incidentally, if this article blew your mind or if you're interested in Smalltalk, I can't recommend this book enough:<p><a href="http://www.lulu.com/shop/andres-valloud/a-mentoring-course-on-smalltalk/paperback/product-3788890.html" rel="nofollow">http://www.lulu.com/shop/andres-valloud/a-mentoring-course-o...</a><p>The author has a radical take on OO in Smalltalk and shows that going to absurd lengths to eliminate if-statements (well, ifTrue: et. al., because it's Smalltalk) can lead to both better readability and better performance.
0x0将近 13 年前
Going down this path seems to put your code at risk for dangerous mixing of concerns, in some cases.<p>Unit-testing the check_for_overheating inside SystemMonitor looks complicated... The "sound_alarms" call inside probably needs to be a reference to a "Speaker.sound_alarms", right? Why should the SystemMonitor be locked to the API of a Speaker? etc.
评论 #4268239 未加载
ricardobeat将近 13 年前
Disclaimer: not a Ruby user. I'm confused by example 4. Why would you return a message from either of them? Shouldn't messages in general belong to the view?<p><pre><code> {{ user.address || "No address on file" }} </code></pre> The "not so good" code is essentially this, but inside a wrapper in view code. What if you need different markup for a missing address, you either stuff it into a method or change the method's return value to nil... and what if only <i>street_name</i> is missing, not the whole address? It looks like a big mess to me.
评论 #4269360 未加载
lincolnq将近 13 年前
Makes some good points. I can't help but notice, though, that the "good" examples are all <i>longer</i>.<p>It makes me want to design a programming language that makes good code shorter than bad code...
评论 #4269626 未加载
n72将近 13 年前
Ick, breaks command/query separation, the other OO rule that along with tell, don't ask I find to be a hallmark of well coded OO systems.<p>class SystemMonitor def check_for_overheating if temperature &#62; 100 sound_alarms end end end
zwieback将近 13 年前
Also see <a href="http://c2.com/cgi/wiki?TellDontAsk" rel="nofollow">http://c2.com/cgi/wiki?TellDontAsk</a>
sukuriant将近 13 年前
This has long been one of my favorite methods of using OO code to my advantage; and is one of the main reasons that my code is OO in the first place.<p>There are many cases where it's easier/lazier to have if-statements.<p>Going further, you can take the things learned in this article to make your general purpose code potentially faster, as well. For example, if a set of things that must be performed in order; and sometimes some of those steps are missing, instead of performing a null-check, you can have a default no-op case; that way, instead of:<p><pre><code> if(firstAction != null) firstAction(); if(secondAction != null) secondAction(); if(thirdAction != null) thirdAction(); </code></pre> in your inner loop, you can have:<p><pre><code> firstAction(); secondAction(); thirdAction(); </code></pre> While whenever firstAction, secondAction, thirdAction are set, you can say:<p><pre><code> firstAction = newFirstAction ?? noop; // etc. </code></pre> All in all, I'm glad this sort of knowledge is getting out there. I'm just grateful for my having really, really good CS teachers back in highschool ( I don't remember my college talking about OO as a way of removing if-statements ).<p>* Users of Java, of course, will just need to write a NoOp instance of their interface to take advantage of this.
评论 #4269121 未加载
jawr将近 13 年前
I liked the first example, but then it felt too preachy; OOP isn't necessarily the correct way to do things.<p>I really like the clean design of the site though, very fresh imo.
ninetax将近 13 年前
Awesome! This is think kind of article I love to see on HN.
InclinedPlane将近 13 年前
Refactoring: <a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/" rel="nofollow">http://www.amazon.com/Refactoring-Improving-Design-Existing-...</a><p>Read it. Learn it. Love it. Make it a habit that is so ingrained you do it automatically.<p>Extract method: do it reflexively.
edoloughlin将近 13 年前
I'm not trying to be elitist or superior, but I can't understand why this has spent such a long time on the front page. Shouldn't the content of the article be considered pretty basic knowledge at this stage of OO? Deferring implementation specifics using polymorphism was one of the first things I learned about OO when I was introduced to it (via C++) around 1992. It was definitely 'aha' worthy then, when the vast majority of commercial development was procedural, but these days? Shouldn't it be considered a basic tool in most devs' repertoire?
评论 #4270125 未加载
omgsean将近 13 年前
If you're interested in this kind of thing I highly recommend Avdi's Objects on Rails book (it's free) and Destroy All Software's screencast collection.
MaxGabriel将近 13 年前
Cool, I haven't heard of this before; I will think about it. Presumably, an exception would be 'view' type objects in an MVC setup?
评论 #4268258 未加载
评论 #4268255 未加载
gav将近 13 年前
The first example isn't a good one. You don't want to have the user class responsible for returning the welcome message.
unconed将近 13 年前
Excellent. As a self-taught hacker, I always felt like I was missing something about OO, because it's introduced with an analogy to real world objects, while glossing over the more subtle contracts that programming objects have with each other. Seems like we need a more developed vocabulary to express these things.
评论 #4268309 未加载
评论 #4268690 未加载
n72将近 13 年前
Relatedly, a long, long time ago I found Allan Holub's PPT Everything You Know is Wrong quite good: <a href="http://ebookbrowse.com/everything-you-know-is-wrong-pdf-d281291032" rel="nofollow">http://ebookbrowse.com/everything-you-know-is-wrong-pdf-d281...</a>
Killswitch将近 13 年前
Wow, short article, but huge impact... I'm gonna start doing this... Makes so much more sense. Thank you.
robotment将近 13 年前
The example is too simple to describe this design.
keymone将近 13 年前
examples could be much better..
tbrownaw将近 13 年前
This principle applies much more broadly than just to programming with objects, for example it's an excellent way to deal with bureaucracies or managers who don't always read their email.