The legacy system was becoming harder to extend.
The application ran on .NET Framework, with its components communicating through WCF. Much of the business logic lived in database stored procedures, making it difficult to trace the impact of a change across the system. Further development required careful coordination.
We needed an approach that would keep day-to-day operations running while gradually making the system easier to maintain and extend.
We changed the architecture step by step.
We planned the modernisation approach, documented the key technical decisions and reviewed them with the client. New modules gradually took over responsibilities from the legacy code, allowing us to transform the application without replacing the entire system at once.
We built several modular monoliths organised around Clean Architecture, with clear responsibilities and communication between modules handled through a mediator. This gave us a clearer structure for ongoing development.
We made testing part of the development process.
We introduced a testing framework covering the full testing pyramid. Unit tests, integration tests and end-to-end tests checked the system at different levels.
Testing accompanied both the modernisation work and the development of new features. These checks helped us identify defects and assess whether changes preserved the existing behaviour.
We developed modules that could be reused.
We built access control as a reusable module that was later adopted by three other products belonging to the client. We used Azure Data Factory to implement data ingestion for the reporting module.
We also developed a new product using these two modules, extending the value of the modernisation work beyond the original platform.
We automated the processing of data from documents.
We developed a separate Azure Functions service that used Azure OpenAI to extract structured data from uploaded documents and pass it to the database. This connected document processing to the platform's data workflow.
We used AI tools to support development.
We used GitHub Copilot and Claude in our day-to-day development work. We also built an MCP server to help coding agents locate relevant code and project information for each task.
We incorporated these tools into the team's workflow alongside technical design, implementation and testing.
The modernisation created a foundation for further development.
We gradually turned the legacy application into an extensible, modular platform. Reusable modules supported additional products, while the testing framework helped us check behaviour at different levels.
We bring the experience gained through this work to operandor projects: understanding the existing system, making changes incrementally and checking the results throughout development.