Git Product home page Git Product logo

frdomain's Introduction

frdomain

Code repo for Functional and Reactive Domain Modeling.

From the book page:

Functional and Reactive Domain Modeling teaches you how to think of the domain model in terms of pure functions and how to compose them to build larger abstractions. You will start with the basics of functional programming and gradually progress to the advanced concepts and patterns that you need to know to implement complex domain models. The book demonstrates how advanced FP patterns like algebraic data types, typeclass based design, and isolation of side-effects can make your model compose for readability and verifiability. On the subject of reactive modeling, the book focuses on higher order concurrency patterns like actors and futures. It uses the Akka framework as the reference implementation and demonstrates how advanced architectural patterns like event sourcing and CQRS can be put to great use in implementing scalable models. You will learn techniques that are radically different from the standard RDBMS based applications that are based on mutation of records. You'll also pick up important patterns like using asynchronous messaging for interaction based on non blocking concurrency and model persistence, which delivers the speed of in-memory processing along with suitable guarantees of reliability.

frdomain's People

Contributors

aryairani avatar debasishg avatar guersam avatar jvliwanag avatar marcelloduarte avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

frdomain's Issues

Service method is <1-1> to Command but can generate multiple Events

@debasishg a question about what comes first, Command or Event.

In the current code the service operations are mapped to a single Event which, in turn is mapped to a Command.
Seems this would not support a functionality where a service operation (logically a Command) would need to generate multiple Events to different Aggregates.

Scenario: funds transfer would update Account balances and update Customer net worth.

Then there is the question of whether the Interpreter is per Aggregate or can work with more than one.

Please advise.

Error while importing project

Hi,

I'm unable to successfully import the project as an sbt project in IntelliJ IDEA 2019.3.
Are others able to import and build OK?

The import output is as follows:

Error while importing sbt project:

List([info] Loading global plugins from /Users/bayo/.sbt/0.13/plugins
[info] Loading project definition from /Users/bayo/dev/frdomain/project
Missing bintray credentials /Users/bayo/.bintray/.credentials. Some bintray features depend on this.
[info] Set current project to frdomain (in build file:/Users/bayo/dev/frdomain/)
>
[info] Defining */*:sbtStructureOptions, */*:sbtStructureOutputFile and 1 others.
[info] The new values will be used by *:cleanKeepFiles
[info] 	Run `last` for details.
[info] Reapplying settings...
Missing bintray credentials /Users/bayo/.bintray/.credentials. Some bintray features depend on this.
[info] Set current project to frdomain (in build file:/Users/bayo/dev/frdomain/)
[info] Applying State transformations org.jetbrains.sbt.CreateTasks from /Users/bayo/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-1/193.5233.102/IntelliJ IDEA 2019.3 EAP.app.plugins/Scala/repo/org.jetbrains/sbt-structure-extractor/scala_2.10/sbt_0.13/2018.2.1+4-88400d3f/jars/sbt-structure-extractor.jar
[info] Reapplying settings...
Missing bintray credentials /Users/bayo/.bintray/.credentials. Some bintray features depend on this.
[info] Set current project to frdomain (in build file:/Users/bayo/dev/frdomain/)
[warn] Credentials file /Users/bayo/.bintray/.credentials does not exist
[info] Updating {file:/Users/bayo/dev/frdomain/}root...
[info] Resolving org.scala-lang#scala-library;2.11.8 ...
[info] Resolving org.scalaz#scalaz-core_2.11;7.2.4 ...
[info] Resolving org.scalaz#scalaz-concurrent_2.11;7.2.4 ...
[info] Resolving org.scalaz#scalaz-effect_2.11;7.2.4 ...
[info] Resolving joda-time#joda-time;2.9.1 ...
[info] Resolving org.joda#joda-convert;1.8.1 ...
[info] Resolving io.spray#spray-json_2.11;1.3.2 ...
[info] Resolving com.typesafe.akka#akka-actor_2.11;2.4.8 ...
[info] Resolving com.typesafe#config;1.3.0 ...
[info] Resolving org.scala-lang.modules#scala-java8-compat_2.11;0.7.0 ...
[info] Resolving com.typesafe.akka#akka-persistence_2.11;2.4.8 ...
[info] Resolving com.typesafe.akka#akka-protobuf_2.11;2.4.8 ...
[info] Resolving com.typesafe.akka#akka-stream_2.11;2.4.8 ...
[info] Resolving com.typesafe#ssl-config-akka_2.11;0.2.1 ...
[info] Resolving com.typesafe#ssl-config-core_2.11;0.2.1 ...
[info] Resolving org.scala-lang.modules#scala-parser-combinators_2.11;1.0.4 ...
[info] Resolving org.reactivestreams#reactive-streams;1.0.0 ...
[info] Resolving com.typesafe.scala-logging#scala-logging-slf4j_2.11;2.1.2 ...
[info] Resolving com.typesafe.scala-logging#scala-logging-api_2.11;2.1.2 ...
[info] Resolving org.scala-lang#scala-reflect;2.11.0 ...
[info] Resolving org.slf4j#slf4j-api;1.7.7 ...
[info] Resolving com.typesafe.slick#slick_2.11;3.0.0 ...
[info] Resolving com.h2database#h2;1.4.187 ...
[info] Resolving com.zaxxer#HikariCP-java6;2.3.8 ...
[info] Resolving com.zaxxer#HikariCP-java6;2.3.8 ...
[info] Resolving com.zaxxer#HikariCP-parent;2.3.8 ...
[info] Resolving com.zaxxer#HikariCP-parent;2.3.8 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving com.zaxxer#HikariCP-parent;2.3.8 ...
[info] Resolving com.zaxxer#HikariCP-parent;2.3.8 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving ch.qos.logback#logback-classic;1.1.3 ...
[info] Resolving ch.qos.logback#logback-core;1.1.3 ...
[info] Resolving org.scalacheck#scalacheck_2.11;1.12.5 ...
[info] Resolving org.scala-sbt#test-interface;1.0 ...
[info] Resolving com.milessabin#si2712fix-plugin_2.11.8;1.2.0 ...
[info] Resolving org.spire-math#kind-projector_2.11;0.8.0 ...
[info] Resolving org.scala-lang#scala-compiler;2.11.7 ...
[info] Resolving org.scala-lang#scala-reflect;2.11.7 ...
[info] Resolving org.scala-lang.modules#scala-xml_2.11;1.0.4 ...
[info] Resolving org.scala-lang#scala-compiler;2.11.8 ...
[info] Resolving org.scala-lang#scala-reflect;2.11.8 ...
[info] Resolving jline#jline;2.12.1 ...
[info] Resolving jline#jline;2.12.1 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[warn] 	::::::::::::::::::::::::::::::::::::::::::::::
[warn] 	::          UNRESOLVED DEPENDENCIES         ::
[warn] 	::::::::::::::::::::::::::::::::::::::::::::::
[warn] 	:: com.zaxxer#HikariCP-java6;2.3.8: several problems occurred while resolving dependency: com.zaxxer#HikariCP-java6;2.3.8 {compile=[default(compile)]}:
[warn] 	several problems occurred while resolving dependency: com.zaxxer#HikariCP-parent;2.3.8 {}:
[warn] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn]
[warn] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn]
[warn]
[warn] 	several problems occurred while resolving dependency: com.zaxxer#HikariCP-parent;2.3.8 {}:
[warn] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn]
[warn] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	:: jline#jline;2.12.1: several problems occurred while resolving dependency: jline#jline;2.12.1 {optional=[compile(*), master(compile)]}:
[warn] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn]
[warn] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[warn] 	::::::::::::::::::::::::::::::::::::::::::::::
[warn]
[warn] 	Note: Unresolved dependencies path:
[warn] 		com.zaxxer:HikariCP-java6:2.3.8 (/Users/bayo/dev/frdomain/build.sbt#L13)
[warn] 		  +- frdomain:frdomain_2.11:0.0.1
[warn] 		jline:jline:2.12.1
[warn] 		  +- org.scala-lang:scala-compiler:2.11.8
[warn] 		  +- frdomain:frdomain_2.11:0.0.1
[trace] Stack trace suppressed: run 'last *:ssExtractDependencies' for the full output.
[trace] Stack trace suppressed: run 'last *:update' for the full output.
[error] (*:ssExtractDependencies) sbt.ResolveException: unresolved dependency: com.zaxxer#HikariCP-java6;2.3.8: several problems occurred while resolving dependency: com.zaxxer#HikariCP-java6;2.3.8 {compile=[default(compile)]}:
[error] 	several problems occurred while resolving dependency: com.zaxxer#HikariCP-parent;2.3.8 {}:
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error]
[error] 	several problems occurred while resolving dependency: com.zaxxer#HikariCP-parent;2.3.8 {}:
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error]
[error]
[error] unresolved dependency: jline#jline;2.12.1: several problems occurred while resolving dependency: jline#jline;2.12.1 {optional=[compile(*), master(compile)]}:
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] (*:update) sbt.ResolveException: unresolved dependency: com.zaxxer#HikariCP-java6;2.3.8: several problems occurred while resolving dependency: com.zaxxer#HikariCP-java6;2.3.8 {compile=[default(compile)]}:
[error] 	several problems occurred while resolving dependency: com.zaxxer#HikariCP-parent;2.3.8 {}:
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error]
[error] 	several problems occurred while resolving dependency: com.zaxxer#HikariCP-parent;2.3.8 {}:
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error]
[error]
[error] unresolved dependency: jline#jline;2.12.1: several problems occurred while resolving dependency: jline#jline;2.12.1 {optional=[compile(*), master(compile)]}:
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss
#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error]
[error] 	several problems occurred while resolving dependency: org.sonatype.oss#oss-parent;7 {}:
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] 	org.sonatype.oss#oss-parent;7!oss-parent.pom(pom.original) origin location must be absolute: file:/Users/bayo/.m2/repository/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
[error] Total time: 13 s, completed Dec 6, 2019 8:13:08 PM)

