Last active
April 30, 2022 12:49
-
-
Save lagenorhynque/a44fe829267bd8504599688e2bc096bf to your computer and use it in GitHub Desktop.
『良いコード/悪いコードで学ぶ設計入門』3章: Money.javaのClojure移植版
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns chapter03.money | |
(:require [clojure.spec.alpha :as s]) | |
(:import (java.util Currency))) | |
(s/def ::amount nat-int?) | |
(s/def ::currency #(instance? Currency %)) | |
(s/def ::money (s/keys :req [::amount | |
::currency])) | |
(s/fdef add | |
:args (s/and (s/cat :this ::money | |
:other ::money) | |
#(= (-> % :this ::currency) | |
(-> % :other ::currency))) | |
:ret ::money) | |
(defn add [this other] | |
(update this ::amount + (::amount other))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chapter03_fundamentalofoop; | |
import java.util.Currency; | |
class Money { | |
final int amount; | |
final Currency currency; | |
Money(final int amount, final Currency currency) { | |
if (amount < 0) { | |
throw new IllegalArgumentException("金額が0以上でありません。"); | |
} | |
if (currency == null) { | |
throw new NullPointerException("通貨を指定してください。"); | |
} | |
this.amount = amount; | |
this.currency = currency; | |
} | |
Money add(final Money other) { | |
if (!currency.equals(other.currency)) { | |
throw new IllegalArgumentException("通貨単位が違います。"); | |
} | |
final int added = amount + other.amount; | |
return new Money(added, currency); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns chapter03.money2 | |
(:require [clojure.spec.alpha :as s]) | |
(:import (java.util Currency))) | |
(s/def ::amount nat-int?) | |
(s/def ::currency #(instance? Currency %)) | |
(s/def ::money (s/keys :req-un [::amount | |
::currency])) | |
(defrecord Money [amount currency]) | |
(s/fdef ->Money | |
:args (s/cat :amount ::amount | |
:currency ::currency) | |
:ret ::money) | |
(s/fdef map->Money | |
:args (s/cat :map ::money) | |
:ret ::money) | |
(s/fdef add | |
:args (s/and (s/cat :this ::money | |
:other ::money) | |
#(= (-> % :this :currency) | |
(-> % :other :currency))) | |
:ret ::money) | |
(defn add [this other] | |
(update this :amount + (:amount other))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (require '[chapter03.money :as money] | |
'[clojure.spec.test.alpha :as st]) | |
nil | |
user=> (st/instrument) | |
[chapter03.money/add] | |
user=> (import (java.util Currency Locale)) | |
java.util.Locale | |
user=> (money/add #::money{:amount -1 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)} | |
#_=> #::money{:amount 200 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
Execution error - invalid arguments to chapter03.money/add at (REPL:1). | |
-1 - failed: nat-int? at: [:this :chapter03.money/amount] spec: :chapter03.money/amount | |
user=> (money/add #::money{:amount 1000 | |
#_=> :currency nil} | |
#_=> #::money{:amount 200 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
Execution error - invalid arguments to chapter03.money/add at (REPL:1). | |
nil - failed: (instance? java.util.Currency %) at: [:this :chapter03.money/currency] spec: :chapter03.money/currency | |
user=> (money/add #::money{:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)} | |
#_=> #::money{:amount 200 | |
#_=> :currency (Currency/getInstance Locale/FRANCE)}) | |
Execution error - invalid arguments to chapter03.money/add at (REPL:1). | |
{:this #:chapter03.money{:amount 1000, :currency #object[java.util.Currency 0x3fbe503c "JPY"]}, :other #:chapter03.money{:amount 200, :currency #object[java.util.Currency 0x7b2bf745 "EUR"]}} - failed: (= (-> % :this :chapter03.money/currency) (-> % :other :chapter03.money/currency)) | |
user=> (money/add #::money{:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)} | |
#_=> #::money{:amount 200 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
#:chapter03.money{:amount 1200, :currency #object[java.util.Currency 0x3fbe503c "JPY"]} | |
user=> (money/add #::money{:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/FRANCE)} | |
#_=> #::money{:amount 200 | |
#_=> :currency (Currency/getInstance Locale/FRANCE)}) | |
#:chapter03.money{:amount 1200, :currency #object[java.util.Currency 0x7b2bf745 "EUR"]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (require '[chapter03.money2 :as money2] | |
#_=> '[clojure.spec.test.alpha :as st]) | |
nil | |
user=> (st/instrument) | |
[chapter03.money2/->Money chapter03.money2/add chapter03.money2/map->Money] | |
user=> (import (java.util Currency Locale)) | |
java.util.Locale | |
user=> (money2/->Money -1 (Currency/getInstance Locale/JAPAN)) | |
Execution error - invalid arguments to chapter03.money2/->Money at (REPL:1). | |
-1 - failed: nat-int? at: [:amount] spec: :chapter03.money2/amount | |
user=> (money2/->Money 1000 nil) | |
Execution error - invalid arguments to chapter03.money2/->Money at (REPL:1). | |
nil - failed: (instance? java.util.Currency %) at: [:currency] spec: :chapter03.money2/currency | |
user=> (money2/->Money 1000 (Currency/getInstance Locale/JAPAN)) | |
#chapter03.money2.Money{:amount 1000, :currency #object[java.util.Currency 0x3fbe503c "JPY"]} | |
user=> (money2/map->Money {:amount -1 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
Execution error - invalid arguments to chapter03.money2/map->Money at (REPL:1). | |
-1 - failed: nat-int? at: [:map :amount] spec: :chapter03.money2/amount | |
user=> (money2/map->Money {:amount 1000 | |
#_=> :currency nil}) | |
Execution error - invalid arguments to chapter03.money2/map->Money at (REPL:1). | |
nil - failed: (instance? java.util.Currency %) at: [:map :currency] spec: :chapter03.money2/currency | |
user=> (money2/map->Money {:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
#chapter03.money2.Money{:amount 1000, :currency #object[java.util.Currency 0x3fbe503c "JPY"]} | |
user=> (money2/add (money2/->Money 1000 (Currency/getInstance Locale/JAPAN)) | |
#_=> (money2/->Money 200 (Currency/getInstance Locale/FRANCE))) | |
Execution error - invalid arguments to chapter03.money2/add at (REPL:1). | |
{:this #chapter03.money2.Money{:amount 1000, :currency #object[java.util.Currency 0x3fbe503c "JPY"]}, :other #chapter03.money2.Money{:amount 200, :currency #object[java.util.Currency 0x7b2bf745 "EUR"]}} - failed: (= (-> % :this :currency) (-> % :other :currency)) | |
user=> (money2/add (money2/->Money 1000 (Currency/getInstance Locale/JAPAN)) | |
#_=> (money2/->Money 200 (Currency/getInstance Locale/JAPAN))) | |
#chapter03.money2.Money{:amount 1200, :currency #object[java.util.Currency 0x3fbe503c "JPY"]} | |
user=> (money2/add (money2/->Money 1000 (Currency/getInstance Locale/FRANCE)) | |
#_=> (money2/->Money 200 (Currency/getInstance Locale/FRANCE))) | |
#chapter03.money2.Money{:amount 1200, :currency #object[java.util.Currency 0x7b2bf745 "EUR"]} | |
user=> (money2/add {:amount -1 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)} | |
#_=> {:amount 200 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
Execution error - invalid arguments to chapter03.money2/add at (REPL:1). | |
-1 - failed: nat-int? at: [:this :amount] spec: :chapter03.money2/amount | |
user=> (money2/add {:amount 1000 | |
#_=> :currency nil} | |
#_=> {:amount 200 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
Execution error - invalid arguments to chapter03.money2/add at (REPL:1). | |
nil - failed: (instance? java.util.Currency %) at: [:this :currency] spec: :chapter03.money2/currency | |
user=> (money2/add {:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)} | |
#_=> {:amount 200 | |
#_=> :currency (Currency/getInstance Locale/FRANCE)}) | |
Execution error - invalid arguments to chapter03.money2/add at (REPL:1). | |
{:this {:amount 1000, :currency #object[java.util.Currency 0x3fbe503c "JPY"]}, :other {:amount 200, :currency #object[java.util.Currency 0x7b2bf745 "EUR"]}} - failed: (= (-> % :this :currency) (-> % :other :currency)) | |
user=> (money2/add {:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)} | |
#_=> {:amount 200 | |
#_=> :currency (Currency/getInstance Locale/JAPAN)}) | |
{:amount 1200, :currency #object[java.util.Currency 0x3fbe503c "JPY"]} | |
user=> (money2/add {:amount 1000 | |
#_=> :currency (Currency/getInstance Locale/FRANCE)} | |
#_=> {:amount 200 | |
#_=> :currency (Currency/getInstance Locale/FRANCE)}) | |
{:amount 1200, :currency #object[java.util.Currency 0x7b2bf745 "EUR"]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
📝 『良いコード/悪いコードで学ぶ設計入門』サポートページのサンプルコード
codes/src/chapter03_fundamentalofoop/Money.java