2015-05-29 7 views
7

Wenn mein Projekt "Person" Maps mit der Form {:firstName :lastName :address} verwendet, und ich diese Form zu {:name {:firstName :lastName} :address} ändern möchte, was kann ich tun, um sicherzustellen, dass ich die entsprechenden Änderungen überall diese vorgenommen habe Objekte werden verwendet?Strukturelle Korrektheit beim Refactoring in Clojure

In Java ist es einfach, wie überall, wo ich noch Person.firstName einen Kompilierungsfehler ausgeben würde. In Clojure I könnte nicht einmal eine Laufzeit Fehler erhalten, aber nur schlechte Daten auf dem Server gespeichert. Ich nehme an, es ist unmöglich, Garantie Richtigkeit, aber was gibt es außer feinzahnigen Kämmen?

+1

Wenn Sie Kompilierungsfehler benötigen, können Sie auch 'core.typed' verwenden. –

+0

Die Antworten, die gegeben wurden, sind gut, aber ich werde bemerken, dass dies eine Situation sein kann, in der die Vertrautheit mit dem regulären Ausdruck Suchen und Ersetzen in einem guten Programmierer-Editor sehr nützlich sein könnte. Wenn reguläre Ausdrücke nicht flexibel genug sind und Sie eine große Codebasis haben, könnte es sogar sinnvoll sein, ein Textmanipulations-Skript in Ihrer bevorzugten Sprache für die String-Manipulation zu programmieren. Oder du benutzt vielleicht sogar Clojure. Es ist schließlich sehr gut beim Lesen der Clojure-Quelle, und Clojure-Makros sind gut beim Umschreiben von Clojure-Quellen. Das hängt davon ab, wie viel Code Sie umgestalten müssen. – Mars

Antwort

6

Clojure verfügt über Bibliotheken, die Daten definieren und validieren. Zum Beispiel könnten Sie https://github.com/Prismatic/schema

In Bezug auf die Schwierigkeit der Kompilierungszeit im Vergleich zu Laufzeitfehlern ... Nun, dieses Problem ist nicht einzigartig für Clojure. Um John Carmack zu zitieren: "Die Herausforderung von Lispeln ist es, Ihr Programm zum Laufen zu bringen. Die Herausforderung von Haskell besteht darin, es zu kompilieren."

4

Ich stimme @noahlz zu - wenn Sie wirklich sicher sein wollen, dann müssen Sie eine Bibliothek wie die, die er vorgeschlagen hat, verwenden. Große Refactoring mit Karten kann ein Problem sein, es ist wahr.

auch sagen, dass Sie leicht Ihre Chancen in Ihrem Fall verbessern könnten, wenn Sie einen Datensatz mit seiner Konstruktorfunktion verwendet, um Ihr person (und immer noch die guten Dinge, über die Karten behalten) zu erstellen:

(defrecord Person [name address]) 

;; Okay. No problem 
(def scott (->Person {:firstname "Scott" :lastname "Lowe"} 
        "23 Hope Street, Edinburgh")) 
;; But then... 
(def scott (->Person "Scott" 
        "Lowe" 
        "23 Hope Street, Edinburgh")) 
;; Boom! 
ArityException Wrong number of args (3) passed to: user/eval990/->Person--1005 

Nun ist diese Beispiel fängt das Problem zur Laufzeit ab, und es wird offensichtlich nur in einigen einfachen Fällen helfen. Aber statische Analysewerkzeuge greifen diesen Fehler auch zur Entwicklungszeit auf (zum Beispiel: Clojure Plugins wie Cursive für IntelliJ verfügbar).