Should Repository be parameterised (object, id type)?

Currently making my way through the book in detail (awesome btw), and I realised that in Chapter 5, AccountService is parameterised on Account, Amount, and Balance, which is awesome, but AccountRepository on which it depends is not; I was curious if it should be ?

trait AccountService[Account, Amount, Balance] {
type AccountOperation[A] = Kleisli[Valid, AccountRepository, A]
def open(no: String, name: String, rate: Option[BigDecimal], openingDate: Option[Date],
accountType: AccountType): AccountOperation[Account]
def close(no: String, closeDate: Option[Date]): AccountOperation[Account]
def debit(no: String, amount: Amount): AccountOperation[Account]
def credit(no: String, amount: Amount): AccountOperation[Account]
def balance(no: String): AccountOperation[Balance]
def transfer(from: String, to: String, amount: Amount): AccountOperation[(Account, Account)] = for {
a <- debit(from, amount)
b <- credit(to, amount)
} yield ((a, b))
}

trait AccountRepository {
def query(no: String): \/[NonEmptyList[String], Option[Account]]
def store(a: Account): \/[NonEmptyList[String], Account]
def balance(no: String): \/[NonEmptyList[String], Balance] = query(no) match {
case \/-(Some(a)) => a.balance.right
case \/-(None) => NonEmptyList(s"No account exists with no $no").left[Balance]
case a @ -\/(_) => a
}
def query(openedOn: Date): \/[NonEmptyList[String], Seq[Account]]
def all: \/[NonEmptyList[String], Seq[Account]]
}

In effect, doesn't this mean that AccountService is coupled to the concrete models due to

type AccountOperation[A] = Kleisli[Valid, AccountRepository, A]

?

Chapter 6: Introduce future at the repository level

The root cause why the operation need to return Future is because repository. Rather than eagerly calling Future.apply in service level, why can't we introduce Future as the return type from repository, and compose it accordingly in service level?

Let's say our repository is non-blocking, we will call this already well-shaped repository in another thread, which is unnecessary.

Exercise 5.1 Solution

Hello there,

I'm trying to implement the solution for Exercise 5.1. I managed to do it for the mutable state interpreter but I cannot seem to get it to work for the State interpreter even though I've aligned the types

The following mutable state interpreter works perfectly

