class: title, smokescreen, shelf, no-footer background-image: url(/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/intro.jpg) # From Xamarin to Flutter ## The journey of a migration --- class: col-2 # About me ![John Thiriet Picture](/assets/images/bio-photo.jpg) @johnthiriet Head of Mobile Technology @ Edenred - Specialized in mobile development *(iOS, Android and Windows)* and .NET - 14 years of professional experience - Former Microsoft MVP and Xamarin MVP - Public Speaker (Techdays, Microsoft Experiences, Xamarin Day, Meetups...) - Press and online writer --- class: col-2 # About my employer ![Edenred Logo](/assets/images/presentations/edenred.png) **Enrich connections. For good.** - 12000 employees in 45 countries - \~ 1 million corporate clients - \~ 60 million users - \~ 2 million partner merchants - Close to 38 billion euros in business volume of which most is digital - Entered CAC 40 in June 2023 --- # Agenda When you manage a **_payment oriented_** app, with **_3+ million users_**, in **_12+ countries_**, with **_100+ screens_**, localized in **_15+ languages_**, with **_10+ developers_**, **technical choices matter**. In this presentation I will tell you about the journey we had **from Xamarin to Flutter**. ![Conclusions](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/agenda.svg# w-2-12th db fr mr-4) 1. Past decisions 2. Why migrating ? 3. The plan 4. The reality 5. Conclusion ??? Notes --- class: title, fogscreen, no-footer background-image: url(/assets/images/presentations/xamarin-from-2020-to-2021/monkey-debug.jpg) # Past decisions --- class: col-2 # The constraints ### Ambitious features - Card management - Profile Management - Maps - Mobile Payments - Qr Codes - In-App Provisioning - Custom NFC Android Wallet ### Great diversity - Multiple continents - Multiple cultures - Various devices range - Remote configuration - Various display rules - Currencies - Formatting --- # Past decisions Six years ago, we went with Xamarin native and the MVVM approach. It delivered solid performance but meant we had to build the UI separately for iOS and Android. Looking back, this choice was a winner, letting us bring our app to over 3 million users in more than 12 countries in Europe, South America, and Asia, all while reusing as much code as possible. > But a 6 years old code base is really old in mobile world and some decisions needed to be made. --- class: title, fogscreen, no-footer background-image: url(/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/why.jpg) # Why migrating ? ??? "Drought" by Bert Kaufmann is licensed under CC BY 2.0. --- class: img-right-full roomy # Challenges ![options](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/challenges.jpg) - Painful new developments - Painful maintenance - Recruitment - Xamarin -> .NET Maui - Timing (Mid 2022) ??? "Hippo War in the Serengeti" by *rboed* is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/?ref=openverse. --- class: roomy img-right-full # Our options ![options](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/options.jpg) - .NET Maui - Native - React Native - Kotlin Multiplatform Mobile ??? "Crossroad" by Guwashi999 is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/?ref=openverse. --- class: roomy, no-footer # Why Flutter ? ![User engagement page mono product food](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/uep-single.svg# h-100pct t-0 r-1 ofv absolute) - Hot Reload - Declarative UI - Component approach - Design system - Real shared UI - Community - Developer interest - Performance - Not Javascript :-D --- class: compact, col-2 # Why Flutter ? ```csharp public class CardsApi : ICardsApi { private readonly IApiClient _apiClient; public CardsApi(IApiClient apiClient) { _apiClient = apiClient; } public async Task
> GetCardsAsync() { try { var dto = await _apiClient.GetAsync
>(); return new CardsAdapter().adapt(dto); } catch (Exception) { ... } } } ``` ```dart class CardsApi implements ICardApi { public CardsApi(this._apiClient); final IApiClient _apiClient; public Future
> GetCardsAsync() async { try { var dto = await _apiClient.GetAsync
>(); return CardsAdapter().adapt(dto); } catch (Exception) { ... } } } ``` > C\# vs Dart --- class: title, fogscreen, no-footer background-image: url(/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/plan.jpg) # The plan ??? "Engineer working on plans for Lake Union area, circa 1960s" by Seattle Municipal Archives is licensed under CC BY 2.0. --- class: compact, no-footer # The plan ![UEP MultiProduct](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/uep-multi.svg# h-100pct t-0 r-1 ofv absolute) 1. Proof of concept (Design System and Components) 2. **Writing architecture guidelines** 3. Writing the application framework 4. Create CI/CD Pipelines 5. **Team onboarding** 6. Tight code review 7. **Progressive release** 8. Xamarin sunset > I will only slightly detail the points in bold in this presentation --- # Architecture guidelines ![Folder structure](https://johnthiriet.com/assets/images/presentations/epitech-alumni-flutter-quelle-architecture-apres-mon-poc/folder_structure.png# w-6-12th db fr mr-4) 1. Folders structure 2. State Management 3. Error Management 4. Localization 5. Unit testing 6. Code generation 7. Data storage 8. Security > [https://devmuaz.medium.com/flutter-clean-architecture-series-part-1-d2d4c2e75c47](https://devmuaz.medium.com/flutter-clean-architecture-series-part-1-d2d4c2e75c47) --- # Architecture guidelines In our applications we ended up following the **Clean Architecture** approach with **Bloc** as a state management solution. ![Architecture overview](/assets/images/posts/2023-10-25-from-xamarin-to-flutter-the-code-architecture-overview.svg) --- class: compact # Architecture guidelines |Layer|Function|Comment| |:-:|:-:|:--:| |**View** | Generates the UI. Listens to Cubit events and invokes Cubit methods. | Rely on BlocBuilder and BlocListener. |**Cubit**| Invokes one or multiple use cases to generate view states. | Maintains view state and mutates it. |**UseCase**| Represent an action or process that provides aggregated data for the view. | Pure, stateless. |**Repository**| Handles the data of a particular model. It chooses where it should get its data from but delegates that to DataSources or Services. | Returns aggregates in DDD terms. |**Service**| A service is a technical repository. | Retrieves non-business model data or infrastructure data such as authentication tokens or phone languages. |**DataSource**| Retrieves a specific model from a specific source. | For exemple calling an API or calling a local database or parsing a local file. --- # Team onboarding ![Onboarding](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/onboarding.svg# w-33pct db fr mr-4) It was clear from the start that it **was not going to be a quick and easy transition**. The initial estimates suggested it would take **more than six months to complete**. We decided early on that we would **train the existing Xamarin developer** team to Flutter. and that they would be the ones working on the migration. When a team has been working on an app for 4 years, the **actual asset is the team**, not the code. --- # Team onboarding For each squad : 1. Give time to play with Flutter on whatever project without directives 2. Onboard them with the guidelines 3. Let them start the work 4. Review developments closely | Team | Step 1 | Step 2 | Step 3 | Step 4 | Step 5 | Step 6 | Step 7 | |:----:|:-------:|:-----------:|:-------:|:-----------:|:-------:|:------:|:-----------------:| | A | Xamarin | Flutter POC | Flutter | Flutter | Flutter | Fully autonomous | - | | B | - | Xamarin | Xamarin | Flutter POC | Flutter | Flutter | Fully Autonomous | --- class: title, fogscreen, no-footer background-image: url(/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/reality.jpg) # The reality ??? "Ship in a storm in the Sargasso Sea. Original from NASA. Digitally enhanced by rawpixel." by Free Public Domain Illustrations by rawpixel is licensed under CC BY 2.0. --- # Reskilling is not easy ![Reskilling](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/reskilling.svg# w-20pct db fr mr-2) - Learning the **Flutter Way** - Similar languages doesn't mean similar technology - Feeling of productivity loss At the teams request, we hired an **external trainer** to help them consolidate their learnings. We were confident the squads would adapt quickly, but it turned out to be **more challenging than expected**. > Acknowledging these challenges and **offering support is crucial** in such migrations. ??? Many developers felt less productive with Flutter compared to Xamarin for quite some time. --- # Adapting to delays ![Delays](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/delay.svg# w-20pct db fr mr-4) - More time spent on Xamarin than anticipated - It was necessary to maintain essential updates and fixes - It caused lots of delays - We had to hire an external team to cover delays - Time is required to get new developers up to speed - Balance cost/benefits constantly checked > Despite their experience in Flutter, this team help was limited to their understanding of our industry, confirming the initial assumption that **the team is the asset**. --- # Progressive release Even with all the care of the world, rewriting a 5 years old application from scratch brings problems. - Regressions - Performance issues - Bugs - Crashes We slowly released the app to one platform first, and then to the others, allowing us to catch most of the bugs before big problems happened. Unfortunately, we did more hotfixes than we ever did with Xamarin ;-) --- class: title, fogscreen, no-footer background-image: url(/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/conclusions.jpg) # Conclusions ??? "Project 365 #200: 190713 The Finishing Line" by comedy_nose is marked with Public Domain Mark 1.0. --- # Conclusions ![Conclusions](/assets/images/presentations/from-xamarin-to-flutter-a-migration-journey/conclusions-numbers.svg# w-10pct db fr mr-4) In numbers : - ~9 months of developments - all of the Xamarin team (except one) stayed and got reskilled - +180000 lines of dart code - faster developments - faster releases - tooling that doesn't get in the way (looking at you Xamarin) - design system implemented > No regrets with the technical choices made. --- # Slides .qrcode.db.fr.w-40pct.ml-4[] Slides are available on [john's blog](/presentations/). Scan the QrCode for direct access. @johnthiriet - [Twitter](https://twitter.com/JohnThiriet) - [LinkedIn](https://linkedin.com/in/JohnThiriet)