{"id":3798,"date":"2024-03-20T14:18:24","date_gmt":"2024-03-20T18:18:24","guid":{"rendered":"https:\/\/www.kuriosit.ca\/?p=3798"},"modified":"2025-03-11T11:02:47","modified_gmt":"2025-03-11T15:02:47","slug":"working-with-legacy-code","status":"publish","type":"post","link":"https:\/\/www.kuriosit.ca\/en\/travailler-avec-le-legacy-code\/","title":{"rendered":"Working with the Legacy Code"},"content":{"rendered":"<style>.wp-block-kadence-column.kb-section-dir-horizontal > .kt-inside-inner-col > .kt-info-box3798_f232f3-86 .kt-blocks-info-box-link-wrap{max-width:unset;}.kt-info-box3798_f232f3-86 .kt-blocks-info-box-link-wrap{border-top:0px solid var(--global-palette7, #eeeeee);border-right:0px solid var(--global-palette7, #eeeeee);border-bottom:0px solid var(--global-palette7, #eeeeee);border-left:0px solid var(--global-palette7, #eeeeee);border-top-left-radius:0px;background:#ffffff;padding-top:0px;padding-right:0px;padding-bottom:25px;padding-left:0px;}.kt-info-box3798_f232f3-86.wp-block-kadence-infobox{max-width:100%;}.kt-info-box3798_f232f3-86 .kadence-info-box-image-inner-intrisic-container .kadence-info-box-image-intrisic{max-width:100%;}.kt-info-box3798_f232f3-86 .kadence-info-box-icon-container .kt-info-svg-icon, .kt-info-box3798_f232f3-86 .kt-info-svg-icon-flip, .kt-info-box3798_f232f3-86 .kt-blocks-info-box-number{font-size:50px;}.kt-info-box3798_f232f3-86 .kt-blocks-info-box-media{border-radius:200px;overflow:hidden;border-top-width:0px;border-right-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:20px;padding-right:20px;padding-bottom:20px;padding-left:20px;margin-top:0px;margin-right:10px;margin-bottom:0px;margin-left:0px;}.kt-info-box3798_f232f3-86 .kt-blocks-info-box-media .kadence-info-box-image-intrisic img{border-radius:200px;}.kt-info-box3798_f232f3-86 .kt-infobox-textcontent h2.kt-blocks-info-box-title{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;margin-top:5px;margin-right:0px;margin-bottom:10px;margin-left:0px;}.kt-info-box3798_f232f3-86 .kt-infobox-textcontent .kt-blocks-info-box-text{color:var(--global-palette3, #1A202C);}.wp-block-kadence-infobox.kt-info-box3798_f232f3-86 .kt-blocks-info-box-text{font-size:18px;font-weight:400;}.kt-info-box3798_f232f3-86 .kt-blocks-info-box-link-wrap:hover .kt-blocks-info-box-text{color:var(--global-palette1, #3182CE);}.kt-info-box3798_f232f3-86 .kt-blocks-info-box-learnmore{background:transparent;border-width:0px 0px 0px 0px;padding-top:4px;padding-right:8px;padding-bottom:4px;padding-left:8px;margin-top:10px;margin-right:0px;margin-bottom:10px;margin-left:0px;}@media all and (max-width: 1024px){.kt-info-box3798_f232f3-86 .kt-blocks-info-box-link-wrap{border-top:0px solid var(--global-palette7, #eeeeee);border-right:0px solid var(--global-palette7, #eeeeee);border-bottom:0px solid var(--global-palette7, #eeeeee);border-left:0px solid var(--global-palette7, #eeeeee);}}@media all and (max-width: 767px){.kt-info-box3798_f232f3-86 .kt-blocks-info-box-link-wrap{border-top:0px solid var(--global-palette7, #eeeeee);border-right:0px solid var(--global-palette7, #eeeeee);border-bottom:0px solid var(--global-palette7, #eeeeee);border-left:0px solid var(--global-palette7, #eeeeee);}}<\/style>\n<div class=\"wp-block-kadence-infobox kt-info-box3798_f232f3-86\"><span class=\"kt-blocks-info-box-link-wrap info-box-link kt-blocks-info-box-media-align-left kt-info-halign-left\"><div class=\"kt-blocks-info-box-media-container\"><div class=\"kt-blocks-info-box-media kt-info-media-animate-none\"><\/div><\/div><div class=\"kt-infobox-textcontent\"><p class=\"kt-blocks-info-box-text\">By <span style=\"font-size:18px\">Mika\u00ebl Hubert-Deschamps<\/span> <\/p><\/div><\/span><\/div>\n\n\n<style>.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-content-wrap{padding-top:var(--global-kb-spacing-xxs, 0.5rem);padding-right:var(--global-kb-spacing-xxs, 0.5rem);padding-bottom:var(--global-kb-spacing-xxs, 0.5rem);padding-left:var(--global-kb-spacing-sm, 1.5rem);border-top:1px solid var(--global-palette2, #2B6CB0);border-right:1px solid var(--global-palette2, #2B6CB0);border-bottom:1px solid var(--global-palette2, #2B6CB0);border-left:1px solid var(--global-palette2, #2B6CB0);border-top-left-radius:16px;}.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-contents-title-wrap{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-contents-title{font-size:var(--global-kb-font-size-md, 1.25rem);font-weight:regular;font-style:normal;text-transform:uppercase;}.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-content-wrap .kb-table-of-content-list{font-size:var(--global-kb-font-size-md, 1.25rem);font-weight:regular;font-style:normal;margin-top:var(--global-kb-spacing-sm, 1.5rem);margin-right:0px;margin-bottom:0px;margin-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-content-wrap .kb-table-of-content-list .kb-table-of-contents__entry:hover{color:var(--global-palette1, #3182CE);}@media all and (max-width: 1024px){.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-content-wrap{border-top:1px solid var(--global-palette2, #2B6CB0);border-right:1px solid var(--global-palette2, #2B6CB0);border-bottom:1px solid var(--global-palette2, #2B6CB0);border-left:1px solid var(--global-palette2, #2B6CB0);}}@media all and (max-width: 767px){.kb-table-of-content-nav.kb-table-of-content-id3798_6d6c93-ab .kb-table-of-content-wrap{border-top:1px solid var(--global-palette2, #2B6CB0);border-right:1px solid var(--global-palette2, #2B6CB0);border-bottom:1px solid var(--global-palette2, #2B6CB0);border-left:1px solid var(--global-palette2, #2B6CB0);}}<\/style>\n\n\n<p class=\"wp-block-paragraph\">In January 2024, I had the chance to co-present the monthly <a href=\"https:\/\/www.meetup.com\/fr-FR\/techno-drinks\/events\/296403401\/\" data-type=\"link\" data-id=\"https:\/\/www.meetup.com\/fr-FR\/techno-drinks\/events\/296403401\/\" target=\"_blank\" rel=\"noopener\">Techno Drinks<\/a> at our offices in <a href=\"https:\/\/www.kuriosit.ca\/en\/\" data-type=\"link\" data-id=\"https:\/\/www.kuriosit.ca\/\">KuriosIT<\/a> in Sherbrooke. The theme of the evening was techniques for working with <em>legacy code<\/em>or legacy code. The presentation went through a number of improvements that can be made to this type of project, whether in terms of code syntax, structure or production methods. This blog post will provide an overview of the points raised during the conference.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before I begin, I would like to acknowledge the excellent work of Michael C. Feathers in his book <em><a href=\"https:\/\/www.amazon.ca\/Working-Effectively-Legacy-Code-EFFECT-ebook\/dp\/B005OYHF0A\" data-type=\"link\" data-id=\"https:\/\/www.amazon.ca\/Working-Effectively-Legacy-Code-EFFECT-ebook\/dp\/B005OYHF0A\" target=\"_blank\" rel=\"noopener\">Working Effectively with Legacy Code<\/a><\/em> published in 2004. This book provides a clear definition of what <em>legacy code<\/em>. It presents refactoring methods according to the desired objective, a multitude of situation scenarios where the author explains possible solutions step by step, and different approaches to adding unit tests. I recommend this book to anyone who wants to learn more about working with old code!<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\" style=\"text-transform:none\">Setting the scene<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As part of an ongoing project with one of our customers, I had to support several applications designed in C#, more specifically in <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/desktop\/winforms\/overview\/?view=netdesktop-8.0\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/desktop\/winforms\/overview\/?view=netdesktop-8.0\" target=\"_blank\" rel=\"noopener\">WinForms<\/a> .NET Framework 4.7.2. These applications have all been in use for several years, and some of them needed (and still need) support to add new features or fix existing bugs. I consider these applications to be <em>legacy<\/em> because in my case, it's much more about an application without documentation. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Whether through a <em><a href=\"https:\/\/fr.wikipedia.org\/wiki\/Readme\" data-type=\"link\" data-id=\"https:\/\/fr.wikipedia.org\/wiki\/Readme\" target=\"_blank\" rel=\"noopener\">readme<\/a><\/em>In fact, we had no information available other than the source code, either through comments in the code, or through the customer's user experience. What's more, no source manager (i.e. <a href=\"https:\/\/github.com\/\" data-type=\"link\" data-id=\"https:\/\/github.com\/\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>) had been used during application development. So we had to sit down, pour ourselves a cup of coffee and... read the code!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After nine months of immersing myself in these applications, I straightened out the structure of the largest of the multiple applications we took over from the customer. I've also added several features and brought back to life some parts that were no longer supported. Here are all the changes made to the main application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\" style=\"text-transform:none\"><strong>New functions<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this project, the aim was to deliver new functionalities while refactoring the application. In the early days of support, even adding and modifying users was complicated for the administrator: you had to connect directly to the database and modify table contents! So the first addition was a user management interface. Subsequently, we re-established several functionalities which, due to lack of maintenance, had been out of service for several years. All these additions (and more) enabled the customer to use his application exactly as he wanted, without needing our support for every operation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\" style=\"text-transform:none\"><strong>Production launch process<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To put the application into production, an executable file was previously produced and deposited on the company's file servers, along with all the libraries and other files required. This method brought a number of problems: it was impossible to put the application into production ourselves due to lack of access, the application was unavailable if the server was down, configuration files were visible and could be modified by the user, and so on. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In short, this is not good practice at all, especially when better options are available. So I used <a href=\"https:\/\/wixtoolset.org\/\" data-type=\"link\" data-id=\"https:\/\/wixtoolset.org\/\" target=\"_blank\" rel=\"noopener\">Wix<\/a> to generate an installation file <em>.msi<\/em> and deploy the application directly to users' workstations. Gone are the random latency errors caused by the file server and the mysterious bugs of missing files or configurations. We're back in control of the application environment!<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\" style=\"text-transform:none\">Unit testing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Remember, an application without tests is considered to be <em>legacy<\/em>&nbsp;! So we added a few unit tests to validate the various service functionalities. These tests resolved several bugs that we hadn't found during functional testing. These tests therefore paid for themselves even before they were added to production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\" style=\"text-transform:none\"><strong>Refactoring<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In order to extend the life of the applications, I did a lot of refactoring. Initially, the structure was monolithic: a main form (WinForms, of course) containing all the logic, with several children exchanging information with the parent. The main class contained over two thousand lines, many of which were no longer in use. I had to remove all the dead code and clarify the variable names.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I also took the opportunity to migrate the main application to <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/core\/whats-new\/dotnet-8\/overview\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/core\/whats-new\/dotnet-8\/overview\" target=\"_blank\" rel=\"noopener\">.NET Core 8<\/a>. This enhancement alone brings a great deal of optimization and security to the application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After these changes, even if the code is easier to read, we still have a monolith... So I created services injected into the main form to better handle the various objects in the application. For example, if an action modifies an employee's information, these changes will now go through the associated centralized service. No more duplicates!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, I undertook a massive clean-up of the code, rewriting segments that were clearly not optimal (see example below). Finally, I grouped all SQL queries under a single file responsible for communications with the database. It was during this stage that a large number of bugs, which were rendering the application unusable, were found and fixed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Speaking of SQL queries, we've also integrated <a href=\"https:\/\/www.learndapper.com\/\" data-type=\"link\" data-id=\"https:\/\/www.learndapper.com\/\" target=\"_blank\" rel=\"noopener\">Dapper<\/a> to link relational objects with those of our application domain. This addition has made it possible to standardize property naming and optimize transactions. Configuring this tool is very simple. The time you save using it and the security gains (such as code injection protection) are considerable!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, we also updated all the external libraries we used. Some of them had serious security problems. It was therefore imperative to update them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Here's an example of a code segment to be optimized:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let's assume 'foo' is a logical value (<em>boolean<\/em>) and 'bar' a character string (<em>string<\/em>). (This example is actually taken from the original code).<\/p>\n\n\n\n<pre class=\"wp-block-code c#\"><code>switch(foo)\n{\n    case false:\n        bar = \"foo is false\"; \/\/ no need for a switch case\n        break;\n    case true:\n        bar = \"foo is true\"; \/\/ a ternary operator also works\n        break;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, the program uses a <em>switch case<\/em> to determine 'bar' according to 'foo'. In reality, a <em>switch case<\/em> is used to choose between <strong>more than three cases<\/strong> and the input parameter is normally a <strong>type other than boolean<\/strong>. The method shown works, but is not optimal. A <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/csharp\/language-reference\/operators\/conditional-operator\" data-type=\"link\" data-id=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/csharp\/language-reference\/operators\/conditional-operator\" target=\"_blank\" rel=\"noopener\">ternary operator<\/a> is therefore more appropriate, since only two cases are possible.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Here's the optimized version replacing the previous block:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>bar = foo ? \"foo is true\" : \"foo is false\"; <\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\" style=\"text-transform:none\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can breathe easy: the code is clear, everything we see is used, optimized and the classes are structured. In short, all these changes are individually trivial, but taken together, they form a formidable weapon against <em>legacy code<\/em>. In just a few months, we've gone from a fragile, monolithic application to a high-performance, stable and flexible work tool. The next developer who doesn't know the history of the application will be able to take control of the code more easily. They'll be able to read the documentation and tests, consult the various injected services and deploy a new version in the blink of an eye!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Curious about how to turn one of your applications into a high-performance, stable and flexible tool? I invite you to read the book by <a href=\"https:\/\/www.amazon.ca\/Working-Effectively-Legacy-Code-EFFECT-ebook\/dp\/B005OYHF0A\" data-type=\"link\" data-id=\"https:\/\/www.amazon.ca\/Working-Effectively-Legacy-Code-EFFECT-ebook\/dp\/B005OYHF0A\" target=\"_blank\" rel=\"noopener\">Michael C. Feathers<\/a> and learn more about the subject we've covered together.<\/p>","protected":false},"excerpt":{"rendered":"<p>It is often necessary to work on legacy code. There are several techniques for dealing with these situations. Here's an overview of the improvements that can be made to this type of project (code syntax, structure and release).<\/p>","protected":false},"author":37,"featured_media":3820,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[42],"tags":[],"class_list":["post-3798","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developpement-logiciel"],"acf":[],"taxonomy_info":{"category":[{"value":42,"label":"D\u00e9veloppement logiciel"}]},"featured_image_src_large":["https:\/\/www.kuriosit.ca\/wp-content\/uploads\/2024\/03\/legacyAI_03.jpeg",1024,1024,false],"author_info":{"display_name":"Simon-Pierre Morin","author_link":"https:\/\/www.kuriosit.ca\/en\/author\/spmorin\/"},"comment_info":0,"category_info":[{"term_id":42,"name":"D\u00e9veloppement logiciel","slug":"developpement-logiciel","term_group":0,"term_taxonomy_id":42,"taxonomy":"category","description":"","parent":0,"count":4,"filter":"raw","cat_ID":42,"category_count":4,"category_description":"","cat_name":"D\u00e9veloppement logiciel","category_nicename":"developpement-logiciel","category_parent":0}],"tag_info":false,"_links":{"self":[{"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/posts\/3798","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/users\/37"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/comments?post=3798"}],"version-history":[{"count":4,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/posts\/3798\/revisions"}],"predecessor-version":[{"id":4608,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/posts\/3798\/revisions\/4608"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/media\/3820"}],"wp:attachment":[{"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/media?parent=3798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/categories?post=3798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kuriosit.ca\/en\/wp-json\/wp\/v2\/tags?post=3798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}