Wie kann ich das Repository- oder Gateway-Muster in Ruby implementieren?
Ich komme aus einer C # -Welt und abstrahiere normalerweise meinen Datenzugriff, aber mit ActiveRecord als Standard-Datenzugriffsmechanismus in Ruby ist es nicht offensichtlich, wie das zu erreichen ist.
Normalerweise würde ich in C # mit abstrakten Interfaces arbeiten und dann eine konkrete Implementierung für EFCustomerRepository
, NHibernateCustomerRepository
und InMemoryCustomerRepository
haben und je nach Situation die passende konkrete Implementierung einfügen.
Also, was ist der Ruby Weg?!
Soweit ich es verstehe, brauchen Sie in dynamischen Sprachen nicht so etwas wie DI (Dependency Injection). Und Ruby hat mächtige Sprachfunktionen, um Dinge wie Mixins zu ermöglichen.
Aber Sie würden das Mixin statisch auf Klassen- oder Modulebene definieren?
Wie schreibe ich meine Geschäftslogik, wenn ich gegen ein In-Memory-Repository entwickeln möchte und in der Produktion zu meinem ActiveRecord-Repository wechseln würde?
Ich könnte hier auf dem falschen Weg sein, da ich es gewohnt bin, in einer statisch getippten Sprache zu denken. Wie würde jemand diese Aufgabe auf Rubin-Art angehen? Grundsätzlich möchte ich meine Persistenzschicht abstrakt machen und ihre Implementierungen austauschbar machen.
BEARBEITEN: Ich beziehe mich auf robert c. Martins (unknobb) Keynote über Architektur
Danke für jede Hilfe ...
Ich verstehe, was du sagst. Ich komme auch aus einem .NET-Hintergrund. Abstrahieren Sie Ihre Geschäftslogik & amp; Ausdauerlogik ist eine gute Idee. Ich habe noch kein Juwel gefunden, das es für dich macht. Aber Sie können selbst leicht etwas Einfaches rollen. Am Ende ist ein Repository-Muster im Grunde eine Klasse, die an Ihre Persistenz-Schicht delegiert.
Folgendes mache ich:
%Vor%Und dann könnten Sie zum Beispiel ein Post-Repository haben.
%Vor%Instanziieren Sie es einfach in Ihrem Controller in einem before_filter oder initialisieren oder wo auch immer. In diesem Fall beschränke ich mich auf den current_user, so dass nur diese Datensätze abgerufen werden und automatisch nur für den aktuellen Benutzer Beiträge erstellt werden.
%Vor%Ich stieß auf Ссылка , was ein kleines DI-Framework ist. Es könnte für dich arbeiten :) Aber DI ist kein stark verwendetes Muster in Ruby. Außerdem instantiiere ich meine Repos, um sie auf einen aktuellen Benutzer oder etwas anderes zu beschränken.
Ich bin auf der Suche nach dem richtigen Weg, um genau das zu tun, was du fragst, und mache ein bisschen darüber, wenn ich es jemals finde. Aber jetzt reicht es schon aus, den sauberen Schnitt zwischen Persistenz & Amp; meine Controller. Wenn dies richtig gemacht wird, ist es nicht schwer, später zu einem anderen System zu wechseln. Oder füge Caching usw. hinzu.
Nun, ActiveRecord bietet bereits eine abstrakte Persistenzschicht - sie hat mehrere verschiedene Adapter , so dass sie verschiedene Datenbank-Backends verwenden kann . Außerdem ist es Open-Source, so dass Sie sich ansehen können, wie es erreicht wurde.
Auf den ersten Blick sehen Sie, dass es auch einen AbstractAdapter hat, den alle anderen Adapter erben, Da Ruby jedoch dynamisch ist, muss die Sprache für die Entschlüsselung AbstractAdapter
keine abstrakten Methoden enthalten, die in untergeordneten Klassen überschrieben werden, und definiert auch keinen "Vertrag", den sie berücksichtigen sollten.
Bearbeiten:
Hier ist eine einfache Skizze, wie Sie Ihren Speicher in Ruby abstrahieren können, nicht sicher, welches Muster genau das ist:
%Vor%@serverinfo, ich weiß nicht viel über C #. Aber als ich von einem Java / C-Hintergrund zu Ruby kam, war ich überwältigt, als ich erkannte, wie flexibel diese Sprache wirklich ist. Du sagst, dass dein wirkliches Problem hier darin besteht, "deine Persistenzschicht wegzuspalten und sie austauschbar zu machen". Sie haben auch gefragt "Wie schreibe ich die Geschäftslogik".
Ich schlage vor, dass Sie Ihre Vorurteile abwerfen und sich fragen: "Wie würde ich meinen Datenzugriff / Speicher in meiner Business-Logik-Ebene ausdrücken?" Mach dir keine Sorgen darüber, was du denkst oder nicht tun kannst; Wenn Sie herausfinden können, wie Sie die Schnittstelle zum Arbeiten nutzen möchten, gibt es wahrscheinlich einen Weg, wie es in Ruby gemacht werden kann.
Sie müssen auch entscheiden, wie Sie die konkrete Implementierung angeben möchten. Ist es möglich, dass Sie für verschiedene Modellobjekte einen anderen Datenspeicher verwenden möchten? Möchten Sie zur Laufzeit wechseln? Möchten Sie das Backend angeben, das in einer Konfigurationsdatei oder in Code verwendet werden soll? Wenn Sie entscheiden können, was Sie wollen , gibt es viele Leute in Stack Overflow, die Ihnen helfen können, wie dafür zu finden.
Tags und Links ruby ruby-on-rails design-patterns architecture