Giter Site home page Giter Site logo

krefty's Introduction

Krefty

CI Licence Maven Central

Krefty is a Kotlin library that empowers the creation of domain-specific types while addressing the Primitive Obsession anti-pattern. It provides a robust framework for constructing types inspired by the Refinement Type Theory, where types are composed of a predicate and a value that satisfies it.

Krefty is particularly useful for Domain-Driven Design (DDD) users, where refined types can be viewed as a viable alternative to Value Objects. Inspired by implementations in Haskell and Scala.

Also check out Arrow-Exact and Values4k which solve the same problem.

Getting started ๐Ÿš€

Add Krefty to your dependencies:

implementation("dev.ustits.krefty:krefty-core:<latest_version>")

For snapshot versions

repositories {
    maven("https://s01.oss.sonatype.org/content/repositories/snapshots")
}

implementation("dev.ustits.krefty:krefty-core:<latest_version>-SNAPSHOT")

Usage

Refinery ๐Ÿญ

Let's consider an example where we need a type for describing names. We must ensure that the name is not empty and that we have a specific type for it:

@JvmInline
value class Name private constructor(private val value: String) {

    companion object : Refinery<String, Name>() {
        override fun Refinement<String>.refine() = filter { it.isNotBlank() }.map { Name(it) }
    }
}

We define a Name class that holds a String value. Refinery serves as a medium to fine-tune the conversion from String to Name. This is done by implementing refine() function, which applies filters to check if the string is non-empty. If the string satisfies this condition, it is then transformed into a Name instance.

You now have the ability to generate Name instances, for example by using the fromOrThrow method:

val grog = Name.fromOrThrow("Grog") // Name instance "Grog"
val void = Name.fromOrThrow("")     // throws RefinementException

For a simplified version of from, you can apply specific Refinery implementations:

  • NullRefinery
  • ThrowingRefinery
  • ResultRefinery

For instance, with ResultRefinery, the usage would look like this:

companion object : ResultRefinery<String, Name>()

Name.from("Scanlan")  // Result.success

Refinement ๐Ÿ›ข๏ธ

Refinement is a core concept in Krefty. You can think of it as a container for a value and a predicate. If the value matches the predicate, it holds that value, otherwise, it holds an error.

Refinement provides familiar operations, like map and filter, to validate and transform the refined type:

refinement
    .filter { it.isNotBlank() }
    .map { NotBlankString(it) }
    .flatMap { refine(it, this::isName) }

Refinery itself can also be used as a transformation:

refinement
    .filter(NotBlankString)
    .flatMap(Name)

You can also use Refinement separately from Refinery, for example by using refine function:

val name = refine("Krefty") { it.isNotBlank() } 
name.getOrThrow()       // "Krefty"
name.isRefined()        // true

val version = refine("") { it.isNotBlank() }
version.getOrThrow()    // throws RefinementException
version.isRefined()     // false

For refinements that involve side effects, the suspendRefine function can be used:

suspendRefine("94926946-2e51-4b14-a9bd-2ce9ad02b29b") {
    service.existsById(it)
}

class Service {
    suspend fun existsById(id: String): Boolean
}

Arrow

Krefty can be used with Either type from Arrow. In order to use it add krefty-arrow to your dependencies:

implementation("dev.ustits.krefty:krefty-arrow:<latest_version>")

Then you can use EitherRefinery to get results as an Either:

Name.from("Keyleth") // Either<RefinementError, Name>

krefty's People

Contributors

ustitc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

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.