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

科技回声

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

GitHubTwitter

首页

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

资源链接

HackerNews API原版 HackerNewsNext.js

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

On logic in a Rails app

91 点作者 alisnic超过 12 年前

20 条评论

michaelfeathers超过 12 年前
The funny thing about the argument that people have about where logic should go in an application (models, controllers, or separate objects) is that everyone assumes that there is one right answer for an application for all time.<p>We should probably move toward guidance like: "this is when you move your logic here" and "when this happens, it's time to move it out of the controller."<p>For what it's worth, I think it is okay to start doing things the naive way in Rails as long as you know when to refactor toward a different scheme. The bad thing is that it is usually earlier than you think.
评论 #4963170 未加载
评论 #4962886 未加载
评论 #4964360 未加载
评论 #4964847 未加载
tinco超过 12 年前
I think many people react negatively to this article because they gloss over the idea that this is a refactoring.<p>When coding you always make the choice between abstraction and readability. If you look at the patterns from GoF, the downside of almost every pattern is that it reduces readability for the simple cases.<p>Thus, when you write your controllers and your models in my opinion you should start out doing it 'the rails way' which is having your business logic in your models, and the controlling logic in your controllers.<p>Then when your app is starting to feel clunky, your controllers are gaining weight and your models have too many responsibilities, that is the point where you start refactoring.<p>And that is also where you decide wether the logic belongs into a concern, or a policy, or whatever fancy pattern is hip right now and fits there. (But you really should make an effort to make clear where logic ends up for someone new to your code, so be consistent!)<p>I think rapid development is one of the key features that made Rails big, don't let these concerns that big apps have drag you down in the beginning.
评论 #4963404 未加载
评论 #4963239 未加载
jeswin超过 12 年前
My experience has been:<p>- A file (not a pattern) is the most effective unit of code organization and navigation.<p>- Any design, which can be split into multiple files in a logical and consistent manner is maintainable.<p>A few years back, I might have cared about the issues mentioned in the original post. Looking back, many of them were just personal preferences.
评论 #4963005 未加载
alisnic超过 12 年前
So far, I got a lot of feedback here and on my blog, which I didn't expect (also the frontpage). There seems to be a general attitude of "why complicating things from day 1?" towards the article I wrote. While I do agree that there is no need to isolate things from the start, I do not see the complications at all.<p>The cost of creating a file and moving behaviour there is exactly 0, but the benefits are there from day 1.
评论 #4964031 未加载
darrencauthon超过 12 年前
It all comes down to testing to me. If the dev is writing a test first, questions about where things go are answered pretty quickly. If the tests become painful or awkward, you're probably doing too much in the code.<p>I think the common Rails response to painful tests is to stop testing. I've heard talk of the "diminishing returns" of testing, or debates of what deserves to be tested. I was once responsible for maintaining many Rails 3 apps that I did not write, and the story was all the same: Either there were no tests, or there were simple tests around simple logic, or there were simple tests covering one or two paths through some <i>really</i> complex logic. Once they felt the pain from their tests, they just stopped writing tests. What else are they going to do... challenge the "Rails Way?"<p>And this is the community that is supposedly known for their testing. Having used Sinatra or Rails for almost all of my web work for a while, let me tell you: The state of testing in the common Rails app is no different than I've seen anywhere else.
评论 #4982487 未加载
评论 #4962867 未加载
programminggeek超过 12 年前
I've been working on the Obvious Architecture, which seeks to decouple your app from both the database and your web framework. Treating Rails or Sinatra or whatever as just a delivery mechanism frees you from a lot of of the potentially bad design decisions that your web framework made about how you should structure your app, the worst offender of this is how rails implies the use of ActiveRecord. You should use Rails for what it's good at - web stuff (routing, asset management, view engine integration).<p>I've got an example Obvious twitter close/status update app in progress at <a href="https://github.com/RetroMocha/obvious_status" rel="nofollow">https://github.com/RetroMocha/obvious_status</a><p>Obvious is still super new and I'm working on documentation and examples. You can read more about Obvious at <a href="http://obvious.retromocha.com" rel="nofollow">http://obvious.retromocha.com</a>
评论 #4963148 未加载
评论 #4963241 未加载
alexborbely超过 12 年前
MVC framework is just a delivery mechanism and your business logic should be outside of it. Your business logic should have no idea about web, console, controllers and routes, it should contain information only about your domain objects and rules. You should be able to extract your application logic and make it available on console, web or mobile just by changing the delivery mechanism. This is the original explanation from <a href="http://cleancoders.com" rel="nofollow">http://cleancoders.com</a> (Bob Martin's website) <a href="http://www.cleancoders.com/codecast/clean-code-episode-7/show" rel="nofollow">http://www.cleancoders.com/codecast/clean-code-episode-7/sho...</a>
评论 #4962852 未加载
评论 #4963249 未加载
评论 #4962807 未加载
stiff超过 12 年前
I think the importance of the Single Responsibility Principle is much overestimated by many people and introducing terms like "single-responsibilty objects" for what are essentially simple procedures is symptomatic of this. There are many properties of classes one can consider beneficial, but they might in fact conflict with each other to some extent, especially when carried out to extremes like in this case, so what you want is to find a good compromise. The "principle" itself is rather a very fuzzy guideline, so I wish it wouldn't be taught to people since it seems to do more harm than good to their understanding good OO design.<p>On another note, I wonder to what extent Rails usage of the Active Record pattern makes "models" so clumsy in large applications. It works great to a certain point, but maybe in large applications the Data Mapper pattern (not to be confused with the DataMapper library) would help to isolate a large aspect of what currently goes in a model while keeping a nice OO interface:<p><a href="http://www.martinfowler.com/eaaCatalog/dataMapper.html" rel="nofollow">http://www.martinfowler.com/eaaCatalog/dataMapper.html</a>
评论 #4963746 未加载
评论 #4963739 未加载
bstar77超过 12 年前
My problem with fat models is exactly what the author describes, data really needs to be separated from the logic. Since all of my current projects are service oriented, I generally abstract into gems, albeit with some minor overhead. That has proved to be the cleanest approach for me. Just throwing code into /lib never seemed to help the organization/readability problems.
stiff超过 12 年前
This seems to be a new trendy design pattern: wrap a single method with a class and claim you just discovered a pinnacle of object-oriented design since you respect the "Single Responsibility Principle"...
评论 #4964045 未加载
评论 #4963529 未加载
gavingmiller超过 12 年前
I think someone needs to plug how awesome the Destroy All Software screencasts are (referenced in the post.) They are well worth their value, and have made me a better developer: <a href="https://www.destroyallsoftware.com/screencasts" rel="nofollow">https://www.destroyallsoftware.com/screencasts</a>
评论 #4963348 未加载
why-el超过 12 年前
I can't help but see the irony in the fact that the Rails community is slowly moving back to app directories similar to those we found in Java's Spring and others. I guess people from the Enterprise world had a point.
评论 #4962781 未加载
评论 #4964449 未加载
评论 #4962940 未加载
jpallen超过 12 年前
We use a very similar set up in a large Node.js app I'm working on. It works very well for the most part, but we're definitely still figuring out the best way to split things up.<p>For example, say we want to work with a 'user' model, and we need to do basic CRUD stuff. One argument would say that we should have a module for each action: creating users (registering, hashing password, sending out welcome email, etc.), deleting users (cleaning up their data, removing them from the db), and for authentication, profile updates, and so on. The downside to this is that we end up with a dependence on the underlying data structure across lots of modules. If we want to change the property 'username' to 'login', or something more complex, we have a lot of modules to change. We also need to understand how a user is created before we can understand how they are updated or deleted, which means we need to have the CreateUser module in our head while we're working on UpdateUser or DeleteUser.<p>Perhaps this problem is worse in our set up because we have only very thin 'models', which are basically just Mongoose wrappers around MongoDB, and so our UpdateUser models is still quite heavily coupled to our database.<p>All things considered, I've found the schema described in this article is better than any alternatives that we've tried. Perhaps we're just floating at the equilibrium point where either more or less abstraction would make the code more complicated. Certainly we refactor as soon as we can when a single module gets too complex. As always, pragmatism rules.
aurelianito超过 12 年前
Given code like this:<p><pre><code> class RatingsController &#60; ApplicationController def create success = RatesBusiness.add_rating(params[:business_id], params[:score], current_user) render json: {success: success} end end </code></pre> Wouldn't it be better something like this (just to adapt to rails)?<p><pre><code> class RatingsController &#60; ApplicationController logic = RatesBusiness end </code></pre> Or, even better<p><pre><code> class ApplicationController &#60; Controller def initialize(logic): // do something end def create: // do something with the logic end end </code></pre> And adding some routes for each logic.<p>But, then, you could just extract the route from the logic name (and get the rails controller back, that now it would be called "Logic")<p>My point is that extracting code just for the fun of it seems worthless. What is the rationale in this case?
评论 #4964456 未加载
tieTYT超过 12 年前
As far as I can see, he's advocating a MVC approach. The controller is used for handling View input/output. The Model is where the data and business logic is supposed to go. For some reason most people think the Controller is where the business logic is supposed to go, but when you research The MVC Pattern, that's not how it's described.<p>If you don't believe me, let me give you a little history. The MVC Pattern was created because of this problem: "I made this cool app with a fat client UI and now the higher ups want a way to view it from a web page. This is so freaking hard because the UI and the data and logic are all mixed together. How could I have planned ahead for this?"<p>MVC is the answer. You take the View and the Control, make them specific to the UI and then you put your UI agnostic code (this includes data AND business logic) in the Model. That way, when the higher ups want a new UI, you just have to create new View and the Controller code.
评论 #4964374 未加载
sakopov超过 12 年前
It's a pretty good practice in MVC. I don't work with Rails, but in ASP.NET MVC, i put controller logic behind IBusinessTask generic interface which defines a type for input and output of its single `Execute` method. Any implementation of this interface would call the Business tier to perform its task. These implementations are then injected into controller via property or constructor injection.
LaGrange超过 12 年前
Bah! Poppycock! My domain objects are also logicless, and I keep all my enterprise stuff in PL/SQL. Also, TDD is for people who can't do formal methods.
评论 #4962504 未加载
dzuc超过 12 年前
What to do about callbacks in the models?
评论 #4982498 未加载
agopaul超过 12 年前
Well, basically this is the approach of Application Service pattern, isn't it?
评论 #4963574 未加载
lucian303超过 12 年前
"I look at Rails as web presentation layer, it makes my app work in the browser."<p>Yes! YES! Not just rails. Any web app regardless of language or framework. Thank you for writing this. It's what Richard C. Martin (Uncle Bob) calls the lost years ... and about 15 of them. Reading books on good object oriented design from 1993 sheds more light on how to build proper systems (that just happen to have their delivery mechanism as the web).<p>The interface should be able to be changed. Right now, this is very difficult in most frameworks (I do PHP but Uncle Bob uses Rails as his example ... it really doesn't matter) and it's quite sad. This isn't a philosophical or abstract discussion. This is about how to build software the right way.<p>You're not building a web app. You're building an app whose delivery mechanism happens to be the web.<p>See Uncle Bob's talk: <a href="http://vimeo.com/43612849" rel="nofollow">http://vimeo.com/43612849</a><p>Period.