Business Logic Layer Pattern on Rails? MVCL - ruby-on-rails

That is a broad question, and I appreciate no short/dumb asnwers like: "Oh that is the model job, this quest is retarded (period)"
PROBLEM Where I work at people created a system over 2 years for managing the manufacture process over demand in the most simplified still broad as possible, involving selling, buying, assemble, The system is coded over Ruby On Rails.
The app has been changed lots of times and the result is a mess on callbacks (some are called several times), 200+ models, and fat controllers: Total bad.
The QUESTION is, if there is a gem, or pattern designed to handle Rails large app logic? The logic whould be able to fully talk to models (whose only concern would be data format handling and validation)
What I EXPECT is to reduce complexity from various controllers, and hard to track callbacks into files with the responsibility to handle a business operation logic. In some cases there is the need to wait for a response, in others, only validation of the input is enough and a bg process would take place.
ie:
--> Sell some products (need to wait the operation to finish)
1. Set a View able to get the products input
2. Controller gets the product list inputed by employee and call the logic
Logic::ExecuteWithResponse('sell', 'products', :prods => #product_list_with_qtt, :when => #date, :employee => current_user() )
This Logic would handle buying order, assemble order, machine schedule, warehouse reservation, and others.
Have in mind that a callback on SalesOrder is not enough, since it depends on where it is called (no field for that), depends on the class of the user, among other stuff not visible for the model, or in some cases it would take long for the model to process.

The inherent complexity of the business object and logic will need to be tackled with, understood, and internalized (or at least documented well) for the team. That will not go away. The recommendation I have is to grab all the logic peppered throughout the "fat" controllers and move them into either the domain objects, application services (service layer), or simply transaction scripts (see Martin Fowler's "Patterns of Enterprise Application Architecture").
Ideally all the business logic embedded in the labyrinth of callbacks can be refactored into components described above to promote understanding. This gets rid of all the incidental complexity built up over time on the controllers. But even after getting rid of all that, I suspect a certain level of inherent complexity will remain in the problem domain.

The idea of Service Layer is to incorporate high level logic which is not associated with certain model in a good way. If you develop enterprise like system with multiple services integrated and have number of data sources you should better look to Domain-Driven Design (DDD) by Eric Evans. Surely, Fowler's Enterprise patterns book is good in this case too.
Also look at DataMapper(2, the first one was similar to ActiveRecord). It has better design approach for such type of systems and have less limitation (on conceptual level) than ActiveRecord in Rails.
Truly say, that's because of dynamic nature of Ruby people so long tackling conceptual problems of ActiveRecord and try to fit it enterprise needs, IMHO.

Some people have done some work out there on service layers and callbacks Pat Maddox (especially callbacks) is one, Jay Fields (his very early works around the rails presenter pattern later to be replaced with a service layer like pattern) is another. I must admit I like the idea of adding a extra layer. To me, business logic just doesn't belong in models and models should be decoupled in complex projects. I also like the idea of an extra layer over callbacks, for me callbacks become too complex as there numbers increase
This is far from full blown DDD and at the moment I don't know how DDD would work in Rails, however ,I am sure it could and I am sure someone is working on it out there right now. For my projects, at the moment, it would be a bit of a overkill to implement, however, I would consider adding a service layer.

Related

Is it possible to properly use DDD with all building blocks in monolith application?

I watched some videos, read some blogs about it. SO has many questions and answers on that subject but I can not find anywhere exact answer for my question.
Almost every question and answer has a lack of usage context.
I have one middle sized, asp.net-mvc, monolith application which is running in one process on IIS. I want to (refactor and) go all the way with DDD (and CQRS without separated storage for reads and writes for now) but for me it looks like impossible mission without breaking some rules/guides/etc.
Bounded Context
For example I have more than one BCs. Each should not cross their boundaries which means should not share their storage. Right?
It is not possible if you use the whole known (everywhere scattered over the web) solution to work with NHibernate session and UoW.
Aggregate Root
Only one AR should be modified in one transaction. When others ARs are involved should introduce eventual consistency (if I remember those are Eric Evans words).
I try to do it but it is not easy in app like that. Pub/Sub not working as desired because if event is published then all subscribers are take their action within one transaction (NSB/MT does that way).
If event handlers wants to modify others ARs they should be executed in separated transactions, right?
Is it possible to deal with it in monolith application (application where whole code works in one process)?
It is not possible if you use the whole known (everywhere scattered
over the web) solution
[...]
if event is published then all subscribers are take their action
within one transaction
I think you're setting yourself useless and harmful constraints by trying to stick to some "state of the art".
Migrating an entire application to DDD + CQRS is a massive undertaking. Some areas of it don't have well-documented beaten paths yet and you'll probably have a fair bit of exploration to do. My best advice would be to stay at a reasonable distance from "the way people do things". Both in traditional ASP.Net web apps because mainstream practices often don't match the way DDD+CQRS works, and in CQRS itself because the case studies out there are few and far between and most probably very domain specific, with a tendency to advocate the use of heavy tools which may not make sense in your context.
You may need to think out of the box, adopt things incrementally and refrain from goldplating everything. You'll be better off starting with very simple implementations that suit your needs exactly than throwing a ton of tools and frameworks at your codebase.
For instance, do you really need a service bus or could a simple Observer pattern suffice ?
Regarding NHibernate, most implementations out there use a (single) Session Per Request approach, but just because it's the most popular doesn't mean it's the only one. Have you tried using multiple ISessions (one for each BC) available at a more programmable level, such as per-action, or managed entirely manually ? Conversely, have you considered sharing a database between Bounded Contexts at first and see for yourself if that's bad or not ?

How do you keep your business rules DRY?

In the perfect application every business rule would exist only once.
I work for a shop that enforces business rules in as much as possible in the database. In many cases to achieve a better user experience we're performing identical validations on the client side. Not very DRY. Being a SPOT purist, I hate this.
On the other end of the spectrum, some shops create dumb databases (the Rails community leans in this direction) and relegate the business logic to a separate tier. But even with this tack, some validation logic ends up repeated client side.
To further complicate the matter, I understand why the database should be treated as a fortress and so I agree that validations be enforced/repeated at the database.
Trying to enforce validations in one spot isn't easy in light of conflicting concerns -- stay DRY, keep the database a fortress, and provide a good user experience. I have some idea for overcoming this issue, but I imagine there are better.
Can we balance these conflicting concerns in a DRY manner?
Anyone who doesn't enforce the required business rules in the database where they belong is going to have bad data, simple as that. Data integrity is the job of the database. Databases are affected by many more sources than the application and to put required rules in the application only is short-sighted. If you do this you will get bad data from imports, from other applications when they connect, from ad hoc queries to fix large amounts of data (think increasing all the prices by 10%), etc. It is foolish in the extreme to enforce rules only through an application. But then again, I'm the person who has to fix the bad data that gets into poorly designed databases where application developers think they should do stuff only in the application.
The data will live on long past the application in many cases. You lose the rules when this happens as well.
In way, a clean separation of concerns where all business logic exists in a single core location is a Utopian fantasy that’s hard to uphold
Can't see why.
handle all of the business logic in a separate tier (in Rails the models would house “most” of this)
Correct. Django does this also.
some business logic does end up spilling into other places (in Rails it might spill over into the controllers
Not really. The business logic can -- and should -- be in the model tier. Some of it will be encoded as methods of classes, libraries, and other bundles of logic that can be used elsewhere. Django does this with Form objects that validate input. These come from the model, but are used as part of the front-end HTML as well as any bulk loads.
There's no reason for business logic to be defined elsewhere. It can be used in other tiers, but it should be defined in the model.
Use an ORM layer to generate the SQL from the model. Everything in one place.
[database] built on constraints that cause it to reject bad data
I think that's a misreading the Database As A Fortress post. It says "A solid data model", "reject data that does not belong, and to prevent relationships that do not make sense". These are simple declarative referential integrity.
An ORM layer can generate this from the model.
The concerns of database-as-a-fortress and single-point-of-truth are one and the same thing. They are not mutually exclusive. And so there is no need what so ever to "balance them".
What you call "database-as-a-fortress" really is the only possible way to implement single-point-of-truth.
"database-as-a-fortress" is a good thing. It means that the database forces anyone to stay away who does not want to comply (to the truth that the database is supposed to adhere to). That so many people find that a problem (rather than the solution that it really is), says everything about how the majority of database users thinks about the importance of "truth" (as opposed to "I have this shit load of objects I need to persist, and I just want the database to do that despite any business rule what so ever.").
The Model-View-Controller framework is one way to solve this issue. The rails community uses a similar concept...
The basic idea is that all business logic is handled in the controller, and where rules need to be applied in the view or model they are passed into it by the controller.
Well, in general, business rules are much more than sets of constraints, so it's obvious not all business rules can be placed in the database. On the other hand, HLGEM pointed out that it's naive to expect the application to handle all data validation: I can confirm this from experience.
I don't think there's a nice way to put all of the business rules in one place and have them applied on the client, the server side and the database. I live with business rules at the entity level (as hibernate recreates them at the database level) and the remaining rules at the service level.
Database-as-a-fortress is nonsense for relational databases. You need an OODB for that.

Building core shop framework in Rails. Suitable or not?

I work at an in-house IT department for company running 10 or so only shops of varying complexity. The shops code has been written over the last 8 years, each shop a new branch growing father and father away from the stem (I guess that makes it a bush?)
The need for more and more complex discounts, campaigns and user monitoring are growing rapidly - and changing rapidly as well (you never know what they come up with). So we have decided to write a new system from scratch and bring the different shops back together having them run on the same core code. We have considered .NET, but due to the fact that the design requirements change so fast we have more or less decided to give Rails a try. But we have some uncertainties/questions about rails.
Is Rails (stack) suitable to run to build a shop framework and who should this be organized?
We are running around 10 shops of which some are very much alike only differing in style, where others stands out in functionality, flow and content. But behind the business logic is all the same. The shops functionality is to a great extend the same as well. As an example the checkout page of one shop might display great details about VAT, discounts, P&P, etc. where as another might only show the necessary minimum.
Which approach would you take? Would you build and maintain a runable template shop with a functional superset of the shops. As new functionality is developed then merge the code with the other shops? Sounds a bit cumbersome.
In the example with the checkout page the views would differ from shop to shop, but the controllers and the models would remain the same, as long as you externalize configurations, like payment method types, and so on.
From this perspective it would make more sense just to create a repository of the views and configurations for each shop and then maintain model and controller code in a separate repository.
Would be possible to arrange the views according to shop, keeping all resources in one repositoary /views/shopname/Product. Would this make sense?
What do you think? how would you do this? Will working with rails in this way bring to much trouble?
Our campaign/discount system is growing steadily complex, both GUI and business logic. (in this view Rails seems interesting with its fast turnaround). Our discounts are property based and these properties are stored in a database row.
Making changes in the requirements to the workings of a discount is a real headache. So we are slowly replacing this property based system with a system that for each discount attaches a class (PHP) and a configuration so that each discount type has its own class and each utilization of such discount could specify some values for this class to operate on given current context (basically: what is in the basket)
In rails what approach would you take?
In rails you can easily extend your model (discount) with yet another property, migrate and you are ready (maybe a bit simplified). Could you write a base discount class that relied on a few basic properties and then write modules that hook into (extends) this class in case you need more advanced functionality?
Specifically what would this be in Rails terms a helper?
Some of this post might be a bit unclear. Please do ask questions. Also I'm in the process of learning Rails so please excuse me if don't use the right terms or if I've missed some of the main ideas of Rails.
Thanks
Michael
Is Rails (stack) suitable to run to
build a shop framework and how should
this be organized?
Sure, it can be suitable see:
http://www.shopify.com/
http://www.liquidmarkup.org/
I would not recommend it as a first project though.
Dont forget Spree Commerce as a viable solution that may or not suid your needs. On the other hand, if you want to roll your own solution, also check ActiveMerchant for payment gateway integration.

Where can I find a dead-simple explanation of MVC?

At my company we're about to build a new site using ASP.NET MVC. My boss (marketing guy) would like to know some more about the technology so I've tried to find a really good, simple and pedagogical presentation of the MVC concept without any luck. Most of them require quite a lot of basic knowledge in programming.
Any suggestions for a good video, slides or other?
Craig Strong has a pretty nice article about MVC in general and how to explain its benefits to business. Check it out here: Updated link.
Define MVC in layman’s terms
Remember you’re technically minded and close to the code. MVC to you
is as clear as day, but saying to the business ‘Model, View,
Contoller’ could give them the impression that you are suffering from
some form tourette syndrome. MVC won’t mean much to the business even
after you define them in relation to the code. To get the business to
understand why this is the answer and least of all what it is, can be
more of a task than expected in my experience. Even some fellow
developers have difficulty understanding this on occasion.
To get the listener to understand what MVC is and why it works what I
have tried in the pass is to apply MVC to a different industries where
the listeners have had more involvement. An example that has worked
for me in the past in a comparison to the property or even the
vehicles. Most people have had dealing’s with builders, carpenters,
plumbers, electricians or have watched the flood of property shows on
the TV. This experience is a good platform to use and to explain why
separation such as MVC works. I know you’re probably thinking that
won’t work as it’s not the same as in software, but remember you’re
not trying to train the business to become developers or have an in
depth understanding of MVC, simply explaining to them that separation
in production is required and that’s what an MVC structure offers.
To give an example of how you could describe this I have very briefly
explained how separation works in property. Keep in mind this is
focused on using the system not developing which could be a completely
different angle of explanation.
View
The view in MVC is the presentation layer. This is what the end user
of a product will see and interact with. A system can have multiple
views of all different types ranging from command line output to
rendered HTML. The view doesn’t consist of business logic in most
clear designs. The interface is fit for purpose and is the area of
interaction. Therefore you could simply output HTML for consumers to
interact with or output SOAP/XML for businesses to interact with. Both
use the same business logic behind the system otherwise known as the
models and controllers.
In the world of property you could think of the view as the interior
of a property or the outer layer of a property that the inhabitants
interact with. The interior can be customised for purpose and the same
property can have many different types of tenants. For example a
property of a particular design could contain residential dwellings.
The same internal space could easily be used as office space, where
although in the same property has a different purpose. However the
property structure is the same. Therefore the environment in which the
users interact does not interfere with the structure of the building.
Controllers
The controller is where the magic happens and defines the business
application logic. This could be where the user has sent a response
from the view, then this response is used to process the internal
workings of the request and processes the response back to the user.
Taking a typical response where a user has requested to buy a book.
The controller has the user id, payment details, shipping address and
item choice. These elements are then processed through the business
logic to complete a purchase. The data is passed through the system
into the model layer and eventually after the entire request satisfies
the business definitions, the order is constructed and the user
receives their item.
If we compare this to a property, we could compare the ordering of a
book online to turning on a light switch. A tenant will flick the
switch to on just like ordering a book. The switch itself is an
element in the view layer which sends the request to the controller
just like clicking a checkout button on a web site. The business logic
in this case is what the electrician installed and are embedded within
the property designs. The switch is flicked, which completes the
circuit. Electricity runs through all the wires including the fuse box
straight through to the light bulb. Just like the user receiving a
book, in this case the tenant receives light. The whole process behind
the scenes involving the electricity cabling is not visible to the the
tenant. They simply interact with the switch within the space and from
there the controller handles the request.
Models
The models in MVC are the bottom most layer and handle the core logic
of the system. In most cases this could be seen as the layer that
interacts with the data source. In systems using MVC, the controller
will pass information to the model in order to store and retrieve
data. Following on from the example above controller definition, this
is where the order details are stored. Additional data such as stock
levels, physical location of product of the book amongst many things
are all stored here. If that was the last book in stock ordered, the
next request for this item may check if it’s available and disallow
the order as the item is no longer available.
Sticking with our example of turning on a light switch, this level in
our structure could be the electricity supply. When the tenant flicks
the switch, the internal circuit must request electricity to power the
request which is similar when the user requested data from the
database, as in data is needed to process a request. If the dwelling
isn’t connected to an electric supply, it cannot complete the process.
Business benefits from using MVC
After you get the message across explaining what MVC is, you will then
have to see what benefits can be obtained from it. I’m not going to go
into a huge amount of detail here are I’m sure you can apply benefits
more accurately which are directly related to you actual situation. To
list just some of the common benefits of an MVC based system here are
a few examples:
Different skill levels can work on different system levels. For example designers can work on the interface (View) with very little
development knowledge and developers can work on the business logic
(Controller) with very little concern for the design level. Then they
simply integrate together on completion.
As a result of the above separation projects can be managed easier and quicker. The designer can start the interfaces before the
developer and vice versa. This development process can be parallel as
opposed to being sequential therefore reducing development time.
Easy to have multiple view types using the same business logic.
Clear route through the system. You clearly know where there different levels of the system are. With a clear route of the system,
logic can be shared and improved. This has added security benefits as
you clearly know the permitted route from the data to the user and can
have clear security checks along the route.
Each layer is responsible for itself. (Relates to point 1) This means that you can have clean file structure which can be maintained
and managed much easier and quicker than a tightly couple system where
you may have lots of duplicate logic.
Having a clear structure means development will be more transparent which should result in reduced development time,
maintenance problems and release cycles if applied properly.
M-V-C Think of it as:
"Order Details (including Customer & Employee info)", "HTML/ASP Form (to display the OrderDetails)" and "Order details service class (having methods to SaveOrderDetails, GetOrderDetails etc.).
The Model (Data Class e.g. OrderDetails)
The data you want to Display
The Controller (Service class)
Knows about the Model (Order Details)
Has methods to manage the Model
And as such can be unit tested Its Single Responsibility is to manage the OrderDetails CRUD operations.
It knows NOTHING about the View
The View (ASP Page)
Displays the Model (OrderDetail's ViewData).
It has to know about the Model's structure so it can correctly display the data to the users on screen.
The View's structure (style, layout, HTML etc., locale) can be changed at anytime without it changing anything in the application's functionality.
And as such, many Views can display the same Model in many different ways.
In multi-tenant web applications, Customer specific Views can be stored in a database table and displayed based on Customer information
You have to explain the benefits of ASP.NET MVC, not the features
You have control over your URLs -- that means SEO for the site will be better -- that means your site will be higher in google
The code is cleaner, which means that it's easier to change, which means that you can add features faster
etc.
How do you save money, make money, reduce risk? That's what your boss wants to know.
Imagine a control room in a factory, the model is the machine itself, the monitoring equipment is the view and the instrument panel is the controller. You could have several different control rooms for the same machine and changes in the controls in one control room would reflect on the monitors in all control rooms.
The point is that you should only model once and then view or control however is most convenient.
The model is the data access layer, which can just be a wrapper for a few simple queries to an ORM that manages the data entity relationships itself. It handles communication to the data source, retrieves data and usually organizes it into objects defined in your application.
The views are just html files with bits of html and css with some templating engine (smarty, mako, etc) code to display the data passed to it the way you want.
The controller puts it all together. Requests made to your page will be routed to a controller (class) and an action (method) within the controller. Just like any other application, the action will do what's requested of it, but it's still part of the controller.
So, the controller uses the model to query data (users, content, etc), then passes the data to a view to be rendered and displayed the way you want.
I wouldn't try to explain the technology to him, I'd try to explain what the MVC architectural principle is all about.
MVC was designed to separate concerns. Plain and simple. Explain to him that when you build anything that what you're building can be classified in two different categories: what the business need is (the domain), and everything else.
MVC separates the Domain from the everything else by introducing layers to separate out the concerns. M is for Model, which is your domain. V is for View, which is the visible part to him, what he sees. C is for Controller, the part that controls what is going on in between the Domain and the View.
The marketing guy would just be interested in the "V" part, the View. Depending on how you design things, the View would just be basic HTML/CSS "templates" that the marketing person could modify. Technically without breaking anything.
Ideally the Model (database) and Controller (logic) shouldn't care if the View (presentation) is XML, HTML, text, etc. The marketing person shouldn't care what the Model and Controller do, except for requesting additional functionality.
Going further with the "ideal", you should technically be able to replace ASP with PHP, Java, Ruby, etc as the Controller without touching the Model or View.
You can very easily do this, that is if you understand marking speak. I dont but I imagine it would go something like this...
This should be use. MVC (if done right) will allow you to decouple the UI from the data (model) and control of the UI (controler). This will allow the UI to be more flexible which will in turn allow to better market it self faster.
To a marketing guy, perhaps the best way to explain the reason for ASP.Net MVC is the ability to broaden your product's reach.
By using MVC, the code is already separated in a fashion that will let you more easily build an interface that feels natural on a desktop, and then the different interface that caters to a general mobile device user, and a still-slightly-different interface that caters to an iPhone user, without risking the backend code getting out of sync and introducing subtle and company-harming bugs. And, if there's a smart client desktop app that could be a product... it, too, can rest on the same codebase.
The Model is "how things work inside the box". The Controller is "what you can touch on the outside of the box" and the view is "what comes out of the box"...
The most important thing for your marketing guy is money, budget, TCO ...
When you don't use MVC you usually mix design, application logic etc. alltogether.
Programmer then must know html design, programming etc... That could mean you need powerful professional to do it all.
if you use MVC, everything is divided into "separate parts". Html coder can prepare html layer, programmer only works with application logic etc...
MVC brings better granularity and everybody can focus on what he or she can do the best!
Listen, for example xhtml validity and css cleanliness is so hard that there is a lot of people who focuses only on this while lot of browsers and platforms compatibility on mind.
Usually one person is NOT the best asp.net programmer, xhtml coder in one ;-)
This is a pretty simple one
http://en.wikipedia.org/wiki/Model-view-controller#Pattern_description
The best way I can thing of is that the model is the data representation, the view is the presentation to the user and the controller is what collects user interaction that changes the model.
The important word in the title of the manager in this case is "marketing." He is a Marketing manager. The concerns one has as a marketing manager have to do with strategy and tactics. These two are not the same thing. Strategy is the big picture word that embraces among other things how a company conceptually addresses customer needs and how the company differentiates itself from its competition. Strategy is typically not what software can portray to a user. Tactics, on the other hand, are the direct methods or approaches that a company takes in winning the business of the customer. Tactics tend to change far more frequently than strategies, and it is likely that the marketing manager, when he asks what advantage MVC may give him, is really asking, "How rapidly can you change whatever it is that you create into something that conforms to new realities in the way we have to deal with customers." In other words, how quickly can you change an offer of "buy 1 and get 1 free" into "buy 2 on Friday and get 1 on the following Tuesday if it is raining in Albany."
Marketing management is about results measured in dollars and cents, not finery and nuanced explanations that are littered with conceptual words lacking any real specificity. Everything a programmer may say might make sense to himself, but a marketing manager needs to know the real likelihood of rapid response to changing customer perceptions or rapid implementation to a different approach to selling to the same customers. He needs to know if it will cost more than an existing method because if he sells $1 million more in product while spending $1.25 million in software development, he will probably lose his job.
So, in short, he is looking for flexibility and cost-effectiveness. He needs software that be adapted to changing conditions quickly, just as he changes his pitch first one way and then another to a difficult-to-persuade prospective customer, and he needs to know that he won't have to be liable for a huge price tag for that flexibility.
Frankly, I don't think that you would be able to deliver on such promises if they were made because in spite of all the advantages of MVC from a development point of view, we are still talking about software here, and as we all know, software is a rigid, demanding taskmaster that takes it own sweet time to mature to the point of trustworthiness and to be rid of its bugs. We as programmers are always in search of the holy grail of software reusability, and while we flail about trying one thing and then another (MVC, MVP, MVVM, and whatever else someone may conceive), the rest of the world is simply asking for something that works. So the best of luck to you. I hope you are able to win your case.

Why all the Active Record hate? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
As I learn more and more about OOP, and start to implement various design patterns, I keep coming back to cases where people are hating on Active Record.
Often, people say that it doesn't scale well (citing Twitter as their prime example) -- but nobody actually explains why it doesn't scale well; and / or how to achieve the pros of AR without the cons (via a similar but different pattern?)
Hopefully this won't turn into a holy war about design patterns -- all I want to know is ****specifically**** what's wrong with Active Record.
If it doesn't scale well, why not?
What other problems does it have?
There's ActiveRecord the Design Pattern and ActiveRecord the Rails ORM Library, and there's also a ton of knock-offs for .NET, and other languages.
These are all different things. They mostly follow that design pattern, but extend and modify it in many different ways, so before anyone says "ActiveRecord Sucks" it needs to be qualified by saying "which ActiveRecord, there's heaps?"
I'm only familiar with Rails' ActiveRecord, I'll try address all the complaints which have been raised in context of using it.
#BlaM
The problem that I see with Active Records is, that it's always just about one table
Code:
class Person
belongs_to :company
end
people = Person.find(:all, :include => :company )
This generates SQL with LEFT JOIN companies on companies.id = person.company_id, and automatically generates associated Company objects so you can do people.first.company and it doesn't need to hit the database because the data is already present.
#pix0r
The inherent problem with Active Record is that database queries are automatically generated and executed to populate objects and modify database records
Code:
person = Person.find_by_sql("giant complicated sql query")
This is discouraged as it's ugly, but for the cases where you just plain and simply need to write raw SQL, it's easily done.
#Tim Sullivan
...and you select several instances of the model, you're basically doing a "select * from ..."
Code:
people = Person.find(:all, :select=>'name, id')
This will only select the name and ID columns from the database, all the other 'attributes' in the mapped objects will just be nil, unless you manually reload that object, and so on.
I have always found that ActiveRecord is good for quick CRUD-based applications where the Model is relatively flat (as in, not a lot of class hierarchies). However, for applications with complex OO hierarchies, a DataMapper is probably a better solution. While ActiveRecord assumes a 1:1 ratio between your tables and your data objects, that kind of relationship gets unwieldy with more complex domains. In his book on patterns, Martin Fowler points out that ActiveRecord tends to break down under conditions where your Model is fairly complex, and suggests a DataMapper as the alternative.
I have found this to be true in practice. In cases, where you have a lot inheritance in your domain, it is harder to map inheritance to your RDBMS than it is to map associations or composition.
The way I do it is to have "domain" objects that are accessed by your controllers via these DataMapper (or "service layer") classes. These do not directly mirror the database, but act as your OO representation for some real-world object. Say you have a User class in your domain, and need to have references to, or collections of other objects, already loaded when you retrieve that User object. The data may be coming from many different tables, and an ActiveRecord pattern can make it really hard.
Instead of loading the User object directly and accessing data using an ActiveRecord style API, your controller code retrieves a User object by calling the API of the UserMapper.getUser() method, for instance. It is that mapper that is responsible for loading any associated objects from their respective tables and returning the completed User "domain" object to the caller.
Essentially, you are just adding another layer of abstraction to make the code more managable. Whether your DataMapper classes contain raw custom SQL, or calls to a data abstraction layer API, or even access an ActiveRecord pattern themselves, doesn't really matter to the controller code that is receiving a nice, populated User object.
Anyway, that's how I do it.
I think there is a likely a very different set of reasons between why people are "hating" on ActiveRecord and what is "wrong" with it.
On the hating issue, there is a lot of venom towards anything Rails related. As far as what is wrong with it, it is likely that it is like all technology and there are situations where it is a good choice and situations where there are better choices. The situation where you don't get to take advantage of most of the features of Rails ActiveRecord, in my experience, is where the database is badly structured. If you are accessing data without primary keys, with things that violate first normal form, where there are lots of stored procedures required to access the data, you are better off using something that is more of just a SQL wrapper. If your database is relatively well structured, ActiveRecord lets you take advantage of that.
To add to the theme of replying to commenters who say things are hard in ActiveRecord with a code snippet rejoinder
#Sam McAfee Say you have a User class in your domain, and need to have references to, or collections of other objects, already loaded when you retrieve that User object. The data may be coming from many different tables, and an ActiveRecord pattern can make it really hard.
user = User.find(id, :include => ["posts", "comments"])
first_post = user.posts.first
first_comment = user.comments.first
By using the include option, ActiveRecord lets you override the default lazy-loading behavior.
My long and late answer, not even complete, but a good explanation WHY I hate this pattern, opinions and even some emotions:
1) short version: Active Record creates a "thin layer" of "strong binding" between the database and the application code. Which solves no logical, no whatever-problems, no problems at all. IMHO it does not provide ANY VALUE, except some syntactic sugar for the programmer (which may then use an "object syntax" to access some data, that exists in a relational database). The effort to create some comfort for the programmers should (IMHO...) better be invested in low level database access tools, e.g. some variations of simple, easy, plain hash_map get_record( string id_value, string table_name, string id_column_name="id" ) and similar methods (of course, the concepts and elegance greatly varies with the language used).
2) long version: In any database-driven projects where I had the "conceptual control" of things, I avoided AR, and it was good. I usually build a layered architecture (you sooner or later do divide your software in layers, at least in medium- to large-sized projects):
A1) the database itself, tables, relations, even some logic if the DBMS allows it (MySQL is also grown-up now)
A2) very often, there is more than a data store: file system (blobs in database are not always a good decision...), legacy systems (imagine yourself "how" they will be accessed, many varieties possible.. but thats not the point...)
B) database access layer (at this level, tool methods, helpers to easily access the data in the database are very welcome, but AR does not provide any value here, except some syntactic sugar)
C) application objects layer: "application objects" sometimes are simple rows of a table in the database, but most times they are compound objects anyway, and have some higher logic attached, so investing time in AR objects at this level is just plainly useless, a waste of precious coders time, because the "real value", the "higher logic" of those objects needs to be implemented on top of the AR objects, anyway - with and without AR! And, for example, why would you want to have an abstraction of "Log entry objects"? App logic code writes them, but should that have the ability to update or delete them? sounds silly, and App::Log("I am a log message") is some magnitudes easier to use than le=new LogEntry(); le.time=now(); le.text="I am a log message"; le.Insert();. And for example: using a "Log entry object" in the log view in your application will work for 100, 1000 or even 10000 log lines, but sooner or later you will have to optimize - and I bet in most cases, you will just use that small beautiful SQL SELECT statement in your app logic (which totally breaks the AR idea..), instead of wrapping that small statement in rigid fixed AR idea frames with lots of code wrapping and hiding it. The time you wasted with writing and/or building AR code could have been invested in a much more clever interface for reading lists of log-entries (many, many ways, the sky is the limit). Coders should dare to invent new abstractions to realize their application logic that fit the intended application, and not stupidly re-implement silly patterns, that sound good on first sight!
D) the application logic - implements the logic of interacting objects and creating, deleting and listing(!) of application logic objects (NO, those tasks should rarely be anchored in the application logic objects itself: does the sheet of paper on your desk tell you the names and locations of all other sheets in your office? forget "static" methods for listing objects, thats silly, a bad compromise created to make the human way of thinking fit into [some-not-all-AR-framework-like-]AR thinking)
E) the user interface - well, what I will write in the following lines is very, very, very subjective, but in my experience, projects that built on AR often neglected the UI part of an application - time was wasted on creation obscure abstractions. In the end such applications wasted a lot of coders time and feel like applications from coders for coders, tech-inclined inside and outside. The coders feel good (hard work finally done, everything finished and correct, according to the concept on paper...), and the customers "just have to learn that it needs to be like that", because thats "professional".. ok, sorry, I digress ;-)
Well, admittedly, this all is subjective, but its my experience (Ruby on Rails excluded, it may be different, and I have zero practical experience with that approach).
In paid projects, I often heard the demand to start with creating some "active record" objects as a building block for the higher level application logic. In my experience, this conspicuously often was some kind of excuse for that the customer (a software dev company in most cases) did not have a good concept, a big view, an overview of what the product should finally be. Those customers think in rigid frames ("in the project ten years ago it worked well.."), they may flesh out entities, they may define entities relations, they may break down data relations and define basic application logic, but then they stop and hand it over to you, and think thats all you need... they often lack a complete concept of application logic, user interface, usability and so on and so on... they lack the big view and they lack love for the details, and they want you to follow that AR way of things, because.. well, why, it worked in that project years ago, it keeps people busy and silent? I don't know. But the "details" separate the men from the boys, or .. how was the original advertisement slogan ? ;-)
After many years (ten years of active development experience), whenever a customer mentions an "active record pattern", my alarm bell rings. I learned to try to get them back to that essential conceptional phase, let them think twice, try them to show their conceptional weaknesses or just avoid them at all if they are undiscerning (in the end, you know, a customer that does not yet know what it wants, maybe even thinks it knows but doesn't, or tries to externalize concept work to ME for free, costs me many precious hours, days, weeks and months of my time, live is too short ... ).
So, finally: THIS ALL is why I hate that silly "active record pattern", and I do and will avoid it whenever possible.
EDIT: I would even call this a No-Pattern. It does not solve any problem (patterns are not meant to create syntactic sugar). It creates many problems: the root of all its problems (mentioned in many answers here..) is, that it just hides the good old well-developed and powerful SQL behind an interface that is by the patterns definition extremely limited.
This pattern replaces flexibility with syntactic sugar!
Think about it, which problem does AR solve for you?
Some messages are getting me confused.
Some answers are going to "ORM" vs "SQL" or something like that.
The fact is that AR is just a simplification programming pattern where you take advantage of your domain objects to write there database access code.
These objects usually have business attributes (properties of the bean) and some behaviour (methods that usually work on these properties).
The AR just says "add some methods to these domain objects" to database related tasks.
And I have to say, from my opinion and experience, that I do not like the pattern.
At first sight it can sound pretty good. Some modern Java tools like Spring Roo uses this pattern.
For me, the real problem is just with OOP concern. AR pattern forces you in some way to add a dependency from your object to infraestructure objects. These infraestructure objects let the domain object to query the database through the methods suggested by AR.
I have always said that two layers are key to the success of a project. The service layer (where the bussiness logic resides or can be exported through some kind of remoting technology, as Web Services, for example) and the domain layer. In my opinion, if we add some dependencies (not really needed) to the domain layer objects for resolving the AR pattern, our domain objects will be harder to share with other layers or (rare) external applications.
Spring Roo implementation of AR is interesting, because it does not rely on the object itself, but in some AspectJ files. But if later you do not want to work with Roo and have to refactor the project, the AR methods will be implemented directly in your domain objects.
Another point of view. Imagine we do not use a Relational Database to store our objects. Imagine the application stores our domain objects in a NoSQL Database or just in XML files, for example. Would we implement the methods that do these tasks in our domain objects? I do not think so (for example, in the case of XM, we would add XML related dependencies to our domain objects...Truly sad I think). Why then do we have to implement the relational DB methods in the domain objects, as the Ar pattern says?
To sum up, the AR pattern can sound simpler and good for small and simple applications. But, when we have complex and large apps, I think the classical layered architecture is a better approach.
The question is about the Active
Record design pattern. Not an orm
Tool.
The original question is tagged with rails and refers to Twitter which is built in Ruby on Rails. The ActiveRecord framework within Rails is an implementation of Fowler's Active Record design pattern.
The main thing that I've seen with regards to complaints about Active Record is that when you create a model around a table, and you select several instances of the model, you're basically doing a "select * from ...". This is fine for editing a record or displaying a record, but if you want to, say, display a list of the cities for all the contacts in your database, you could do "select City from ..." and only get the cities. Doing this with Active Record would require that you're selecting all the columns, but only using City.
Of course, varying implementations will handle this differently. Nevertheless, it's one issue.
Now, you can get around this by creating a new model for the specific thing you're trying to do, but some people would argue that it's more effort than the benefit.
Me, I dig Active Record. :-)
HTH
Although all the other comments regarding SQL optimization are certainly valid, my main complaint with the active record pattern is that it usually leads to impedance mismatch. I like keeping my domain clean and properly encapsulated, which the active record pattern usually destroys all hope of doing.
I love the way SubSonic does the one column only thing.
Either
DataBaseTable.GetList(DataBaseTable.Columns.ColumnYouWant)
, or:
Query q = DataBaseTable.CreateQuery()
.WHERE(DataBaseTable.Columns.ColumnToFilterOn,value);
q.SelectList = DataBaseTable.Columns.ColumnYouWant;
q.Load();
But Linq is still king when it comes to lazy loading.
#BlaM:
Sometimes I justed implemented an active record for a result of a join. Doesn't always have to be the relation Table <--> Active Record. Why not "Result of a Join statement" <--> Active Record ?
I'm going to talk about Active Record as a design pattern, I haven't seen ROR.
Some developers hate Active Record, because they read smart books about writing clean and neat code, and these books states that active record violates single resposobility principle, violates DDD rule that domain object should be persistant ignorant, and many other rules from these kind of books.
The second thing domain objects in Active Record tend to be 1-to-1 with database, that may be considered a limitation in some kind of systems (n-tier mostly).
Thats just abstract things, i haven't seen ruby on rails actual implementation of this pattern.
The problem that I see with Active Records is, that it's always just about one table. That's okay, as long as you really work with just that one table, but when you work with data in most cases you'll have some kind of join somewhere.
Yes, join usually is worse than no join at all when it comes to performance, but join usually is better than "fake" join by first reading the whole table A and then using the gained information to read and filter table B.
The problem with ActiveRecord is that the queries it automatically generates for you can cause performance problems.
You end up doing some unintuitive tricks to optimize the queries that leave you wondering if it would have been more time effective to write the query by hand in the first place.
Try doing a many to many polymorphic relationship. Not so easy. Especially when you aren't using STI.

Resources