ActiveRecord y AdequateRecord

45 views
Skip to first unread message

Pablo Astigarraga

unread,
Apr 15, 2014, 3:11:45 PM4/15/14
to rub...@googlegroups.com
Hoy me puse a leer un articulo de Aaron Patterson (@tenderlove , rails y ruby core) sobre cambios que esta haciendo sobre ActiveRecord para hacer algunos usos mas rápido (#find, #find_by, y #find_by_xxx), medio en serio y medio en joda lo llama "AdequateRecord".

Mi pregunta viene más por el lado general de ActiveRecord que de esto en particular, pero leer el artículo me hizo pensar en eso no más. :)

Más allá de preferencias a nivel de gustos - yo por ejemplo prefiero usar Sequel u Ohm si tengo elección: cuales son los problemas de diseño que tiene Active Record? Todo el mundo menciona esto re seguido pero nunca me han dado ejemplos concretos, tengo claro que me parece que trata de hacer demasiado y el codebase tiene una complejidad importante pero no cuales son los problemas concretos by design que la gente le ve.

Opiniones?

Joaquín Vicente

unread,
Apr 15, 2014, 5:07:44 PM4/15/14
to rub...@googlegroups.com
Uno de las críticas que se le hace al patrón ActiveRecord (o al menos a como se lo usa en el 99% de los casos con Rails) es que mezcla en un mismo objeto la lógica de negocios y la persistencia.
Eso tiene dos problemas:
1) Las clases tienden a ser más complejas, porque tienen dos responsabilidades (logica y persistencia)
2) El modelo está atado a la BD y a la hora de testear esto implica o tests lentos, o tests que requieren muchos mocks y stubs.

Ambos problemas se pueden resolver usando POROs y una capa de servicio que se encague de la persistencia, pero The Rails Way™ tiende a meter la lógica dentro de ActiveRecord


--
Has recibido este mensaje porque estás suscrito al grupo "rubysur" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a rubysur+u...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Guillermo Iguaran

unread,
Apr 15, 2014, 6:03:16 PM4/15/14
to rub...@googlegroups.com
ActiveRecord (la librería) esta hecha para usarse precisamente como lo sugiere Active Record (el patrón) metiendo lógica y persistencia en un mismo objeto, así que creo que en ese caso estaríamos hablando de "The Active Record Way"

De todas formas creo que Pablo se refiere a los problemas de diseño de ActiveRecord la librería, no del patrón o de como lo usan los usuarios.

Guillermo Iguaran

unread,
Apr 15, 2014, 6:32:40 PM4/15/14
to rub...@googlegroups.com
Una critica que se hace frecuentemente es la cantidad de objetos que se deben instanciar cada vez que se crea una nueva instancia de un objeto de ActiveRecord[1] (tanto al crear un nuevo registro como al instanciar usando info existente en la BD) y es esto una de las cosas que se mejora dramáticamente con “AdequateRecord” donde Patterson ha logrado reducir significativamente el numero de objetos instanciados cuando se usan los #find y los ha llevado a números menores a los que tenia Rails 2.3 y 3.0[2]



Juan Manuel Costello

unread,
Apr 16, 2014, 8:27:49 AM4/16/14
to rub...@googlegroups.com
Joaquin, como usas POROs en tu clases de entidades? No pude encontrar ninguna gema copada para hacer un mapeo de clases contra la base de datos. Alguna idea simple, elegante y copada? 


--

geronimo diaz

unread,
Apr 16, 2014, 9:15:44 AM4/16/14
to rub...@googlegroups.com
2014-04-16 9:27 GMT-03:00 Juan Manuel Costello <sudo...@gmail.com>:
Joaquin, como usas POROs en tu clases de entidades? No pude encontrar ninguna gema copada para hacer un mapeo de clases contra la base de datos. Alguna idea simple, elegante y copada? 


Juan, steve klabnik muestra un poco de POROs en este post http://blog.steveklabnik.com/posts/2011-09-06-the-secret-to-rails-oo-design quizas te sirva de guia.

Saludos.
 

Michel Martens

unread,
Apr 16, 2014, 10:12:10 AM4/16/14
to rub...@googlegroups.com
No leí todo el código de activerecord, pero por lo que veo intenta
solucionar muchos problemas distintos y lo resuelve con código de mala
calidad y mal estilo. Por ejemplo, miren este archivo:

https://github.com/rails/rails/blob/v4.1.0.rc2/activerecord/lib/active_record.rb

Si pensamos en que las clases tienen que tener una responsabilidad, no
es evidente qué responsabilidad tienen estas dos:

autoload :Base
autoload :Core

También es raro esto:

