10000 GitHub - m2f-kt/Archer: Arrow Companion that implements Clean architecture backbone
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

m2f-kt/Archer

Repository files navigation

Coverage Status License Maven Central

Archer

Archer is a lightweight framework for FCA (Functional Clean Architecture). It’s based on Arrow as a foundation and provides all the necessary elements.

Installation

dependencies {
    implementation("com.m2f-kt:archer-core:{version}")
}

Clean Architecture in a nutshell

Normally when we talk about clean architecture we can state its benefits:

  • Abstraction
  • Reusability
  • Scalability

But it comes with serious tradeoffs:

  • Boilerplate
  • Maintainability
graph LR

UC["UC"]

Repo["Repo"]

DSL(("DSL"))

DSR(("DSR"))

MRTD{{"Map to Domain"}}

MDTD{{"Map to DBO"}}

MDBTD{{"Map Domain"}}

UC -->|"1: Req data"| Repo

Repo -->|"2: Fetch remote"| DSR

DSR -->|"3: Return data"| MRTD

MRTD -->|"3a: Map to Domain"| Repo

Repo -->|"4: Store local"| MDTD

MDTD -->|"4a: Map to DBO"| DSL

DSL -->|"5: Return data"| MDBTD

MDBTD -->|"5a: Map to Domain"| Repo

Repo -->|"6: Return data"| UC

classDef mapping fill:#b44,stroke:#333,stroke-width:2px;

class MRTD,MDTD,MDBTD mapping;
Loading

Legend

DSL -> DataSource Local
DSR -> DataSource Remote
UC  -> UseCase

To implement this diagram we would need normally an interface and implementation for each of the actors in the diagram, this is:

  • Usecase interface + Implementation (Optional)
  • Repository interface + Implementation
  • N * (DataSources + Implementation) where N is the number of different datasources the repository would orchestrate. ( on average 2)
  • X + Y Mappers Where X is the number of models different than the domain and Y is the number of data sources that expects and input model (database for example)

If we follow the previous example diagram we may need:

  • 2 Usecase elements
  • 2 Repository Elements
  • 4 DataSource Elements (network and local)
  • 3 Mappers (network -> domain), (local -> domain), (domain -> local)

What does Archer provide?

This structure can be tedious to implement and the more use cases you need, the harder to maintain it comes. Archer provides contractual data sources and Repositories for you to avoid the need to create all the boilerplate ( except the mapping, sorry, mappings are needed :D).

With archer that same structure could be implemented the following way:

// This DSL creates a GetDataSource, a computation that accepts an Int and returns a String
val remoteDataSource = getDataSource<Int, String> { param: Int -> “${ param }” }

// This is a default storage but devs can implement their own one.
// A Store dataSource has 2 tipe of queries, Get<Int> and Put<Int, String>, and the developer
// can implement both in order to provide a storage mechanism
val store: StoreDataSource<Int, String> = InMemoryDataSource()

val repositoryStrategy = remoteDataSource cacheWith store expiresIn 5.minutes

// ice stands for Idle | Content | Error
val resultIce = ice {
    repository.get(StoreSync, 0)
}

// Arrow's Either
val resultEither = either {
    repository.get(StoreSync, 0)
}

val resultNullable = nullable {
    repository.get(StoreSync, 0)
}

val resultFailingIce = ice {
    raise(DataNotFound)
}

result shouldBe Ice.Content("0")
resultEither shouldBe Right("0")
resultNullable shouldBe "0"
resultFailingIce shouldBe Ice.Error(DataNotFound) // with either and nullable DSLs it would be Either.Left(DataNotFount) and null respectively

About

Arrow Companion that implements Clean architecture backbone

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  
0