Slide 1

Slide 1 text

@yot88 Test your Architecture with ArchUnit

Slide 2

Slide 2 text

@yot88 Your current software architecture In group, discuss what are your current architecture rules inside your team and how you ensure that your code is always matching those rules Examples : All our events must reside in the events package Our repository layer can only be accessed through our application layer …

Slide 3

Slide 3 text

https://www.archunit.org/ ArchUnit is a free, simple and extensible library for checking the architecture of your Java code. It does so by analyzing given Java bytecode, importing all classes into a Java code structure. ArchUnit’s focus is to automatically test architecture and coding rules, using any plain Java unit testing framework.

Slide 4

Slide 4 text

@yot88 “Once upon a time somebody experienced looked at the code and drew up some nice architecture diagrams, showing the components the system should consist of, and how they should interact. But when the project got bigger, the use cases more complex, and new developers dropped in and old developers dropped out, there were more and more cases where new features would just be added in any way that fit. And suddenly everything depended on everything, and every change could have an unforeseeable effect on any other component. Of course, you could have one or several experienced developers, having the role of the architect, who look at the code once a week, identify violations and correct them. But a safer way is to just define the components in code and rules for these components that can be automatically tested, for example as part of your continuous integration build.” ArchUnit’s promise

Slide 5

Slide 5 text

What can be done with it ? – Checks https://www.archunit.org/use-cases Namespace Dependency Checks Types().That().ResideInNamespace("Model").Should() .NotDependOnAny(Types().That().ResideInNamespace("Controller")); Class Namespace Containment Rule Attribute Access Rule Classes().That().HaveNameContaining("Canvas").Should() .ResideInNamespace(typeof(ICanvas).Namespace); Classes().That().DoNotHaveAnyAttributes(typeof(Display)).Should() .NotDependOnAny(Classes().That().AreAssignableTo(typeof(ICanvas)));

Slide 6

Slide 6 text

What can be done with it ? – Checks https://www.archunit.org/use-cases Layers Checks Cycle Rule Slices().Matching("Module.(*)").Should() .BeFreeOfCycles(); [Fact] public void TypesShouldBeInCorrectLayer() { IArchRule exampleClassesShouldBeInExampleLayer = Classes().That().Are(ExampleClasses).Should().Be(ExampleLayer); IArchRule forbiddenInterfacesShouldBeInForbiddenLayer = Interfaces().That().Are(ForbiddenInterfaces).Should().Be(ForbiddenLayer); //check if your architecture fulfills your rules exampleClassesShouldBeInExampleLayer.Check(Architecture); forbiddenInterfacesShouldBeInForbiddenLayer.Check(Architecture); //you can also combine your rules IArchRule combinedArchRule = exampleClassesShouldBeInExampleLayer .And(forbiddenInterfacesShouldBeInForbiddenLayer); combinedArchRule.Check(Architecture); }

Slide 7

Slide 7 text

How to use it in .NET ? Add dependency(ies) Define your own rules as described after Check your rules with your favorite test runner (xUnit here) https://archunitnet.readthedocs.io/en/latest/guide/

Slide 8

Slide 8 text

@yot88 Archunit – Layered Architecture Presentation Layer (Controller) Application Layer (Service) Data Access Layer (Repository) Model (Service) https://github.com/ythirion/archunit-examples

Slide 9

Slide 9 text

Archunit – Layered Architecture Explains why it fails Presentation Layer (Controller) Application Layer (Service) Data Access Layer (Repository) Model (Service) Define your Layers Define Layer rules

Slide 10

Slide 10 text

@yot88 Why use it ? • Can be really difficult to maintain clean boundaries between layers Team rules can easily be broken by inadvertence • Document your architecture decisions (at least structural ones) With a clear DSL • Automate their check and ensure to respect them at any time Can easily be checked with ScalaTest in your CI

Slide 11

Slide 11 text

@yot88 What else can we do with it ?

Slide 12

Slide 12 text

@yot88 Reading Writing ArchUnit can help us ensure our guidelines and reduce cognitive load while reading code Remember this

Slide 13

Slide 13 text

@yot88 Archunit – Check naming conventions All our services in a namespace “Services” should be suffixed by Service All our classes implementing ICommandHandler should be suffixed by “CommandHandler”

Slide 14

Slide 14 text

Archunit – Check team rules / guidelines Easy DSL to create custom rules, imagine in your team you decide… that interfaces should always be prefixed by a big I that controller classes should be in their dedicated package

Slide 15

Slide 15 text

Archunit – Check class dependencies Restrict class dependencies Module cycles Help identify cycle dependencies A Module1 B Module2 ctor private method

Slide 16

Slide 16 text

@yot88 Archunit – Check function return types (CommandHandler) You work with CommandHandlers and want to constrain the return values :

Slide 17

Slide 17 text

@yot88 Archunit – Check function return types (API) You work with Rest Controllers and want to force the use of a generic APIResponse in public functions

Slide 18

Slide 18 text

Arnaoudova’s six categories of linguistic anti-patterns Complete list here https://veneraarnaoudova.com/linguistic-anti-pattern-detector-lapd/LAs/ Methods that do the opposite than they say Methods that do more than they say Methods that say more than they do Identifiers whose name says that they contain more than what the entity contains Identifiers whose name says that they contain less than what the entity contains Identifiers whose name says that the opposite than the entity contains

Slide 19

Slide 19 text

Arnaoudova’s six categories of linguistic anti-patterns She studied their occurrence in 7 huge open-source projects : 11% of setters also return a value in addition to setting a field 2.5% of methods : method name and the corresponding comment gave opposite descriptions of the working of the method 64% of identifiers starting with ‘is’ turned out not to be Boolean

Slide 20

Slide 20 text

Archunit – Can check Linguistic Anti-Patterns

Slide 21

Slide 21 text

@yot88 We already use SonarQube why we should use it ? You could declare some of those rules in Sonar BUT Cost less with ArchUnit Easier rule creation We can check high level rules as well as fine-grained Layer constraints Class A cannot have dependencies on something else … We have fast feedback Even with SonarLint Already integrated in your CI / CD Just a dependency to add Rules automation with XUnit

Slide 22

Slide 22 text

@yot88 Any questions / feedback before we conclude ?

Slide 23

Slide 23 text

@yot88 Reflect • What can we do with it ? • Which rules could be useful ? • Any volunteers to go further ?