autoload :Migration
autoload :Migrator, 'active_record/migration'
autoload :ModelSchema
autoload :Schema
autoload :SchemaDumper
autoload :SchemaMigration

Son seis clases que tienen responsabilidades similares y algunas
incluso son interdependientes. Si hubiera un librería sólo para
modificar el schema de una base de datos, la complejidad sería menor.
De ese estilo hay varios grupos de clases que se pueden distinguir, y
que cada uno de esos grupos podría ser una herramienta genérica.

Por otro lado, el autoload, eager_autoload, eager_load, on_load y
similares son indirecciones innecesarias y costosas.

Esto también me llama la atención:

autoload :DatabaseTasks
autoload :SQLiteDatabaseTasks, 'active_record/tasks/sqlite_database_tasks'
autoload :MySQLDatabaseTasks, 'active_record/tasks/mysql_database_tasks'
autoload :PostgreSQLDatabaseTasks,
'active_record/tasks/postgresql_database_tasks'

Me parece raro que una librería incluya rake tasks, sobre todo cuando
se propone como agnóstica con respecto a la base de datos.

Con todo esto, activerecord tiene 17108 líneas de código sin contar
las dependencias. Las dependencias son activesupport, activemodel y
arel. Así se describe activemodel:

"Active Model provides a known set of interfaces for usage in model classes.
They allow for Action Pack helpers to interact with non-Active
Record models,
for example. Active Model also helps with building custom ORMs for
use outside of
the Rails framework."

Entonces es raro que activerecord dependa de activemodel.

Y la descripción de arel:

Arel Really Exasperates Logicians

Arel is a SQL AST manager for Ruby. It

1. Simplifies the generation of complex SQL queries
2. Adapts to various RDBMSes

It is intended to be a framework framework; that is, you can build
your own ORM
with it, focusing on innovative object and collection modeling as opposed to
database compatibility and query generation.

La idea de arel está bien, pero parece medio ineficiente que tenga
3184 líneas de código. Pero creo que peor que esas 3184 líneas de
código es el hecho de que activerecord tiene 17108 y ni siquiera se
encarga de lo que hace arel. Entonces activerecord no tiene lo que
hace activemodel ni lo que hace arel, y es database agnostic, entonces
tampoco debería tener código específico de cada base de datos. Por eso
me parece que 17108 líneas de código es demasiado, y las
responsabilidades que asume son muy diversas (validaciones,
migraciones, callbacks, locks, caching, etc.).

No sé cuántas líneas de código debería tener, pero si Ohm tiene 605 y
Scrivener, lo que uso para validaciones, tiene 90, me imagino que
ActiveRecord + Arel + ActiveModel no deberían superar las 1700 líneas
de código en total.

Francesco Rodríguez

unread,
Apr 16, 2014, 10:40:28 AM4/16/14
to rub...@googlegroups.com
Lo primero que me gustó de Sequel es su sistema de plugins. Con ActiveRecord viene
todo junto, como si todo los modelos necesitaran manejar passwords, validaciones, STI,
etc.

e.g.:


Francesco.

--
Has recibido este mensaje porque estás suscrito al grupo "rubysur" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a rubysur+u...@googlegroups.com.
Para obtener más opciones, visita https://groups.google.com/d/optout.

Juan Manuel Costello

unread,
Apr 16, 2014, 10:43:38 AM4/16/14
to rub...@googlegroups.com
Geronimo, ese articulo en realidad no me sirvio. Lo que trato de encontrar es una forma de hacer que mis entidades de negocio sean POROs. Osea que no herede de ninguna clase y pueda mapearla de alguna forma contra algun metodo de persistencia.


Para acceder a más opciones, visita https://groups.google.com/d/optout.

Francesco Rodríguez

unread,
Apr 16, 2014, 10:48:58 AM4/16/14
to rub...@googlegroups.com
No sabía que se podía hacer:

> User.benchmark {
>   User.first
> }
=> Benchmarking (52.2ms)

bastante útil.

Francesco

Sebastian Moreno

unread,
Apr 16, 2014, 11:20:31 AM4/16/14
to rub...@googlegroups.com
Juan Manuel Costello

Creo que estás hijackeando el thread de pote, tu pregunta no tiene nada que ver con la inicial,
y al menos a mi me está metiendo ruido.

Seguramente da para otro thread, diciendo que la pregunta surgió a partir de este. :-)

Saludos
Seba


~s

Juan Manuel Costello

unread,
Apr 16, 2014, 11:30:35 AM4/16/14
to rub...@googlegroups.com
Perdon, no fue mi cometido. Solo preguntaba ya que mencinaron el uso de POROs contra ActiveRecord.

Hernan Fernandez

