Mind The Gap!
Setting Up A Code Structure
Building Bridges
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
Why do we need architecture?
Functional view
Components Layers
Cross-cutting concerns Dependencies
Non-Functional view
Scalability Robustness Security
Architect‘s
view
…
…
Different roles
same objects, different views
The Gap
Diagram vs. Code
Architect vs. Developer
Architect Developer
Representation Diagram Code (Text)
Scope Broad Narrow
Detail level Low (abstract) High (concrete)
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?
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
Technology
Java EE
Shop shop.war Container
Deployable (Artifact)
Deployment vs. Non-Functional Requirements
Scalability
Availability
Maintainability
Artifacts
Deployable artifact per component
shop/
pom.xml user/ pom.xml catalog/ pom.xml cart/ pom.xml order/ pom.xml shipping/ pom.xml <parent> <groupId>com.acme.shop</groupId> <artifactId>parent</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>user</artifactId> <packaging>war</packaging> <groupId>com.acme.shop</groupId> <artifactId>parent</artifactId> <packaging>pom</packaging> <version>1.0.0-SNAPSHOT</version>Layering a component
Root package = com.acme.shop.user
groupId + artifactId
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
Dependencies cannot be validated?!
REST API Web UI
Services
Persistence
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
EJBcom.acme.shop.persistence.dao
DAOscom.acme.shop.persistence.model
JPA entities Rules developers should know aboutConcepts architects should be aware
External dependencies of a component
REST API Web UI
Services
Persistence JAX-RS
EJB
JSF
JPA
CDI
DAO Model
External 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> <version>2.2</version><scope>provided</scope>
</dependency> </dependencies>
Provided by container Valid for all components
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>
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 between components
user
catalog
order cart
shipping
Synchronuous - REST Asynchronuous - JMS
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/ pom.xml app/ pom.xmlVisibilities
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>
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>
Deployment of libraries
Option: API versioning
Cart 2.1.0 Application User 1.0 API Requires further component separation
user.app.war cart.app.war
user.api.jar cart.api.jar user.api.jar
Common functionality
common-core-shared-util-helper
Big balls of mud
Cover mostly technical aspects
layers
shop/
common/ pom.xml rest/ pom.xml web/ pom.xml services/ pom.xml persistence/ pom.xml user/ <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 be delivered 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
Unit Component
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
Structural overview
shop/
common rest web services persistence test user api app config test … Libraries Components with similar structuresStructural 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 … testLayering in component with defined content &
dependencies
Component 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
The Gap
Code
Architecture Development
Test Build-/Integration
-management
Different Roles Different Views Different Interests
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
Spread The Knowledge
Documentation
Word Documents UML Diagrams Wiki
...
Keep documentation as close as possible to code! Store in version control system
Challenges
Structures and rules are dynamic
Documentation is always out-of-date
Teams change
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
Component „Cart“ can only depend on components „User“, „Catalog“ and „Order“