103 votes

Pourquoi toute la haine Active Record?

Comme j'en apprendre plus et plus sur la programmation orientée objet, et de commencer à mettre en œuvre les différents modèles de conception, je reviens à des cas où les gens sont à la haine sur Active Record.

Souvent, les gens disent qu'il n'est pas à l'échelle (en citant Twitter comme leur premier exemple), mais personne n'explique d'ailleurs pourquoi il n'a pas d'échelle; et / ou la façon d'atteindre les avantages de l'AR sans les inconvénients (via un similaire, mais différent modèle?)

Nous espérons que cela ne se transforme pas en une guerre sainte sur les modèles de conception -- tout ce que je veux savoir, c'est **** quel est le problème avec Active Record.

Si ce n'est pas à l'échelle, pourquoi pas?

Quels sont les autres problèmes?

90voto

Orion Edwards Points 54939

Il y a ActiveRecord le Modèle de Conception et de ActiveRecord les Rails de l'ORM de la Bibliothèque, et il y a aussi une tonne de knock-offs .NET, et d'autres langues.

Ce sont toutes des choses différentes. Ils ont surtout suivre ce modèle de conception, mais de les étendre et de modifier de plusieurs façons différentes, donc avant que quelqu'un dit "ActiveRecord Suce" il doit être qualifié en disant: "qui ActiveRecord, il ya des tas?"

Je ne suis familier avec les Rails' ActiveRecord, je vais essayer de répondre à toutes les plaintes qui ont été soulevées dans le contexte de l'utiliser.

@BlaM

Le problème que je vois avec les Enregistrements Actifs, c'est qu'elle est toujours juste sur une table

Code:

class Person
    belongs_to :company
end
people = Person.find(:all, :include => :company )

Cela génère le SQL avec LEFT JOIN companies on companies.id = person.company_id, et de générer automatiquement des associés de la Société les objets de sorte que vous pouvez le faire people.first.company et il n'a pas besoin de toucher la base de données, car les données sont déjà présentes.

@pix0r

Le problème inhérent avec Active Record est que les requêtes de base de données sont automatiquement généré et exécuté pour remplir des objets et modifier des enregistrements de base de données

Code:

person = Person.find_by_sql("giant complicated sql query")

C'est pas recommandée, car elle est moche, mais pour le cas où vous avez simplement besoin d'écrire du SQL brut, c'est facile à faire.

@Tim Sullivan

...et vous sélectionnez plusieurs instances du modèle, vous êtes essentiellement faire un "select * from ..."

Code:

people = Person.find(:all, :select=>'name, id')

Cela permettra de sélectionner uniquement le nom et l'ID de la base de données, tous les autres attributs "' dans le mappé objets sera juste nul, à moins que vous recharger manuellement cet objet, et ainsi de suite.

51voto

Sam McAfee Points 4615

J'ai toujours trouvé que ActiveRecord est bon pour rapide CRUD applications en fonction de l'endroit où le Modèle est relativement plat (comme dans, pas beaucoup de hiérarchies de classes). Cependant, pour les applications complexes OO hiérarchies, d'une DataMapper est sans doute une meilleure solution. Alors que ActiveRecord suppose un rapport de 1:1 entre vos tables et vos objets de données, ce genre de relation devient difficile à manier avec la plus complexe des domaines. Dans son livre sur les modèles, Martin Fowler souligne que ActiveRecord tend à se décomposer dans des conditions où votre Modèle est assez complexe, et suggère un DataMapper comme alternative.

J'ai trouvé que cela soit vrai dans la pratique. Dans le cas où vous avez beaucoup de l'héritage dans votre domaine, il est plus difficile de carte de l'héritage à votre SGBDR que c'est la carte d'associations ou de composition.

La façon dont je le fais, c'est de "domaine" des objets qui sont accessibles par votre contrôleurs via ces DataMapper (ou "couche de service") des classes. Ces ne sont pas directement en miroir de la base de données, mais d'agir comme votre OO représentation pour certains objet du monde réel. Disons que vous avez une classe d'Utilisateur dans votre domaine, et le besoin d'avoir des références ou des collections d'autres objets, déjà chargé lorsque vous récupérer cet objet Utilisateur. Les données peuvent provenir de plusieurs tables différentes, et une ActiveRecord modèle peut faire, il est vraiment difficile.