unread,
Apr 16, 2014, 12:06:04 PM4/16/14
to rub...@googlegroups.com
Hola
Me parece injusta la comparación de Ohm con ActiveRecord, las
características, scope y funcionalidad los hacen para mi
incomparables, menos para medir por lineas de código.
Que AR tiene Technical Debt, seguro, pero cada tanto aparece alguien
que da un paso adelante y soluciona o mejora una parte, podes
solucionar sin dificultades el 80% de los problemas que se presentan.

Hernan

Michel Martens

unread,
Apr 16, 2014, 12:45:33 PM4/16/14
to rub...@googlegroups.com
2014-04-16 13:06 GMT-03:00 Hernan Fernandez <hern...@gmail.com>:
> Me parece injusta la comparación de Ohm con ActiveRecord, las
> características, scope y funcionalidad los hacen para mi
> incomparables, menos para medir por lineas de código.
> Que AR tiene Technical Debt, seguro, pero cada tanto aparece alguien
> que da un paso adelante y soluciona o mejora una parte, podes
> solucionar sin dificultades el 80% de los problemas que se presentan.

Es una estimación nomás. Calculé que con casi el triple de líneas de
código de Ohm + Scrivener se puede solucionar el problema de tener un
modelo que persista en una base de datos con SQL y que tenga
validaciones. De todas formas no entiendo por qué te parece injusta la
comparación.

Ruby se caracteriza por ser un lenguaje de muy alto nivel y muy
expresivo. Veinte mil líneas de código en Ruby pueden expresar
muchísima información. Bases de datos como LevelDB o LMDB, que están
escritas en C, tienen menos código que ActiveRecord (18016 y 7897
líneas de código respectivamente). El código fuente de Lua también
está en C y son 14553 líneas de código. En comparación, el código
fuente de Ruby debe andar por el millón de líneas de código. Ese
millón de líneas de código justifica el alto nivel y la expresividad,
por eso tener una librería como ActiveRecord con 20K líneas de código
es ridículo.

Bruno Aguirre

unread,
Apr 16, 2014, 12:53:28 PM4/16/14
to rub...@googlegroups.com
Voy a hacerme una remera con esa respuesta

Hernan Fernandez

unread,
Apr 16, 2014, 2:54:47 PM4/16/14
to rub...@googlegroups.com
> --
> Has recibido este mensaje porque estás suscrito al grupo "rubysur" de Grupos de Google.
> Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a rubysur+u...@googlegroups.com.
> Para obtener más opciones, visita https://groups.google.com/d/optout.


Ohm -> Object-hash mapping library for Redis.

ActiveRecord -> Active Record is the M in MVC - the model - which is
the layer of the system responsible for representing business data and
logic. Active Record facilitates the creation and use of business
objects whose data requires persistent storage to a database. It is an
implementation of the Active Record pattern which itself is a
description of an Object Relational Mapping system.

Mi cuestionamiento va por el lado de Ohm persiste contra redis
solamente, AR persiste contra cualquier adaptador que se haga,
transacciones, migraciones, herencia, etc. Decía que el scope,
funcionalidad, características no son las mismas, compararlo por
líneas de código no me parece justo.



Hernan

Michel Martens

unread,
Apr 16, 2014, 3:44:59 PM4/16/14
to rub...@googlegroups.com
2014-04-16 15:54 GMT-03:00 Hernan Fernandez <hern...@gmail.com>:
> Mi cuestionamiento va por el lado de Ohm persiste contra redis
> solamente, AR persiste contra cualquier adaptador que se haga,
> transacciones, migraciones, herencia, etc. Decía que el scope,
> funcionalidad, características no son las mismas, compararlo por
> líneas de código no me parece justo.

Antes de que saliera Rails yo usaba una librería para hacer algo
parecido a lo que hace ActiveRecord, que es eso que describiste.
Funcionaba sólo con MySQL y no tenía migraciones, y tiene 451 líneas
de código bastante feo. La versión 1.0.0 de activerecord tampoco tenía
migraciones, pero por lo demás debería ser comparable con la versión
4, y tiene 3653 líneas de código.

En mi caso, en algún momento tuve que trabajar con ActiveRecord, luego
con Sequel, y luego con Ohm. Digo que son comparables porque pude
reemplazar por completo uno por otro, pero por supuesto que cada uno
tiene distintos modos de atacar el problema.

Entonces no pretendo comparar Ohm con ActiveRecord en cuanto a lo que
abarca, y por eso tripliqué la cantidad de líneas de código en la
estimación. Y ahora menciono la versión 1.0.0 y de paso otra librería
similar para ver si te parecen comparables. La otra es pensar que
activerecord 4 es sólo comparable con sí mismo, pero no nos sirve para
nada.
Reply all
Reply to author
Forward
0 new messages