Skip to content

Latest commit

 

History

History
200 lines (145 loc) · 7.45 KB

README.md

File metadata and controls

200 lines (145 loc) · 7.45 KB

Tamplate

Goal

The goal for this project is to provide a multi-sbt project with Generated OpenApi documentation. This project has two main sub-modules:

  • seedName - akka-http server
  • common - common things could be defined for other sub-modules

Stack technologies

  • JDK 11
  • SBT
  • akka-http as the web server. I could have gone with finch, twitter server, or http4s here as well.
  • Circe for json serialization
  • Cats for FP awesomeness
  • ScalaTest for test
  • Tapir for automatically generating an api documentation

Resources

Architecture

Domain Driven Design (DDD)

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).

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.

Onion (or Hexagonal) Architecture

In concert with DDD, the Onion Architecture and Hexagonal Architecture from Cockburn give us patterns on how to separate our domain from the ugliness of implementation.

We fit DDD an Onion together via the following mechanisms:

The domain package The domain package constitutes the things inside our domain. It is deliberately free of the ugliness of JDBC, JSON, HTTP, and the rest. 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.

Inside of the domain, we see a few concepts:

  1. Service - the coarse grained use cases that work with other domain concepts to realize your use-cases
  2. 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.
  3. payloads or models - things like Tweet, etc are all domain objects. We keep these lean (i.e. free of behavior).

The repository package The repository package is where the ugliness lives. It has JDBC things, and the like. it contains implementations of our Repositories. We may have 2 different implementations, an in-memory version as well as a doobie version.

The http package It contains the HTTP endpoints that we surface via akka-http. You will also typically see JSON things in here via circe

The util package The util package could be considered infrastructure, as it has nothing to do with the domain.

NOTE All business logic is located in domain package, every package inside is related to some domain.

Service classes contains high level logic that relate to data manipulation, that means that services MUST NOT implement storage.

For storage there are dedicated classes.

Command line

In order to run locally on a developer machine via the command line, go to source folder and execute

~/your-project-name/> sbt runServer

And also

~/your-project-name/> sbt ";project seed-api; ~reStart"

Exmaple

Try from commandline

curl -X GET "http://localhost:9000/api/v1/tweet/funnytweets?limit=10" -H "accept: application/json"

Try from swagger-ui
Open http://localhost:9000/docs/ in your browser

Pre-Commit Hook

Pre Commit is a project on github to setup and maintain git commit hooks. The default hooks are defined in .pre-commit-config.yaml

For installation on osx run

brew install pre-commit

To setup the hooks with pre-commit run:

pre-commit install -f --install-hooks

After that scalafmt checks your changed files for codestyle:

Note: Conflicts should be resolved

Deployment

This section describes how to deploy template to either STAGE or PROD.

Dependency Udpates

sbt dependencyUpdates

Lists newer versions of integrated dependencies from Maven/Ivy

sbt dependencyUpdates

Pre-Commit Hook

This is for manage and configure Git hooks. We setup scalastyle and scalafmt for this project. pre-commit-hook is a Git hook manager that runs scalafmt on CHANGED .scala and .sbt files each time you commit them. It doesn’t allow you to commit if in your code something is not satisfactory with your configuration file.

pre-commit install -f --install-hooks

pre-commit

We use pre-commit to setup and maintain shared commit hooks. Its configured in .pre-commit-config.yaml with scalastyle and scalafmt

  • .scalafmt.conf (see pre-commit-hook.yaml)
  • scalastyle-config.xml - (see pre-commit-hook.yaml)

Install pre-commit either via pip OS independently:

pip install pre-commit

or via homebrew if you are on Mac OS:

brew install pre-commit

Register the hooks

pre-commit install -f --install-hooks

NOTE: make sure that you have above tools locally installed. For that, follow the instruction on:

You can also run scalafmt, scalastyle through sbt scalafmt/sbt scalastyle yet we use it for the pre-commit hook.

Conflicts MUST BE resolved. The pre-commit will only show the error, not automatically fix them. To fix some issues automatically, run scalafmt and/or scalastyle yourself.

More about Git hook for scalstyle and scalafrm

Known issues

Please change in SwaggerRoutes

getFromResourceDirectory("META-INF/resources/webjars/swagger-ui/swaggerVersion/")

to

getFromResourceDirectory(s"META-INF/resources/webjars/swagger-ui/$swaggerVersion/")

Configuration via Pureconfig

Pureconfig's config file does not support uppercase and underscores. Read here

Integration test

We use sbt suggested structure for integration test.

src
  >it
  >main
  >test

How to use sbt-coverage

Run the tests with enabled coverage:

$ sbt clean test

To generate the coverage reports run

$ sbt coverageReport

Coverage reports will be in target/scala-2.12/scoverage-report/index.html.