Au lieu de charger l'Utilisateur de l'objet directement et l'accès aux données à l'aide d'un ActiveRecord API de style, votre code de contrôleur récupère un objet Utilisateur en appelant l'API de la UserMapper.getUser() la méthode, par exemple. C'est que mappeur qui est responsable du chargement de tous les objets associés à partir de leurs tables respectives et de le retourner Utilisateur "domaine" de l'objet à l'appelant.

Essentiellement, vous êtes juste en ajoutant une autre couche d'abstraction pour rendre le code plus gérable. Si votre DataMapper classes contiennent des SQL personnalisée, ou les appels à une couche d'abstraction de données de l'API, ou encore accéder à un ActiveRecord motif d'eux-mêmes, n'a pas vraiment d'importance pour le code du contrôleur qui reçoit nice, peuplée de l'Utilisateur de l'objet.

De toute façon, c'est comment je le fais.

11voto

MattMcKnight Points 4736

Je pense qu'il y a probablement un ensemble très différent de motifs entre pourquoi les gens sont "haïr" sur ActiveRecord et ce qui est "mauvais".

Sur le haïr problème, il y a beaucoup de venin vers quelque chose de Rails liés. Aussi loin que ce qui est mal avec elle, il est probable que c'est comme toutes les technologies, et il y a des situations où c'est un bon choix et des situations où il y a de meilleurs choix. La situation où vous n'obtenez pas de profiter de la plupart des fonctionnalités de Rails ActiveRecord, dans mon expérience, est l'endroit où la base de données est mal structuré. Si vous accédez à des données sans les clés primaires, avec des choses qui violent la première forme normale, où il ya beaucoup de procédures stockées requis pour accéder aux données, vous êtes mieux d'utiliser quelque chose qui est plus seulement un SQL wrapper. Si votre base de données est relativement bien structuré, ActiveRecord vous permet de profiter de cela.

Pour ajouter à la thématique de répondre à des commentateurs qui disent que les choses sont difficiles dans ActiveRecord avec un fragment de code duplique

@Sam McAfee Dire que vous avez une classe d'Utilisateur dans votre domaine, et le besoin d'avoir des références ou des collections d'autres objets, déjà chargé lorsque vous récupérer cet objet Utilisateur. Les données peuvent provenir de plusieurs tables différentes, et une ActiveRecord modèle peut faire, il est vraiment difficile.

user = User.find(id, :include => ["posts", "comments"])
first_post = user.posts.first
first_comment = user.comments.first

En utilisant l'option inclure, ActiveRecord vous permet de remplacer la valeur par défaut de lazy-loading comportement.

7voto

Frunsi Points 4550

Mon long et en fin de réponse, même pas complète, mais une bonne explication POURQUOI je déteste ce modèle, les opinions et même de certaines émotions:

1) version courte: Active Record crée une "couche mince" de "la forte liaison" entre la base de données et le code de l'application. Qui résout pas logique, n'importe quoi-des problèmes, pas de problèmes à tous. À mon humble avis il ne fournit pas de VALEUR, à l'exception de certaines sucre syntaxique pour le programmeur (qui peut alors utiliser un objet "syntaxe" pour accéder à certaines données, qui existe dans une base de données relationnelle). L'effort de créer de confort pour les programmeurs devrait (à mon humble avis...) mieux être investi dans des bas au niveau de la base de données, les outils d'accès, par exemple, certaines variations de simple, facile, simple hash_map get_record( string id_value, string table_name, string id_column_name="id" ) et des méthodes similaires (bien sûr, les concepts et l'élégance varie fortement avec la langue utilisée).

2) version longue: Dans une base de données des projets menés par où j'ai eu le "conceptuel de contrôle" des choses, j'ai évité AR, et c'était bon. J'ai l'habitude de construire une architecture en couches (vous tôt ou tard, ne divisez votre logiciel dans les couches, au moins dans un milieu à de grands projets de taille):

A1) la base de données, tables, relations, même une certaine logique si le SGBD permet (MySQL est également cultivé maintenant)

A2) très souvent, il n'est plus qu'un magasin de données: système de fichiers (blob dans la base de données ne sont pas toujours une bonne décision...), les systèmes existants (imaginez-vous "comment" ils seront accessibles, beaucoup de variétés possible.. mais ce n'est pas le point...)

B) l'accès à la base de la couche (à ce niveau, les méthodes de l'outil, des aides pour faciliter l'accès aux données dans la base de données sont les bienvenus, mais AR ne fournit pas de valeur ici, à l'exception de certaines sucre syntaxique)