// works fine
  class AccountRepoMutableInterpreter extends AccountRepoInterpreter[Task] {

    // mutable state
    var table = Map.empty[String, Account]

    // Natural transformation from Free Monad to Task is the interpreter
    val interpreter = new (AccountRepoInstruction ~> Task) {
      override def apply[A](fa: AccountRepoInstruction[A]): Task[A] = fa match {
        // give meaning to each instruction
        case Query(no) =>
          Task.now(table.get(no).get)

        case Store(acc) =>
          Task.now(table = table + (acc.no -> acc)).void

        case Delete(no) =>
          Task.now(table = table - no).void
      }
    }

    override def apply[A](instruction: AccountRepo[A]): Task[A] =
      instruction.foldMap(interpreter)
  }


  import AccountService._
  val testInterpreter = new AccountRepoMutableInterpreter
  val account = Account("a-123", "John K")
  val comp = for {
    a <- store(account.copy(balance = Balance(1000)))
    q <- query(account.no)
    c <- delete(account.no)
    _ <- store(account.copy(balance = Balance(2000)))
  } yield ()

  // interpret free instructions and give it meaning getting back a Task and execute it synchronously
  testInterpreter(comp).unsafePerformSync

  println(testInterpreter.table)
}

However, the state implementation fails to compile even though the types align correctly (according to IntelliJ

  // does not work even though types align
  class AccountRepoStateInterpreter extends AccountRepoInterpreter[AccountState] {
    val interpreter = new (AccountRepoInstruction ~> AccountState) {
      override def apply[A](fa: AccountRepoInstruction[A]): AccountState[A] = fa match {
        case Query(no) =>
          val errMsg: Err[(AccountMap, Account)] = -\/(new Error("could not find member"))
          val result: AccountState[Account] = StateT[Err, AccountMap, Account] {
            accountMap =>
              accountMap.get(no) match {
                case Some(acc) =>
                  \/-( (accountMap, acc) )

                case None =>
                  errMsg
              }
          }
          result

        case Store(acc) =>
          val result: AccountState[Unit] = StateT[Err, AccountMap, Unit] { accountMap =>
            val updatedMap = accountMap + (acc.no -> acc)
            \/-( (updatedMap, ()) )
          }
          result

        case Delete(no) =>
          val result: AccountState[Unit] = StateT[Err, AccountMap, Unit] { accountMap =>
            val updatedMap = accountMap - no
            \/-( (updatedMap, ()) )
          }
          result
      }
    }

    override def apply[A](instruction: AccountRepo[A]): AccountState[A] = instruction.foldMap(interpreter)
  }

Any idea what I'm missing here?
Thanks a lot

Here is the full example

import java.util.Date

import scala.language.higherKinds
import scalaz.concurrent.Task

object Example extends App {
  import scalaz._
  import Scalaz._
  // https://github.com/debasishg/frdomain/tree/master/src/main/scala/frdomain/ch5/domain/model
  import frdomain.ch5.domain.model._
  // https://github.com/debasishg/frdomain/blob/master/src/main/scala/frdomain/ch5/domain/model/Account.scala#L10
  import common._

  case class Balance(amount: Amount = 0)
  case class Account(no: String, name: String, dateOfOpening: Date = today, dateOfClosing: Option[Date] = None,
                     balance: Balance = Balance(0))

  object Account {
    implicit val showAccount: Show[Account] = Show.shows { case a: Account => a.toString }
  }

  sealed trait AccountRepoInstruction[+A]
  case class Query(no: String) extends AccountRepoInstruction[Account]
  case class Store(account: Account) extends AccountRepoInstruction[Unit]
  case class Delete(no: String) extends AccountRepoInstruction[Unit]

  type AccountRepo[A] = Free[AccountRepoInstruction, A]

  trait AccountRepository {
    def store(account: Account): AccountRepo[Unit] =
      Free.liftF(Store(account))

    def query(no: String): AccountRepo[Account] =
      Free.liftF(Query(no))

    def delete(no: String): AccountRepo[Unit] =
      Free.liftF(Delete(no))

    def update(no: String, update: Account => Account): AccountRepo[Unit] =
      for {
        acc <- query(no)
        _   <- store(update(acc))
      } yield ()

    def updateBalance(no: String, amount: Amount, update: (Account, Amount) => Account): AccountRepo[Unit] =
      for {
        acc <- query(no)
        _   <- store(update(acc, amount))
      } yield ()
  }

  trait AccountService[Account, Amount, Balance] {
    def open(no: String, name: String, openingDate: Option[Date]): AccountRepo[Account]
    def close(no: String, closeDate: Option[Date]): AccountRepo[Account]
    def debit(no: String, amount: Amount): AccountRepo[Account]
    def credit(no: String, amount: Amount): AccountRepo[Account]
    def balance(no: String): AccountRepo[Balance]
  }

  object AccountService extends AccountService[Account, Amount, Balance] with AccountRepository {
    override def open(no: String, name: String, openingDate: Option[Date]) = {
      for {
        _   <- store(Account(no, name, openingDate.getOrElse(today)))
        acc <- query(no)
      } yield acc
    }

    override def close(no: String, closeDate: Option[Date]): AccountRepo[Account] = for {
      _ <- update(no, acc => acc.copy(dateOfClosing = Some(today)))
      a <- query(no)
    } yield a

    override def debit(no: String, amount: Amount): AccountRepo[Account] = for {
      _ <- updateBalance(no, amount, (acc, am) => acc.copy(balance = Balance(acc.balance.amount - am)))
      a <- query(no)
    } yield a

    override def credit(no: String, amount: Amount): AccountRepo[Account] = for {
      _ <- updateBalance(no, amount, (acc, am) => acc.copy(balance = Balance(acc.balance.amount + am)))
      a <- query(no)
    } yield a

    override def balance(no: String): AccountRepo[Balance] =
      query(no).map(acc => acc.balance)
  }

  trait AccountRepoInterpreter[M[_]] {
    def apply[A](instruction: AccountRepo[A]): M[A]
  }

  type AccountMap = Map[String, Account]
  type Err[A] = Error \/ A
  type AccountState[A] = StateT[Err, AccountMap, A]

  // does not work even though types align
  class AccountRepoStateInterpreter extends AccountRepoInterpreter[AccountState] {
    val interpreter = new (AccountRepoInstruction ~> AccountState) {
      override def apply[A](fa: AccountRepoInstruction[A]): AccountState[A] = fa match {
        case Query(no) =>
          val errMsg: Err[(AccountMap, Account)] = -\/(new Error("could not find member"))
          val result: AccountState[Account] = StateT[Err, AccountMap, Account] {
            accountMap =>
              accountMap.get(no) match {
                case Some(acc) =>
                  \/-( (accountMap, acc) )

                case None =>
                  errMsg
              }
          }
          result

        case Store(acc) =>
          val result: AccountState[Unit] = StateT[Err, AccountMap, Unit] { accountMap =>
            val updatedMap = accountMap + (acc.no -> acc)
            \/-( (updatedMap, ()) )
          }
          result

        case Delete(no) =>
          val result: AccountState[Unit] = StateT[Err, AccountMap, Unit] { accountMap =>
            val updatedMap = accountMap - no
            \/-( (updatedMap, ()) )
          }
          result
      }
    }

    override def apply[A](instruction: AccountRepo[A]): AccountState[A] = instruction.foldMap(interpreter)
  }

  val stateInterpreter = new AccountRepoStateInterpreter

  // works fine
  class AccountRepoMutableInterpreter extends AccountRepoInterpreter[Task] {

    // mutable state
    var table = Map.empty[String, Account]

    // Natural transformation from Free Monad to Task is the interpreter
    val interpreter = new (AccountRepoInstruction ~> Task) {
      override def apply[A](fa: AccountRepoInstruction[A]): Task[A] = fa match {
        // give meaning to each instruction
        case Query(no) =>
          Task.now(table.get(no).get)

        case Store(acc) =>
          Task.now(table = table + (acc.no -> acc)).void

        case Delete(no) =>
          Task.now(table = table - no).void
      }
    }

    override def apply[A](instruction: AccountRepo[A]): Task[A] =
      instruction.foldMap(interpreter)
  }


  import AccountService._
  val testInterpreter = new AccountRepoMutableInterpreter
  val account = Account("a-123", "John K")
  val comp = for {
    a <- store(account.copy(balance = Balance(1000)))
    q <- query(account.no)
    c <- delete(account.no)
    _ <- store(account.copy(balance = Balance(2000)))
  } yield ()

  // interpret free instructions and give it meaning getting back a Task and execute it synchronously
  testInterpreter(comp).unsafePerformSync

  println(testInterpreter.table)
}

I'm using Scala 7.2.8 and Scala 2.12.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.