As the financial technology (Fintech) landscape continues to evolve at a rapid pace, the necessity for upgrading products built in the 1990s has become increasingly evident. These legacy systems, once pioneering in their time, now grapple with a multitude of challenges that hinder their ability to meet contemporary demands. The primary issue lies in the outdated code bases, which need to be designed to handle the complexities of modern financial transactions, regulatory requirements, and cybersecurity threats. These systems often need more flexibility to integrate with newer technologies, leading to inefficiencies and increased operational risks. Furthermore, maintaining and updating legacy code is resource-intensive, requiring specialized knowledge that is becoming scarce as the workforce familiar with these older technologies retires.
However, the conversion process from VB6 to C # offers a promising solution. It can enable your systems to support new functionalities, scale effectively, and provide a high level of security and user experience that today’s market demands. This modernization process, with our expertise at Founding Minds Software, can lead to a more competitive and compliant Fintech industry.
Challenges and Key Considerations in Upgrading Legacy Fintech Products
One significant challenge when upgrading Fintech products is dealing with Integrated Development Environments (IDEs). These older systems often rely on development tools and environments that have become obsolete or significantly evolved. For example, many Fintech applications from the 1990s were developed using earlier versions of Visual Studio, often with Visual Basic (VB) as the programming language of choice.
What is COM?
COM (Component Object Model) is a Microsoft framework that allows software components to interact regardless of the programming languages they were written in. It provides a way for different applications to communicate through a common set of interfaces and follows a binary standard, ensuring compatibility at a low level.
Although COM has been foundational in the Windows ecosystem, it can be complex and has certain limitations. With the advent of .NET, many of COM’s functions are now handled in more modern and managed ways, but COM remains important in legacy systems and specific interoperability scenarios.
Running Old Visual Basic Code
Running old VB code in modern environments poses several challenges:
1. Compatibility Issues: Modern versions of Visual Studio have largely abandoned native support for older VB6 code. While some compatibility options exist, they are often limited and may not support all the features and libraries used in the original code. For instance, certain VB6 features, such as late binding, may not be fully supported in C #, which can lead to issues during the migration process.
2. Environment Compatibility Challenges: While modern servers might technically support VB6 applications, relying on them for long-term operations is not advisable. The inherent compatibility, security, performance, and maintenance limitations highlight the critical need to modernize these legacy systems.
3. Migration Complexity: Upgrading VB6 code to newer versions like C# involves significant code changes. The syntax and structure of C# are different, and automated migration tools often fall short, requiring extensive manual intervention.
4. Dependencies and Libraries: Many 1990s Fintech applications rely on third-party libraries or components that are no longer maintained. These dependencies might not work with newer IDEs or pose security risks if they no longer receive updates.
Below are some additional challenges:
1. Complex Interdependencies: Over time, intricate dependencies between modules, databases, and external systems may have evolved, making it difficult to isolate and update specific components without impacting others.
2. Regulatory Compliance: Ensuring compliance with current regulatory standards and requirements poses a challenge, as older systems may not have been designed with modern regulations in mind.
3. Security Vulnerabilities: Legacy systems are more susceptible to security breaches due to outdated protocols and a lack of ongoing security updates.
4. Scalability and Performance: Legacy Fintech products may need help to scale to handle increased transaction volumes and may not leverage advancements in performance optimization.
5. Skills and Knowledge Transfer: Finding developers with expertise in outdated technologies like VB6, COBOL, Fortran, or older versions of languages like C/C++ can be challenging. Moreover, knowledge transfer from retiring staff adds to the complexity.
6. User Experience Expectations: Modern users expect intuitive interfaces and seamless experiences. This includes features such as responsive design, real-time updates, and personalized content. However, older Fintech products may not provide these features without significant redesign and modernization. Therefore, it’s important to consider user experience when planning the upgrade and to ensure that the new system meets these expectations.
What is UnManaged Code?
Unmanaged code refers to software that runs directly on the operating system without the safety features, memory management, or runtime checks provided by a managed runtime environment like the .NET Common Language Runtime (CLR) or the Java Virtual Machine (JVM). It is typically written in low-level languages like C, C++, or Assembly, which allow direct memory manipulation and require manual resource management.
Critical Considerations for Upgrading Projects
When approaching the modernisation of these legacy systems, several factors must be taken into account:
1. Assessment of Existing Code: Conduct a thorough analysis of the current code base to understand its structure, dependencies, and any potential compatibility issues. This includes identifying any proprietary or outdated libraries that may need to be replaced. The assessment should also consider the system’s architecture, data flow, and business logic. This step is crucial as it forms the basis for the migration strategy and helps identify potential risks and challenges.
2. Choosing the Right Tools: Select IDEs and tools that offer the best support for legacy code while facilitating the transition to modern technologies. This might involve using specialized migration tools or opting IDEs that provide robust backward compatibility options.
3. Incremental Upgrades: Rather than attempting a complete overhaul in one go, consider an incremental approach. This involves gradually refactoring and replacing components of the system. For example, you could start by converting a small module or a single feature from VB6 to C #. This approach can help manage risks and maintain functionality throughout the upgrade process. It also allows for continuous testing and validation, ensuring that each component works as expected before moving on to the next one.
4. Testing and Validation: Rigorous testing is crucial to ensure that the upgraded system performs as expected. This includes not only functional testing but also performance, security, and compliance checks to meet current standards.
5. Skills and Expertise: Ensure that the team working on the upgrade has the necessary expertise in both the old and new technologies. This might require specialized training or hiring consultants with experience in legacy systems.
6. Documentation and Knowledge Transfer: Legacy systems often need better documentation. Improving and updating documentation during the upgrade process is essential for future maintenance and scalability.
Key Technical Considerations for Upgrading Projects
Here are some critical technical areas to consider when undertaking an upgrade
1. Limiting the Use of Win32 APIs
In VB6, we can use win32 APIs to perform specific tasks. One such is given below
Declare Function CreateFile Lib “kernel32” Alias “CreateFileA” _
(ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
The API mentioned above creates a file by calling the CreateFileA method, which is executed by the Windows operating system’s kernel32 module. If we convert this code to C#, it will use its .NET counterpart, as shown below.
[DllImport(“kernel32.dll”, EntryPoint = “CreateFileA”, CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
extern public static int CreateFile([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpFileName, int dwDesiredAccess, int dwShareMode, System.IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
However, this is not the desired result since the above method uses unmanaged code. This can lead to memory leaks and other resource management issues. In .NET, it’s better to use managed code for file manipulation, such as the System.IO.File class, which provides a safer and more reliable way to work with files.
2. Steer Clear of the Microsoft.VisualBasic Namespace
This Microsoft.VisualBasic namespace contains a lot of the old VB 6.0 runtime functions which you should try and avoid using in a .NET solution. If you’re writing new code, consider using standard .NET libraries or other modern .NET practices instead of Microsoft.VisualBasic namespace. If you’re dealing with legacy code that relies on this namespace, consider refactoring to use more modern and commonly accepted .NET patterns.
3. Watch Out for Runtime Errors
The converted code may contain many runtime errors, so we need to be ready to debug and fix them. If an error occurs in a module that doesn’t align with .NET standards, it might be better to rewrite the code. This approach can save time and effort in the long run, leading to more robust code.
4. Adhering to Naming Conventions and Code Style
VB6 and C# have different naming conventions and coding style guidelines, and companies may also have their own coding standards. Ensure that the converted code follows these conventions and guidelines to improve readability and maintainability.
5. Handling Errors
Examine the error handling mechanisms. VB6 used `On Error GoTo` for error handling, while C# uses `try-catch-finally`. Ensure proper translation and consider improving error-handling practices.
6. Assessing Control Structures and Logic Flow
Review the control structures (e.g., `if`, `for`, `while`) for logical consistency. The conversion tool might only sometimes correctly handle complex logic, so manual verification is essential.
7. Exercise Caution with Memory Management
VB6 relied on manual resource management, while C# benefits from garbage collection. Verify that resources are appropriately managed, mainly when dealing with unmanaged resources or external libraries.
By addressing these challenges and considerations, Fintech companies can effectively modernize their legacy systems, ensuring they remain robust, secure, and capable of meeting the demands of today’s financial landscape.
What are win32 APIs?
Win32 APIs, or Windows 32-bit Application Programming Interfaces, are a comprehensive set of functions and services provided by Microsoft for interacting with the Windows operating system. They form the backbone for Windows-based software development, allowing applications to perform a wide range of operations, such as managing system resources, interacting with hardware, handling user interfaces, networking, and much more.
Post-Completion Steps for a Module in Code Conversion from VB6 to C#
Testing code converted from VB6 to C# involves a structured approach to ensure that the new implementation is functionally equivalent to the original and performs as expected. Here’s a detailed plan to test the converted code:
-
Initial Preparation
-
Understand the Original Functionality
- Documentation Review: Gather and review any existing documentation, including requirements, specifications, and user manuals for the original VB6 application.
- Functional Analysis: Understand the core functionalities, workflows, and user interactions in the VB6 application.
-
Setup Testing Environment
- Parallel Environments: Set up two environments, one for the original VB6 application and another for the converted C# application, ensuring that they mimic production settings.
- Test Data: Prepare or replicate test data that covers various scenarios, including edge cases, for both applications.
-
Understand the Original Functionality
-
Testing Strategy
- Unit Testing: Write Unit Tests: For the C# application, write comprehensive unit tests to cover all functions and methods. Use a testing framework like MSTest, NUnit, or xUnit.
- Mock Dependencies: Use mocking frameworks like Moq to isolate units and test them independently.
-
Types of Testing
-
Functional Testing
- Functional Test Cases
- Automated Functional Tests
-
Regression Testing
- Run Regression Tests
- Integration Testing
-
End-to-end Testing:
Conduct end-to-end tests that simulate real user scenarios to ensure all components work seamlessly together.
-
Functional Testing
-
-
- Comparison Testing
- Behavioral Comparison
- Side-by-Side Execution of VB6 and C# applications
- Consistency Check
- Data Integrity
- Data Comparison
-
Performance Testing
- Benchmarking
- Performance Metrics using the VB6 application
- Performance Tests on the C# application
-
User Acceptance Testing (UAT)
- Stakeholder Involvement
- Engage Users for valuable feedback on usability and functionality
- Acceptance Criteria
-
-
Error Handling and Debugging
- Logging and Monitoring: Ensure robust logging mechanisms in the C# application to capture errors and exceptions.
- Monitor for Issues: Continuously monitor both applications during testing phases to identify and resolve any issues promptly.
-
Documentation and Review
- Update Technical Documentation: Update technical documentation to reflect changes in architecture, code, and functionality.
- User Manuals: Revise user manuals to guide users on any changes in the new application.
- Peer Code Review: Conduct thorough code reviews to ensure code quality, consistency, and adherence to best practices.
- Refactoring: Refactor code based on review feedback to improve performance, readability, and maintainability.
By following this comprehensive testing plan, you can ensure that the converted C# application is reliable, efficient, and functionally equivalent to the original VB6 application.
Conclusion
Converting legacy VB6 applications to C# is a crucial step for modernizing and future-proofing Fintech systems. This process involves addressing numerous challenges, from managing outdated code and dependencies to ensuring compatibility and performance in a new environment. By adopting a structured approach that includes comprehensive testing, thorough documentation, and continuous stakeholder engagement, organizations can successfully navigate these complexities.
The benefits of such a conversion are manifold. Modern C# applications offer enhanced security, better performance, and greater scalability. They are easier to maintain and integrate with contemporary technologies, providing a more robust foundation for future development. Ultimately, upgrading from VB6 to C# not only preserves the functionality of legacy systems but also unlocks new opportunities for innovation and growth in the ever-evolving Fintech landscape.
About the author:
Tobe Raju Varghese is a Technical Lead with over a decade of experience at Founding Minds Software. He collaborates with major Fintech providers in the United States to migrate their legacy systems to modern .NET applications. With a strong background in the retirement domain and pricing, Tobe excels in building and supporting products. He specializes in migration from SQL systems and managing complex ETL processes, ensuring smooth and efficient transitions to updated technologies. His deep understanding of Fintech solutions and meticulous approach to problem-solving make him a key player in driving technological advancements for his clients.