Mind The Gap! Setting Up A Code Structure Building Bridges
Representation Of Architectural Concepts In Code Structures
Why do we need architecture? Complex business problems too many details to keep overview Making big problems smaller Separation of higher level aspects and their relations Create abstract views with less details Adds new complexity
Why do we need architecture? Functional view Components Layers Cross-cutting concerns Dependencies Non-Functional view Scalability Robustness Security
Architect s view
Developer s view
Different roles same objects, different views Architect Developer Representation Diagram Code (Text) Scope Broad Narrow Detail level Low (abstract) High (concrete) Reality Blue pill Red pill The Gap Diagram vs. Code Architect vs. Developer
Representation of architecture in code structures Language elements with additional roles Package Layer Class Service But: abstractions are not visible in code How does the developer know about it? Does even the architect know about it?
Representation Of Architectural Concepts In Code Structures
Example Yet Another Web Shop High level functional requirements User management Product catalog Shopping cart Order-/payment Shipping High level non-functional requirements Maintainable Scalable Robust
Technology Java EE Container Shop shop.war Deployable (Artifact)
Deployment vs. Non-Functional Requirements Scalability Availability Maintainability Artifacts Maven
Deployable artifact per component shop/ pom.xml user/ pom.xml catalog/ pom.xml cart/ pom.xml order/ pom.xml shipping/ pom.xml <groupid>com.acme.shop</groupid> <artifactid>parent</artifactid> <packaging>pom</packaging> <version>1.0.0-snapshot</version> <parent> <groupid>com.acme.shop</groupid> <artifactid>parent</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>user</artifactid> <packaging>war</packaging>
Layering a component Root package = com.acme.shop.user groupid + artifactid REST API Web UI com.acme.shop.user.rest com.acme.shop.user.web com.acme.shop.user.services.api com.acme.shop.user.services.impl com.acme.shop.persistence.dao com.acme.shop.persistence.model Services Persistence DAO Model Dependencies cannot be validated?!
Class roles in layers com.acme.shop.user.rest JAX-RS resources com.acme.shop.user.web Models, views, controllers Validators, converters com.acme.shop.user.services EJB com.acme.shop.persistence.dao DAOs com.acme.shop.persistence.model JPA entities Rules developers should know about Concepts architects should beaware about
External dependencies of a component JAX-RS REST API Web UI JSF EJB JMS Services CDI JPA DAO Persistence Model
External dependencies <parent> <groupid>com.acme.shop</groupid> <artifactid>user</artifactid> <version>1.0.0-snapshot</version> </parent> <packaging>war</packaging> Valid for all components <dependencies> <dependency> <groupid>javax.faces</groupid> <artifactid>faces-api</artifact> <version>2.2</version> <scope>provided</scope> </dependency> </dependencies> Provided by container
Dependency Management <groupid>com.acme.shop</groupid> <artifactid>parent</artifactid> <version>1.0.0-snapshot</version> <packaging>pom</packaging> <dependencymanagement> <dependencies> <dependency> <groupid>javax.faces</groupid> <artifactid>faces-api</artifact> <version>2.2</version> <scope>provided</scope> </dependency> </dependencies> </dependencymanagement>
Using managed dependencies <parent> <groupid>com.acme.shop</groupid> <artifactid>user</artifactid> <version>1.0.0-snapshot</version> </parent> <packaging>war</packaging> <dependencies> <dependency> <groupid>javax.faces</groupid> <artifactid>faces-api</artifact> </dependency> </dependencies>
Dependencies between components cart catalog user order Synchronuous - REST Asynchronuous - JMS shipping
Dependencies between components Communication via remote protocols REST over HTTP JMS Compile time dependencies not explicitly required but convenient! Re-use code Shared artifacts, i.e. libraries APIs, domain models
Splitting up a component shop/ pom.xml user/ pom.xml api/ app/ Visibilities pom.xml pom.xml api public app private <parent> <groupid>com.acme.shop</groupid> <artifactid>shop</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>user</artifactid> <packaging>pom</packaging> <parent> <groupid>com.acme.shop</groupid> <artifactid>user</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>user.api</artifactid> <parent> <groupid>com.acme.shop</groupid> <artifactid>user</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>user.app</artifactid> <packaging>war</packaging>
Splitting up a component <parent> <groupid>com.acme.shop</groupid> <artifactid>user</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>user.app</artifactid> <packaging>war</packaging> <dependency> <groupid>com.acme.shop</groupid> </artifactid>user.api</artifactid> </dependency> compile scope
Use API of another component <parent> <groupid>com.acme.shop</groupid> <artifactid>cart</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>cart.app</artifactid> <packaging>war</packaging> <dependency> <groupid>com.acme.shop</groupid> </artifactid>user.api</artifactid> </dependency> compile scope
Deployment of libraries user.app.war cart.app.war cart.api.jar user.api.jar user.api.jar Option: API versioning Cart 2.1.0 Application User 1.0 API Requires further component separation
Common functionality common-core-shared-util-helper Big balls of mud Cover mostly technical aspects layers shop/ common/ user/ pom.xml rest/ web/ pom.xml pom.xml services/ pom.xml persistence/ pom.xml <parent> <groupid>com.acme.shop</groupid> <artifactid>common</artifactid> <version>1.0.0-snapshot</version> </parent> <artifactid>common.web</artifactid> <dependencies> <dependency> <groupid>javax.faces</groupid> <artifactid>faces-api</artifactid> </dependency> </dependencies>
Component configuration Artifacts that need to bedelivered with deployables Property-, XML, YAML-files, etc... Migration scripts user/ pom.xml api/ pom.xml app/ pom.xml config/ pom.xml Deliverable artifacts (JAR, ZIP)
Test code Part of architecture shop/ test *ST.java Components user/test *CT.java Mockito Component stubs user/app *Test.java Mockito System Component Unit
Component stubs Component tests require API and implementation of own component APIs of other components Stubs for other components Stubs can be provided per owning component user/test src/main/java com.acme.shop.user.test.usermanagementstub.java Test module may depend on other test modules
Structural overview shop/ common rest web services persistence test user api app config test Libraries Components with similar structures public vs. private artifacts
Structural overview (continued) cart api com.acme.shop.api app com.acme.shop.rest com.acme.shop.ui com.acme.shop.services com.acme.shop.persistence config test test Layering in component with defined content & dependencies Component test System test
Some Observations It s an evolution Neither architecture nor code structures are static Deployment is the starting point Separate following requirements Architecture is not only about packages Build system defines core dependencies Different roles different views Architect vs. Developer vs. Build-/Integrationmanager
Representation Of Architectural Concepts In Code Structures
The Gap Architecture Different Roles Different Views Different Interests Development Code Build-/Integration -management Test
Spread The Knowledge Mr. Project Lead: Tear down these walls! Cross-functional teams Architect!= Architect Project vs. Enterprise Work together Pair Programming Reviews Establish rules Who is allowed to change POM files?
Spread The Knowledge Documentation Word Documents UML Diagrams Wiki... Keep documentation as close as possible to code! Store in version control system Generate from code
Challenges Structures and rules are dynamic Documentation is always out-of-date Teams change Difficult to avoid gaps in the long term
Spread The Knowledge! Static code analysis Define structural rules Break build on violations Provide reasonable feedback to developers Which Tool? SonarGraph Degraph jqassistant
jqassistant Open Source http://jqassistant.org Based on Neo4j Scan software structures during the build Packages, Classes, Fields, Methods Maven artifacts and dependencies Analyze Apply concepts Package com.acme.shop.cart = Component Cart Verify constraints Report Component Cart can only depend on components User, Catalog and Order
buschmais.de facebook.com/buschmais twitter.com/buschmais