Domain Driven Refactoring
Over time, applications can become susceptible to technical debt and inefficient code. Through targeted refactoring, we can optimize your applications sustainably and make them future-proof.
Before accompanying you in your refactoring journey, we would like to present you with a possible approach that focuses on maintaining and ensuring the functionality of your application systems.
How does Domain Driven Refactoring work?
Technical, tactical, and team organizational Domain-Driven Transformation
Step 1: Ensure technical stability
Step 2: Strengthen domain expertise
Strategic Domain-Driven Transformation
Step 3: Rediscovery of the domain
Step 4: Modeling the domain's target architecture
Step 5: Aligning current and target architectures
Technical, tactical, and team organizational Domain-Driven Transformation
Before strategic measures can be taken, we ensure that the technical foundation of your applications is prepared for your future developments. Building on this, team organizational measures can be taken to increase the efficiency and productivity of the development processes.
Step 1: Ensure technical stability
Automate build and deployment processes
Automate building, testing, and deploying the application after every commit using CI/CD servers like Jenkins, GitHub Actions, or GitLab CI, and utilize partial deployments.
Ensure consistent infrastructure resources
Deploy infrastructure resources independent of providers using Infrastructure as Code solutions with Terraform and leveraging AWS, Azure, and GCP providers.
Strengthen your technology base
Update programming languages, frameworks, and dependencies to their latest versions to close security gaps, improve performance, and potentially adopt alternative frameworks.
Track down bugs
We increase your test coverage during bug fixing and apply the scout rule by revising code and covering it with tests. This includes implementing various types of tests such as unit tests for classes, integration tests for components, and UI tests for the frontend.
Resolve compiler warnings
In programming languages like Java and TypeScript, warnings and error messages are issued during startup and operation. Neglected syntax changes or outdated code standards are brought up to date based on your chosen programming language.
Introduce code metrics
To maintain an overview of code quality even after changes, introduce metrics such as test coverage, code complexity, and code quality. Use dashboard solutions like SonarQube or CodeCov to detect cyclomatic complexity and security vulnerabilities early on.
Ensure general error robustness
Focusing on robustness against null pointers, ensuring the functionality of classes and interfaces, and handling unexpected behaviors. At this point, we support you in implementing optionals, exception handling, and design by contract.
Implement security policies
By implementing security policies such as preventing SQL injections, cross-site scripting, and restricting access to databases and functions, we prioritize the security of your application.
Step 2: Strengthen domain expertise
Separate domain-specific and technical code
Measures include separating database access from domain-specific source code through repositories, moving user interface accesses from domain classes to the UI layer, and reviewing inheritance relationships between domain-specific and technical classes.
Increase cohesion
Using the existing Ubiquitous Language, we develop domain models enriched with domain-specific knowledge. Classes serve a specific purpose and are not overloaded with getter and setter methods.
Make the domain visible
The source code should always reflect the respective domain expertise. To achieve this, we replace standard types with domain-specific types and make the identity of entities immutable.
Reduce coupling
On one hand, we divide existing modules into smaller, domain-separated bounded contexts. Additionally, we resolve cycles, replace direct references with ID references, and improve the folder structures of your repository.
Use documentation effectively
Domain expertise should not only exist in the minds of developers. Therefore, we assist you in creating domain stories or domain events within existing source code.
Software as a socio-technical system
Each repository is not future-proof without interaction between developers, business areas, and end users. If you have already adjusted the architectural cut and team organization, we would be happy to be part of your stream-aligned or platform teams.
Strategic Domain-Driven Transformation
To reflect domain expertise in your application systems' source code, database model, and infrastructure level, we have identified exemplary measures to help you gain an initial impression of the possibilities of domain-driven transformation.
Step 3: Rediscovery of the domain
Identify the current situation
Together with your domain experts, domain modelers, and developers, we participate in your discussions and workshops to identify the Ubiquitous Language and exclude technical jargon from the discussion.
Identify essential processes
Which steps are actually justified by domain expertise? We assist you in transitioning the current application to technically superior solutions and reducing the depicted processes to their essence.
Find subdomains in the target process
After identifying the current situation, we adjust the depicted software processes to the target processes.
Step 4: Modeling the domain's target architecture
Create target Context Map
From each identified subdomain, we create a bounded context that will represent the target state. These bounded contexts can emerge from event storming, domain stories, etc.
Categorize subdomains
Based on the existing subdomains of work processes, we create a context map that divides your subdomains into Core, Supporting, and Generic Subdomains. These subdomains support the team in dividing legacy systems into microservices or modular monoliths.
Assign bounded contexts to teams
During the division of application responsibilities, we can take on parts of a bounded context as part of the development team and assume technical responsibility for implementation.
Define interaction between bounded contexts
To maintain the autonomy of a subdomain, we examine the interfaces and communication paths between bounded contexts more closely.
Step 5: Aligning current and target architectures
Align target Context Map with source code
To divide overloaded domain classes into subdomains, we duplicate existing classes and reduce them to their actually required functionality. Additionally, we develop a concept for communication between domains.
Refactoring the layers of your systems
The transformation of your application systems also includes domain-specific division of your databases, user interfaces, and business logic.
Find subdomains in the target process
After identifying the current situation, we adjust the depicted software processes to the target processes. Let's find relationships and subdomain boundaries in the source code. Domain-Driven Design can assist us with domain storytelling, event storming, and identification of pivotal events.