Sometimes you are in a situation, where you allow one artifact to use another one, but would like to restrict the usage to dependencies of a certain type. For example let us assume you do not want the UI layer to create new instances of classes defined in the "Model" layer. Only "Business" and "Persistence" would be allowed to create "Model" instances. You can solve this by creating a new interface that restricts the usage of certain dependency types:
artifact UI { include "**/ui/**" connect to Business, Model.UI } artifact Business { include "**/business/**" connect to Persistence, Model } artifact Persistence { include "**/persistence/**" connect to Model } artifact Model { include "**/model/**" interface UI { include all // everything in "Model" exclude dependency-types NEW } }
Now it would be marked as an architecture violation if a class from the UI layer would create a new instance of an object from the model layer. Please note that we had to remove the public modifier from "Model". If we had kept it there would have been an implicit connection from UI to the default interface of Model bypassing our special restriction.
Currently the language supports the following list of language agnostic abstract dependency types:
// instance creation NEW // inheritance EXTENDS // interface implementation IMPLEMENTS // function or method calls CALL // reading a field or variable READ // writing to a field or variable WRITE // all other uses USES
In the next section we will look at another advanced concept called "connection schemes".