[{"data":1,"prerenderedAt":709},["ShallowReactive",2],{"/en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo/":3,"navigation-en-us":36,"banner-en-us":455,"footer-en-us":471,"Michael Friedrich":681,"next-steps-en-us":694},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":26,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},"/en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Refactor code into modern languages with AI-powered GitLab Duo ","This detailed tutorial helps developers use AI to modernize code by switching to a new programming language and gain knowledge about new features in the same language.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662465/Blog/Hero%20Images/GitLab_Duo_Workflow_Unified_Data_Store__1_.png","https://about.gitlab.com/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Refactor code into modern languages with AI-powered GitLab Duo \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2024-08-26\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Michael Friedrich","2024-08-26","Whether you are tasked with modernizing the code base or framework by\nswitching to a new programming language, or you need knowledge about new\nlanguage features in the same language, AI-powered [GitLab\nDuo](https://about.gitlab.com/gitlab-duo/) can help. Learn how to approach\ncode refactoring challenges with best practices using examples from the past\n20 years of my coding career. \n\n\nThe prompts and examples in this article are shown in different IDEs: VS\nCode and JetBrains IDEs (IntelliJ IDEA, PyCharm, and CLion) with the [GitLab\nDuo\nextensions/plugins](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html)\ninstalled. The development environment uses GitLab.com, including updates to\nAnthropic Claude 3.5 as Large Language Model (LLM) for GitLab Duo [Code\nSuggestions](https://docs.gitlab.com/ee/user/gitlab_duo/#code-suggestions)\nand [Chat](https://docs.gitlab.com/ee/user/gitlab_duo/#gitlab-duo-chat).\nSpoiler: They are even more powerful and efficient.\n\n\nYou can navigate into each section of the article, or read top-down. The\nsource code and challenges with exercises are provided for self-learning,\ntoo.\n\n\n- [Refactor code to modern programming language\nstandards](#refactor-code-to-modern-programming-language-standards)\n    - [Generate Java 7 and refactor to Java 8](#generate-java-7-and-refactor-to-java-8)\n    - [Refactor across C++ standards](#refactor-across-c%2B%2B-standards)\n        - [Migration: Refactor C++03 into C++14](#migration-refactor-c%2B%2B03-into-c%2B%2B14)\n        - [Downgrade: Refactor C++23 to C++11](#downgrade-refactor-c%2B%2B23-to-c%2B%2B11)\n    - [Explain and refactor COBOL](#explain-and-refactor-cobol)\n- [Refactor a language into another\nlanguage](#refactor-a-language-into-another-language)\n    - [Refactor C to Rust](#refactor-c-to-rust)\n    - [Refactor Perl to Python](#refactor-perl-to-python)\n- [More refactoring hands-on](#more-refactoring-hands-on)\n    - [Refactor JavaScript](#refactor-javascript)\n    - [Refactor Bash to ZSH or SH](#refactor-bash-to-zsh-or-sh)\n    - [More use cases and tutorials](#more-use-cases-and-tutorials)\n- [Key takeaways](#key-takeaways)\n\n\n## Refactor code to modern programming language standards\n\n\nThe next sections show how to refactor, explain, and understand the language\nspecific differences in a defined programming language. \n\n\n### Generate Java 7 and refactor to Java 8 \n\n\nA customer wanted to know if GitLab Duo supports Java 7. While testing the\nCode Suggestions and Chat prompts to generate Java 7 specific code, I also\nthought of migration help. Anthropic Claude 3.5 is capable of understanding\nthe language-specific differences, and so is GitLab Duo.\n\n\nThe following example shows a prompt to generate Java 7 code with Code\nSuggestions.\n\n\n```java\n\n// Generate a new class for a File Manager. Use Java 7 features only.\n\nimport java.io.*;\n\nimport java.nio.file.*;\n\nimport java.util.*;\n\n\npublic class FileManager {\n    private Path rootDirectory;\n\n    public FileManager(String rootPath) throws IOException {\n        this.rootDirectory = Paths.get(rootPath);\n        if (!Files.exists(rootDirectory)) {\n            Files.createDirectories(rootDirectory);\n        }\n    }\n\n    public void createFile(String fileName, String content) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);\n    }\n\n    public String readFile(String fileName) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        return new String(Files.readAllBytes(filePath));\n    }\n\n    public void deleteFile(String fileName) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        Files.delete(filePath);\n    }\n\n    public List\u003CString> listFiles() throws IOException {\n        List\u003CString> fileList = new ArrayList\u003C>();\n        try (DirectoryStream\u003CPath> stream = Files.newDirectoryStream(rootDirectory)) {\n            for (Path file : stream) {\n                fileList.add(file.getFileName().toString());\n            }\n        }\n        return fileList;\n    }\n\n    public void copyFile(String sourceFileName, String destinationFileName) throws IOException {\n        Path sourcePath = rootDirectory.resolve(sourceFileName);\n        Path destinationPath = rootDirectory.resolve(destinationFileName);\n        Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);\n    }\n\n    public void moveFile(String sourceFileName, String destinationFileName) throws IOException {\n        Path sourcePath = rootDirectory.resolve(sourceFileName);\n        Path destinationPath = rootDirectory.resolve(destinationFileName);\n        Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);\n    }\n\n    public long getFileSize(String fileName) throws IOException {\n        Path filePath = rootDirectory.resolve(fileName);\n        return Files.size(filePath);\n    }\n\n    public boolean fileExists(String fileName) {\n        Path filePath = rootDirectory.resolve(fileName);\n        return Files.exists(filePath);\n    }\n}\n\n```\n\n\nYou can continue with the following steps in your IDE:\n\n\n1. Learn and understand the generated code: Select the code in the editor\n(blue color in the screenshot), switch into GitLab Duo Chat and send the\n`/explain` slash command as prompt.\n\n\n![Validate the generated code with the `/explain` slash command in GitLab\nDuo\nChat](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/intellij_java7_generate_refactor.png)\n\n\n2. Refactor the Java 7 code into Java 8: Select the code in the editor,\nswitch into Chat, and send `/refactor using Java 8 features` as refined\nprompt.\n\n3. Practice an alternative to refactoring: Create a new file `java8.java`\nand generate Java 8 specific code using Code Suggestions with the prompt `//\nGenerate a new class for a File Manager. Use Java 8 features only.`.\n\n4. Continue writing Java 8 code in the same context with AI-powered code\ncompletions.\n\n\nYou can watch all steps in this recording.\n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/XKRv6uBkD2I\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\nThe source code is available in the [GitLab Duo Challenge - Generate and\nrefactor Java 7 to 8\nproject](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-generate-refactor-java-7-to-8).\n\n\n### Refactor across C++ standards\n\n\nThe C++ standard has a long history and can be considered stable and mature.\nDepending on the target architecture and platforms, the supported standard\ndepends on the compiler on the host operating system.\n\n\nIn my career, I needed to support 25 different Linux and Windows\ndistributions in open source projects, and have seen varying compiler\nsupport for newer language features and C++ standards. In 2015, we settled\non C++11 features, and later never touched based on C++14 or C++17. \n\n\nRefactoring functions and algorithms to a new C++ standard would have\nrequired too much effort, and help explaining the differences was needed.\nBack then, we researched through books, online search, Stack Overflow, and\nsometimes tools assistance for refactoring.\n\n\nThings have changed with AI-powered assistants and GitLab Duo: You can\ninstruct Code Suggestions and Chat to provide source code in a specific C++\nstandard. Then, it is also possible to compare the different outputs. \n\n\nThe following example uses a prompt to specifically generate source code for\nthe C++03 standard. It implements a simple config parser for the `.ini`\nconfiguration format.\n\n\n```c++\n\n/* Create a config parser which can parse an ini format\n\nUse C++03 standard only\n */\n\n#include \u003Ciostream>\n\n#include \u003Cfstream>\n\n#include \u003Cstring>\n\n#include \u003Cmap>\n\n#include \u003Csstream>\n\n\nclass ConfigParser {\n\nprivate:\n    std::map\u003Cstd::string, std::map\u003Cstd::string, std::string> > config;\n\npublic:\n    ConfigParser() {}\n\n    bool parse(const std::string& filename) {\n        std::ifstream file(filename.c_str());\n        if (!file.is_open()) {\n            return false;\n        }\n\n        std::string line;\n        std::string currentSection;\n\n        while (std::getline(file, line)) {\n            // Trim whitespace\n            size_t first = line.find_first_not_of(\" \\t\");\n            size_t last = line.find_last_not_of(\" \\t\");\n            if (first == std::string::npos) continue; // Skip empty lines\n            line = line.substr(first, (last - first + 1));\n\n            if (line[0] == '[' && line[line.length() - 1] == ']') {\n                // This is a section\n                currentSection = line.substr(1, line.length() - 2);\n            } else {\n                // This is a key-value pair\n                size_t delimiterPos = line.find('=');\n                if (delimiterPos != std::string::npos) {\n                    std::string key = line.substr(0, delimiterPos);\n                    std::string value = line.substr(delimiterPos + 1);\n                    config[currentSection][key] = value;\n                }\n            }\n        }\n\n        file.close();\n        return true;\n    }\n\n    std::string getValue(const std::string& section, const std::string& key) const {\n        std::map\u003Cstd::string, std::map\u003Cstd::string, std::string> >::const_iterator sectionIt = config.find(section);\n        if (sectionIt != config.end()) {\n            std::map\u003Cstd::string, std::string>::const_iterator keyIt = sectionIt->second.find(key);\n            if (keyIt != sectionIt->second.end()) {\n                return keyIt->second;\n            }\n        }\n        return \"\";\n    }\n\n    void printConfig() const {\n        std::map\u003Cstd::string, std::map\u003Cstd::string, std::string> >::const_iterator sectionIt;\n        for (sectionIt = config.begin(); sectionIt != config.end(); ++sectionIt) {\n            std::cout \u003C\u003C \"[\" \u003C\u003C sectionIt->first \u003C\u003C \"]\" \u003C\u003C std::endl;\n            std::map\u003Cstd::string, std::string>::const_iterator keyIt;\n            for (keyIt = sectionIt->second.begin(); keyIt != sectionIt->second.end(); ++keyIt) {\n                std::cout \u003C\u003C keyIt->first \u003C\u003C \" = \" \u003C\u003C keyIt->second \u003C\u003C std::endl;\n            }\n            std::cout \u003C\u003C std::endl;\n        }\n    }\n};\n\n\nint main() {\n    ConfigParser parser;\n    if (parser.parse(\"config.ini\")) {\n        std::cout \u003C\u003C \"Config file parsed successfully.\" \u003C\u003C std::endl;\n        parser.printConfig();\n\n        std::cout \u003C\u003C \"Value of 'key1' in 'section1': \" \u003C\u003C parser.getValue(\"section1\", \"key1\") \u003C\u003C std::endl;\n    } else {\n        std::cout \u003C\u003C \"Failed to parse config file.\" \u003C\u003C std::endl;\n    }\n    return 0;\n}\n\n```\n\n\nThe same prompts can be applied to [explaining\ncode](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#explain-code-in-the-ide),\n[generating\ntests](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#write-tests-in-the-ide),\nand even [refactoring\ncode](https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#refactor-code-in-the-ide):\n`/explain focus on C++03 features`, `/tests for C++03 features`, `/refactor\ninto C++03`. \n\n\nThe following C++ standards have been tested working with GitLab Duo Code\nSuggestions:\n\n\n- C++03\n\n- C++11\n\n- C++14\n\n- C++17\n\n- C++20\n\n- C++23\n\n\nYou can find the source code in the [Challenge - Refactor Cpp Standards\nConfig Parser\nproject](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-cpp-standards-config-parser). \n\n\nThere are many different combinations to refactor source code between the\nC++ standards. The following examples reflect on modernizing the C++ code\nwith version upgrades, but also test a downgrade where ambitious developers\nwanted to use C++20 but had to use C++11 to support enterprise customer\nenvironments.\n\n\n#### Migration: Refactor C++03 into C++14 \n\n\nThe goal is to modernize the code, and understand the changes between C++03\nand C++14. Open the\n[03.cpp](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-cpp-standards-config-parser/-/blob/main/03.cpp?ref_type=heads)\nsource code in the IDE, select it, and use the following Chat prompt: \n\n\n```markdown\n\n/refactor into C++14 and explain the changes\n\n```\n\n\nPotential Chat response: \n\n\n```markdown\n\n…\n\n\nExplanations of the changes:\n\n\n1. Default constructor: Changed `ConfigParser() {}` to `ConfigParser() =\ndefault;` to use the default constructor.\n\n2. File opening: Removed `.c_str()` when opening the file, as C++11 and\nlater support `std::string` directly.\n\n3. Lambda functions: Introduced a lambda function trim to handle string\ntrimming, making the code more readable and reusable.\n\n4. Auto keyword: Used `auto` for type deduction in various places, improving\ncode readability.\n\n5. Range-based for loops: In the `printConfig` method, replaced traditional\nfor loops with range-based for loops, which are more concise and less\nerror-prone.\n\n6. Structured bindings: Used structured bindings in the range-based for\nloops to directly access key-value pairs.\n\n7. If statements with initializers: In the `getValue` method, used if\nstatements with initializers to combine the find operation and the check in\na single line.\n\n8. String member functions: Used `front()` and `back()` instead of\narray-style access for the first and last characters of strings.\n\n9. Uniform initialization: Used uniform initialization `{}` instead of\nparentheses `()` for object creation.\n\n10. Removed `std::endl`: Replaced `std::endl` with `'\\n'` for better\nperformance, as `std::endl` forces a flush of the output buffer.\n\n\nThese changes make the code more modern, concise, and potentially more\nefficient while maintaining the same functionality.\n\n\n```\n\n\n![Changes reflected in\ncode](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp03_to_14_01.png)\n\n\n![Changes reflected in code\n2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675060/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp03_to_14_02.png)\n\n\n#### Downgrade: Refactor C++23 to C++11\n\n\nSometimes, developers started a new feature proof-of-concept in a modern C++\nstandard like C++20. The actual supported versions for enterprise customer\nenvironments require older compilers with C++11 support. Downgrading the\nversions come at a cost, and require evaluating which language features are\nstill supported, and which other disadvantages could come across.\n\n\nOpen the\n[23.cpp](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-cpp-standards-config-parser/-/blob/main/23.cpp?ref_type=heads)\nsource code in the IDE, select it, and use the following Chat prompt: \n\n\n```markdown\n\n/refactor into C++11, explain the necessary changes and potential problems\n\n```\n\n\nPotential Duo Chat response: \n\n\n```markdown\n\nThe main changes required to make this code compatible with C++11 are:\n\n\n1. Remove the C++23 standard comment, as it's no longer applicable.\n\n2. Replace `std::string::find_first_not_of` and\n`std::string::find_last_not_of` with C++11 compatible alternatives in the\ntrim function.\n\n3. Use `const auto&` instead of `auto` for loop variables to avoid\nunnecessary copying.\n\n\nPotential problems in the original code:\n\n\n1. The original code used C++23 features, which might not be widely\nsupported yet.\n\n2. The `trim` function used `std::string::find_first_not_of` and\n`std::string::find_last_not_of`, which are not available in C++11.\n\n3. The use of `auto` instead of `const auto&` in some loops could lead to\nunnecessary copying of complex objects.\n\n\nThese issues have been addressed in the refactored version. The `trim`\nfunction now uses `std::find_if_not` with lambda functions to achieve the\nsame result in a C++11 compatible way. The use of `const auto&` ensures that\nno unnecessary copying occurs when iterating over the config map.\n\n```\n\n\n![The `trim` function now uses `std::find_if_not` with lambda functions to\nachieve the same result in a C++11 compatible\nway](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp23_to_11_01.png)\n\n\n![The use of `const auto&` ensures that no unnecessary copying occurs when\niterating over the config\nmap](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/duo_refactor_cpp_clion_chat_cpp23_to_11_02.png)\n\n\n**Async practice**: Test more version refactoring scenarios.\n\n\n### Explain and refactor COBOL\n\n\nYou can use GitLab Duo to explain the source code, analyze, fix and refactor\nfor COBOL programs. I have never written nor learned COBOL, and found this\nhelpful [COBOL Programming\nCourse](https://github.com/openmainframeproject/cobol-programming-course)\nwith many examples.\n\n\nI then asked Chat how to get started with COBOL, create a COBOL program, and\ncompile a COBOL program on macOS.\n\n\n```markdown\n\nPlease explain what COBOL is and its syntax\n\n\nPlease create a COBOL program that shows the first steps\n\n\nTell me more about the COBOL compiler. Which system do I need? Can I do it\non my macOS?\n\n\n```\n\n\n![Asking GitLab Duo Chat to explain and its\nsyntax](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/vscode_chat_cobol_generate_example.png)\n\n\nOpen a COBOL program, select the source code, switch to Duo Chat and send\nthe `/explain` prompt to explain purpose and functionality.\n\n\nYou can also refine the prompts to get more high-level summaries, for\nexample:\n\n\n```markdown \n\n/explain like I am five\n\n```\n\n\n> Tip: Programming languages share similar algorithms and functionality. For\nCOBOL, Chat offered to explain it using Python, and, therefore, I adjusted\nfuture prompts to ask for an explanation in Python.\n\n\n```markdown\n\n/explain in a different programming language\n\n```\n\n\nYou can also use the `/refactor` slash command prompt in Chat to improve the\ncode quality, fix potential problems, and try to refactor COBOL into Python.\n\n\n```markdown\n\n/refactor fix the environment error\n\n\n/refactor fix potential problems\n\n\n/refactor into Python\n\n```\n\n\nThe [GitLab Duo Coffee Chat - Challenge: Explain and Refactor COBOL\nprograms](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-explain-refactor-cobol-program)\nrecording shows all discussed steps in a practical use case, including how\nto find a missing period: \n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/pwlDmLQMMPo\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\n## Refactor a language into another language\n\n\nModernization and code quality improvements sometimes require the change of\na programming language. Similar refactor prompts with GitLab Duo can help\nspeed up the migration process. The COBOL example with Python is just one of\nmany requirements in enterprise environments -- let's dive into more use\ncases.\n\n\n### Refactor C to Rust \n\n\nIn early 2024, several programming languages, like C, have been called out\nfor not being memory safe. The recommendations for future projects include\n[memory safe\nlanguages](https://about.gitlab.com/blog/memory-safe-vs-unsafe/)\nlike Rust. But how do you start a migration, and what are the challenges?\n\n\nLet's try it with a simple example in C. The code was generated using Code\nSuggestions and should print the basic operating system information, like\nthe name, version, and platform. The C code compiles cross-platform on\nWindows, Linux, and macOS.\n\n\n```c\n\n// Read OS files to identify the platform, name, versions\n\n// Print them on the terminal\n\n#include \u003Cstdio.h>\n\n#include \u003Cstdlib.h>\n\n#include \u003Cstring.h>\n\n\n#ifdef _WIN32\n    #include \u003Cwindows.h>\n#elif __APPLE__\n    #include \u003Csys/utsname.h>\n#else\n    #include \u003Csys/utsname.h>\n#endif\n\n\nvoid get_os_info() {\n    #ifdef _WIN32\n        OSVERSIONINFOEX info;\n        ZeroMemory(&info, sizeof(OSVERSIONINFOEX));\n        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\n        GetVersionEx((OSVERSIONINFO*)&info);\n\n        printf(\"Platform: Windows\\n\");\n        printf(\"Version: %d.%d\\n\", info.dwMajorVersion, info.dwMinorVersion);\n        printf(\"Build: %d\\n\", info.dwBuildNumber);\n    #elif __APPLE__\n        struct utsname sys_info;\n        uname(&sys_info);\n\n        printf(\"Platform: macOS\\n\");\n        printf(\"Name: %s\\n\", sys_info.sysname);\n        printf(\"Version: %s\\n\", sys_info.release);\n    #else\n        struct utsname sys_info;\n        uname(&sys_info);\n\n        printf(\"Platform: %s\\n\", sys_info.sysname);\n        printf(\"Name: %s\\n\", sys_info.nodename);\n        printf(\"Version: %s\\n\", sys_info.release);\n    #endif\n}\n\n\nint main() {\n    get_os_info();\n    return 0;\n}\n\n```\n\n\nOpen the source code in\n[`os.c`](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-c-to-rust/-/blob/897bf57a14bb7be07d842e7f044f93a61456d611/c/os.c)\nin JetBrains CLion, for example. Select the source code and use the Chat\nprompt `/explain` to explain purpose and functionality. Next, use\n`/refactor` in the Chat prompt to refactor the C code, and then take it one\nstep further: `/refactor into Rust`. \n\n\nInitialize a new Rust project (Tip: Ask Duo Chat), and copy the generated\nsource code into the `src/main.rs` file. Run `cargo build` to compile the\ncode. \n\n\n![Initialize a new Rust project, and copy the generated source code into the\n`src/main.rs` file. Run `cargo build` to compile the\ncode.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/jetbrains_clion_c_rust.png)\n\n\nIn the [GitLab Duo Coffee Chat: Challenge - Refactor C into\nRust](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-c-to-rust)\nrecording, you can learn all steps, and additionally, you'll see a\ncompilation error which gets fixed with the help of Chat and `/refactor`\nslash command. The session also shows how to improve the maintanability of\nthe new Rust code by adding more error handling. \n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/nf8g2ucqvkI\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\n### Refactor Perl to Python \n\n\nThat one script that runs on production servers, does its job, the author\nleft the company ten years ago, and nobody wants to touch it. The problem\nmight also apply to multiple scripts, or even a whole application. A\ndecision was made to migrate everything to modern Python 3, with the goal to\nmodernize the code, and understand the changes between Perl and Python.\n\n\nA customer recently asked in a GitLab Duo workshop whether a direct\nmigration is possible using GitLab Duo. Short answer: Yes, it is. Longer\nanswer: You can use refined Chat prompts to refactor Perl code into Python,\nsimilar to other examples in this article.\n\n\nOpen the `script.pl` source code in IDE, select it, and open Chat.\n\n\n```perl\n\n#!/usr/bin/perl\n\nuse strict;\n\nuse warnings;\n\n\nopen my $md_fh, '\u003C', 'file.md' or die \"Could not open file.md: $!\";\n\n\nmy $l = 0;\n\nmy $e = 0;\n\nmy $h = 0;\n\n\nwhile (my $line = \u003C$md_fh>) {\n  $l++;\n  if ($line =~ /^\\s*$/) {\n    $e++;\n    next;\n  }\n  if ($line =~ /^#+\\s*(.+)/) {\n    print \"$1\\n\";\n    $h++; \n  }\n}\n\n\nprint \"\\nS:\\n\"; \n\nprint \"L: $l\\n\";\n\nprint \"E: $e\\n\"; \n\nprint \"H: $h\\n\";\n\n```\n\n\nYou can use the following prompts to:\n\n\n1. `/explain` its purpose, and `/refactor` to improve the code.\n\n2. `/refactor into Python` to get a working Python script.\n\n\n![Refactor into\nPython](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/pycharm_duo_refactor_perl_python.png)\n\n\n> Tip: You can refactor Perl code into more target languages. The [GitLab\nDuo Coffee Chat: Challenge - Refactor Perl to\nPython](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-perl-python)\nrecording shows PHP, Ruby, Rust, Go, Java, VB.NET, C#, and more.\n\n> \n\n> If you want to continue using Perl scripts, you can configure [Perl as\nadditional\nlanguage](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/supported_extensions.html#add-support-for-more-languages)\nin Duo Code Suggestions. Chat already understands Perl and can help with\nquestions and slash command prompts, as you can see in the following\nrecording.\n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/03HGhxXg9lw\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\n## More Refactoring Hands-on \n\n\n### Refactor JavaScript \n\n\nEddie Jaoude shows how to refactor JavaScript to improve code quality or add\nfunctionality in a practical example. \n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/mHn8KOzpPNY\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\n### Refactor Bash to ZSH or SH\n\n\nI have used Bash as a shell for 20 years and most recently switched to ZSH\non macOS. This resulted in script not working, or unknown errors in my\nterminal. Another use case for refactoring are shell limitations – some\noperating systems or Linux/Unix distributions do not provide Bash, only SH,\nfor example, Alpine.\n\n\n![Refactor shell\nscripts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675059/Blog/Content%20Images/intellj_refactor_shell_scripts.png)\n\n\nThe [GitLab Duo Coffee Chat: Challenge - Refactor Shell\nScripts](https://gitlab.com/gitlab-da/use-cases/ai/ai-workflows/gitlab-duo-challenges/code-challenges/challenge-refactor-shell-scripts)\nshows an example with a C program that can tail syslog files, and a build\nscript written in Bash. Throughout the challenge, Chat is queried with\n`/explain` and `/refactor` prompts to improve the code. It is also possible\nto refactor Bash into POSIX-compliant SH or ZSH. The session concludes with\nasking Chat to provide five different Shell script implementations, and\nexplain the key summaries. \n\n\n\u003C!-- blank line -->\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/mssqYjlKGzU\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\u003C!-- blank line -->\n\n\n### More use cases and tutorials\n\n\n- [Documentation: GitLab Duo use\ncases](https://docs.gitlab.com/ee/user/gitlab_duo/use_cases.html)\n\n- [Tutorial: Top tips for efficient AI-powered code suggestions with GitLab\nDuo](https://about.gitlab.com/blog/top-tips-for-efficient-ai-powered-code-suggestions-with-gitlab-duo/)\n\n- [Tutorial: 10 best practices for using AI-powered GitLab Duo\nChat](https://about.gitlab.com/blog/10-best-practices-for-using-ai-powered-gitlab-duo-chat/)\n\n\n## Key takeaways \n\n\n1. GitLab Duo provides efficient help with explaining and refactoring code. \n\n1. You can refactor code between language standards, and ask follow-up\nquestions in Chat.\n\n1. Code Suggestions prompts can generate specific language standards, and\ncode completion respects the current code context. \n\n1. Refactoring code into new programming languages helps with longer term\nmigration and modernization plans.\n\n1. Code can be \"downgraded\" into older system's supported language\nstandards.\n\n1. GitLab Duo can explain complex code and programming languages with\ndifferent programming language examples.\n\n1. The update to Anthropic Claude 3.5 on GitLab.com has improved the quality\nand speed of Code Suggestions and Chat once again (self-managed upgrade to\n17.3 recommended).\n\n1. There are no boundaries except your imagination, and production pain\npoints.\n\n\nLearn more about efficient Code Suggestions and Chat workflows, and start\nyour AI-powered code refactoring journey with GitLab Duo today!\n\n\n> [Start your free trial of GitLab\nDuo!](https://about.gitlab.com/solutions/gitlab-duo-pro/sales/?type=free-trial&toggle=gitlab-duo-pro_)\n","ai-ml",[23,24,25],"AI/ML","tutorial","DevSecOps",{"slug":27,"featured":6,"template":28},"refactor-code-into-modern-languages-with-ai-powered-gitlab-duo","BlogPost","content:en-us:blog:refactor-code-into-modern-languages-with-ai-powered-gitlab-duo.yml","yaml","Refactor Code Into Modern Languages With Ai Powered Gitlab Duo","content","en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo.yml","en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":451,"_type":30,"title":452,"_source":32,"_file":453,"_stem":454,"_extension":35},"/shared/en-us/main-navigation","en-us",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":392,"minimal":423,"duo":442},{"config":41},{"href":42,"dataGaName":43,"dataGaLocation":44},"/","gitlab logo","header",{"text":46,"config":47},"Get free trial",{"href":48,"dataGaName":49,"dataGaLocation":44},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":51,"config":52},"Talk to sales",{"href":53,"dataGaName":54,"dataGaLocation":44},"/sales/","sales",{"text":56,"config":57},"Sign in",{"href":58,"dataGaName":59,"dataGaLocation":44},"https://gitlab.com/users/sign_in/","sign in",[61,105,203,208,313,373],{"text":62,"config":63,"cards":65,"footer":88},"Platform",{"dataNavLevelOne":64},"platform",[66,72,80],{"title":62,"description":67,"link":68},"The most comprehensive AI-powered DevSecOps Platform",{"text":69,"config":70},"Explore our Platform",{"href":71,"dataGaName":64,"dataGaLocation":44},"/platform/",{"title":73,"description":74,"link":75},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":76,"config":77},"Meet GitLab Duo",{"href":78,"dataGaName":79,"dataGaLocation":44},"/gitlab-duo/","gitlab duo ai",{"title":81,"description":82,"link":83},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":84,"config":85},"Learn more",{"href":86,"dataGaName":87,"dataGaLocation":44},"/why-gitlab/","why gitlab",{"title":89,"items":90},"Get started with",[91,96,101],{"text":92,"config":93},"Platform Engineering",{"href":94,"dataGaName":95,"dataGaLocation":44},"/solutions/platform-engineering/","platform engineering",{"text":97,"config":98},"Developer Experience",{"href":99,"dataGaName":100,"dataGaLocation":44},"/developer-experience/","Developer experience",{"text":102,"config":103},"MLOps",{"href":104,"dataGaName":102,"dataGaLocation":44},"/topics/devops/the-role-of-ai-in-devops/",{"text":106,"left":107,"config":108,"link":110,"lists":114,"footer":185},"Product",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"View all Solutions",{"href":113,"dataGaName":109,"dataGaLocation":44},"/solutions/",[115,140,164],{"title":116,"description":117,"link":118,"items":123},"Automation","CI/CD and automation to accelerate deployment",{"config":119},{"icon":120,"href":121,"dataGaName":122,"dataGaLocation":44},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[124,128,132,136],{"text":125,"config":126},"CI/CD",{"href":127,"dataGaLocation":44,"dataGaName":125},"/solutions/continuous-integration/",{"text":129,"config":130},"AI-Assisted Development",{"href":78,"dataGaLocation":44,"dataGaName":131},"AI assisted development",{"text":133,"config":134},"Source Code Management",{"href":135,"dataGaLocation":44,"dataGaName":133},"/solutions/source-code-management/",{"text":137,"config":138},"Automated Software Delivery",{"href":121,"dataGaLocation":44,"dataGaName":139},"Automated software delivery",{"title":141,"description":142,"link":143,"items":148},"Security","Deliver code faster without compromising security",{"config":144},{"href":145,"dataGaName":146,"dataGaLocation":44,"icon":147},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[149,154,159],{"text":150,"config":151},"Application Security Testing",{"href":152,"dataGaName":153,"dataGaLocation":44},"/solutions/application-security-testing/","Application security testing",{"text":155,"config":156},"Software Supply Chain Security",{"href":157,"dataGaLocation":44,"dataGaName":158},"/solutions/supply-chain/","Software supply chain security",{"text":160,"config":161},"Software Compliance",{"href":162,"dataGaName":163,"dataGaLocation":44},"/solutions/software-compliance/","software compliance",{"title":165,"link":166,"items":171},"Measurement",{"config":167},{"icon":168,"href":169,"dataGaName":170,"dataGaLocation":44},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[172,176,180],{"text":173,"config":174},"Visibility & Measurement",{"href":169,"dataGaLocation":44,"dataGaName":175},"Visibility and Measurement",{"text":177,"config":178},"Value Stream Management",{"href":179,"dataGaLocation":44,"dataGaName":177},"/solutions/value-stream-management/",{"text":181,"config":182},"Analytics & Insights",{"href":183,"dataGaLocation":44,"dataGaName":184},"/solutions/analytics-and-insights/","Analytics and insights",{"title":186,"items":187},"GitLab for",[188,193,198],{"text":189,"config":190},"Enterprise",{"href":191,"dataGaLocation":44,"dataGaName":192},"/enterprise/","enterprise",{"text":194,"config":195},"Small Business",{"href":196,"dataGaLocation":44,"dataGaName":197},"/small-business/","small business",{"text":199,"config":200},"Public Sector",{"href":201,"dataGaLocation":44,"dataGaName":202},"/solutions/public-sector/","public sector",{"text":204,"config":205},"Pricing",{"href":206,"dataGaName":207,"dataGaLocation":44,"dataNavLevelOne":207},"/pricing/","pricing",{"text":209,"config":210,"link":212,"lists":216,"feature":300},"Resources",{"dataNavLevelOne":211},"resources",{"text":213,"config":214},"View all resources",{"href":215,"dataGaName":211,"dataGaLocation":44},"/resources/",[217,250,272],{"title":218,"items":219},"Getting started",[220,225,230,235,240,245],{"text":221,"config":222},"Install",{"href":223,"dataGaName":224,"dataGaLocation":44},"/install/","install",{"text":226,"config":227},"Quick start guides",{"href":228,"dataGaName":229,"dataGaLocation":44},"/get-started/","quick setup checklists",{"text":231,"config":232},"Learn",{"href":233,"dataGaLocation":44,"dataGaName":234},"https://university.gitlab.com/","learn",{"text":236,"config":237},"Product documentation",{"href":238,"dataGaName":239,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":241,"config":242},"Best practice videos",{"href":243,"dataGaName":244,"dataGaLocation":44},"/getting-started-videos/","best practice videos",{"text":246,"config":247},"Integrations",{"href":248,"dataGaName":249,"dataGaLocation":44},"/integrations/","integrations",{"title":251,"items":252},"Discover",[253,258,262,267],{"text":254,"config":255},"Customer success stories",{"href":256,"dataGaName":257,"dataGaLocation":44},"/customers/","customer success stories",{"text":259,"config":260},"Blog",{"href":261,"dataGaName":5,"dataGaLocation":44},"/blog/",{"text":263,"config":264},"Remote",{"href":265,"dataGaName":266,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":268,"config":269},"TeamOps",{"href":270,"dataGaName":271,"dataGaLocation":44},"/teamops/","teamops",{"title":273,"items":274},"Connect",[275,280,285,290,295],{"text":276,"config":277},"GitLab Services",{"href":278,"dataGaName":279,"dataGaLocation":44},"/services/","services",{"text":281,"config":282},"Community",{"href":283,"dataGaName":284,"dataGaLocation":44},"/community/","community",{"text":286,"config":287},"Forum",{"href":288,"dataGaName":289,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":291,"config":292},"Events",{"href":293,"dataGaName":294,"dataGaLocation":44},"/events/","events",{"text":296,"config":297},"Partners",{"href":298,"dataGaName":299,"dataGaLocation":44},"/partners/","partners",{"backgroundColor":301,"textColor":302,"text":303,"image":304,"link":308},"#2f2a6b","#fff","Insights for the future of software development",{"altText":305,"config":306},"the source promo card",{"src":307},"/images/navigation/the-source-promo-card.svg",{"text":309,"config":310},"Read the latest",{"href":311,"dataGaName":312,"dataGaLocation":44},"/the-source/","the source",{"text":314,"config":315,"lists":317},"Company",{"dataNavLevelOne":316},"company",[318],{"items":319},[320,325,331,333,338,343,348,353,358,363,368],{"text":321,"config":322},"About",{"href":323,"dataGaName":324,"dataGaLocation":44},"/company/","about",{"text":326,"config":327,"footerGa":330},"Jobs",{"href":328,"dataGaName":329,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":329},{"text":291,"config":332},{"href":293,"dataGaName":294,"dataGaLocation":44},{"text":334,"config":335},"Leadership",{"href":336,"dataGaName":337,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":339,"config":340},"Team",{"href":341,"dataGaName":342,"dataGaLocation":44},"/company/team/","team",{"text":344,"config":345},"Handbook",{"href":346,"dataGaName":347,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":349,"config":350},"Investor relations",{"href":351,"dataGaName":352,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":354,"config":355},"Trust Center",{"href":356,"dataGaName":357,"dataGaLocation":44},"/security/","trust center",{"text":359,"config":360},"AI Transparency Center",{"href":361,"dataGaName":362,"dataGaLocation":44},"/ai-transparency-center/","ai transparency center",{"text":364,"config":365},"Newsletter",{"href":366,"dataGaName":367,"dataGaLocation":44},"/company/contact/","newsletter",{"text":369,"config":370},"Press",{"href":371,"dataGaName":372,"dataGaLocation":44},"/press/","press",{"text":374,"config":375,"lists":376},"Contact us",{"dataNavLevelOne":316},[377],{"items":378},[379,382,387],{"text":51,"config":380},{"href":53,"dataGaName":381,"dataGaLocation":44},"talk to sales",{"text":383,"config":384},"Get help",{"href":385,"dataGaName":386,"dataGaLocation":44},"/support/","get help",{"text":388,"config":389},"Customer portal",{"href":390,"dataGaName":391,"dataGaLocation":44},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":393,"login":394,"suggestions":401},"Close",{"text":395,"link":396},"To search repositories and projects, login to",{"text":397,"config":398},"gitlab.com",{"href":58,"dataGaName":399,"dataGaLocation":400},"search login","search",{"text":402,"default":403},"Suggestions",[404,406,410,412,416,420],{"text":73,"config":405},{"href":78,"dataGaName":73,"dataGaLocation":400},{"text":407,"config":408},"Code Suggestions (AI)",{"href":409,"dataGaName":407,"dataGaLocation":400},"/solutions/code-suggestions/",{"text":125,"config":411},{"href":127,"dataGaName":125,"dataGaLocation":400},{"text":413,"config":414},"GitLab on AWS",{"href":415,"dataGaName":413,"dataGaLocation":400},"/partners/technology-partners/aws/",{"text":417,"config":418},"GitLab on Google Cloud",{"href":419,"dataGaName":417,"dataGaLocation":400},"/partners/technology-partners/google-cloud-platform/",{"text":421,"config":422},"Why GitLab?",{"href":86,"dataGaName":421,"dataGaLocation":400},{"freeTrial":424,"mobileIcon":429,"desktopIcon":434,"secondaryButton":437},{"text":425,"config":426},"Start free trial",{"href":427,"dataGaName":49,"dataGaLocation":428},"https://gitlab.com/-/trials/new/","nav",{"altText":430,"config":431},"Gitlab Icon",{"src":432,"dataGaName":433,"dataGaLocation":428},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":430,"config":435},{"src":436,"dataGaName":433,"dataGaLocation":428},"/images/brand/gitlab-logo-type.svg",{"text":438,"config":439},"Get Started",{"href":440,"dataGaName":441,"dataGaLocation":428},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":443,"mobileIcon":447,"desktopIcon":449},{"text":444,"config":445},"Learn more about GitLab Duo",{"href":78,"dataGaName":446,"dataGaLocation":428},"gitlab duo",{"altText":430,"config":448},{"src":432,"dataGaName":433,"dataGaLocation":428},{"altText":430,"config":450},{"src":436,"dataGaName":433,"dataGaLocation":428},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":456,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"title":457,"button":458,"image":462,"config":466,"_id":468,"_type":30,"_source":32,"_file":469,"_stem":470,"_extension":35},"/shared/en-us/banner","is now in public beta!",{"text":84,"config":459},{"href":460,"dataGaName":461,"dataGaLocation":44},"/gitlab-duo/agent-platform/","duo banner",{"altText":463,"config":464},"GitLab Duo Agent Platform",{"src":465},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":467},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":472,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":473,"_id":677,"_type":30,"title":678,"_source":32,"_file":679,"_stem":680,"_extension":35},"/shared/en-us/main-footer",{"text":474,"source":475,"edit":481,"contribute":486,"config":491,"items":496,"minimal":669},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":476,"config":477},"View page source",{"href":478,"dataGaName":479,"dataGaLocation":480},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":482,"config":483},"Edit this page",{"href":484,"dataGaName":485,"dataGaLocation":480},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":487,"config":488},"Please contribute",{"href":489,"dataGaName":490,"dataGaLocation":480},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":492,"facebook":493,"youtube":494,"linkedin":495},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[497,520,576,605,639],{"title":62,"links":498,"subMenu":503},[499],{"text":500,"config":501},"DevSecOps platform",{"href":71,"dataGaName":502,"dataGaLocation":480},"devsecops platform",[504],{"title":204,"links":505},[506,510,515],{"text":507,"config":508},"View plans",{"href":206,"dataGaName":509,"dataGaLocation":480},"view plans",{"text":511,"config":512},"Why Premium?",{"href":513,"dataGaName":514,"dataGaLocation":480},"/pricing/premium/","why premium",{"text":516,"config":517},"Why Ultimate?",{"href":518,"dataGaName":519,"dataGaLocation":480},"/pricing/ultimate/","why ultimate",{"title":521,"links":522},"Solutions",[523,528,530,532,537,542,546,549,553,558,560,563,566,571],{"text":524,"config":525},"Digital transformation",{"href":526,"dataGaName":527,"dataGaLocation":480},"/topics/digital-transformation/","digital transformation",{"text":150,"config":529},{"href":152,"dataGaName":150,"dataGaLocation":480},{"text":139,"config":531},{"href":121,"dataGaName":122,"dataGaLocation":480},{"text":533,"config":534},"Agile development",{"href":535,"dataGaName":536,"dataGaLocation":480},"/solutions/agile-delivery/","agile delivery",{"text":538,"config":539},"Cloud transformation",{"href":540,"dataGaName":541,"dataGaLocation":480},"/topics/cloud-native/","cloud transformation",{"text":543,"config":544},"SCM",{"href":135,"dataGaName":545,"dataGaLocation":480},"source code management",{"text":125,"config":547},{"href":127,"dataGaName":548,"dataGaLocation":480},"continuous integration & delivery",{"text":550,"config":551},"Value stream management",{"href":179,"dataGaName":552,"dataGaLocation":480},"value stream management",{"text":554,"config":555},"GitOps",{"href":556,"dataGaName":557,"dataGaLocation":480},"/solutions/gitops/","gitops",{"text":189,"config":559},{"href":191,"dataGaName":192,"dataGaLocation":480},{"text":561,"config":562},"Small business",{"href":196,"dataGaName":197,"dataGaLocation":480},{"text":564,"config":565},"Public sector",{"href":201,"dataGaName":202,"dataGaLocation":480},{"text":567,"config":568},"Education",{"href":569,"dataGaName":570,"dataGaLocation":480},"/solutions/education/","education",{"text":572,"config":573},"Financial services",{"href":574,"dataGaName":575,"dataGaLocation":480},"/solutions/finance/","financial services",{"title":209,"links":577},[578,580,582,584,587,589,591,593,595,597,599,601,603],{"text":221,"config":579},{"href":223,"dataGaName":224,"dataGaLocation":480},{"text":226,"config":581},{"href":228,"dataGaName":229,"dataGaLocation":480},{"text":231,"config":583},{"href":233,"dataGaName":234,"dataGaLocation":480},{"text":236,"config":585},{"href":238,"dataGaName":586,"dataGaLocation":480},"docs",{"text":259,"config":588},{"href":261,"dataGaName":5,"dataGaLocation":480},{"text":254,"config":590},{"href":256,"dataGaName":257,"dataGaLocation":480},{"text":263,"config":592},{"href":265,"dataGaName":266,"dataGaLocation":480},{"text":276,"config":594},{"href":278,"dataGaName":279,"dataGaLocation":480},{"text":268,"config":596},{"href":270,"dataGaName":271,"dataGaLocation":480},{"text":281,"config":598},{"href":283,"dataGaName":284,"dataGaLocation":480},{"text":286,"config":600},{"href":288,"dataGaName":289,"dataGaLocation":480},{"text":291,"config":602},{"href":293,"dataGaName":294,"dataGaLocation":480},{"text":296,"config":604},{"href":298,"dataGaName":299,"dataGaLocation":480},{"title":314,"links":606},[607,609,611,613,615,617,619,623,628,630,632,634],{"text":321,"config":608},{"href":323,"dataGaName":316,"dataGaLocation":480},{"text":326,"config":610},{"href":328,"dataGaName":329,"dataGaLocation":480},{"text":334,"config":612},{"href":336,"dataGaName":337,"dataGaLocation":480},{"text":339,"config":614},{"href":341,"dataGaName":342,"dataGaLocation":480},{"text":344,"config":616},{"href":346,"dataGaName":347,"dataGaLocation":480},{"text":349,"config":618},{"href":351,"dataGaName":352,"dataGaLocation":480},{"text":620,"config":621},"Sustainability",{"href":622,"dataGaName":620,"dataGaLocation":480},"/sustainability/",{"text":624,"config":625},"Diversity, inclusion and belonging (DIB)",{"href":626,"dataGaName":627,"dataGaLocation":480},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":354,"config":629},{"href":356,"dataGaName":357,"dataGaLocation":480},{"text":364,"config":631},{"href":366,"dataGaName":367,"dataGaLocation":480},{"text":369,"config":633},{"href":371,"dataGaName":372,"dataGaLocation":480},{"text":635,"config":636},"Modern Slavery Transparency Statement",{"href":637,"dataGaName":638,"dataGaLocation":480},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":640,"links":641},"Contact Us",[642,645,647,649,654,659,664],{"text":643,"config":644},"Contact an expert",{"href":53,"dataGaName":54,"dataGaLocation":480},{"text":383,"config":646},{"href":385,"dataGaName":386,"dataGaLocation":480},{"text":388,"config":648},{"href":390,"dataGaName":391,"dataGaLocation":480},{"text":650,"config":651},"Status",{"href":652,"dataGaName":653,"dataGaLocation":480},"https://status.gitlab.com/","status",{"text":655,"config":656},"Terms of use",{"href":657,"dataGaName":658,"dataGaLocation":480},"/terms/","terms of use",{"text":660,"config":661},"Privacy statement",{"href":662,"dataGaName":663,"dataGaLocation":480},"/privacy/","privacy statement",{"text":665,"config":666},"Cookie preferences",{"dataGaName":667,"dataGaLocation":480,"id":668,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"items":670},[671,673,675],{"text":655,"config":672},{"href":657,"dataGaName":658,"dataGaLocation":480},{"text":660,"config":674},{"href":662,"dataGaName":663,"dataGaLocation":480},{"text":665,"config":676},{"dataGaName":667,"dataGaLocation":480,"id":668,"isOneTrustButton":107},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[682],{"_path":683,"_dir":684,"_draft":6,"_partial":6,"_locale":7,"content":685,"config":689,"_id":691,"_type":30,"title":18,"_source":32,"_file":692,"_stem":693,"_extension":35},"/en-us/blog/authors/michael-friedrich","authors",{"name":18,"config":686},{"headshot":687,"ctfId":688},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659879/Blog/Author%20Headshots/dnsmichi-headshot.jpg","dnsmichi",{"template":690},"BlogAuthor","content:en-us:blog:authors:michael-friedrich.yml","en-us/blog/authors/michael-friedrich.yml","en-us/blog/authors/michael-friedrich",{"_path":695,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":696,"eyebrow":697,"blurb":698,"button":699,"secondaryButton":703,"_id":705,"_type":30,"title":706,"_source":32,"_file":707,"_stem":708,"_extension":35},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":46,"config":700},{"href":701,"dataGaName":49,"dataGaLocation":702},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":704},{"href":53,"dataGaName":54,"dataGaLocation":702},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1755803106606]