Packages stay easier to test when higher-level layers depend on lower-level interfaces deliberately.

dependency direction Track which layer owns a dependency so imports do not grow into cycles.

Dependency Direction

layer
dependency_direction.go
Replay: real traced execution (multi-file project)
package main

import "fmt"

func main() {
	var layer = "handler"
	allowed := map[string][]string{
		"handler": {"domain", "log"},
		"domain":  {"time"},
		"storage": {"domain", "database/sql"},
	}

	dependencies := allowed[layer]
	stable := layer != "domain" || len(dependencies) == 1

	fmt.Println("layer=", layer)
	fmt.Println("dependency_count=", len(dependencies))
	for _, dependency := range dependencies {
		fmt.Println("depends_on=", dependency)
	}
	fmt.Println("stable_core=", stable)
}
package main

import "fmt"

func main() {
	var layer = "domain"
	allowed := map[string][]string{
		"handler": {"domain", "log"},
		"domain":  {"time"},
		"storage": {"domain", "database/sql"},
	}

	dependencies := allowed[layer]
	stable := layer != "domain" || len(dependencies) == 1

	fmt.Println("layer=", layer)
	fmt.Println("dependency_count=", len(dependencies))
	for _, dependency := range dependencies {
		fmt.Println("depends_on=", dependency)
	}
	fmt.Println("stable_core=", stable)
}
package main

import "fmt"

func main() {
	var layer = "storage"
	allowed := map[string][]string{
		"handler": {"domain", "log"},
		"domain":  {"time"},
		"storage": {"domain", "database/sql"},
	}

	dependencies := allowed[layer]
	stable := layer != "domain" || len(dependencies) == 1

	fmt.Println("layer=", layer)
	fmt.Println("dependency_count=", len(dependencies))
	for _, dependency := range dependencies {
		fmt.Println("depends_on=", dependency)
	}
	fmt.Println("stable_core=", stable)
}
  1. layer ← "handler", allowed ← map[string][]string{"domain":[]string{"time"}, "handler":[]string{"domain", "log"}, "storage":[]string{"domain", "database/sql"}}

    5func main() {6  var layer→ "handler" = "handler" //@layer="domain", "storage"7  allowed→ map[string][]string{"domain":[]string{"time"}, "handler":[]string{"domain", "log"}, "storage":[]string{"domain", "database/sql"}} := map[string][]string{8    "handler": {"domain", "log"},9    "domain":  {"time"},10    "storage": {"domain", "database/sql"},11  }1213  dependencies→ []string{"domain", "log"} := allowed[layer][]string{"domain", "log"}14  stable→ true := layer"handler" != "domain" || len(dependencies[]string{"domain", "log"}) == 11516  fmt.Println("layer=", layer"handler")17  fmt.Println("dependency_count=", len(dependencies[]string{"domain", "log"}))18  for _, dependency := range dependencies {
    outputlayer= handler
    dependency_count= 2
  2. for _, dependency := range dependencies

    pass 1 of 2
    17fmt.Println("dependency_count=", len(dependencies))18for _, dependency"domain" := range dependencies[]string{"domain", "log"} {19  fmt.Println("depends_on=", dependency"domain")20}
    outputdepends_on= domain
  3. for _, dependency := range dependencies

    pass 2 of 2
    17fmt.Println("dependency_count=", len(dependencies))18for _, dependency"log" := range dependencies[]string{"domain", "log"} {19  fmt.Println("depends_on=", dependency"log")20}
    outputdepends_on= log
  4. fmt.Println("stable_core=", stable)

    20  }21  fmt.Println("stable_core=", stabletrue)22}
    outputstable_core= true
  1. layer ← "domain", allowed ← map[string][]string{"domain":[]string{"time"}, "handler":[]string{"domain", "log"}, "storage":[]string{"domain", "database/sql"}}

    5func main() {6  var layer→ "domain" = "domain"7  allowed→ map[string][]string{"domain":[]string{"time"}, "handler":[]string{"domain", "log"}, "storage":[]string{"domain", "database/sql"}} := map[string][]string{8    "handler": {"domain", "log"},9    "domain":  {"time"},10    "storage": {"domain", "database/sql"},11  }1213  dependencies→ []string{"time"} := allowed[layer][]string{"time"}14  stable→ true := layer"domain" != "domain" || len(dependencies[]string{"time"}) == 11516  fmt.Println("layer=", layer"domain")17  fmt.Println("dependency_count=", len(dependencies[]string{"time"}))18  for _, dependency := range dependencies {
    outputlayer= domain
    dependency_count= 1
  2. for _, dependency := range dependencies

    17fmt.Println("dependency_count=", len(dependencies))18for _, dependency"time" := range dependencies[]string{"time"} {19  fmt.Println("depends_on=", dependency"time")20}
    outputdepends_on= time
  3. fmt.Println("stable_core=", stable)

    20  }21  fmt.Println("stable_core=", stabletrue)22}
    outputstable_core= true
  1. layer ← "storage", allowed ← map[string][]string{"domain":[]string{"time"}, "handler":[]string{"domain", "log"}, "storage":[]string{"domain", "database/sql"}}

    5func main() {6  var layer→ "storage" = "storage"7  allowed→ map[string][]string{"domain":[]string{"time"}, "handler":[]string{"domain", "log"}, "storage":[]string{"domain", "database/sql"}} := map[string][]string{8    "handler": {"domain", "log"},9    "domain":  {"time"},10    "storage": {"domain", "database/sql"},11  }1213  dependencies→ []string{"domain", "database/sql"} := allowed[layer][]string{"domain", "database/sql"}14  stable→ true := layer"storage" != "domain" || len(dependencies[]string{"domain", "database/sql"}) == 11516  fmt.Println("layer=", layer"storage")17  fmt.Println("dependency_count=", len(dependencies[]string{"domain", "database/sql"}))18  for _, dependency := range dependencies {
    outputlayer= storage
    dependency_count= 2
  2. for _, dependency := range dependencies

    pass 1 of 2
    17fmt.Println("dependency_count=", len(dependencies))18for _, dependency"domain" := range dependencies[]string{"domain", "database/sql"} {19  fmt.Println("depends_on=", dependency"domain")20}
    outputdepends_on= domain
  3. for _, dependency := range dependencies

    pass 2 of 2
    17fmt.Println("dependency_count=", len(dependencies))18for _, dependency"database/sql" := range dependencies[]string{"domain", "database/sql"} {19  fmt.Println("depends_on=", dependency"database/sql")20}
    outputdepends_on= database/sql
  4. fmt.Println("stable_core=", stable)

    20  }21  fmt.Println("stable_core=", stabletrue)22}
    outputstable_core= true