Cron Merdek
Cron Merdek

Reputation: 1124

How to keep track of dependencies with immutable design?

What is the way to design software in functional way, when there are dependencies between objects?

class Link(val name: String, val links: Vector[Link] = Vector()){

    def changeName(newName: String): Link = {
        new Link(newName, links)
    }

    def connect(other: Link): Link = {
        new Link(name, links :+ other)
    }
}

object Main
{
    def main(args: Array[String]): Unit = {
            val A = new Link("A")
            val B = new Link("B")
            val Alinked = A connect B 
            val updatedB = B changeName "B2"
            println(Alinked.links.contains(updatedB))
    }
}

Output

false

I connect A and B, but then B is being changed. It implies, that I have to reconnect new object to previous. In complex hierarchies it can get really hard to control such updates.

How to make automatical relinking? Delegates? Actors?

Upvotes: 3

Views: 95

Answers (1)

0__
0__

Reputation: 67310

If you need to keep the identity of immutable copies of objects together, I think one solution is to introduce a unique identifier:

case class Link(id: Int)(val name: String, val links: Vector[Link] = Vector()) {
  def changeName(newName: String): Link =
    new Link(id)(newName, links)

  def connect(other: Link): Link =
    new Link(id)(name, links :+ other)
}

def test(): Boolean = {
  val A         = Link(0)("A")
  val B         = Link(1)("B")
  val Alinked   = A connect B 
  val updatedB  = B changeName "B2"
  Alinked.links.contains(updatedB)
}

assert(test())

That is, once an object is created, you carry the same id across all copies. The case class here makes sure that equals is correctly defined by looking at the id field.

Upvotes: 1

Related Questions