C) les objets de l'application de la couche: "les objets de l'application" sont parfois de simples lignes d'une table dans la base de données, mais la plupart du temps ils sont composés d'objets de toute façon, et avoir un peu plus de logique attaché, donc, d'investir du temps dans l'AR objets à ce niveau est simplement inutile, du gaspillage des codeurs de temps, parce que la "valeur réelle", le "plus logique" de ces objets doit être mis en œuvre sur le dessus de l'AR objets, de toute façon, avec ou sans AR! Et, par exemple, pourquoi voudriez-vous d'avoir une abstraction de "l'entrée de Journal des objets"? La logique d'application du code écrit mais qui ont la capacité de mettre à jour ou les supprimer? semble stupide, et App::Log("I am a log message") est certaines grandeurs plus facile à utiliser que le=new LogEntry(); le.time=now(); le.text="I am a log message"; le.Insert();. Et pour exemple: à l'aide d'un "Journal de l'entrée de l'objet" dans l'affichage de l'historique de votre demande de travail pour 100, 1000 ou même 10000 lignes de log, mais tôt ou tard, vous aurez à optimiser - et je parie que dans la plupart des cas, vous utilisez cette belle petite instruction SQL SELECT dans votre application logique (qui rompt totalement l'AR idée..), au lieu d'envelopper cette petite phrase en rigide fixe AR idée cadres avec beaucoup de code d'emballage et de le cacher. Le temps que vous avez perdu avec l'écriture et/ou de construction d'AR code aurait pu être investi dans une beaucoup plus intelligent de l'interface pour la lecture des listes des entrées de l' (beaucoup, beaucoup de manières, le ciel est la limite). Les codeurs doivent oser inventer de nouvelles abstractions pour réaliser leur application logique que l'ajustement à la demande, et pas bêtement ré-implémenter idiot modèles, que du bon son, à première vue!

D) l'application de la logique - met en œuvre la logique de l'interaction des objets et de création, de suppression et d'inscription(!) de la logique de l'application des objets (NON, ces tâches doivent rarement être ancré dans la logique de l'application des objets de lui-même: la feuille de papier sur votre bureau vous dire les noms et emplacements de tous les autres feuilles dans votre bureau? oublier "statique" méthodes pour la liste des objets, c'est idiot, un mauvais compromis créé pour faire de la façon humaine de penser ajustement dans [certains-pas-tous-AR-cadre-comme-]AR la pensée)

E) l'interface utilisateur - eh bien, ce que je vais écrire dans les lignes qui suivent est très, très, très subjective, mais dans mon expérience, les projets qui s'appuient sur les AR souvent négligé la partie de l'INTERFACE utilisateur d'une application - temps a été perdu sur la création d'un obscur des abstractions. En fin de compte ces demandes perdu beaucoup de codeurs temps et se sentir comme les applications des programmeurs pour des programmeurs, les tech-inclinée à l'intérieur et à l'extérieur. Les codeurs se sentir bien (dur travail fini, tout est fini et correcte selon le concept sur le papier...), et les clients "juste pour apprendre que ça doit être comme ça", parce que c'est "professionnel".. ok, désolé, je m'égare ;-)

