Class: Packwerk::Layer::Checker

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Includes:
Checker
Defined in:
lib/packwerk/layer/checker.rb

Overview

This enforces “layered architecture,” which allows each class to be designated as one of N layers configured by the client in ‘packwerk.yml`, for example:

layers:

- orchestrator
- business_domain
- platform
- utility
- specification

Then a package can configure: enforce_layers: true | false | strict layer: utility

This is intended to provide: A) Direction for which dependency violations to tackle B) What dependencies should or should not exist C) A potential sequencing for modularizing a system (starting with lower layers first).

Instance Method Summary collapse

Constructor Details

#initializeChecker

Returns a new instance of Checker.



35
36
37
# File 'lib/packwerk/layer/checker.rb', line 35

def initialize
  @violation_type = T.let(@violation_type, T.nilable(String))
end

Instance Method Details

#invalid_reference?(reference) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
52
53
# File 'lib/packwerk/layer/checker.rb', line 49

def invalid_reference?(reference)
  constant_package = Package.from(reference.constant.package, layers)
  referencing_package = Package.from(reference.package, layers)
  !referencing_package.can_depend_on?(constant_package, layers: layers)
end

#layer_configObject



103
104
105
# File 'lib/packwerk/layer/checker.rb', line 103

def layer_config
  @layer_config ||= T.let(Config.new, T.nilable(Config))
end

#layersObject



98
99
100
# File 'lib/packwerk/layer/checker.rb', line 98

def layers
  @layers ||= T.let(Layers.new, T.nilable(Packwerk::Layer::Layers))
end

#message(reference) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/packwerk/layer/checker.rb', line 70

def message(reference)
  constant_package = Package.from(reference.constant.package, layers)
  referencing_package = Package.from(reference.package, layers)

  message = <<~MESSAGE
    Layer violation: '#{reference.constant.name}' belongs to '#{reference.constant.package}', whose layer type is "#{constant_package.layer}".
    This constant cannot be referenced by '#{reference.package}', whose layer type is "#{referencing_package.layer}".
    Packs in a lower layer may not access packs in a higher layer. See the `layers` in packwerk.yml. Current hierarchy:
    - #{layers.names_list.join("\n- ")}

    #{standard_help_message(reference)}
  MESSAGE

  message.chomp
end

#standard_help_message(reference) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/packwerk/layer/checker.rb', line 88

def standard_help_message(reference)
  standard_message = <<~MESSAGE.chomp
    Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
    To receive help interpreting or resolving this error message, see: https://github.com/Shopify/packwerk/blob/main/TROUBLESHOOT.md#Troubleshooting-violations
  MESSAGE

  standard_message.chomp
end

#strict_mode_violation?(listed_offense) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
# File 'lib/packwerk/layer/checker.rb', line 60

def strict_mode_violation?(listed_offense)
  constant_package = listed_offense.reference.package
  constant_package.config[layer_config.enforce_key] == 'strict'
end

#violation_typeObject



40
41
42
# File 'lib/packwerk/layer/checker.rb', line 40

def violation_type
  @violation_type ||= layer_config.violation_key
end