|
| 1 | +Scala 2.13 Project |
| 2 | +============================= |
| 3 | + |
| 4 | +## Goal |
| 5 | +The goal for this project is to demonstrate how to start easily a new scala 2.13 project (using FP techniques? :) ). |
| 6 | + |
| 7 | +## Stack technologies |
| 8 | + |
| 9 | +- [JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) |
| 10 | +- [SBT](http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html) |
| 11 | +- [akka-http](https://doc.akka.io/docs/akka-http/current/) as the web server. I could have gone with finch, twitter server, or http4s here as well. |
| 12 | +- [Circe](https://circe.github.io/circe/) for json serialization |
| 13 | +- [Cats](https://typelevel.org/cats/) for FP awesomeness |
| 14 | +- [Scapegoat](https://github.com/sksamuel/scapegoat) for linting |
| 15 | +- [ScalaTest](http://www.scalatest.org/) for test |
| 16 | + |
| 17 | +## Architecture |
| 18 | +### Domain Driven Design (DDD) |
| 19 | +Domain driven design is all about developing a _ubiquitous language_, which is a language that you can use to discuss your software with business folks (who presumably do not know programming). |
| 20 | + |
| 21 | +DDD is all about making your code expressive, making sure that how you _talk_ about your software materializes in your code. One of the best ways to do this is to keep you _domain_ pure. That is, allow the business concepts and entities to be real things, and keep all the other cruft out. However, HTTP, JDBC, SQL are not essential to domain, so we want to _decouple_ those as much as possible. |
| 22 | + |
| 23 | +### Onion (or Hexagonal) Architecture |
| 24 | +In concert with DDD, the [Onion Architecture](https://jeffreypalermo.com/2008/08/the-onion-architecture-part-3/) and [Hexagonal Architecture from Cockburn](https://java-design-patterns.com/patterns/hexagonal/) give us patterns on how to separate our domain from the ugliness of implementation. |
| 25 | + |
| 26 | +We fit DDD an Onion together via the following mechanisms: |
| 27 | + |
| 28 | +**The domain package** |
| 29 | +The domain package constitutes the things inside our domain. It is deliberately free of the ugliness of JDBC, JSON, HTTP, and the rest. |
| 30 | +We use `Services` as coarse-grained interfaces to our domain. These typically represent real-world use cases. Often times, you see a 1-to-1 mapping of `Services` to `R` or HTTP API calls your application surfaces. |
| 31 | + |
| 32 | +Inside of the **domain**, we see a few concepts: |
| 33 | + |
| 34 | +1. `Service` - the coarse grained use cases that work with other domain concepts to realize your use-cases |
| 35 | +1. `Repository` - ways to get data into and out of persistent storage. **Important: Repositories do not have any business logic in them, they should not know about the context in which they are used, and should not leak details of their implementations into the world**. |
| 36 | +1. `payloads` or `models` - things like `Tweet`, etc are all domain objects. We keep these lean (i.e. free of behavior). |
| 37 | + |
| 38 | +**The repository package** |
| 39 | +The repository package is where the ugliness lives. It has JDBC things, and the like. |
| 40 | +it contains implementations of our `Repositories`. We may have 2 different implementations, an in-memory version as well as a **doobie** version. |
| 41 | + |
| 42 | +**The http package** |
| 43 | +It contains the HTTP endpoints that we surface via **akka-http**. You will also typically see JSON things in here via **circe** |
| 44 | + |
| 45 | +**The util package** |
| 46 | +The util package could be considered infrastructure, as it has nothing to do with the domain. |
| 47 | + |
| 48 | +**NOTE** |
| 49 | +All business logic is located in `domain` package, every package inside is |
| 50 | +related to some domain. |
| 51 | + |
| 52 | +Service classes contains high level logic that relate to data manipulation, |
| 53 | +that means that services MUST NOT implement storage. |
| 54 | + |
| 55 | +For storage there are dedicated classes. |
| 56 | + |
| 57 | +## Conventions |
| 58 | + |
| 59 | +## Versioning |
| 60 | + |
| 61 | +## Database |
| 62 | + |
| 63 | +## Configuration |
| 64 | +1.`application.conf` |
| 65 | +1.`stage.application.conf` |
| 66 | +1.`prod.application.conf` |
| 67 | +We use **Pure Config** to load configuration objects when the application starts up. **pure config** Provides a neat mapping of config file to case classes for us, so we really do not have to do any code. |
| 68 | + |
| 69 | +## Run |
| 70 | + |
| 71 | +To run project locally and load the corresponding secretes, it is recommended to |
| 72 | +choose one of the following alternatives. |
| 73 | + |
| 74 | +## Command line |
| 75 | + |
| 76 | +In order to run locally on a developer machine via the command line, go to |
| 77 | +source folder and execute |
| 78 | + |
| 79 | +``` |
| 80 | +~/scala213/> sbt runServer |
| 81 | +``` |
| 82 | + |
| 83 | +For `<command>` use one of `~compile | test | run` |
| 84 | + |
| 85 | +## IntelliJ |
| 86 | +FIXME |
| 87 | +1. Open settings (`File -> Settings or CTRL+ALT+S`) |
| 88 | +1. Choose Plugins |
| 89 | +1. Open "browse repositories" window and type `BashSupport` |
| 90 | +1. Click "Install" button and wait until the installation completes |
| 91 | +1. Restart Intellij IDEA |
| 92 | +1. Open Run/Debug Configuration (`Run -> Edit Configurations`) |
| 93 | +1. Click "+" button and select "Bash" item from drop down |
| 94 | +1. Give a name and select `sbt` file from source code |
| 95 | +1. Enter `run` into "Program arguments" field |
| 96 | +1. Click "Apply" and "OK" |
| 97 | +1. Click green button on the right side at the top of the window (or `Shift+F10`) |
| 98 | + |
| 99 | +## Testing |
| 100 | + |
| 101 | +``` |
| 102 | +``` |
| 103 | + |
| 104 | +## Pre-Commit Hook |
| 105 | + |
| 106 | +[Pre Commit](https://github.com/pre-commit/pre-commit) is a project on github to setup and maintain |
| 107 | +git commit hooks. The default hooks are defined in `.pre-commit-config.yaml` |
| 108 | + |
| 109 | +For installation on osx run |
| 110 | + |
| 111 | +``` |
| 112 | +brew install pre-commit |
| 113 | +``` |
| 114 | + |
| 115 | +To setup the hooks with pre-commit run: |
| 116 | + |
| 117 | +``` |
| 118 | +pre-commit install -f --install-hooks |
| 119 | +``` |
| 120 | + |
| 121 | +After that scalafmt checks your changed files for codestyle: |
| 122 | + |
| 123 | +_Note:_ Conflicts should be resolved |
| 124 | + |
| 125 | +## Deployment |
| 126 | + |
| 127 | +This section describes how to deploy `scala213` to either `STAGE` or `PROD`. |
| 128 | + |
| 129 | +## Dependency Udpates |
| 130 | + |
| 131 | +``` |
| 132 | +sbt dependencyUpdates |
| 133 | +``` |
| 134 | + |
| 135 | +Lists newer versions of integrated dependencies from Maven/Ivy |
| 136 | + |
| 137 | +sbt dependencyUpdates |
| 138 | + |
| 139 | +## Linting |
| 140 | + |
| 141 | +Linting is done via scapegoat. It is a static code analyzer inspecting the code with a set of 117 rules. |
| 142 | +Certain files can be excluded, rules can be changed. Configuration is described [here](https://github.com/sksamuel/scapegoat). |
| 143 | + |
| 144 | +The report can be picked up by Jenkins and should be part of the deployment pipeline. |
| 145 | + |
| 146 | +## Publish |
| 147 | + |
| 148 | +Not to be confused with Sbt's "publishing"!. |
| 149 | + |
| 150 | +``` |
| 151 | +haha FIXME |
| 152 | +``` |
| 153 | + |
| 154 | +## Release |
| 155 | + |
| 156 | +``` |
| 157 | +haha FIXME |
| 158 | +``` |
| 159 | + |
| 160 | +## Resources |
| 161 | + |
| 162 | +- For setting up the initial `seed` structure, we utilized |
| 163 | + [Scala Pet Store](https://github.com/pauljamescleary/scala-pet-store). |
| 164 | + |
| 165 | +- For STAGE/ PROD configuration, we utilized [Production |
| 166 | + Configuration](https://www.playframework.com/documentation/2.6.x/ProductionConfiguration#overriding-configuration-with-system-properties) |
| 167 | + |
| 168 | +## Known issues |
| 169 | + |
| 170 | +### Configuration via Pureconfig |
| 171 | + |
| 172 | +Pureconfig's config file does not support uppercase and underscores. [Read here](https://github.com/pureconfig/pureconfig/issues/394) |
| 173 | + |
| 174 | +### sbt-partial-unification |
| 175 | +In order to use cats... |
| 176 | + |
| 177 | +## How to use sbt-coverage |
| 178 | + |
| 179 | +Run the tests with enabled coverage: |
| 180 | +``` |
| 181 | +$ sbt clean test |
| 182 | +``` |
| 183 | + |
| 184 | +To generate the coverage reports run |
| 185 | +``` |
| 186 | +$ sbt coverageReport |
| 187 | +``` |
| 188 | + |
| 189 | +Coverage reports will be in target/scala-2.12/scoverage-report/index.html. |
0 commit comments