Skip to content

Instantly share code, notes, and snippets.

@tvoklov
Created March 28, 2023 17:52
Show Gist options
  • Save tvoklov/8457b8c3f7eb1b12c1837c92563ad9fb to your computer and use it in GitHub Desktop.
Save tvoklov/8457b8c3f7eb1b12c1837c92563ad9fb to your computer and use it in GitHub Desktop.

HI!!!!!

TODAY I WILL MAKE INSANE DI USING SCALA THAT YOU WILL HATE!!! ZIO DOES IT BETTER, BUT ZIO SUCKS FOR OTHER REASONS!!!!

OK, LETS GO!!!

import cats.Monad

import scala.reflect.ClassTag

object DiMoreLikeDontInjectthings extends App {

  trait SomeTrait[F[_]] {
    def someFunc: F[Unit]
    def someOtherFunc(withParam: String): F[Int]
  }

  object SomeTrait {

    def apply[F[_]: SomeTrait]: SomeTrait[F] = implicitly

  }

  case class BigConfig(smallConfig: SmallConfig)
  case class SmallConfig(value1: String)

  object SmallConfig {

    implicit def smallConfig(implicit bigConfig: BigConfig): SmallConfig = bigConfig.smallConfig

  }

  class ProductionTrait[F[_]: Monad](config: SmallConfig) extends SomeTrait[F] {
    println("initiating production")

    override def someFunc: F[Unit]                        = Monad[F].pure(println("using production"))
    override def someOtherFunc(withParam: String): F[Int] = ???
  }

  object ProductionTrait {

    implicit def productionTrait[F[_]: Monad](implicit smallConfig: SmallConfig): ProductionTrait[F] =
      new ProductionTrait[F](smallConfig)

  }

  class Stub[F[_]: Monad] extends SomeTrait[F] {
    println("initiating stub")

    override def someFunc: F[Unit]                        = Monad[F].pure(println("using stub"))
    override def someOtherFunc(withParam: String): F[Int] = ???
  }

  object Stub {

    implicit def stub[F[_]: Monad]: Stub[F] =
      new Stub[F]

  }

  def usingTrait[F[_]: SomeTrait] = SomeTrait[F].someFunc

  val prodCode = {
    implicit val bigConfig = BigConfig(SmallConfig("value 1"))

    import SmallConfig._
    import ProductionTrait.productionTrait

    println("RUNNING PROD CODE")

    usingTrait[Option]
    usingTrait[Option]

    println()
  }

  val stubCode = {
    implicit val bigConfig = BigConfig(SmallConfig("value 1"))

    import Stub._

    println("RUNNING STUB CODE")

    usingTrait[Option]
    usingTrait[Option]

    println()
  }

  object ProductionTrait2 {

    private var productionTraitInstances: Map[ClassTag[_], Any] = Map.empty

    implicit def productionTrait[F[_] : Monad](implicit smallConfig: SmallConfig, classTag: ClassTag[F[_]]): ProductionTrait[F] = {
      productionTraitInstances.get(classTag) match {
        case Some(value) => value.asInstanceOf[ProductionTrait[F]]
        case None =>
          val pt = new ProductionTrait[F](smallConfig)
          productionTraitInstances = productionTraitInstances + (classTag -> pt)
          pt
      }
    }

  }

  val prodCodeUsingASinglePT = {
    implicit val bigConfig = BigConfig(SmallConfig("value 1"))

    import SmallConfig._
    import ProductionTrait2._

    println("RUNNING PROD CODE, BUT IT DOESNT INITIATE PROD EVERY TIME")

    usingTrait[Option]
    usingTrait[Option]
    usingTrait[Option]
    usingTrait[Option]

    println()
  }

}

running this code returns the following output:

RUNNING PROD CODE
initiating production
using production
initiating production
using production

RUNNING STUB CODE
initiating stub
using stub
initiating stub
using stub

RUNNING PROD CODE, BUT IT DOESNT INITIATE PROD EVERY TIME
initiating production
using production
using production
using production
using production

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment