<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dom Jocubeit</title>
    <description>The latest articles on DEV Community by Dom Jocubeit (@djocubeit).</description>
    <link>https://dev.to/djocubeit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F895903%2F32c22aaf-fd3b-45d4-b5d2-5fb6d755ef5e.png</url>
      <title>DEV Community: Dom Jocubeit</title>
      <link>https://dev.to/djocubeit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/djocubeit"/>
    <language>en</language>
    <item>
      <title>Software Bill of Materials (SBOM) and Flutter Apps</title>
      <dc:creator>Dom Jocubeit</dc:creator>
      <pubDate>Sun, 30 Jul 2023 05:09:40 +0000</pubDate>
      <link>https://dev.to/djocubeit/software-bill-of-materials-sbom-and-flutter-apps-3666</link>
      <guid>https://dev.to/djocubeit/software-bill-of-materials-sbom-and-flutter-apps-3666</guid>
      <description>&lt;p&gt;In my last article, &lt;a href="https://dom.jocubeit.com/flutter-takes-a-leap-towards-enhanced-security-with-slsa-compliance"&gt;Flutter Takes a Leap Towards Enhanced Security with SLSA Compliance&lt;/a&gt;, we touched on the Software Bill of Materials (&lt;a href="https://www.cisa.gov/sbom"&gt;SBOM&lt;/a&gt;) and how Google has achieved Supply Chain Levels for Software Artifacts (&lt;a href="https://slsa.dev/"&gt;&lt;strong&gt;SLSA&lt;/strong&gt;&lt;/a&gt;) Level 1 for Flutter.&lt;/p&gt;

&lt;p&gt;With the ability to build performant native-compiled applications for desktops on Windows, Mac, and Linux leveraging a single codebase and access to native functionality with full access to the underlying Win32, Cocoa, or UNIX platform APIs; we will see enterprise desktop applications being built in Flutter and Dart.&lt;/p&gt;

&lt;p&gt;In this article, I want to delve deeper into the SBOM and its relevance to Flutter apps and Dart packages, particularly to this market segment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Evolution of SBOM
&lt;/h2&gt;

&lt;p&gt;The concept of SBOM can be traced back to the late 1990s when the Open Source Software (OSS) movement gained momentum. As software ecosystems expanded, so did the usage of third-party dependencies, which brought challenges of security vulnerabilities and license compliance.&lt;/p&gt;

&lt;p&gt;To address these concerns, the National Telecommunications and Information Administration (NTIA) introduced SBOM in 2019. The idea was to create a standardised way to document a software project's components and their origins, allowing for improved security, risk management, and supply chain visibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Significance of SBOM
&lt;/h2&gt;

&lt;p&gt;In the enterprise environment, desktop applications are critical tools that facilitate business processes, streamline operations, and improve productivity. However, as these applications become more complex and interconnected, managing security, license compliance, and supply chain transparency become increasingly challenging.&lt;/p&gt;

&lt;p&gt;This is where the Software Bill of Materials (SBOM) emerges as a powerful and indispensable asset for enterprise desktop applications, especially when developed using technologies like Flutter and Dart packages. Let's explore how SBOM empowers enterprise developers and stakeholders:&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhanced Security
&lt;/h3&gt;

&lt;p&gt;Security breaches and cyber-attacks pose significant risks to enterprise data and operations. The use of third-party dependencies in desktop applications increases the attack surface, potentially exposing vulnerabilities that malicious actors can exploit. By adopting SBOM, enterprises gain greater visibility into the software components used in their applications, allowing them to perform comprehensive security assessments.&lt;/p&gt;

&lt;p&gt;With SBOM, developers can identify known vulnerabilities in the third-party packages they utilise. Armed with this knowledge, they can quickly prioritise and apply security patches, reducing the window of exposure and strengthening the application's overall security posture. Enterprises can also leverage SBOM to assess the security profiles of potential software vendors, ensuring that their desktop applications come from trusted sources.&lt;/p&gt;

&lt;h3&gt;
  
  
  License Compliance
&lt;/h3&gt;

&lt;p&gt;Compliance with open-source licenses is a vital aspect of enterprise software development. Non-compliance can lead to legal challenges, financial penalties, and damage to an organisation's reputation. SBOM enables developers to maintain a precise record of the licenses associated with each software component in their desktop applications.&lt;/p&gt;

&lt;p&gt;With this comprehensive license inventory, enterprises can easily identify license conflicts or potential violations and take the necessary steps to remedy the situation. SBOM empowers organisations to make informed decisions about the open-source packages they include in their applications, ensuring that the licenses align with their business goals and legal requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supply Chain Transparency
&lt;/h3&gt;

&lt;p&gt;For enterprise desktop applications, understanding the supply chain of software components is crucial. The use of third-party dependencies introduces a chain of interconnected packages, and vulnerabilities in one component can cascade to affect the entire application. SBOM provides transparency into this intricate web of dependencies.&lt;/p&gt;

&lt;p&gt;With SBOM, enterprises can trace the origins of each component used in their desktop applications, verifying the authenticity and integrity of the software supply chain. This information empowers stakeholders to make informed decisions about the risk associated with specific dependencies, leading to better-informed development practices and mitigating potential security and compliance issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Streamlined Vendor Management
&lt;/h3&gt;

&lt;p&gt;Enterprise desktop applications often involve collaboration with external vendors or development teams. The adoption of SBOM in the development process streamlines vendor management by providing a clear view of the software components introduced by each party.&lt;/p&gt;

&lt;p&gt;By exchanging SBOM data with vendors, enterprises can assess the security and compliance risks associated with third-party contributions effectively. This proactive approach fosters better collaboration and facilitates smoother integration of vendor code into the final desktop application, leading to a more robust and secure end product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where SBOM may be Mandatory?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.federaltimes.com/it-networks/2022/10/24/sbom-disclosure-rules-loom-for-federal-software-procurement/"&gt;SBOM has become increasingly mandatory in various sectors&lt;/a&gt;, especially in government, military, and industries where security, compliance, and transparency are of utmost importance. he White House Office of Management and Budget last month &lt;a href="https://www.whitehouse.gov/wp-content/uploads/2022/09/M-22-18.pdf"&gt;gave federal agencies a year&lt;/a&gt; to collect software attestations and artefacts like SBOMs from government software vendors verifying adherence to secure development practices. Let's take a look at some examples of where SBOM is or will become mandatory:&lt;/p&gt;

&lt;h3&gt;
  
  
  Government Agencies and Contractors
&lt;/h3&gt;

&lt;p&gt;Government agencies at the local, state, and federal levels often deal with sensitive data and critical systems. To ensure the security and integrity of their software infrastructure, these agencies may mandate the use of SBOM. SBOM enables government bodies to assess the risk associated with the software components they use, facilitating better decision-making and ensuring compliance with security standards and regulations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defence and Military Organisations
&lt;/h3&gt;

&lt;p&gt;In the defence and military sectors, security is paramount. Any vulnerability or compromise in the software systems used for defence applications could have severe consequences. SBOM becomes mandatory in these industries to maintain a clear inventory of software components and their security profiles. It allows defence organisations to assess the supply chain of their software, detect potential threats, and respond proactively to security incidents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Healthcare and Medical Devices
&lt;/h3&gt;

&lt;p&gt;In the healthcare industry, the safety and privacy of patient data are critical concerns. For medical devices and healthcare software, regulatory bodies such as the U.S. Food and Drug Administration (FDA) require manufacturers to provide an SBOM. This allows regulators and stakeholders to assess the security and compliance aspects of medical devices, ensuring patient safety and protecting sensitive medical information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Financial Services
&lt;/h3&gt;

&lt;p&gt;Financial institutions handle vast amounts of sensitive customer data and transactions. To maintain regulatory compliance and secure their systems against potential cyber threats, financial organisations may enforce SBOM practices. SBOM helps financial institutions evaluate the security posture of their applications, including third-party components, ensuring a robust and resilient software environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Critical Infrastructure and Utilities
&lt;/h3&gt;

&lt;p&gt;Industries operating critical infrastructure, such as energy, transportation, and utilities, are prime targets for cyber-attacks. SBOM plays a vital role in these sectors to identify and address security vulnerabilities in software systems that control critical operations. By implementing SBOM, these industries can enhance their cybersecurity strategies and safeguard against potential disruptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aerospace and Aviation
&lt;/h3&gt;

&lt;p&gt;The aerospace and aviation industries rely heavily on complex software systems to operate aircraft and manage air traffic. To ensure the safety of passengers and air transportation, SBOM may be required to identify potential risks in the software used for flight controls, navigation, and communication systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  SBOM for Flutter and Dart
&lt;/h2&gt;

&lt;p&gt;Flutter, Google's UI toolkit, has rapidly gained popularity in the development of cross-platform applications. As Flutter apps often rely on numerous third-party packages, managing their security and licensing aspects can be challenging. Integrating SBOM into Flutter projects empowers developers to mitigate risks effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  SPDX Format and its Relevance
&lt;/h3&gt;

&lt;p&gt;SPDX (Software Package Data Exchange) is an industry-standard format for describing and sharing SBOM information. It provides a standardised way to document software components, licenses, and copyright information. The use of the SPDX format ensures consistency and interoperability between different tools and platforms, streamlining SBOM sharing and analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utilising the SBOM Package for Flutter and Dart
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://pub.dev/packages/sbom"&gt;sbom&lt;/a&gt; package available on pub.dev is a valuable resource for Flutter developers seeking to generate SBOM SPDX files seamlessly. The SBOM is generated from the Dart files contained in the package plus and the &lt;code&gt;pubspec.yaml&lt;/code&gt;. Generation is controlled by a configuration file named &lt;code&gt;sbom.yaml&lt;/code&gt; which must be present in the top-level directory of the package. The configuration file allows the setting of the SBOM format, generation directives and field overrides. Overrides can be found in the example directory when viewing the source code on &lt;a href="https://github.com/shamblett/sbom"&gt;GitHub&lt;/a&gt;. Generation is effectively a merge of any field overrides in this file and data generated from the package environment and its &lt;code&gt;pubspec&lt;/code&gt; file. Currently, only the Software Package Data Exchange (SPDX) format is supported at specification version 2.2, but support for other SBOM format types such as CycloneDX and SWID will be added in future releases.&lt;/p&gt;

&lt;p&gt;Adding the &lt;code&gt;sbom.yaml&lt;/code&gt; is as easy as including the following in your package root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;spdx&lt;/span&gt;

&lt;span class="na"&gt;spdx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;SPDXFormat&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tagvalue'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the &lt;code&gt;sbom&lt;/code&gt; executable to the global path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% dart pub global activate sbom

Resolving dependencies... &lt;span class="o"&gt;(&lt;/span&gt;1.1s&lt;span class="o"&gt;)&lt;/span&gt;
+ args 2.4.2
+ collection 1.18.0
+ crypto 3.0.3
+ meta 1.9.1
+ path 1.8.3
+ pub_cache 0.3.2
+ pub_semver 2.1.4
+ sbom 2.0.0
+ source_span 1.10.0
+ string_scanner 1.2.0
+ term_glyph 1.2.1
+ typed_data 1.3.2
+ yaml 3.1.2
Building package executables...
Built sbom:sbom.
Installed executable sbom.
Activated sbom 2.0.0.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now execute the &lt;code&gt;sbom&lt;/code&gt; command in the package root directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% sbom

SBOM generator &lt;span class="k"&gt;for &lt;/span&gt;Dart packages
Parsing SBOM configuration file
Generating the SBOM
SBOM &lt;span class="nb"&gt;type &lt;/span&gt;is SPDX
SBOM generation &lt;span class="nb"&gt;complete&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generator will create a new file called &lt;code&gt;sbom.spdx&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Transparency
&lt;/h3&gt;

&lt;p&gt;The Dart &lt;code&gt;sbom&lt;/code&gt; generator only generates the SPDX for your package. It doesn't recursively generate SBOMs for every dependency and their dependencies, etc. To provide a fully transparent bill of materials for an application, the SBOM package could be improved to perform this for every dependency, currently, this would have to be done manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Have We Learned?
&lt;/h2&gt;

&lt;p&gt;In sectors where security, compliance, and transparency are paramount, the use of SBOM has become mandatory. Government agencies, military organisations, healthcare providers, financial institutions, critical infrastructure operators, and aerospace and aviation industries all benefit from SBOM's ability to enhance software security, ensure license compliance, and provide supply chain transparency. As software development continues to evolve, SBOM will continue to be an essential tool in safeguarding critical systems and protecting against cybersecurity threats across various sectors.&lt;/p&gt;

&lt;p&gt;For enterprise desktop applications developed using Flutter and Dart packages, SBOM becomes a game-changing asset, empowering organisations to create secure, compliant, and transparent software systems. The enhanced security, license compliance, and supply chain transparency that SBOM offers are instrumental in safeguarding sensitive data, mitigating risks and maintaining customers' trust.&lt;/p&gt;

&lt;p&gt;By embracing SBOM as a best practice, enterprises can effectively manage the complexities of modern software development, strengthen their software supply chains, and build resilient desktop applications that stand up to the rigorous demands of the business landscape. In the ever-evolving world of technology and cybersecurity, SBOM stands as a reliable tool to empower enterprises with the knowledge and insight needed to stay ahead of potential threats and challenges and increase an organisation's security posture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other Information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This articles was originally posted on my personal blog at &lt;a href="https://dom.jocubeit.com/software-bill-of-materials-sbom-and-flutter-apps"&gt;https://dom.jocubeit.com/software-bill-of-materials-sbom-and-flutter-apps&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>sbom</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Flutter Takes a Leap Towards Enhanced Security with SLSA Compliance</title>
      <dc:creator>Dom Jocubeit</dc:creator>
      <pubDate>Sun, 23 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/djocubeit/flutter-takes-a-leap-towards-enhanced-security-with-slsa-compliance-2c22</link>
      <guid>https://dev.to/djocubeit/flutter-takes-a-leap-towards-enhanced-security-with-slsa-compliance-2c22</guid>
      <description>&lt;h2&gt;
  
  
  Flutter 3.10 ships with SLSA Level 1 compliance
&lt;/h2&gt;

&lt;p&gt;In the fast-paced digital world, ensuring the security and integrity of software is of paramount importance. With the increasing frequency and sophistication of cyber-attacks, developers and organisations are continually seeking ways to bolster their security practices. In this pursuit, the Software Bill of Materials (&lt;a href="https://www.cisa.gov/sbom"&gt;SBOM&lt;/a&gt;) has emerged as a crucial framework for promoting transparency and accountability in the software supply chain. Recently, Flutter, Google's popular open-source UI software development toolkit, announced its new compliance with the Supply chain Levels for Software Artifacts (&lt;a href="https://slsa.dev/"&gt;SLSA&lt;/a&gt;), marking a significant milestone in enhancing the security posture of Flutter apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SLSA?
&lt;/h2&gt;

&lt;p&gt;SLSA, which stands for Supply chain Levels for Software Artifacts, is a framework developed by Google to establish a set of security requirements and best practices for software supply chains. It is designed to create a transparent and robust software supply chain ecosystem, safeguarding software components from potential security threats. SLSA has multiple levels, each representing an increasing level of security rigour.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLSA Level 1&lt;/strong&gt;: The first level focuses on establishing a strong foundation for security. It requires the use of a formalised Bill of Materials, ensuring that all components in the supply chain are listed. Additionally, it enforces that the software is built with well-defined and reproducible build processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLSA Level 2&lt;/strong&gt;: Level 2 builds upon the foundations laid in Level 1 and introduces stricter security measures. At this level, software suppliers are required to cryptographically sign the provenance of each software artifact in the supply chain. This cryptographic signing enables consumers to verify the authenticity and integrity of the artifacts they receive, reducing the risk of tampering or unauthorised modifications during distribution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SLSA Level 3&lt;/strong&gt;: Level 3 further enhances security by enforcing the principle of "defence-in-depth." It requires the adoption of hardware-based security measures, such as hardware-backed cryptographic signing and verification. Hardware security mechanisms provide an additional layer of protection against attacks, making it significantly more challenging for adversaries to compromise the software supply chain.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flutter's Journey to SLSA Compliance
&lt;/h2&gt;

&lt;p&gt;Flutter has emerged as one of the leading frameworks for building high-quality, cross-platform applications. With its ever-growing popularity, the Flutter team recognised the need to fortify its security practices to inspire even greater confidence among developers and end-users.&lt;/p&gt;

&lt;p&gt;The journey to achieve SLSA compliance was a collaborative effort involving the Flutter development team, the broader open-source community, and security experts. The process commenced with a comprehensive audit of Flutter's supply chain, identifying potential areas of improvement and addressing any vulnerabilities.&lt;/p&gt;

&lt;p&gt;One of the core components of SLSA is the implementation of a Software Bill of Materials (SBOM). Flutter tackled this requirement by creating a structured and standardised SBOM that lists all the software components and dependencies used in the framework. This SBOM acts as a critical reference point for developers and users to understand the software's composition and any potential security implications.&lt;/p&gt;

&lt;p&gt;To achieve higher levels of SLSA compliance, Flutter had to introduce additional security measures. This involved implementing cryptographic signing of software artifacts at Level 2 and adopting hardware-based security mechanisms at Level 3. These measures significantly reduce the risk of supply chain attacks and ensure that software consumers can trust the authenticity and integrity of the artifacts they receive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Flutter's SLSA Compliance
&lt;/h2&gt;

&lt;p&gt;Flutter's compliance with SLSA brings forth numerous benefits for developers, organisations, and end-users alike:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Security&lt;/strong&gt;: SLSA compliance ensures that Flutter apps are built with robust security practices, safeguarding users from potential threats and vulnerabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trust and Transparency&lt;/strong&gt;: By adhering to SLSA's principles, Flutter provides transparency into its supply chain, building trust among developers and users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Risk of Supply Chain Attacks&lt;/strong&gt;: The cryptographic signing of artifacts and hardware-based security mechanisms make it exceedingly difficult for malicious actors to tamper with Flutter's software components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Industry Leadership&lt;/strong&gt;: Flutter's commitment to SLSA compliance sets an example for other software projects, encouraging the industry to prioritise security in software development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Future-Proofing&lt;/strong&gt;: As software security threats evolve, SLSA compliance ensures that Flutter remains resilient against emerging challenges.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Flutter's compliance with SLSA is a significant achievement that demonstrates its dedication to improving the security of its software supply chain. By embracing the SLSA framework, Flutter takes a proactive approach to fortifying its software against potential attacks, ensuring that its vast community of developers can build and deploy applications with greater confidence. As the digital landscape continues to evolve, initiatives like SLSA become increasingly vital to creating a secure and trustworthy software ecosystem.&lt;/p&gt;

&lt;p&gt;Flutter's commitment to security sets a strong example for other software projects, encouraging the broader tech industry to prioritise security at every step of the development process. With SLSA compliance now in place, Flutter is undoubtedly positioned to deliver even more secure and reliable experiences for its users; especially considering they indicated they wanted to pursue Level 2 back in March 2023 in their &lt;a href="https://opensource.googleblog.com/2023/03/flutter-cocoon-achieves-slsa-level-3.html"&gt;article about achieving Level 3 compliance in the Cocoon engine&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  About the image
&lt;/h3&gt;

&lt;p&gt;The poster image was created using &lt;a href="https://fotor.com"&gt;Fotor.com&lt;/a&gt;'s AI image generator. It's an original image representing bad actors or cyber criminals.&lt;/p&gt;

&lt;h3&gt;
  
  
  About the article
&lt;/h3&gt;

&lt;p&gt;This post originally appears on my personal web site at &lt;a href="https://dom.jocubeit.com/flutter-takes-a-leap-towards-enhanced-security-with-slsa-compliance"&gt;https://dom.jocubeit.com/flutter-takes-a-leap-towards-enhanced-security-with-slsa-compliance&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>slsa</category>
      <category>sbom</category>
    </item>
    <item>
      <title>Exploring Dart 3.0’s New Class Modifiers with Real-World Examples</title>
      <dc:creator>Dom Jocubeit</dc:creator>
      <pubDate>Wed, 19 Jul 2023 11:00:00 +0000</pubDate>
      <link>https://dev.to/djocubeit/exploring-dart-30s-new-class-modifiers-with-real-world-examples-1onn</link>
      <guid>https://dev.to/djocubeit/exploring-dart-30s-new-class-modifiers-with-real-world-examples-1onn</guid>
      <description>&lt;p&gt;Dart 3.0 introduces a set of powerful &lt;a href="https://dart.dev/language/class-modifiers"&gt;class modifiers&lt;/a&gt; that provide developers with more control over inheritance, implementation, and type hierarchy. These modifiers, namely &lt;code&gt;base&lt;/code&gt;, &lt;code&gt;interface&lt;/code&gt;, &lt;code&gt;final&lt;/code&gt;, and &lt;code&gt;sealed&lt;/code&gt;, complement the existing modifiers &lt;code&gt;abstract&lt;/code&gt; and &lt;code&gt;mixin&lt;/code&gt; to offer distinct guarantees and restrictions when applied to classes or mixins.&lt;/p&gt;

&lt;p&gt;In this article, we will delve into these modifiers using real-world object examples, showcasing their practical applications and benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base Modifier
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;base&lt;/code&gt; modifier ensures the enforcement of inheritance and implementation within a &lt;code&gt;class&lt;/code&gt; or &lt;code&gt;mixin&lt;/code&gt;'s own library. It offers several guarantees such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The base class constructor is invoked whenever an instance of a subtype is created.&lt;/li&gt;
&lt;li&gt;All private members implemented in the base class are inherited by subtypes.&lt;/li&gt;
&lt;li&gt;The addition of newly implemented members in the base class does not break existing subtypes unless a subtype already declares a member with the same name and incompatible signature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To illustrate this, let’s consider the example of a Vehicle class defined in the library &lt;code&gt;base_vehicle.dart&lt;/code&gt;. The &lt;code&gt;base&lt;/code&gt; modifier is applied to ensure that the Vehicle class is extended within its own library, disallowing implementation outside of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Library base_vehicle.dart&lt;/span&gt;
&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moveForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;meters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Library test.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'base_vehicle.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Example usage&lt;/span&gt;
&lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="n"&gt;myVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Can be constructed&lt;/span&gt;

&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;passengers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ERROR: Cannot be implemented&lt;/span&gt;
&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moveForward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The interface Modifier
&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;interface&lt;/code&gt; modifier, developers can define interfaces in Dart. These interfaces can be implemented by libraries outside their defining library but cannot be extended. The key guarantees provided by the &lt;code&gt;interface&lt;/code&gt; modifier are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instance methods within the interface always invoke known implementations from the same library.&lt;/li&gt;
&lt;li&gt;Other libraries cannot override methods in a way that could cause unexpected behaviour within the interface class.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s consider an example where a Vehicle &lt;code&gt;interface&lt;/code&gt; is defined in &lt;code&gt;vehicle_interface.dart&lt;/code&gt; and implemented in another library, &lt;code&gt;test.dart&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Library vehicle_interface.dart&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moveForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;meters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Library test.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'vehicle_interface.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Example usage&lt;/span&gt;
&lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="n"&gt;myVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Can be constructed&lt;/span&gt;

&lt;span class="c1"&gt;// ERROR: Cannot be inherited&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;passengers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Can be implemented&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moveForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;meters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The final Modifier
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;final&lt;/code&gt; modifier closes the type hierarchy, preventing subtyping from external classes. It disallows both inheritance and implementation, ensuring that the API remains stable and instance methods are not overwritten by third-party subclasses. However, &lt;code&gt;final&lt;/code&gt; classes can still be extended or implemented within the same library. It is worth noting that the &lt;code&gt;final&lt;/code&gt; modifier encompasses the effects of the &lt;code&gt;base&lt;/code&gt; modifier, requiring any subclasses to be marked as &lt;code&gt;base&lt;/code&gt;, &lt;code&gt;final&lt;/code&gt;, or &lt;code&gt;sealed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Consider the following example where a &lt;code&gt;final&lt;/code&gt; Vehicle class is defined in &lt;code&gt;final_vehicle.dart&lt;/code&gt;, and its usage is demonstrated in &lt;code&gt;test.dart&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Library final_vehicle.dart&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moveForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;meters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Library test.dart&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'final_vehicle.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Example usage&lt;/span&gt;
&lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="n"&gt;myVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Can be constructed&lt;/span&gt;

&lt;span class="c1"&gt;// ERROR: Cannot be inherited&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;passengers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ERROR: Cannot be implemented&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moveForward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;meters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The sealed Modifier
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;sealed&lt;/code&gt; modifier allows developers to create a known and enumerable set of subtypes, ensuring exhaustive handling through switch statements. Sealed classes cannot be extended or implemented outside their defining library but can have factory constructors and define constructors for their subclasses. Subclasses of sealed classes, however, are not implicitly abstract.&lt;/p&gt;

&lt;p&gt;Let’s explore a practical example of a &lt;code&gt;sealed&lt;/code&gt; Vehicle class with several subclasses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Truck&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bicycle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// ERROR: Cannot be instantiated&lt;/span&gt;
&lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="n"&gt;myVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vehicle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Subclasses can be instantiated&lt;/span&gt;
&lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="n"&gt;myCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getVehicleSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vehicle&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ERROR: The switch is missing the Bicycle subtype or a default case.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'vroom'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Truck&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'VROOOOMM'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What have we learned?
&lt;/h2&gt;

&lt;p&gt;Dart 3.0’s new class modifiers, including &lt;code&gt;base&lt;/code&gt;, &lt;code&gt;interface&lt;/code&gt;, &lt;code&gt;final&lt;/code&gt;, and &lt;code&gt;sealed&lt;/code&gt;, will empower developers to design more robust and maintainable code. By using real-world examples, we have demonstrated how these modifiers offer practical solutions for enforcing inheritance, implementing interfaces, closing the type hierarchy, and ensuring exhaustive handling of subtypes. Incorporating these modifiers into your Dart projects will enhance code clarity, prevent unexpected behaviours, and contribute to overall code quality and reliability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This post originally appears on my personal web site at &lt;a href="https://dom.jocubeit.com/exploring-dart-30s-new-class-modifiers-with-real-world-examples"&gt;https://dom.jocubeit.com/exploring-dart-30s-new-class-modifiers-with-real-world-examples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used another free credit at STOCKIMG.AI to generate a horizontal poster using disco diffusion for the article poster image. This time I used the image from my second post as the primer, with some words about class modifiers, inheritance, type hierarchy and interfaces. The image above is the generated result. Again, I was expecting something similar to the second image and the result didn’t disappoint. With all three articles being in the same vein, I decided to use it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Exploring Dart 3.0's Powerful Pattern Matching and Destructuring</title>
      <dc:creator>Dom Jocubeit</dc:creator>
      <pubDate>Thu, 13 Jul 2023 14:33:11 +0000</pubDate>
      <link>https://dev.to/djocubeit/exploring-dart-30s-powerful-pattern-matching-and-destructuring-3ikd</link>
      <guid>https://dev.to/djocubeit/exploring-dart-30s-powerful-pattern-matching-and-destructuring-3ikd</guid>
      <description>&lt;p&gt;Dart is a versatile programming language and has introduced new features that enhance code expressiveness and development productivity. Among these features, pattern matching and destructuring stand out as powerful tools. In this article, we'll delve into the world of patterns in Dart, exploring their various use cases and showcasing real-world examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns in Dart: Matching Values and Destructuring Objects
&lt;/h2&gt;

&lt;p&gt;Patterns are a syntactic category in Dart, representing the shape of a set of values that can be matched against actual values. They serve two main purposes: pattern matching and pattern destructuring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern Matching
&lt;/h3&gt;

&lt;p&gt;Pattern matching enables developers to test whether a value meets specific criteria, such as having a particular shape, being a constant, equaling something else, or having a specific type. Let's look at some real-world examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Matching a Shape:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:math'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

  &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hexagon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Hexagon&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sideLength&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Area: &lt;/span&gt;&lt;span class="si"&gt;$area&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Hexagon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;sideLength:&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Area: &lt;/span&gt;&lt;span class="si"&gt;$area&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="n"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Area: 50 &lt;/span&gt;
  &lt;span class="n"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hexagon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;sideLength:&lt;/span&gt; &lt;span class="mf"&gt;6.9&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Area: 123.6944084225314&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Matching a Constant:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;gmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'gmail.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;r'^[\w-]+@([\w-]+\.)+[\w-]+$'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;example:&lt;/span&gt;
        &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Valid email from example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;gmail:&lt;/span&gt;
        &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Valid email from gmail.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Valid email from another domain'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Invalid email format'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;validateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'john.doe@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Valid email from example.com&lt;/span&gt;
  &lt;span class="n"&gt;validateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'jane.smith@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Valid email from gmail.com&lt;/span&gt;
  &lt;span class="n"&gt;validateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'foo@bar.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Valid email from another domain&lt;/span&gt;
  &lt;span class="n"&gt;validateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'invalid_email'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Invalid email format&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern Destructuring
&lt;/h3&gt;

&lt;p&gt;Pattern destructuring provides a convenient way to break down an object into its constituent parts, extracting values for further use. Let's explore some practical scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Destructuring a List:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processCoordinates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'x: &lt;/span&gt;&lt;span class="si"&gt;$x&lt;/span&gt;&lt;span class="s"&gt;, y: &lt;/span&gt;&lt;span class="si"&gt;$y&lt;/span&gt;&lt;span class="s"&gt;, z: &lt;/span&gt;&lt;span class="si"&gt;$z&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;processCoordinates&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;10.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;20.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5.1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Output: x: 10.5, y: 20.3, z: 5.1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Destructuring a Map Entry:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MapEntry&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;userEntry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;value:&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userEntry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Username: &lt;/span&gt;&lt;span class="si"&gt;$username&lt;/span&gt;&lt;span class="s"&gt;, Age: &lt;/span&gt;&lt;span class="si"&gt;$age&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MapEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'JohnDoe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;processUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Username: JohnDoe, Age: 25&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Use Cases for Patterns in Dart
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Simplifying Data Validation: Patterns prove valuable when validating complex data structures like JSON. They allow us to check if the structure conforms to our expectations and extract specific values effortlessly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhancing Switch Statements: Switch statements become more powerful with pattern matching, enabling multiple cases to share a body or matching against various patterns to execute specific code blocks based on input conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient Variable Assignment: Patterns provide a concise and expressive way to declare and assign variables simultaneously, making code more readable and reducing redundancy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What have we learned?
&lt;/h2&gt;

&lt;p&gt;With pattern matching and destructuring, Dart empowers developers to write more expressive and concise code. Whether you're validating data, manipulating objects, or enhancing control flow, patterns offer a powerful and flexible toolset. By leveraging these features, you can improve your Dart programming skills and boost productivity in real-world scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used another free credit at &lt;a href="http://STOCKIMG.AI"&gt;STOCKIMG.AI&lt;/a&gt; to generate a horizontal poster using disco diffusion for the article poster image. This time I used the image from my first post as the primer, with some words about pattern matching and destructuring. The image above is the generated result. This time I was expecting something similar and result is interesting. Given the two article topics are similar, I thought Id go ahead and use it.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>patternmatching</category>
      <category>destructuring</category>
    </item>
    <item>
      <title>Replacing tuples with records</title>
      <dc:creator>Dom Jocubeit</dc:creator>
      <pubDate>Mon, 03 Jul 2023 11:40:00 +0000</pubDate>
      <link>https://dev.to/djocubeit/replacing-tuples-with-records-9an</link>
      <guid>https://dev.to/djocubeit/replacing-tuples-with-records-9an</guid>
      <description>&lt;h2&gt;
  
  
  A refactoring use-case for dart’s new language feature
&lt;/h2&gt;

&lt;p&gt;With the release of Dart 3.0 came a new feature — records. You can learn about records in the Dart language documentation.&lt;/p&gt;

&lt;p&gt;For those unaware, to paraphrase: records are an anonymous, immutable, aggregate type. Records let you bundle multiple objects into a single object, but unlike other collection types, records are fixed-sized, heterogeneous, and typed. Records are real values; you can store them in variables, nest them, pass them to and from functions, and store them in data structures such as lists, maps, and sets.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical use-case
&lt;/h2&gt;

&lt;p&gt;I had an occasion to use the new records feature in updating a widget. I thought I’d share where the records feature works and the benefits gained.&lt;/p&gt;

&lt;p&gt;The widget is not important, but for reference, it’s a table. The table has an undo feature for changes to rows.&lt;/p&gt;

&lt;p&gt;In the original version, a tuple (package:tuple) with five dimensions was used to record the nature and details of a change to a row permitting a user to reverse the change if necessary. The tuples are stored on a stack, so undo is simply a matter of calling stack.pop(). The old code looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:stack/stack.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:tuple/tuple.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;reordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UndoState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// undo action, old state, new state, old index, new index&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Tuple5&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RowState&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RowState&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example of creating a tuple and adding it to the stack looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:tuple/tuple.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;onReorder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// undo action&lt;/span&gt;
        &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// old state&lt;/span&gt;
        &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// new state (n/a)&lt;/span&gt;
        &lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// old index&lt;/span&gt;
        &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// new index&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the comments on each element to imbue its semantics.&lt;/p&gt;

&lt;p&gt;Even worse is accessing the elements of the tuple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_undoRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Retrieve the last action and delete it from the stack&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="c1"&gt;// Undo the last action&lt;/span&gt;
      &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;item1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reordered&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;rowState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;item2&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;oldIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;item4&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;item5&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rowState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The elements have to be accessed using the itemN syntax. It's very unclear what the element represents in the structure, so appropriately named variables are required here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replacing with records
&lt;/h2&gt;

&lt;p&gt;A simple swap in replacement of the tuple with a record looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:stack/stack.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;reordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;(&lt;/span&gt;&lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RowState&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RowState&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;)&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We immediately remove the need for the tuple package, so that can go.&lt;/p&gt;

&lt;p&gt;And using it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;onReorder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;undoRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// undo action&lt;/span&gt;
        &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// old state&lt;/span&gt;
        &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// new state (n/a)&lt;/span&gt;
        &lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// old index&lt;/span&gt;
        &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// new index&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undoRecord&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And accessing the record fields is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_undoRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Retrieve the last action and delete it from the stack&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="c1"&gt;// Undo the last action&lt;/span&gt;
      &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reordered&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;rowState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;oldIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rowState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we access the fields of the record using the $n syntax.&lt;/p&gt;

&lt;p&gt;Have we swapped out one evil for another? Not quite, we did remove a dependency remember?&lt;/p&gt;

&lt;h2&gt;
  
  
  Where records shine
&lt;/h2&gt;

&lt;p&gt;Records have a compelling feature — named fields. We can name the fields, and then access them using their field names.&lt;/p&gt;

&lt;p&gt;Here is the updated code using named fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:stack/stack.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;reordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UndoState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;
      &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="n"&gt;UndoAction&lt;/span&gt; &lt;span class="n"&gt;undoAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;RowState&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;oldState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;RowState&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example of creating a record and adding it to the stack now looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;onReorder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;undoRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;undoAction:&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reordered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;oldState:&lt;/span&gt; &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nl"&gt;newState:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;oldIndex:&lt;/span&gt; &lt;span class="n"&gt;oldIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;newIndex:&lt;/span&gt; &lt;span class="n"&gt;newIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undoRecord&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And accessing the fields is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_undoRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Retrieve the last action and delete it from the stack&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="c1"&gt;// Undo the last action&lt;/span&gt;
      &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;undoAction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;UndoAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reordered&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
          &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newIndex&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="n"&gt;_tableSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;oldIndex&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastAction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;oldState&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What an improvement! Comments and variable assignments are gone because it’s now understandable. A dependency is gone, because records are now a first-class language feature. A big thank you to the Dart team.&lt;/p&gt;

&lt;p&gt;After writing this article I decided to double-check my link to the tuple package in pub.dev. The following notice is present:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By and large, Records serve the same use cases that package:tuple had been used for. New users coming to this package should likely look at using Dart Records instead. Existing uses of package:tuple will continue to work, however, we don’t intend to enhance the functionality of this package; we will continue to maintain this package from the POV of bug fixes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, I understand some people will argue a class is a better structure for this, and they might be right. I feel however that a record works well in this instance, and happy to be enlightened with justified reasoning.&lt;/p&gt;

&lt;p&gt;What do you think, are records a valid replacement for the tuple package here?&lt;/p&gt;

&lt;h2&gt;
  
  
  Other information
&lt;/h2&gt;

&lt;p&gt;This post originally appears on my personal web site at &lt;a href="https://dom.jocubeit.com/replacing-tuples-with-records"&gt;https://dom.jocubeit.com/replacing-tuples-with-records&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I used my one free credit at STOCKIMG.AI to generate a horizontal poster using disco diffusion for the article poster image. My casual, yet very inadequate prompt was: “dart programming language code flying in background, records in the foreground”. The image above is the generated result. Nothing like what I was expecting, but kinda cool; so I thought I’d use it anyway.&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>records</category>
      <category>refactoring</category>
    </item>
  </channel>
</rss>