Eh bien, il est vrai, tout cela est subjectif, mais ses mon expérience (Ruby on Rails exclu, il peut être différent, et je n'ai aucune expérience pratique de cette approche).

Dans les projets rémunérés, j'ai souvent entendu la demande de commencer avec la création de quelques "active record" des objets comme un bloc de construction pour le plus haut niveau de la logique d'application. Dans mon expérience, ce ostensiblement souvent était une sorte de prétexte pour que le client (un logiciel de dev de l'entreprise dans la plupart des cas) n'ont pas un bon concept, un grand écran, un aperçu de ce que le produit devrait être finalement. Les clients pensent dans des supports rigides ("dans le projet il y a dix ans ça a bien fonctionné.."), ils peuvent chair entités, ils peuvent définir des entités relations, ils peuvent se décomposer de données de relations et de définir de base de la logique de l'application, mais ensuite, ils ont arrêter et de le remettre à vous, et pense que c'est tout ce dont vous avez besoin... il leur manque souvent un concept complet de la logique de l'application, interface utilisateur, la facilité d'utilisation et ainsi de suite et ainsi de suite... il manque le grand écran et ils manquent d'amour pour les détails, et ils veulent que vous suivez que l'AR sorte de choses, parce que.. eh bien, pourquoi, il a travaillé dans ce projet il y a des années, il garde les personnes occupées et le silence? Je ne sais pas. Mais les "détails" de séparer les hommes et les garçons, ou .. comment a été l'annonce d'origine slogan ? ;-)

Après de nombreuses années (dix ans d'expérience de développement), à chaque fois qu'un client fait mention d'un "modèle d'enregistrement active", mon réveil sonne. J'ai appris à essayer de les faire revenir à ce qui est indispensable conceptionnelle phase, laissez-les réfléchir à deux fois, essayez de montrer leur conceptionnelle faiblesses ou tout simplement les éviter à tout si elles sont undiscerning (à la fin, vous le savez, un client qui ne sait pas encore ce qu'il veut, peut-être même qu'il en sait, mais ne veut pas, ou tente d'externaliser les travaux de concept pour MOI gratuitement, me coûte beaucoup de précieuses heures, des jours, des semaines et des mois de mon temps, vivre c'est trop court ... ).

Donc, finalement: TOUT CELA est pourquoi je déteste ce stupide "active record "modèle", et je ne et éviter autant que possible.

EDIT: je dirais même appeler cela un Pas de Modèle. Il ne résout aucun problème (les modèles ne sont pas destinés à créer sucre syntaxique). Il crée de nombreux problèmes: la racine de tous ses problèmes (mentionné dans beaucoup de réponses ici..), qu' il vient se cache le bon vieux bien développé et puissant SQL derrière une interface qui est par les modèles de la définition extrêmement limitée.

Ce modèle remplace la flexibilité avec le sucre syntaxique!

Pensez à ce sujet, le problème n'AR résoudre pour vous?

5voto

Juanjo Points 41

Certains messages sont l'obtention de me confondre. Certaines réponses sont en train de "ORM" vs "SQL" ou quelque chose comme ça.

Le fait est que l'AR est juste une simplification de la programmation modèle où vous tirer parti de votre domaine d'objets d'y écrire la base de données de code d'accès.

Ces objets ont généralement les attributs de l'entreprise (propriétés du bean) et certains comportements (méthodes que l'habitude de travailler sur ces propriétés).

L'AR dit juste "ajouter certaines méthodes de ces objets du domaine" de base de données tâches connexes.

Et je dois dire que, de mon avis et de l'expérience, que je n'aime pas le motif.

À première vue, il peut sembler assez bonne. Certains modernes et des outils Java comme Spring Roo utilise ce modèle.

Pour moi, le vrai problème, c'est juste de la programmation orientée objet avec inquiétude. AR motif vous oblige en quelque sorte à ajouter une dépendance de votre objet à infraestructure objets. Ces infraestructure objets de laisser le domaine de l'objet de requête de la base de données à travers les méthodes proposées par AR.

J'ai toujours dit que les deux couches sont la clé de la réussite d'un projet. La couche de service (où la prestation logique réside ou peut être exportée à travers une sorte de technologie d'accès distant, en tant que Services Web, par exemple) et la couche domaine. À mon avis, si nous ajoutons quelques dépendances (pas vraiment nécessaire) de la couche domaine des objets pour résoudre le modèle AR, nos objets du domaine sera plus difficile de les partager avec d'autres couches ou (plus rare) des applications externes.

Spring Roo, de la mise en œuvre de l'AR est intéressant, car il ne repose pas sur l'objet lui-même, mais dans certains AspectJ fichiers. Mais si plus tard, vous ne voulez pas travailler avec Roo et ont de refactoriser le projet, l'AR méthodes seront mises en œuvre directement dans votre domaine d'objets.

Un autre point de vue. Imaginez que nous ne pas utiliser une Base de données Relationnelle pour stocker des objets. Imaginez l'application stocke notre domaine d'objets dans une Base de données NoSQL ou tout simplement dans des fichiers XML, par exemple. Serions-nous mettre en œuvre les méthodes de ces tâches dans notre domaine d'objets? Je ne le crois pas (par exemple, dans le cas de la XM, nous tenons à ajouter XML dépendances liées à notre domaine d'objets...Vraiment triste, je pense). Pourquoi alors avons-nous pour mettre en œuvre le relationnel méthodes dans le domaine des objets, à l'Ar modèle dit?

Pour résumer, l'AR modèle peut sembler plus simple et bon pour les petits et les applications simples. Mais, lorsque nous avons complexes et des applications importantes, je pense que le classique de l'architecture en couches est une meilleure approche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X