<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Pavel Sulimau on Medium]]></title>
        <description><![CDATA[Stories by Pavel Sulimau on Medium]]></description>
        <link>https://medium.com/@pasul?source=rss-dea2d0cc5369------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Wtv6JMt0zE9pKh7x4b4yKg.jpeg</url>
            <title>Stories by Pavel Sulimau on Medium</title>
            <link>https://medium.com/@pasul?source=rss-dea2d0cc5369------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 13 Apr 2026 19:42:56 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@pasul/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Flutter: Module-based Code Coverage Thresholds]]></title>
            <link>https://itnext.io/flutter-module-based-code-coverage-thresholds-988b88144833?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/988b88144833</guid>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[modules]]></category>
            <category><![CDATA[unit-testing]]></category>
            <category><![CDATA[code-coverage]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Sun, 18 Aug 2024 07:46:36 GMT</pubDate>
            <atom:updated>2024-08-18T07:46:36.533Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*tB2ATvm3EQzbmikbFkS9UQ.png" /></figure><p>One of the ways to “encourage” developers to write tests is to have a code coverage check as part of the Continuous Integration (CI) process. Some teams even set an ambitious goal of achieving a 100% code coverage threshold, which, in my opinion, is often not worth the effort. While it can serve as an impressive metric for developers to showcase to their managers, it does not necessarily ensure the absence of bugs. In fact, it may provide a misleading sense of security.</p><h3>Module-based Threshold Concept</h3><p>In <a href="https://medium.com/itnext/flutter-modularized-dependency-injection-4362649f84ed"><strong>this article</strong></a>, I shared a clean approach to separating your app into modules. The <a href="https://github.com/Pavel-Sulimau/flutter_modularized_di"><strong>GitHub repository</strong></a> already includes various tests and CI checks.</p><p>Let’s enhance it further by ensuring that, in addition to running unit tests, we also collect code coverage data and verify that it exceeds the specified thresholds.</p><p>The concept is that different modules can have varying thresholds. For instance, the <strong>domain</strong> module, which contains more business logic than the others, should be tested more rigorously. For the sake of the fun, let’s aim for 100% there in this module. Conversely, for the <strong>presentation</strong> module, we might set a lower target threshold, let’s make it just 40%. Typically, BLoCs/Cubits are tested more thoroughly than widgets/screens. Other modules may not have a specific target threshold. In practice, this means setting the threshold to 0%, allowing the check to pass regardless of the coverage value.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Maj3HKMdLlxk7L5l3f7Lug.png" /><figcaption>Different code coverage thresholds for various modules</figcaption></figure><h3>Implementation</h3><p>The most useful tool for running tests with varying code coverage thresholds is <a href="https://pub.dev/packages/very_good_cli">very_good_cli</a>.</p><p>With a command like very_good test --coverage --min-coverage 100, we can easily validate the coverage.</p><p>The question is how to apply this based on the module. The most straightforward approach for me is to create a special file in the test folder of each module where a custom threshold is specified. Then, we can use a small script that reads the threshold from the file and passes it to the very_good test command. I named this script test_with_coverage.sh and placed it in the scripts folder.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/590846260df5e565b06cf09c055b4603/href">https://medium.com/media/590846260df5e565b06cf09c055b4603/href</a></iframe><p>With <a href="https://melos.invertase.dev/">Melos</a> we can easily invoke the script for each of the intended modules.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ecfae20723a94b6bc6860f93edff51bc/href">https://medium.com/media/ecfae20723a94b6bc6860f93edff51bc/href</a></iframe><p>All the changes required to set this up are detailed in <a href="https://github.com/Pavel-Sulimau/flutter_modularized_di/pull/6/files"><strong>this small PR</strong></a>.</p><h3>Conclusion</h3><p>In summary, by leveraging tools like very_good_cli, Melos, and custom scripting, we can ensure that each part of the application is tested according to its specific needs. This approach provides a balanced and practical testing strategy.</p><h3>Resources</h3><p><a href="https://github.com/Pavel-Sulimau/flutter_modularized_di">GitHub - Pavel-Sulimau/flutter_modularized_di: Modularized Flutter Counter App Honoring Clean Architecture Principles and Using Simple DI Abstractions to Preserve Encapsulation within Modules.</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=988b88144833" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-module-based-code-coverage-thresholds-988b88144833">Flutter: Module-based Code Coverage Thresholds</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fluttercon Europe 2024]]></title>
            <link>https://itnext.io/fluttercon-europe-2024-b202aafd1c20?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/b202aafd1c20</guid>
            <category><![CDATA[fluttercon]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[conference]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Mon, 08 Jul 2024 06:54:29 GMT</pubDate>
            <atom:updated>2024-07-09T11:05:01.907Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZAQMtwIEkJadb9d-FunZew.jpeg" /></figure><p>Having experienced the incredible <a href="https://itnext.io/flutteron-2023-worth-watching-talks-720213bf708f">scale and excitement of FlutterCon 2023</a>, I knew attending <a href="https://fluttercon.dev/">Fluttercon Europe</a> 2024 was a must for me. This year, my excitement was heightened as I participated not only as an attendee but also as a speaker!</p><p>In this article, I’ll share some insights from the presentations I attended. Although I couldn’t catch all the talks in real time, I plan to watch the recordings of the other sessions once they become available.</p><h3>Day 1 — July 3</h3><h4>Opening Keynote by <strong>Andrew Brogdon</strong></h4><p><em>9:00 AM — Widget Way</em></p><p>Andrew provided an overview of Flutter’s current state, its roadmap, and the potential influence of Generative AI on its future. He also discussed Flutter’s impact on large companies and explored ways to create more opportunities.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_N7WRW9ssid0HlHSEvp5_Q.jpeg" /></figure><h4>Zero runtime errors: Exploring Static Code Analysis techniques in Flutter by Daria Orlova</h4><p><em>10:20 AM — Async Area</em></p><p>Developers typically favor developing new features over troubleshooting bugs, yet bugs are an inevitable aspect of software development. Static code analysis presents a proactive approach by detecting potential errors before the code is compiled, thereby streamlining the development process and boosting productivity. This talk provides comprehensive guidance on how to effectively implement static code analysis in your project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Gfega7-8t7O-Sne_I9fTxw.jpeg" /></figure><h4>Showing that you care about security — OpenSSF Scorecards for Dart and Flutter projects by Chris Swan</h4><p><em>11:15 AM — Async Way</em></p><p>Google uses OpenSSF Scorecard badges on Dart and Flutter repositories to highlight the commitment to security through various practices like dependency pinning and branch protection. This presentation will guide you on applying these security measures to your Dart and Flutter projects, covering the initial setup in a repository, expanding it across multiple repositories within an organization, and automating the maintenance of these security practices to reduce manual effort.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uHSC_Myqv8iLhQ7aKrbnGg.jpeg" /></figure><h4>Navigation in Flutter — the not-so-obvious parts by Matej Rešetár</h4><p><em>12:10 PM — Widget Way</em></p><p>Just use <a href="https://pub.dev/packages/go_router">go_router</a> with <a href="https://pub.dev/packages/go_router_builder">go_router_builder</a> and you’re good to go :) If you are not satisfied with it, consider using <a href="https://pub.dev/packages/auto_route">auto_route</a>. That’s pretty much it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x0g52QUSJd9gmQzeeyPGvw.jpeg" /></figure><h4>Realtime Communications with Flutter by Simon Lightfoot</h4><p><em>1:40 PM — Widget Way</em></p><p>Discover how to overcome Firebase/Firestore limitations in Flutter projects by switching to a backend written purely in Dart.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3peQGOY-IujMSRbotWo6oQ.jpeg" /></figure><h4>One Size Doesn’t Fit All: Tailoring Flutter Architectures for Team and Business Success by Jan Stępień</h4><p><em>3:15 PM — Flutter Forest</em></p><p>In the startup environment, Jan learned to balance ideal long-term architecture with the immediate needs of the business by adopting a pragmatic approach, prioritizing features, and refactoring gradually, so he shared his insights on the topic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*e93-4O_9LjGMXNIz0SD72Q.jpeg" /></figure><h4>Code Quality Gates for Large-Scale Flutter Apps by Pavel Sulimau</h4><p><em>3:45 PM — Flutter Forest</em></p><p>Well, this was a talk I simply couldn’t miss attending, given that I was the presenter! I endeavored to pack as many guidelines and tools as possible into 20 minutes, aiming to ensure that attendees could set a higher code quality standard for their projects.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OaAUi0poq5-7e6Nri_xBdQ.jpeg" /></figure><h4>Compilers, Virtual Machines, and Code Analysis — What makes Dart and Flutter run by Norbert Kozsir</h4><p><em>4:20 PM — Dart Gen</em></p><p>This session dived into the mechanics behind Flutter, focusing on the Dart compiler, DartVM, Dart Analyzer, and the Engine, beyond everyday coding practices.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GvFJIfVNLBh4Y3-vtf5NZQ.jpeg" /></figure><h4>Debugging performance issues with the Flutter DevTools by Alexandre Moureaux</h4><p><em>5:20 PM — Widget Way</em></p><p>During this live-coding session, we addressed performance issues in a dummy app through real-life examples and utilized the performance view in the DevTools to guide our process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dn47T798zut5MVGPvWYxGw.jpeg" /></figure><h3>Day 2 — July 4</h3><h4>Android Platform Views Past, Present, Future by John McCutchan</h4><p><em>9:20 — Dart Den</em></p><p>That was an insightful exploration into how Platform Views are implemented on the Android platform, including their advantages and disadvantages.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D0QslRBVdvE8OG-Rsc8--w.jpeg" /></figure><h4>Dart FFI: A Beginner’s Guide to High-Performance Integration by Matteo Maria Terzuolo</h4><p><em>10:15 AM — Async Area</em></p><p>Dart FFI lets you enhance your Dart applications by calling functions from languages like C or Rust, ideal for tasks needing extra performance such as image processing or machine learning. This talk explored the benefits and challenges of using Dart FFI, as well as alternative approaches to enhance your app’s performance.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zVgFWq2Q4_x0O0f3X16VjQ.jpeg" /></figure><h4>Building Real-Time Audio/Video Apps with Flutter and WebRTC by Masahiro Aoki</h4><p><em>11:10 AM — Async Area</em></p><p>This session provided a comprehensive guide to creating real-time audio and video communication applications using Flutter and WebRTC. It covered a range of topics from basic to advanced concepts.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8LYgVXu0w-V83DTXK62K2A.jpeg" /></figure><h4>Demystifying App Architecture: The LeanCode Guide by <strong>Mateusz Wojtczak and Marcin Chudy</strong></h4><p><em>1:25 — Dart Gen</em></p><p>LeanCode has developed more than 40 Flutter apps, each presenting unique challenges and opportunities for learning. The talk explored their preferences in state management and other practices, encouraging attendees to understand the reasoning behind their choices and how they minimize redundancy in development.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jN0-WbGa5440k2y27XMneg.jpeg" /></figure><h4>Self-host private pub packages by <strong>Pascal Welsch</strong></h4><p><em>2:20 PM — Widget Way</em></p><p>Their Flutter agency encountered difficulties in sharing packages across projects because of the significant costs and maintenance challenges associated with self-hosting Dart and Flutter packages. In this talk, Pascal discussed how they discovered a cost-effective method to host their own pub repository, including utilizing their own domain. Moreover, they offered it as an open-source solution to the Flutter Community without any sponsorship.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ea8UG3u-gW9rE4iWkDGJ6g.jpeg" /></figure><h4>Presentation events — a missing piece in BLoC by Marcin Wojnarowski</h4><p><em>3:30 PM — Widget Way</em></p><p>This talk explores how to incorporate presentation events into BLoCs, addressing their inability to handle one-off occurrences like snackbars or redirects, thereby solving a fundamental problem in BLoC’s state management within the Flutter ecosystem.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eViwTOXF9G_FK_lI39TYfw.jpeg" /></figure><h4>The past, present, and future of native interop by <strong>Daco Harkes and Hossein Yousefi</strong></h4><p><em>4:10 PM — Flutter Forest</em></p><p>Discover how JNIgen/FFIgen simplifies the integration of Flutter with native code, thereby improving app performance and facilitating feature development. This presentation highlighted its advantages for plugin development and discussed future plans.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*34YIY5uydV5GOPecg3JU9Q.jpeg" /></figure><h3>Day 3 — July 5</h3><h4>Hacking and protection of Mobile Apps and backend APIs. Threat modeling exercise by Tomáš Soukal</h4><p><em>9:20 — Flutter Forest</em></p><p>The audience was educated on safeguarding mobile apps and APIs against attacks such as botnets and token hijacking, employing strategies rooted in OWASP MAS (Mobile Application Security) practices.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6CcD3KPMYhdtvXt6tRW7xw.jpeg" /></figure><h4>Developer Diary: Journey of a payment integration by <strong>Nino Handler</strong></h4><p><em>10:15 AM — Flutter Forest</em></p><p>Nino shared insights into their journey of successfully integrating an “unknown” payment provider into an app. He detailed the transition from a high-maintenance, native library approach on Android and iOS to a more sustainable, browser-based payment flow. The presentation covered challenges and solutions associated with WebViews, In-App browsers, Firebase Hosting, and navigation using Deep Links.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OAeZQ9HiyUxOcIf2_lU11g.jpeg" /></figure><h4>Migrating 2+ Million Daily Users to Flutter with 50+ Engineers by Csongor Vogel, Lucas Britto, Bruno Reginato</h4><p><em>11:10 AM — Widget Way</em></p><p>Talabat’s migration to Flutter showcased approaches, challenges, and lessons from integrating Flutter into a native Android and iOS setup, emphasizing the importance of a learning culture and quality standards for a huge mobile team.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vnTbK5ZYZd82QGf4EWb_Fw.jpeg" /></figure><h4>App Architecture: Faster, Better… Simpler by Kirill Bubochkin</h4><p><em>1:25 PM — Async Area</em></p><p>This talk challenges the overcomplication of app architecture by newcomers following popular trends, suggesting a simpler approach and discussing the pitfalls of misapplying principles like SOLID, DRY, and Clean Architecture, with insights on using the DCM feature for code analysis.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*53oOUm1Torf4SFkhql24hg.jpeg" /></figure><h4>Working with forms as an ecosystem by Vasyl Dytsiak</h4><p><em>2:20 PM — Async Area</em></p><p>This talk explored the creation of a supportive ecosystem for complex form handling in Flutter, highlighting how specialized form engines like reactive_forms, coupled with supportive packages such as reactive_forms_widgets and reactive_forms_generator, streamlined development, ensured code consistency and saved time. It encouraged open-source contribution and demonstrated the use of these tools for advanced form functionalities.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7TF9varOUu9vJJQkmqUZuQ.jpeg" /></figure><h4>Speechless Slide Karaoke with Chet Haase</h4><p><em>3:00 PM — Stadia Room</em></p><p>Oh, that one was a delightful mix of laughter and fun!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ynMjKtyesb8_AfarfwbbJA.jpeg" /></figure><h3>FlutterCon is far more than just talks and workshops!</h3><p>Beyond these formal events, numerous fun and cool activities were happening. Here, I’m excited to share just a glimpse of the engaging experiences that were part of the conference.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gjmeo0rau9u8I9BrWQUZRQ.gif" /><figcaption>Table tennis warm-up</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MRjH_oW45jDlxGkDrG5JZg.jpeg" /><figcaption>A variety of food choices, including healthy stuff</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DNkuU9RBLaRZnlYHI1p5qQ.png" /><figcaption><a href="https://recyclo.dev/">Recyclo</a> game running on Apple TV from <a href="https://wearecommunity.io/communities/mobilepeople">Mobile People community</a>, of course, developed with Flutter</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HvX-gGPIYCf_oCYKOxelhA.jpeg" /><figcaption>Enthusiastic <a href="https://flutternl.org/#/">Flutter Netherlands</a> community enjoying a game of Padel</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PCBsJQUF8_sD4AUcdB2Mkw.jpeg" /><figcaption>A code challenge by <a href="https://www.meetup.com/flutter-berlin/">Flutter Berlin</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HextVRflpeQvpVvOsg3joQ.jpeg" /><figcaption>An exciting quiz from <a href="https://leancode.co/">LeanCode</a> with a wonderful prize — <a href="https://www.flutterfriends.dev/">Flutter&amp;Friends</a> ticket + Lego</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W21CT7bIfnnEk4f3q76nfg.jpeg" /><figcaption><a href="https://www.widgetbook.io/">Widgetbook</a> party!</figcaption></figure><h3>Conclusion</h3><p>The magnitude and impact of FlutterCon Europe cannot be overstated! This conference goes beyond just presentations; it’s about connecting with great individuals from the community, engaging in insightful discussions, and enjoying fun activities together. I’m thrilled to have had the opportunity to speak at this year’s event and am eagerly anticipating attending the conference again next year.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yqfJGRz3hIKYZcHvBevjTw.jpeg" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b202aafd1c20" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/fluttercon-europe-2024-b202aafd1c20">Fluttercon Europe 2024</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Detecting Cyclic Dependencies in a Monorepo]]></title>
            <link>https://itnext.io/flutter-detecting-cyclic-dependencies-in-a-monorepo-1dc88fe0d02d?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/1dc88fe0d02d</guid>
            <category><![CDATA[app-architecture]]></category>
            <category><![CDATA[monorepo]]></category>
            <category><![CDATA[dependencies]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[clean-architecture]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Sat, 15 Jun 2024 22:25:30 GMT</pubDate>
            <atom:updated>2024-06-15T22:25:30.128Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*TSgANMbu4vedeCBLCMJmDg.png" /></figure><p>When you’re developing a Flutter application that’s intended to be more than just a Proof of Concept (PoC) to be set aside in a few weeks, I recommend opting for a monorepo approach in most scenarios.</p><h3>Monorepo Advantages</h3><p>Adopting a monorepo means that your codebase is organized into Flutter/Dart packages rather than mere directories. This setup introduces “physical” boundaries instead of merely “logical” ones.</p><p>The <strong>advantages</strong> of this strategy include:</p><ul><li><strong>Improved Separation of Concerns</strong><br>Encapsulation is now enforced by the analyzer/compiler, necessitating the explicit export of types from one package for their use in another. This enhances modularity and clarity in your project structure.</li><li><strong>High Reusability Potential</strong><br>It becomes significantly easier to reuse a package in another application within the same repository, or to migrate the package to a different repository. This is particularly beneficial compared to extracting types from a large, monolithic package, especially when those types are tightly coupled with integrated with the rest of the package’s content.</li><li><strong>Optimized Build Times and CI Resources<br></strong>To understand how a monorepo can lead to optimizations in terms of time and cost, I recommend reading the <a href="https://medium.com/itnext/flutter-selective-ci-checks-2d79ffbd26e5">Selective CI Checks</a> article. It offers practical solutions for making your Continuous Integration processes more efficient.</li></ul><h3>A nuance in Dart Analyzer/Compiler</h3><p>One peculiar aspect of Flutter/Dart monorepos is that the Dart compiler permits cyclic dependencies between packages. This implies that if package A depends on package B, you can also make package B depend on package A. While this might seem like a flexible feature, I view it more as a drawback than a benefit. The presence of cyclic dependencies is often considered a red flag, as it results in tightly coupled code that can become challenging to maintain.</p><p>In contrast, compilers for other programming languages, such as C# or Kotlin, will immediately flag cyclic dependencies as errors, preventing their occurrence. This restriction helps ensure a cleaner, more maintainable codebase by encouraging developers to think more carefully about their project’s architecture and dependency structure.</p><h3>Melos to the Rescue</h3><p>Fortunately, the <a href="https://melos.invertase.dev/">Melos tool</a>, which I’ve discussed in my previous articles, not only significantly eases the management of Flutter/Dart monorepos but also comes equipped with a <strong>built-in feature to detect cyclic dependencies</strong>.</p><p>The command to leverage this feature is melos list --cycles.</p><p>Running this command produces immediate results without incurring additional resource consumption. This makes it an ideal check to integrate into your project’s CI pipeline, ensuring your codebase remains free from cyclic dependencies without impacting your CI resources.</p><p>To illustrate how this works in practice, let’s revisit the application discussed in the <a href="https://medium.com/itnext/flutter-modularized-dependency-injection-4362649f84ed">Modularized Dependency Injection</a> article, which has the following module structure.</p><h3>Well Organized Dependencies</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/796/1*R6_29HBc4I_w285rOmkPVQ.png" /><figcaption>Cleanly separated modules with one-direction dependencies</figcaption></figure><p>When I execute the melos list --cycles command within the repository containing the aforementioned package structure, Melos reports no issues. This outcome is as pleasing to me as it is to Melos!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/784/1*sB02K0d3mDhvnUWtWP4Gzw.png" /></figure><h3>Cyclic Dependency Example</h3><p>When I introduce a cyclic dependency by linking the domain package back to the data package, the solution still compiles, and the application runs without any apparent issues. However, this practice is akin to walking on thin ice. It’s a very slippery slope that I strongly advise against.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ivHyJIvqhDIZdKDYFsHs0Q.png" /><figcaption>Not recommended cyclic dependency</figcaption></figure><p>The melos list --cycles command complains immediately in this case, cool!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/784/1*Pre0uLkYyKyrDrGeHDKmsg.png" /></figure><p>Make sure you check <a href="https://github.com/Pavel-Sulimau/flutter_modularized_di/pull/5">this PR</a> to see how it is integrated into the CI flow.</p><h3>Further Reading</h3><p>In addition to being mindful of dependencies in a monorepo it is also important to correctly manage the external dependencies of your packages. To gain a deeper understanding there, I highly recommend checking out <a href="https://medium.com/itnext/flutter-mind-your-dependencies-52072df6d96">this dedicated article on the topic</a>.</p><h3>Useful Links</h3><ul><li><a href="https://medium.com/itnext/flutter-modularized-dependency-injection-4362649f84ed">https://medium.com/itnext/flutter-modularized-dependency-injection-4362649f84ed</a></li><li><a href="https://medium.com/itnext/flutter-selective-ci-checks-2d79ffbd26e5">https://medium.com/itnext/flutter-selective-ci-checks-2d79ffbd26e5</a></li><li><a href="https://medium.com/itnext/flutter-mind-your-dependencies-52072df6d96">https://medium.com/itnext/flutter-mind-your-dependencies-52072df6d96</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1dc88fe0d02d" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-detecting-cyclic-dependencies-in-a-monorepo-1dc88fe0d02d">Flutter: Detecting Cyclic Dependencies in a Monorepo</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Choosing Mobile UI Tests Automation Tool]]></title>
            <link>https://itnext.io/flutter-choosing-ui-tests-automation-tool-1a42336b09d7?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a42336b09d7</guid>
            <category><![CDATA[automation-testing]]></category>
            <category><![CDATA[quality-assurance]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[ui-test-automation]]></category>
            <category><![CDATA[mobile]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Sat, 04 May 2024 21:33:59 GMT</pubDate>
            <atom:updated>2024-05-08T18:35:56.865Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*NtaegCa2dsnDnaGz9_PH4Q.png" /></figure><p>In the large-scale Flutter projects that our team has been working on for the last 4+ years, the topic of Mobile UI Tests Automation has always been on the table. With our first app, we released updates every month, gradually moving to biweekly releases for subsequent apps. The automation of functional application testing, conducted at least on a nightly basis, facilitates faster and more confident application releases. The importance of this is clear to both the team and the business.</p><p>Our first Flutter app used <a href="https://docs.flutter.dev/testing/integration-tests">Flutter Integration Testing</a>, in combination with Github Actions and <a href="https://firebase.google.com/docs/test-lab">Firebase Test Lab</a>. However, our experience with Flutter Integration Testing was not the smoothest. Additionally, its limitations in covering WebViews or Native views could pose significant problems.</p><p>Another Flutter team used the first version of Patrol on a different project. In both instances, it was primarily the developers who wrote these tests, but there was a desire among QAs to take ownership.</p><p>Our latest Flutter projects had a more complex setup. The teams have been working on a white-label framework, building several Full Flutter applications while also integrating some Flutter features into existing native apps (iOS + Android). These existing native apps already had automation running, so last year we conducted an investigation to identify which automation tool would best suit our needs for the Full Flutter ones.</p><h3>The Tools We Considered</h3><p>The table below provides a brief overview of the tools under consideration. Please note that some known limitations of certain tools are not depicted in the table.</p><p>What I found <strong>really interesting</strong> is that Maestro was formerly known as Conductor, and Patrol was previously named Maestro! You can check <a href="https://github.com/mobile-dev-inc/maestro/pull/33/files">this rename</a> in the Maestro repo and <a href="https://github.com/leancodepl/patrol/pull/258/files">this one</a> in the Patrol repo.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XhXvffS48UkZ9LhOs_Bo8A.png" /></figure><p>It’s important to note that black-box testing of Flutter views is conducted based on the provided semantics information. By default, this information is included in widgets that display text. However, you can attach semantics information to any widget using Flutter’s <a href="https://api.flutter.dev/flutter/widgets/Semantics-class.html">Semantics widget</a>.</p><p>Additionally, <a href="https://github.com/flutter/flutter/issues/17988">the long-living accessibility-id issue</a> was finally resolved in Flutter 3.19, thanks to <a href="https://blog.mobile.dev/the-power-of-open-source-making-maestro-work-better-with-flutter-d92b386f9a33">Bartek Pacia</a>! As a result, a new accessibility identifier property of the Semantics widget is now propagated to the native accessibility hierarchy.</p><h3>What Was Important to Us?</h3><p>We paid special attention to the following aspects of the tools under consideration:</p><ul><li>Maturity and maintainability</li><li>Black-box testing</li><li>Inspecting tools</li><li>Compatibility with our QAs&#39; skills</li></ul><h3>Our Choice</h3><p>Given that <strong>WebdriverIO</strong> is a mature tool already in use for our native apps and familiar to our QAs, and since it is technically capable of covering both full Flutter and Add-to-app Flutter apps, our decision to broaden its use was straightforward. This choice also amplified our motivation to pay closer attention to the Semantics trees in our apps, as they are not only crucial for impaired individuals, but also serve as a bridge to UI Tests automation tools!</p><h3>Bonus: A Demo of Maestro’s Ease of Use!</h3><p>Even though we didn’t choose Maestro for our latest Flutter apps, I was struck by its speed and ease of use.</p><p>So, to give you a notion of it, I wiped off the dust from my first Flutter pet project I started 5 years ago and decided to automate a test case. The project is <a href="https://memme.pasul.dev/"><strong>MemMe</strong></a>, a laconic flashcards app designed to make memorization easy.</p><p><a href="https://maestro.mobile.dev/getting-started/installing-maestro">With just one command</a>, I installed Maestro and began experimenting with <a href="https://maestro.mobile.dev/getting-started/maestro-studio">Maestro Studio</a>. I wrote the following flow to test the case of adding a new flashcard to the freshly installed application. It was so quick and enjoyable to write that I finished the test before even finishing my cup of tea!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/28939db23a0e5a49bdcc8e5e466592bd/href">https://medium.com/media/28939db23a0e5a49bdcc8e5e466592bd/href</a></iframe><p>The animation below demonstrates the test flow run. By the way, the video <a href="https://maestro.mobile.dev/cli/recording-your-flow">was recorded using the built-in feature in Maestro</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UIylfyLAX_9qcEa8ZYqD6A.gif" /><figcaption>add_new_card_flow.yaml</figcaption></figure><h3>Conclusion</h3><p>Don’t hesitate to invest time exploring the world of Mobile UI Tests automation. With the right tools and understanding, this investment can significantly enhance your ability to deliver high-quality, reliable applications. It’s an investment that quite often pays off.</p><h3>Resources</h3><ul><li><a href="https://patrol.leancode.co/">https://patrol.leancode.co/</a></li><li><a href="https://fluttium.dev/">https://fluttium.dev/</a></li><li><a href="https://maestro.mobile.dev/">https://maestro.mobile.dev/</a></li><li><a href="https://appium.io/">https://appium.io/</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a42336b09d7" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-choosing-ui-tests-automation-tool-1a42336b09d7">Flutter: Choosing Mobile UI Tests Automation Tool</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Selective CI Checks]]></title>
            <link>https://itnext.io/flutter-selective-ci-checks-2d79ffbd26e5?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/2d79ffbd26e5</guid>
            <category><![CDATA[monorepo]]></category>
            <category><![CDATA[optimization]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Sat, 20 Apr 2024 00:07:33 GMT</pubDate>
            <atom:updated>2024-04-20T08:11:37.864Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*y0oSSCVJyUgc4DG0l8bvTA.png" /></figure><p>Has your Flutter project already reached the stage when Continuous Integration (CI) pipelines require optimization to save both time and money? Well, there are a bunch of approaches for optimization, one of which is <strong>selective CI checks</strong>.</p><p>Since you are looking for ways to optimize your CI, the odds are you have a sizeable project and may already use a Monorepo.</p><p><a href="https://medium.com/itnext/flutter-modularized-dependency-injection-4362649f84ed"><strong>In this article</strong></a>, I showed a clean small monorepo conveying the idea of dealing with Flutter app modularization. I’ll use the same repository here to share a way to implement selective CI checks.</p><h3>Full CI Checks Setup</h3><p>First, let’s implement some basic CI checks.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KL8RMbyNzretxfYal6IZXQ.png" /></figure><p>For the Counter App in my repository, which consists of 5 modules and uses <a href="https://melos.invertase.dev/">Melos</a> to manage the monorepo, I used the following CI checks in the basic Github Workflow.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3a0cf41ca06ca18920e809cb0786da40/href">https://medium.com/media/3a0cf41ca06ca18920e809cb0786da40/href</a></iframe><p>Each of the CI steps outlined in the above workflow executes for each of the five modules in the monorepo. This isn’t the most efficient use of resources as not every pull request involves changes to all the modules. Therefore, there’s space for improvement!</p><h3>Selective CI Checks Setup</h3><p>The concept behind selective CI checks is to only validate the segments of code that are relevant or impacted by a specific change, such as a pull request. Methods like git diff or path filters can be employed.</p><p>For Flutter Monorepos that use Melos, the Melos <a href="https://melos.invertase.dev/filters#--diff">Diff Filter</a> is a handy tool, especially when combined with <a href="https://melos.invertase.dev/filters#--include-dependents">IncludeDependends Filter</a>. Utilizing the command melos list --diff=origin/main..HEAD --include-dependends, we can obtain a list of packages that have changed compared to the main branch, as well as their dependents. Afterward, we can set the filter list into <a href="https://melos.invertase.dev/environment-variables#melos_packages">melos_packages</a> variable which will act as a global scope for all the melos commands. Here comes the corresponding workflow.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5a762275b68bf3c03205d8055b680c82/href">https://medium.com/media/5a762275b68bf3c03205d8055b680c82/href</a></iframe><h3>Selective CI Checks In Action</h3><p>For the sake of the example I opened <a href="https://github.com/Pavel-Sulimau/flutter_modularized_di/pull/3">a tiny PR</a> with a change in data module to show that the Selective CI checks will run only on it and on app module because it depends on data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZMrKaPeUoeERQGXDp-kS_w.png" /></figure><p>The following screenshot illustrates the significant difference in resource allocation, which is <strong>quite noticeable even for such a small repository</strong>. Just think of the substantial improvement potentially achievable on a production project with hundreds, or even thousands, of tests and other CI checks!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GPmSBPk-Y4CGZ3xEMHPFCQ.png" /></figure><h3>Conclusion</h3><p>Verifying everything with every code change is inefficient, particularly for large projects. The act of optimizing is a delicate balance of efficiency, cost, and performance. By implementing the right strategy, you can achieve significant improvements in your CI pipelines.</p><h3>Useful Links</h3><ul><li><a href="https://github.com/Pavel-Sulimau/flutter_modularized_di/pull/3">https://github.com/Pavel-Sulimau/flutter_modularized_di</a></li><li><a href="https://github.com/Pavel-Sulimau/flutter_modularized_di/blob/a65af8b2657fbdb5607f40bbc2225af0f8890dbd/.github/workflows/ci.yaml#L42C3-L42C15">https://github.com/Pavel-Sulimau/flutter_modularized_di/blob/a65af8b2657fbdb5607f40bbc2225af0f8890dbd/.github/workflows/ci.yaml#L42C3-L42C15</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2d79ffbd26e5" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-selective-ci-checks-2d79ffbd26e5">Flutter: Selective CI Checks</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter  vs Competitors: Popularity]]></title>
            <link>https://pasul.medium.com/flutter-vs-competitors-popularity-f79536688ec3?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/f79536688ec3</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[cross-platform-mobile]]></category>
            <category><![CDATA[xamarin]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Mon, 18 Mar 2024 11:02:14 GMT</pubDate>
            <atom:updated>2024-03-18T16:04:33.048Z</atom:updated>
            <content:encoded><![CDATA[<h3>Flutter vs Competitors: Popularity</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*RE2PnT4s9J6LNlOjWJIS3Q.png" /></figure><p>It’s been over 5 years since Flutter released its 1.0 version in December 2018. Today, Flutter officially supports 6 platforms:</p><ul><li>Mobile: iOS and Android</li><li>Desktop: Windows, MacOS, Linux</li><li>Web</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/922/1*UhBh9xEfT9SdeC6yK0mvWQ.png" /></figure><p>In this post, I’d like to compare the popularity of Flutter with other cross-platform mobile development technologies.</p><h3>Google Trends: Interest over time</h3><blockquote>Numbers represent search interest relative to the highest point on the chart for the given region and time. A value of 100 is the peak popularity for the term. A value of 50 means that the term is half as popular. A score of 0 means that there was not enough data for this term.</blockquote><p>I began by comparing the interest in <a href="https://flutter.dev/"><strong>Flutter</strong></a> with that of <a href="https://reactnative.dev/"><strong>React Native</strong></a>, <a href="https://dotnet.microsoft.com/en-us/apps/xamarin"><strong>Xamarin</strong></a>, <a href="https://dotnet.microsoft.com/en-us/apps/maui"><strong>.NET MAUI</strong></a><strong> (</strong>which is the successor of Xamarin), and <a href="https://ionicframework.com/"><strong>Ionic</strong></a> using Google Trends for the last 10 years.</p><p>This is the <a href="https://trends.google.com/trends/explore?cat=31&amp;date=2016-03-17%202024-03-17&amp;q=Flutter,React%20Native,Xamarin,MAUI,Ionic"><strong>query link</strong></a> for the chart you can see in the picture below. The tool allows us to compare only 5 terms, so I didn’t include <a href="https://cordova.apache.org/"><strong>Apache Cordova</strong></a>, which is even less popular than Ionic. Also, I didn’t include <a href="https://www.jetbrains.com/lp/compose-multiplatform/"><strong>Compose Multiplatform</strong></a> the data for which will not even reach the value of 1 in this popularity chart.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*evzm-QgB5ylePWCPeDwlrA.png" /></figure><h3>Stack Overflow Trends: Asked Questions</h3><p>Let’s also take a look at the number of questions asked on Stack Overflow with the help of <a href="https://stackoverflow.blog/2017/05/09/introducing-stack-overflow-trends/?_ga=2.228000541.1222420578.1710713708-274148527.1710713708">Stack Overflow Trends</a>. This is the <a href="https://insights.stackoverflow.com/trends?tags=flutter%2Creact-native%2Cxamarin%2Cmaui%2Cionic-framework%2Ccordova"><strong>query link</strong></a><strong> </strong>for the chart below.</p><blockquote>It tracks interest in programming languages and technologies based on the number of Stack Overflow questions asked per month.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w2zs1eAdQlorcTMd4-X5yw.png" /></figure><h3>Leaders: Flutter vs React Native</h3><p>The charts above paint a vivid picture, clearly demonstrating that Flutter and React Native have been significantly more popular in recent years compared to their competitors.<br>In the table below, you can find additional numbers found on GitHub and other relevant platforms as of today.<br>The latest stable versions are <strong>Flutter 3.19.3 </strong>and <strong>React Native 0.73.6</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6tPkCKU9Bwchm8LyJrHx0g.png" /></figure><h3>Sources</h3><ul><li><a href="https://trends.google.com/trends/explore?cat=31&amp;date=2016-03-17%202024-03-17&amp;q=Flutter,React%20Native,Xamarin,MAUI,Ionic">https://trends.google.com/trends/explore?cat=31&amp;date=2016-03-17%202024-03-17&amp;q=Flutter,React%20Native,Xamarin,MAUI,Ionic</a></li><li><a href="https://insights.stackoverflow.com/trends?tags=flutter%2Creact-native%2Cxamarin%2Cmaui%2Cionic-framework%2Ccordova">https://insights.stackoverflow.com/trends?tags=flutter%2Creact-native%2Cxamarin%2Cmaui%2Cionic-framework%2Ccordova</a></li><li><a href="https://flutter.dev/">https://flutter.dev/</a></li><li><a href="https://reactnative.dev/">https://reactnative.dev/</a></li><li><a href="https://github.com/flutter/flutter">https://github.com/flutter/flutter</a></li><li><a href="https://github.com/facebook/react-native">https://github.com/facebook/react-native</a></li><li><a href="https://dotnet.microsoft.com/en-us/apps/xamarin">https://dotnet.microsoft.com/en-us/apps/xamarin</a></li><li><a href="https://dotnet.microsoft.com/en-us/apps/maui">https://dotnet.microsoft.com/en-us/apps/maui</a></li><li><a href="https://ionicframework.com/">https://ionicframework.com/</a></li><li><a href="https://cordova.apache.org/">https://cordova.apache.org/</a></li><li><a href="https://www.jetbrains.com/lp/compose-multiplatform/">https://www.jetbrains.com/lp/compose-multiplatform/</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f79536688ec3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Modularized Dependency Injection]]></title>
            <link>https://itnext.io/flutter-modularized-dependency-injection-4362649f84ed?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/4362649f84ed</guid>
            <category><![CDATA[maintainability]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[app-modularization]]></category>
            <category><![CDATA[dependency-injection]]></category>
            <category><![CDATA[architecture]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Sat, 02 Mar 2024 17:50:40 GMT</pubDate>
            <atom:updated>2024-04-04T12:57:34.672Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*AN0lti4ZD5zRLUZ8UdSDvQ.png" /></figure><h3>Modularization? Why?</h3><p>Let’s say you’re already at the stage when the <strong>maintainability</strong> of your Flutter project is an important aspect for you, so you want to ensure you’re adhering to the best guidelines to achieve suitable architecture and code quality and keep it at the desired level.<br>So in that case <a href="https://en.wikipedia.org/wiki/Separation_of_concerns">separation of concerns</a>, <a href="https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)">encapsulation</a>, <a href="https://en.wikipedia.org/wiki/Coupling_(computer_programming)">coupling</a>, and <a href="https://en.wikipedia.org/wiki/Cohesion_(computer_science)">cohesion</a> are the things that you would like to govern in your chosen architecture.<br>It’s preferable to use physical separation over logical, i.e. divide your project into Dart/Flutter packages instead of merely grouping stuff into different directories. If you already have a not-tiny Flutter app with just logical separation, I bet you’ll likely fail to refactor it into physical packages that will mirror the directory structure you already have. This challenge often arises because it’s easy to breach or overlook architectural constraints when there is no physical separation.</p><h3>Dependency Injection in modules? How?</h3><p>It stands to reason that the exact architecture depends on your project, team, knowledge, etc. I’ve got no intention to discuss architectures in the scope of this article, but rather want to concentrate on how you can organize Dependency Injection (DI) in a modularized Flutter app.</p><h4>Refactoring The CounterApp</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7nPkZPeut6XzgENg69hDLA.png" /></figure><p>To convey the concept, let’s take the Counter Flutter App and modify it by introducing some basic packages. The diagram below depicts the packages I’ve selected and how they depend on each other.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ohAapSdvzt3VSfWN-aCseg.png" /></figure><h4>Cross-Cutting Concerns</h4><p>A <a href="https://en.wikipedia.org/wiki/Cross-cutting_concern">cross-cutting concerns</a> package typically contains things that affect the entire application and can be used by all the layers. I put DI abstractions into it.</p><p>The first one is called DI and this interface is responsible for obtaining objects from a DI container.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/88813dc6fa6fae9c703c395546b1c17d/href">https://medium.com/media/88813dc6fa6fae9c703c395546b1c17d/href</a></iframe><p>The second interface is called DIRegistrar, it provides the API to register dependencies in a DI Container. This interface must be exposed only to its actual implementation and to the ModuleDependencies abstraction and implementations.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d54b18b461a3f8ed7cd1724a072644f7/href">https://medium.com/media/d54b18b461a3f8ed7cd1724a072644f7/href</a></iframe><p>The third part of the puzzle is ModuleDependencies. It must be implemented by all the modules that have dependencies.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3caa1fceb2c05e7b2c7d2b441751116c/href">https://medium.com/media/3caa1fceb2c05e7b2c7d2b441751116c/href</a></iframe><h4>DI Abstractions Usage</h4><p>The modules are supposed to encapsulate the implementation details and expose only what is necessary.</p><p>For example, the fact that I added <a href="https://pub.dev/packages/flutter_bloc">flutter_bloc</a> state management in the presentation package is an implementation detail, so it can be easily replaced just inside this package without the need to modify the other packages at all.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/58b4c53dd55605ec44ae82c581959e77/href">https://medium.com/media/58b4c53dd55605ec44ae82c581959e77/href</a></iframe><p>In the data package I decided to use <a href="https://pub.dev/packages/shared_preferences">shared_preferences</a> to keep the state of the counter between the application launches. Again, this is “known” only to the data package itself.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9f2bef102644078fe6839b4782ce5256/href">https://medium.com/media/9f2bef102644078fe6839b4782ce5256/href</a></iframe><p>The app, of course, will have the transitive dependencies on shared_preferences and flutter_bloc in the end, as this is inevitable and intended for the root package that eventually bundles everything together in an artifact, e.g. ipa, apk.</p><p>At the initialization phase of the application, we simply go through all the configured modules and tell them to register their dependencies.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3353a5c7f0cf16ad76916d35bcc82e7e/href">https://medium.com/media/3353a5c7f0cf16ad76916d35bcc82e7e/href</a></iframe><p>You might’ve noticed the GetItDI class in the piece of code above. This is the implementation of DIRegistrar that I put in the app package. This implementation uses the <a href="https://pub.dev/packages/get_it">get_it</a> package. Again, should you want to switch to another DI Container, you’ll be able to do that as easily as just changing the implementation of DIRegistrar in the app layer without affecting all the other packages in any way.</p><p>Hopefully, the concept is clear to you by now, but you’re more than welcome to <a href="https://github.com/Pavel-Sulimau/flutter_modularized_di"><strong>explore the repository</strong></a> to inspect the remaining bits!</p><h3>Conclusion</h3><p>By dividing your project into physical modules, you immediately benefit from the compiler and static analysis working in your favor. This makes it significantly more difficult to overlook any architectural violations as they arise. The overhead of managing a <a href="https://en.wikipedia.org/wiki/Monorepo">Monorepo</a> is minor compared to the numerous benefits it offers. Additionally, it’s important to become familiar with the <a href="https://melos.invertase.dev/">Melos tool</a>, as it greatly simplifies Monorepo management in the Flutter and Dart ecosystem.</p><h3>Resources</h3><p><a href="https://github.com/Pavel-Sulimau/flutter_modularized_di">GitHub - Pavel-Sulimau/flutter_modularized_di: Modularized Flutter Counter App Honoring Clean Architecture Principles and Using Simple DI Abstractions to Preserve Encapsulation within Modules.</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4362649f84ed" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-modularized-dependency-injection-4362649f84ed">Flutter: Modularized Dependency Injection</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Sharing Dependencies in a Flutter Monorepo]]></title>
            <link>https://itnext.io/flutter-sharing-dependencies-in-a-flutter-monorepo-54f5e1cdb6a9?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/54f5e1cdb6a9</guid>
            <category><![CDATA[dependencies]]></category>
            <category><![CDATA[monorepo]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Mon, 12 Feb 2024 23:03:30 GMT</pubDate>
            <atom:updated>2024-02-12T23:03:30.459Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*MgkEq5mVzBaDCUJhvMqZKA.png" /></figure><p>I believe many Dart &amp; Flutter monorepo projects are already using Melos. It’s a useful tool for managing multiple packages, and I’m glad to see it continually improving.</p><h4>Shared Dependencies Feature</h4><p>In this article, I am eager to shine a spotlight on the <a href="https://melos.invertase.dev/commands/bootstrap#shared-dependencies">Shared Dependencies</a> feature that was introduced in <a href="https://pub.dev/packages/melos/changelog#320">Melos 3.2.0</a>.</p><p>Essentially, if you want to share a dependency version between the packages in your monorepo, just add the dependency to the melos.yaml file, and melos bootstrap command will make sure your pubscpec.yamlfiles are updated accordingly to match the version defined in the melos.yaml file. It works not only for dependencies or dev_dependencies but for environment configuration as well.</p><p>More context about it can be gained from <a href="https://github.com/invertase/melos/issues/94">its feature reques</a>t and the <a href="https://github.com/invertase/melos/pull/526">PR where it was implemented</a>.</p><h4>Shared Dependencies In Practice</h4><p>Let’s see how it works in practice using the <a href="https://github.com/flame-engine/flame">Flame</a> project as an example. <br>At the moment of writing a bunch of packages from the Flame monorepo <a href="https://github.com/flame-engine/flame/blob/78380b9d3bb895e20f382c4a1227bcc11e5038b9/melos.yaml#L20C7-L20C19">depend on meta v1.9.1</a>, you can see the copied bootstrap configuration below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/67f152135183919aa9df63b0c69aa12d/href">https://medium.com/media/67f152135183919aa9df63b0c69aa12d/href</a></iframe><p>After I update the meta version to meta: ^1.10.0 in the melos.yaml and run the melos bs command, I get 49 packages bootstrapped, 9 of them that depend on meta got the very same update right away! That’s quite handy and may ease the dependencies management in Dart/Flutter monorepos.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-E3fj7Hqt0JcsYzHmkWPXg.png" /></figure><h4>Conclusion</h4><p>While it’s true that package management in the Dart/Flutter ecosystem is less mature compared to other platforms like .NET, we are fortunate to have tools like Melos at our disposal that can simplify the process. By actively contributing to such tools, we can play a role in improving the developer experience and fostering greater satisfaction within the community.</p><h4>Resources</h4><ul><li><a href="https://melos.invertase.dev/commands/bootstrap#shared-dependencies">https://melos.invertase.dev/commands/bootstrap#shared-dependencies</a></li><li><a href="https://pub.dev/packages/melos/changelog#320">https://pub.dev/packages/melos/changelog#320</a></li><li><a href="https://github.com/invertase/melos/issues/94">https://github.com/invertase/melos/issues/94</a></li><li><a href="https://github.com/invertase/melos/pull/526">https://github.com/invertase/melos/pull/526</a></li><li><a href="https://github.com/flame-engine/flame/blob/78380b9d3bb895e20f382c4a1227bcc11e5038b9/melos.yaml#L16C1-L25C16">https://github.com/flame-engine/flame/blob/78380b9d3bb895e20f382c4a1227bcc11e5038b9/melos.yaml#L16C1-L25C16</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=54f5e1cdb6a9" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-sharing-dependencies-in-a-flutter-monorepo-54f5e1cdb6a9">Flutter: Sharing Dependencies in a Flutter Monorepo</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Code Coverage tools in VS Code]]></title>
            <link>https://itnext.io/flutter-code-coverage-tools-in-vs-code-25c89c2304a1?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/25c89c2304a1</guid>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[vscode]]></category>
            <category><![CDATA[unit-testing]]></category>
            <category><![CDATA[code-coverage-tools]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Mon, 05 Feb 2024 15:36:35 GMT</pubDate>
            <atom:updated>2024-02-28T11:47:45.194Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*nzlnkHEGf1ZaZZcqjgGQcQ.png" /></figure><p>When you work on a Flutter/Dart project where code coverage is measured or even enforced, then you will likely want to have a setup that will help you see the picture locally.</p><p>One way is to run tests collecting the coverage with a terminal command or some script, i.e. flutter test --coverage, see <a href="https://docs.flutter.dev/reference/flutter-cli">more info on Flutter CLI here</a>.</p><p>However, if you primarily use <a href="https://code.visualstudio.com/">VS Code</a>, then you can utilize a more convenient <a href="https://dartcode.org/docs/launch-configuration/">launch configuration</a> to be able to run your tests and generate the coverage right from the tests themselves. More specifically, we would need to use a <a href="https://dartcode.org/docs/custom-codelens/">custom codelens configuration</a>.</p><h3>‘Coverage’ codelens launch configuration in VS Code</h3><p>As soon as the following configuration is added to the launch.json file, a new button will be made available to allow us to run the tests.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/37da4968143bbed0ad018d81bd7fbdf9/href">https://medium.com/media/37da4968143bbed0ad018d81bd7fbdf9/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6gfBNmIW-ntY8zsNEZ_log.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*e1KQkDEgQVkdBpFUuqcefQ.png" /></figure><p>After executing the ‘Coverage’ command on a test(s), you will notice the lcov.info file appearing in the coverage directory.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1r_0OdrEFpuNVqfZzoSHRw.png" /></figure><p>Be aware of <a href="https://github.com/dart-lang/test/issues/1265#issuecomment-644995230">this issue</a> if you’re trying to make it work on a plain Dart (non-Flutter) package.</p><h3>VS Code Extensions for Code Coverage</h3><p>While various tools exist that can generate HTML reports based on coverage files, analyzing coverage directly in VS Code can be accomplished using the following two extensions:</p><ol><li><a href="https://marketplace.visualstudio.com/items?itemName=Flutterando.flutter-coverage"><strong>Flutter Coverage</strong></a><br>This extension adds a tree view to the test view container. It shows the coverage per file/folder.</li><li><a href="https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters"><strong>Coverage Gutters</strong></a><br>Displays which lines of a file are covered and which are not.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v2x4_OkyYVGuWzx8Z8koAA.png" /><figcaption>Flutter Coverage in Action</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TOPJ8X_8oKA2HeGSNy0_jg.png" /><figcaption>Coverage Gutters in Action</figcaption></figure><h3>Conclusion</h3><p>For VS Code users, custom codelens configurations and specific extensions can provide coverage analysis directly within the editor, simplifying the process significantly.</p><h3>Resources</h3><ul><li><a href="https://dartcode.org/docs/launch-configuration/">https://dartcode.org/docs/launch-configuration/</a></li><li><a href="https://dartcode.org/docs/custom-codelens/">https://dartcode.org/docs/custom-codelens/</a></li><li><a href="https://marketplace.visualstudio.com/items?itemName=Flutterando.flutter-coverage">https://marketplace.visualstudio.com/items?itemName=Flutterando.flutter-coverage</a></li><li><a href="https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters">https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters</a></li><li><a href="https://github.com/dart-lang/test/issues/1265#issuecomment-644995230">https://github.com/dart-lang/test/issues/1265#issuecomment-644995230</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=25c89c2304a1" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/flutter-code-coverage-tools-in-vs-code-25c89c2304a1">Flutter: Code Coverage tools in VS Code</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OpenAPI Excellence: Maximising Quality with Automation Tools]]></title>
            <link>https://itnext.io/openapi-excellence-maximising-quality-with-automation-tools-2203a02b0456?source=rss-dea2d0cc5369------2</link>
            <guid isPermaLink="false">https://medium.com/p/2203a02b0456</guid>
            <category><![CDATA[open-api]]></category>
            <category><![CDATA[api-testing]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[swagger]]></category>
            <category><![CDATA[quality]]></category>
            <dc:creator><![CDATA[Pavel Sulimau]]></dc:creator>
            <pubDate>Tue, 23 Jan 2024 15:50:05 GMT</pubDate>
            <atom:updated>2024-02-02T17:25:52.327Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*QM73htyeP5SSk7hZMtYoQA.png" /></figure><h3>What is OpenAPI?</h3><blockquote><strong>The OpenAPI Specification (OAS)</strong> provides a formal standard for describing HTTP APIs.</blockquote><p>It is a specification language for HTTP APIs that defines structure and syntax, typically written in YAML or JSON.</p><p>It was originally based on the Swagger 2.0 Specification, donated by SmartBear Software in 2015. Currently, the OAS is maintained, evolved and promoted by the OpenAPI Initiative (<strong>OAI</strong>), a consortium of industry experts with an open governance structure under the Linux Foundation umbrella.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*heghjBmTh00raCQ3rguSOw.png" /><figcaption><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#appendix-a-revision-history">OpenAPI Specification Revision History</a></figcaption></figure><p>OpenAPI Specification enables you to describe your APIs in language-agnostic terms, effectively separating them from dependencies on any particular programming language. This approach not only facilitates a clearer understanding of how an API functions but also streamlines processes such as generating client code, crafting tests, enforcing design standards, and much more.</p><blockquote>This description, which may be stored as one or more documents (such as local files or HTTP-accessible network resources), is called an <strong>OpenAPI Description</strong> (<strong>OAD</strong>).</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T1zh7cyb_hVKdkUkBjxdLQ.png" /><figcaption><a href="https://learn.openapis.org/specification/structure.html">Structure of an OpenAPI Description</a></figcaption></figure><p>Below, you can see an example of OpenAPI Description. This sample illustrates how OAD conveys essential details about an API, including its endpoints, supported operations, and data structures, in a structured and easily understandable format.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3831d029d69683989f5207c1afb797aa/href">https://medium.com/media/3831d029d69683989f5207c1afb797aa/href</a></iframe><h3>What are the Swagger Tools?</h3><p><a href="https://swagger.io/tools/swagger-editor/"><strong>Swagger Editor</strong></a><strong><br></strong>This is an intuitive API editor that assists in designing and documenting APIs using the OpenAPI Specification. It offers real-time feedback and syntax checking to streamline the API design process.</p><p><a href="https://swagger.io/tools/swagger-ui/"><strong>Swagger UI</strong></a><br>This tool visualizes OpenAPI Specification definitions in an interactive interface. It allows users to explore and interact with the API’s endpoints, providing a clear and user-friendly presentation of the API’s capabilities.</p><p><a href="https://swagger.io/tools/swagger-codegen/"><strong>Swagger Codegen</strong></a><br>It generates server stubs and client SDKs directly from OpenAPI Specification definitions. This automation significantly reduces the manual coding effort, ensuring a seamless and efficient API implementation.</p><h3>Swagger Codegen in Dart/Flutter</h3><p>I can’t stress enough the advantages you get by using the Swagger Codegen packages. Those tools have saved huge amounts of resources and quite some headaches on many projects for me. There are plenty of them for various libraries and programming languages.</p><p>In the Flutter/Dart world I’ve been using the <a href="https://pub.dev/packages/swagger_dart_code_generator">swagger_dart_code_generator package</a> since 2020 on projects of various sizes and it has proved itself as quite a reliable one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6kvfcKRwXldUJbKqLnD78Q.png" /></figure><h3>Enforcing Consistency and Standards in OAD files</h3><p>Luckily, code formatters, code linters, static code analyzers, various types of tests, and code reviews became industry standards in <a href="https://martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> software development practice.</p><p>That’s awesome that there are open-source tools available that can bring more consistency and better standards to the OpenAPI definitions a back-end API provides.</p><p>If your back-end teams do not use any tools in their CI to check the quality of the OAD files, it’s a good idea to start doing so. Give a read to <a href="https://learn.openapis.org/best-practices.html">the best practices on learn.openapis.org</a>.</p><h4><strong>Keep a Single Source of Truth</strong></h4><p>OADs should be committed to source control, and, in fact, they should be among the first files to be committed. Information should <strong>not</strong> be duplicated in different places, so keeping a single source of truth is always a nice idea.</p><h4><strong>Enforce formatting</strong></h4><p>The same formatting style enforced for all team members is never a bad idea, especially with huge JSON/YAML files that OAD can become. Tools like <a href="https://editorconfig.org/"><strong>EditorConfig</strong></a> are great for keeping coding styles consistent across different editors and IDEs. Additionally, a tool like <a href="https://www.npmjs.com/package/prettier"><strong>Prettier</strong></a> can be integrated into your CI pipeline to automatically ensure that everyone sticks to the agreed-upon formatting rules.</p><h4><strong>Keep the quality bar with an OAD Linter</strong></h4><p><a href="https://stoplight.io/open-source/spectral"><strong>Spectral</strong></a> is a powerful open-source tool that’s helpful for working with JSON or YAML data, specially designed for OpenAPI, AsyncAPI, and JSON Schema.</p><p>Spectral comes with several features right out of the box:</p><ul><li>Custom Rulesets: You can create your own rules to lint JSON or YAML objects, tailoring checks to your specific needs.</li><li>Ready-to-use Rulesets: Spectral has built-in rulesets for validating and linting OpenAPI v2 &amp; v3.x and AsyncAPI Documents.</li><li>API Style Guides: Automated <a href="https://stoplight.io/api-style-guides-guidelines-and-best-practices?utm_source=github.com&amp;utm_medium=referral&amp;utm_campaign=github_repo_spectral">API Style Guides</a> using rulesets improve consistency across all your APIs.</li><li>Built-in Functions: A variety of pre-made functions are available for <a href="https://meta.stoplight.io/docs/spectral/e5b9616d6d50c-custom-rulesets#adding-rules">creating custom rules</a>. These include checks for patterns, parameters, alphabetical ordering, character limits, and verifying the presence of specific keys in an object.</li><li>Custom Functions: Create custom functions for advanced use cases.</li></ul><p>For the example’s sake, I used a <a href="https://api.apis.guru/v2/specs/visualcrossing.com/weather/4.6/openapi.yaml">Weather OAD</a> I found at <a href="https://apis.guru/">APIs Guru</a>. Here is the OAD 3.0.1 file in yaml format.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae808009aebf7b4406783990f9b4b7ef/href">https://medium.com/media/ae808009aebf7b4406783990f9b4b7ef/href</a></iframe><p>Below you can see just a few rules added to the Spectral config file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/65cf02bffaa9ff9ac8ab718b26659280/href">https://medium.com/media/65cf02bffaa9ff9ac8ab718b26659280/href</a></iframe><p>When Spectral linter scans the poorly described OAD from VisualCrossing it immediately gives quite useful feedback, see the screenshots below. It’s worth noting that the effectiveness of Spectral increases with the number of rules configured. More rules mean more comprehensive checks, leading to higher quality and more reliable API descriptions in the long run.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fZIBP7qw91FO8zORGM6uXw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WWnM4S46uGEEtYRwSjWSvA.png" /></figure><h4>Validating Back-End Responses against OAD/JSON Schema</h4><p><a href="https://json-schema.org/"><strong>JSON Schema</strong></a> is a specification for defining the structure of JSON data i.e. JSON request body and response in case of APIs. Basically, JSON schema defines various keys and their values and certain constraints on the values.</p><p>OpenAPI Specification 3.1 (released in February 2021) <a href="https://www.openapis.org/blog/2021/02/18/openapi-specification-3-1-released">supports 100% compatibility with the latest draft (2020–12) of JSON Schema</a>.</p><p>This means that JSON Schema validation tools like <a href="https://ajv.js.org/"><strong>Ajv</strong></a><strong> </strong>can be used to ensure that the actual responses from your back-end endpoints are compliant with what is defined in OpenAPI Description of the backend. Ajv can be used in the scope of integration tests or <a href="https://www.sergigisbert.com/blog/validating-api-requests-and-json-schemas-with-postman/">in PostMan tests</a>.</p><h3>Conclusion</h3><p>The abundance of valuable open-source tools available for enhancing and maintaining the quality of back-end endpoints and their contracts is a significant asset. Given their benefits, it’s hard to justify not using these tools in any serious project. Avoiding them out of laziness or reluctance to invest time in the initial setup shouldn’t be an excuse.</p><p>Feel free to <a href="https://github.com/Pavel-Sulimau/open_api_playground"><strong>check out the demo repository</strong></a> with the stuff mentioned above and bring value to your projects.</p><h3>Resources</h3><ul><li><a href="https://www.openapis.org">https://www.openapis.org</a></li><li><a href="https://swagger.io">https://swagger.io</a></li><li><a href="https://pub.dev/packages/swagger_dart_code_generator">https://pub.dev/packages/swagger_dart_code_generator</a></li><li><a href="https://github.com/Pavel-Sulimau/open_api_playground">https://github.com/Pavel-Sulimau/open_api_playground</a></li><li><a href="https://json-schema.org/">https://json-schema.org</a></li><li><a href="https://ajv.js.org/">https://ajv.js.org</a></li><li><a href="https://www.sergigisbert.com/blog/validating-api-requests-and-json-schemas-with-postman/">https://www.sergigisbert.com/blog/validating-api-requests-and-json-schemas-with-postman</a></li><li><a href="https://learning.postman.com/docs/api-governance/configurable-rules/spectral/">https://learning.postman.com/docs/api-governance/configurable-rules/spectral</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2203a02b0456" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/openapi-excellence-maximising-quality-with-automation-tools-2203a02b0456">OpenAPI Excellence: Maximising Quality with Automation Tools</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>