<?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: Appcircle</title>
    <description>The latest articles on DEV Community by Appcircle (@appcircle).</description>
    <link>https://dev.to/appcircle</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%2Forganization%2Fprofile_image%2F6178%2F501cdc03-fdf3-4976-9953-62fda6aeef62.png</url>
      <title>DEV Community: Appcircle</title>
      <link>https://dev.to/appcircle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/appcircle"/>
    <language>en</language>
    <item>
      <title>Best CI/CD Tools for Mobile</title>
      <dc:creator>Eren Kan</dc:creator>
      <pubDate>Wed, 22 May 2024 11:03:57 +0000</pubDate>
      <link>https://dev.to/appcircle/best-cicd-tools-for-mobile-2216</link>
      <guid>https://dev.to/appcircle/best-cicd-tools-for-mobile-2216</guid>
      <description>&lt;h2&gt;
  
  
  The Rise of Mobile DevOps: Choosing the Right Tool for Your Needs
&lt;/h2&gt;

&lt;p&gt;Since 2015, the DevOps industry has grown rapidly, especially after 2020. At first, we used DevOps tools for backend technologies like Jenkins, Azure DevOps, GitLab CI, and GitHub Actions. But now, more specialized tools have emerged, with Mobile DevOps leading the way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrlrsoei93ott70ept43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrlrsoei93ott70ept43.png" alt="Mobile Devops" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Mobile DevOps is Different
&lt;/h3&gt;

&lt;p&gt;Mobile projects have unique DevOps needs compared to backend technologies. Mobile apps must be built and tested across various devices, operating systems, and versions. This creates specific challenges and needs.&lt;/p&gt;

&lt;p&gt;In Mobile DevOps, we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mac OS Management:&lt;/strong&gt; Building and testing iOS apps require a macOS environment. Managing these environments can be complex and costly, so we need tools to streamline this process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signing Identity Management:&lt;/strong&gt; Mobile apps need to be signed with certificates to be installed on devices or published to app stores. We need to manage these signing identities securely and efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing Distribution:&lt;/strong&gt; Distributing pre-release versions to testers can be challenging. Tools should provide easy ways to distribute these versions to testers across different devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App Store Publishing:&lt;/strong&gt; Automating the process of publishing apps to various app stores can save time and reduce errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration with Third-Party Mobile-Specific Tools:&lt;/strong&gt; Mobile DevOps tools should seamlessly integrate with third-party tools like crash reporting, analytics, and user feedback systems to provide a comprehensive development and monitoring environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These needs have shown the limits of traditional backend DevOps tools. They often don't meet mobile project needs or result in high customization and management costs. Plus, the lack of Hot Deploy in mobile development makes updating versions complex, like releasing new versions. The practice of binary distribution has increased the focus on version stability and quick releases. As a result, the Mobile DevOps industry has gained a lot of momentum, especially after 2020.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Evolution of DevOps Tools for Mobile
&lt;/h3&gt;

&lt;p&gt;As demand for specialized Mobile DevOps tools grew, key players emerged, offering solutions to meet mobile development challenges. These tools now provide features that address mobile app developers' and operations teams' specific needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuacnkf62mikgw2jr5jtu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuacnkf62mikgw2jr5jtu.png" alt="Build triggers" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mobile-Specific Build Integrations
&lt;/h4&gt;

&lt;p&gt;Mobile-specific build integrations ensure that the DevOps tool works well with mobile development environments. This includes support for popular frameworks like React Native, Flutter, and Swift.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fast and Up-to-Date Build Infrastructure
&lt;/h4&gt;

&lt;p&gt;Building and testing mobile apps quickly is crucial. Mobile DevOps tools must provide a fast and up-to-date build infrastructure that handles the complexities of mobile development.&lt;/p&gt;

&lt;h4&gt;
  
  
  Signing Identities Management
&lt;/h4&gt;

&lt;p&gt;Managing signing identities involves handling certificates, provisioning profiles, and keys securely. Good Mobile DevOps tools automate this process, reducing errors and ensuring apps are signed correctly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Beta Testing Distribution
&lt;/h4&gt;

&lt;p&gt;Distributing beta versions of mobile apps allows for early detection of issues. Tools should offer easy ways to distribute beta versions to testers and provide detailed reporting on test results.&lt;/p&gt;

&lt;h4&gt;
  
  
  Publishing to Application Stores
&lt;/h4&gt;

&lt;p&gt;Automating the app publishing process saves time and reduces errors. Tools need to integrate with major app stores, enabling seamless publishing workflows.&lt;/p&gt;

&lt;h4&gt;
  
  
  On-Prem Support
&lt;/h4&gt;

&lt;p&gt;For organizations with strict security and compliance needs, on-premises support is essential. Mobile DevOps tools that offer on-prem support provide the flexibility and control needed to manage processes within the organization's infrastructure.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pricing Model
&lt;/h4&gt;

&lt;p&gt;The pricing model of a Mobile DevOps tool can impact its adoption. Fixed pricing, credit-based pricing, and pay-as-you-go models each offer different benefits. Organizations need to choose based on their needs and budget.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support Services
&lt;/h4&gt;

&lt;p&gt;Comprehensive support services, including community support, Service Level Agreements (SLA), and Customer Success Management (CSM), are crucial for smooth operation. The availability and quality of these services greatly influence the tool's effectiveness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evaluating Key Players in the Mobile DevOps Industry
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuurlod8lqyh6n1qicxf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuurlod8lqyh6n1qicxf.jpg" alt="comparison" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s a comparison of key players in the Mobile DevOps industry based on the above factors:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Factor&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://appcircle.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Appcircle&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://bitrise.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Bitrise&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://codemagic.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Codemagic&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.jenkins.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Jenkins&lt;/strong&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile-Specific Build Integrations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fast and Up-to-Date Build Infrastructure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Signing Identities Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Not Available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Beta Testing Distribution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;td&gt;Not Available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Publishing to Application Stores&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mature&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;On-Prem Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully Supported&lt;/td&gt;
&lt;td&gt;Cloud&lt;/td&gt;
&lt;td&gt;Cloud&lt;/td&gt;
&lt;td&gt;Fully Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pricing Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fixed Price&lt;/td&gt;
&lt;td&gt;Credit Based&lt;/td&gt;
&lt;td&gt;Pay as You Go&lt;/td&gt;
&lt;td&gt;Open Source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Support Services&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Community, SLA, and CSM&lt;/td&gt;
&lt;td&gt;SLA and Community&lt;/td&gt;
&lt;td&gt;Community, SLA&lt;/td&gt;
&lt;td&gt;Community, SLA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Microsoft App Center announced it would shut down its services in March 2024, so it is not included in this evaluation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making an Informed Decision
&lt;/h3&gt;

&lt;p&gt;When choosing a Mobile DevOps tool, consider your mobile development project's specific needs. Compare the features and capabilities of each tool to find the best fit. Also, consider the tool's long-term support and scalability to ensure it can grow with your organization.&lt;/p&gt;

&lt;p&gt;By evaluating these criteria, you can choose the most suitable Mobile DevOps tool for your needs. This will streamline your development processes and improve the quality and performance of your mobile apps.&lt;/p&gt;




</description>
      <category>mobile</category>
      <category>cicd</category>
      <category>appcircle</category>
      <category>bitrise</category>
    </item>
    <item>
      <title>The Journey of Microsoft App Center: A Retrospective from Birth to Sunset</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Wed, 17 Apr 2024 18:28:42 +0000</pubDate>
      <link>https://dev.to/appcircle/the-journey-of-microsoft-app-center-a-retrospective-from-birth-to-sunset-p55</link>
      <guid>https://dev.to/appcircle/the-journey-of-microsoft-app-center-a-retrospective-from-birth-to-sunset-p55</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Genesis of App Center&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After Apple launched iOS and Google introduced Android, both achieving great results, Microsoft decided to make a move to strengthen its presence in the mobile ecosystem. However, the "Windows Phone" domain did not experience the expected growth in the industry, and market focus shifted towards iOS/Android-based smart devices.&lt;/p&gt;

&lt;p&gt;Consequently, Microsoft developed a new strategy to reposition itself in the sector. Instead of competing by introducing new devices, it chose to develop platforms that would serve iOS/Android developers.&lt;/p&gt;

&lt;p&gt;This initiative began with Microsoft's release of the "Xamarin" development framework in May 2011. Xamarin provided C#/.NET developers with a cross-platform development environment, enabling them to create iOS and Android applications. This framework quickly became popular, enabling thousands of ".NET developers" to become "mobile developers," and highlighting the need for server-based services. To respond quickly, Microsoft acquired HockeyApp in November 2014, making its first step into cloud-based mobile services. This acquisition was also part of Microsoft's efforts to expand its range of mobile application development tools and services.&lt;/p&gt;

&lt;p&gt;In March 2017, Microsoft consolidated all of its mobile-related cloud services, including Xamarin Test Cloud, HockeyApp, and CodePush, with the goal of providing a comprehensive 360-degree suite of tools for mobile developers. This initiative led to the launch of the MS App Center. The development framework "Xamarin," paired with the cloud service "MS App Center," effectively addressed a wide array of needs for mobile developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Rise of App Center&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alongside supporting the Xamarin ecosystem with App Center services, Microsoft also positioned itself as an alternative to &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Google Firebase&lt;/a&gt; and &lt;a href="https://aws.amazon.com/amplify/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt;, thus solidifying its place in the mobile ecosystem.&lt;/p&gt;

&lt;p&gt;After a while, Microsoft began to develop "DevOps" features in addition to the "runtime features" on App Center. Starting with "Xamarin" and later extending compilation support to "Native iOS", "Native Android", and "React Native", Microsoft App Center solidified its position in the industry.&lt;/p&gt;

&lt;p&gt;As the mobile ecosystem entered a new era, Microsoft accelerated the adoption of App Center by addressing specific challenges such as the lack of specialized CI/CD products for mobile projects and developers' limited access to MAC OS build machine. &lt;/p&gt;

&lt;p&gt;App Center offered a comprehensive suite of services (almost for free) like &lt;strong&gt;Error Tracking and Reporting, Mobile Analytics, Beta Test Distribution, Push Notifications, Code Push, App Build for Mobile and Windows,&lt;/strong&gt; etc., which significantly attracted the industry’s interest.&lt;/p&gt;

&lt;p&gt;While Microsoft Azure DevOps continued to evolve in the backend DevOps area, MS App Center became more prominent on the mobile front. Integrations between Azure DevOps and MS App Center increased enterprise adoption of App Center.&lt;/p&gt;

&lt;p&gt;App Center became a preferred choice for beta distribution among many companies. Over time, it started surpassing Google Firebase and AWS Amplify in this regard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Retirement of App Center…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While Microsoft managed sustained success with Xamarin, the usage metrics for App Center were satisfactory. However, App Center was not commercially profitable, and the emergence of alternatives like &lt;a href="https://developer.apple.com/xcode-cloud/" rel="noopener noreferrer"&gt;Xcode Cloud&lt;/a&gt; and &lt;a href="https://appcircle.io/?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=journey_of_appcenter" rel="noopener noreferrer"&gt;Appcircle&lt;/a&gt; increased competition. The rise of Firebase’s runtime features also created alternatives to App Center, prompting Microsoft to reassess its strategies.&lt;/p&gt;

&lt;p&gt;While Microsoft continued to make significant investments in &lt;a href="https://azure.microsoft.com/en-us/products/devops" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt;, it defined a new strategy and began recommending the more corporate solution of the Azure DevOps family instead of App Center. As the DevOps sector began to rise in the early 2020s, Microsoft continued to position Azure DevOps as an alternative to other players in the industry such as GitLab CI, Circle CI, and Jenkins. I'm not even mentioning the acquisition of Github, as that is a completely parallel strategy.&lt;/p&gt;

&lt;p&gt;In recent years, MS App Center has increasingly failed to meet the industry's needs. Its lack of support for Flutter, not prioritizing issues on Github, and failing to meet roadmap targets indicated a decline in its priority within Microsoft. However, because it did not produce a solution in the Mobile DevOps area, the closure of MS App Center was not widely anticipated.&lt;/p&gt;

&lt;p&gt;Currently, Microsoft is focusing on growing within the Community through Github Actions, while continuing to emphasize Azure DevOps in the Enterprise world. For mobile needs, it is trying to address Runtime features (&lt;strong&gt;Error Tracking and Reporting, Mobile Analytics&lt;/strong&gt;) by directing them towards Azure services for solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exit Planning from App Center&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Considering the services provided by App Center, I would like to share some alternatives:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build:&lt;/strong&gt; App Center’s build feature was relatively limited, but it filled a crucial gap especially in Xamarin and Windows builds. For mobile solutions, transitioning to &lt;a href="https://appcircle.io/build?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=journey_of_appcenter" rel="noopener noreferrer"&gt;Appcircle Build&lt;/a&gt; and &lt;a href="https://developer.apple.com/xcode-cloud/" rel="noopener noreferrer"&gt;Xcode Cloud&lt;/a&gt; might be necessary, although custom pipelines will be needed for Xamarin and Windows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beta Distribution:&lt;/strong&gt; One of App Center’s most popular features was its Beta Distribution capability used for distributing mobile packages. Alternatives like &lt;a href="https://appcircle.io/testing-distribution?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=journey_of_appcenter" rel="noopener noreferrer"&gt;Appcircle Testing Distribution&lt;/a&gt; and &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Google Firebase&lt;/a&gt; can be considered. If you need more corporate capabilities (SSO/LDAP Login, Pipeline Integration, Reporting, etc.), Appcircle offers a good solution, while Google Firebase can be considered for community-based products.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analytics &amp;amp; Diagnostics:&lt;/strong&gt; You can set up your own services in Microsoft Azure, but &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Google Firebase&lt;/a&gt; and &lt;a href="https://aws.amazon.com/amplify/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt; can also be considered. There are many solutions available in this area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CodePush:&lt;/strong&gt; For the Code Push feature that App Center offers for React Native projects, you can set up the &lt;a href="https://github.com/microsoft/code-push" rel="noopener noreferrer"&gt;open source&lt;/a&gt; project available on GitHub on your own servers.&lt;/p&gt;

&lt;p&gt;Large service providers like Microsoft, &lt;a href="https://killedbygoogle.com/" rel="noopener noreferrer"&gt;Google&lt;/a&gt;, and AWS can suddenly shut down their services based on their own strategies. This situation can lead to unexpected results, especially for corporations. &lt;/p&gt;

&lt;p&gt;Therefore, I recommend that corporate organizations use reasonably priced, paid services to establish long-term agreements.&lt;/p&gt;

</description>
      <category>appcenter</category>
      <category>mobile</category>
      <category>devops</category>
    </item>
    <item>
      <title>Isolation as Key: Optimizing Performance in Concurrent Builds on a Single Host</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Tue, 02 Apr 2024 14:54:54 +0000</pubDate>
      <link>https://dev.to/appcircle/isolation-as-key-optimizing-performance-in-concurrent-builds-on-a-single-host-4k9a</link>
      <guid>https://dev.to/appcircle/isolation-as-key-optimizing-performance-in-concurrent-builds-on-a-single-host-4k9a</guid>
      <description>&lt;p&gt;&lt;a href="https://appcircle.io/blog/isolation-as-key-optimizing-performance-in-concurrent-builds-on-a-single-host?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=isolation" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjxbn50bpdcbdi7hh8p7.png" alt="isolation techniques" width="800" height="386"&gt;&lt;/a&gt;&lt;br&gt;
Running multiple builds on a single host for mobile application development is a common practice, but it introduces security and efficiency concerns. This article is about the importance of isolation techniques in mitigating these risks effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definitions:&lt;/strong&gt;&lt;br&gt;
By leveraging strategies such as containerization and virtual machine (VM) deployment, developers can ensure that each runner operates independently, minimizing conflicts such as managing different Xcode versions, test cases (simulators and emulators), and library dependencies, thus optimizing performance.&lt;/p&gt;

&lt;p&gt;Runners are the machines that execute jobs in a CI/CD workflow. For example, a runner can clone your repository locally, install testing software, and then run commands that evaluate your code. Additionally, insights from best practices in managing multiple runners from other development platforms are integrated to provide comprehensive guidance for creating secure and efficient development environments for mobile applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isolation Techniques: Best Practice&lt;/strong&gt;&lt;br&gt;
To accommodate multiple builds on a single host, developers often deploy replicas of runners with unique names. This approach enables the execution of numerous runners and jobs on a single host. However, to prevent conflicts and ensure smooth operation, it’s imperative to establish sufficient isolation between these runners.&lt;br&gt;
...&lt;br&gt;
&lt;a href="https://appcircle.io/blog/isolation-as-key-optimizing-performance-in-concurrent-builds-on-a-single-host?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=isolation" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;u&gt;Read More&lt;/u&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vm</category>
      <category>runner</category>
      <category>mobile</category>
      <category>devops</category>
    </item>
    <item>
      <title>Measuring Mobile DevOps Maturity with DORA Metrics</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Tue, 26 Mar 2024 16:00:11 +0000</pubDate>
      <link>https://dev.to/appcircle/measuring-mobile-devops-maturity-with-dora-metrics-1hjk</link>
      <guid>https://dev.to/appcircle/measuring-mobile-devops-maturity-with-dora-metrics-1hjk</guid>
      <description>&lt;p&gt;&lt;a href="https://appcircle.io/blog/measuring-mobile-devops-maturity-with-dora-metrics?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=dora_metrics" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpawwfg3r1h2rix8pr66n.png" alt="DevOps Maturity" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discover how Appcircle transforms mobile DevOps in our latest article! 🚀 &lt;br&gt;
Learn about tailored DORA metrics on Mobile DevOps &lt;/p&gt;

&lt;p&gt;Let's redefine Mobile DevOps together! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/blog/measuring-mobile-devops-maturity-with-dora-metrics?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=dora_metrics" rel="noopener noreferrer"&gt;https://appcircle.io/blog/measuring-mobile-devops-maturity-with-dora-metrics&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>devops</category>
    </item>
    <item>
      <title>Update on App Center's Retirement</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Fri, 22 Mar 2024 13:58:43 +0000</pubDate>
      <link>https://dev.to/appcircle/update-on-app-centers-retirement-5e73</link>
      <guid>https://dev.to/appcircle/update-on-app-centers-retirement-5e73</guid>
      <description>&lt;p&gt;&lt;a href="https://appcircle.io/blog/navigating-the-retirement-of-app-center-embracing-appcircle-as-the-ultimate-alternative?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=appcenter_retirement" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2j596gcm49bfgjt3h85.png" alt="App Center Retirement" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have an update on App Center's retirement. In our blog, "Navigating the Retirement of AppCenter: Embracing Appcircle as the Ultimate Alternative," we explore the challenges of App Center's retirement and how Appcircle is the ideal replacement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/blog/navigating-the-retirement-of-app-center-embracing-appcircle-as-the-ultimate-alternative?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=appcenter_retirement" rel="noopener noreferrer"&gt;https://appcircle.io/blog/navigating-the-retirement-of-app-center-embracing-appcircle-as-the-ultimate-alternative&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>devops</category>
    </item>
    <item>
      <title>Transforming Kotlin Collections - Functions with Examples</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Mon, 17 Oct 2022 07:11:36 +0000</pubDate>
      <link>https://dev.to/appcircle/transforming-kotlin-collections-functions-with-examples-dgd</link>
      <guid>https://dev.to/appcircle/transforming-kotlin-collections-functions-with-examples-dgd</guid>
      <description>&lt;ul&gt;
&lt;li&gt;This article originaly posted to &lt;a href="https://blog.appcircle.io/article/transforming-kotlin-collections-functions-with-examples" rel="noopener noreferrer"&gt;Appcircle&lt;/a&gt; blog and is written by Safa Orhan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Knowing about the standard library functions in Kotlin saves a lot of time while working on complex data structures. Whether you are mapping the API response model into your business model or you are sorting, filtering, and manipulating data; knowing  these operation on Kotlin collections come really handy.&lt;/p&gt;

&lt;p&gt;In this post, we are gonna go through some collection transformation operations that I use frequently.&lt;/p&gt;

&lt;h2&gt;Kotlin Collections - Transformation Operations&lt;/h2&gt;

&lt;h2&gt;1. Mapping&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mapping means to modify each item in a collection by applying a transformation lambda which results in the creation of another collection.&lt;/p&gt;

&lt;p&gt;If you are working on lists of data that you need to transform from one model into another or if you want to convert the API response model into a domain layer model you should use mapping operations in Kotlin.&lt;/p&gt;

&lt;h3&gt;.map()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
Using the &lt;code&gt;.map()&lt;/code&gt; function is the most common way to convert a collection of items into another. It applies the given transform lambda to each of the items of the receiver collection and yields them into a newly created list.&lt;/p&gt;

&lt;h3&gt;.mapIndexed()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also need the index of each item when transforming them, you can use the &lt;code&gt;.mapIndexed()&lt;/code&gt; function. It will feed the index of each item to the transform lambda so that you can utilize the order of the items.&lt;/p&gt;

&lt;h3&gt;.mapNotNull()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another convenient mapping function is &lt;code&gt;.mapNotNull()&lt;/code&gt;. You can use it if you want to filter out null items after the conversion.&lt;/p&gt;

&lt;p&gt;For example, if you have a list of objects which may or may not have text property, you can use &lt;code&gt;.mapNotNull()&lt;/code&gt; to get a list of texts without any nulls being in it.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Kotlin's standard library also has &lt;code&gt;.mapIndexedNotNull()&lt;/code&gt; method which combines &lt;code&gt;.mapIndexed()&lt;/code&gt; and &lt;code&gt;.mapNotNull()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also you can find &lt;code&gt;.mapKeys()&lt;/code&gt; and &lt;code&gt;.mapValues()&lt;/code&gt; methods which are defined on &lt;code&gt;Map&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Please check out the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#map" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; if you need more information on the topic.&lt;/p&gt;

&lt;h2&gt;2. Zipping&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you have two lists of the same size and you want to merge each item from the first list with the corresponding item coming from the second list you want zipping.&lt;/p&gt;

&lt;p&gt;Kotlin standard library has convenient functions to zip and unzip collections including &lt;code&gt;List&lt;/code&gt;s, &lt;code&gt;Array&lt;/code&gt;s, and &lt;code&gt;Sequence&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Let's take a look at what we have:&lt;/p&gt;

&lt;h3&gt;.zip()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;.zip()&lt;/code&gt; without any transformation to create a list of pairs. The pairs have their first item from the receiver list and the second from the argument. If you want to combine two different data sources into one and if the sources has the same number of items, the function &lt;code&gt;.zip()&lt;/code&gt; is really useful.&lt;/p&gt;

&lt;h3&gt;.zip() with transform lambda&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't need pairs but you want to define your own zipping logic, good news: &lt;code&gt;.zip()&lt;/code&gt; can also take a transform lambda as an argument. So you don't need to chain a &lt;code&gt;.zip()&lt;/code&gt; command with a &lt;code&gt;.map()&lt;/code&gt;. Instead, pass a lambda and combine two items coming from two data sources in a way you would prefer.&lt;/p&gt;

&lt;h3&gt;.unzip()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another great function in Kotlin is the &lt;code&gt;.unzip()&lt;/code&gt;. The name gives it all away: it does the opposite of &lt;code&gt;.zip()&lt;/code&gt;. If you have a list of pairs and want to create two lists that contain the firsts and seconds of each item, then just &lt;code&gt;.unzip()&lt;/code&gt; it!&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you want to see some examples please check out the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#zip" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's check out another group of transformation operations:&lt;/p&gt;

&lt;h2&gt;3. Association&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Association is when you want to traverse a &lt;code&gt;List&lt;/code&gt; and convert it into a &lt;code&gt;Map&lt;/code&gt; by associating each item with one of its properties. Understanding association operations is easier to show than tell, so let's take a look at what sort of functions we have in the standard library:&lt;/p&gt;

&lt;h3&gt;.associateWith()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.associateWith()&lt;/code&gt; function, structures the items of the List as keys of a &lt;code&gt;Map&lt;/code&gt;. The values for each key are computed by running the given lambda on the item. Please note that maps cannot have duplicate keys, so if the receiver collection has repetitive items, only the last one will remain in the map.&lt;/p&gt;

&lt;h3&gt;.associateBy()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kotlin also has &lt;code&gt;.associateBy()&lt;/code&gt;, which functions almost the same. The difference is items of the receiver collections are not used as keys but values.&lt;/p&gt;

&lt;p&gt;That means if the lambda returns the same values for different items, only the last one will be present in the resulting map.&lt;/p&gt;

&lt;h3&gt;.associate()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last associating function in the standard library is &lt;code&gt;.associate()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using this function, you can define the logic of building the map. You need to pass a lambda that returns &lt;code&gt;Pair&lt;/code&gt;s and a &lt;code&gt;Map&lt;/code&gt; will be built for you using these &lt;code&gt;Pair&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Please note that this function has some performance implications since it generates &lt;code&gt;Pair&lt;/code&gt;s as an intermediate step.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you want to learn more on association you can take a look at the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#associate" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's see how we can flatten collections:&lt;/p&gt;

&lt;h2&gt;4. Flattening&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Flattening in general is removing the nestedness in a collection. Consider you are given a list of lists. If you want to remove all child lists and get their elements into one single-level list, you need to flatten that list.&lt;/p&gt;

&lt;p&gt;Let's begin with:&lt;/p&gt;

&lt;h3&gt;.flatten()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the most simple way of flattening a list of lists into just list. Just call &lt;code&gt;.flatten()&lt;/code&gt; on the receiver collection to have a flat list.&lt;/p&gt;

&lt;h3&gt;.flatMap()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or, if you want to apply some kind of transformation whilst flattening, you can use &lt;code&gt;.flatMap()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please note that &lt;code&gt;.flatMap()&lt;/code&gt; is just a shorter form of &lt;code&gt;.map().flatten()&lt;/code&gt; chain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you want to see some code examples, you may check the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#flatten" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; on flattening.&lt;/p&gt;

&lt;p&gt;Now let's check out last chapter:&lt;/p&gt;

&lt;h2&gt;5. String Representation&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are generating user-visible text out of Kotlin collections or trying to log an internal state you will need to represent collections as strings. I really liked when I learned that Kotlin standard library has a function just for this reason:&lt;/p&gt;

&lt;h3&gt;.joinToString()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If don't pass any parameters to &lt;code&gt;.joinToString()&lt;/code&gt;, string representations of each items will be concatenated in a string and separated by commas with spaces by default.&lt;/p&gt;

&lt;h3&gt;Customizing the separator, prefix and postfix strings&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if you need to change the separator strings or add some more useful information to the start or to the end you can pass some arguments for &lt;code&gt;separator&lt;/code&gt;, &lt;code&gt;prefix&lt;/code&gt; and &lt;code&gt;postfix&lt;/code&gt; parameters.&lt;/p&gt;

&lt;h3&gt;The limit and truncated arguments&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.joinToString()&lt;/code&gt; also support limiting and truncating the list. If you have a long list and don't want to print everything and make a mess, you can limit how many elements you want in the resulting string and what string to use in the place of an ellipsis.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Finally, it also supports passing a transform lambda if you also want to define how each item will be converted into a string.&lt;/p&gt;

&lt;p&gt;You can study the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#string-representation" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; to learn more about the topic.&lt;/p&gt;




&lt;p&gt;That was it! Now you have learned how to transform Kotlin collections using a handful of convenience functions.&lt;/p&gt;

&lt;p&gt;If you like the article please share in your social media and if you want to learn more on Kotlin's standard library functions, let us know!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/contact?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=transforming_kotlin_collections_functions_with_examples" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9pfolgwlhw0k8nzem9v.png" alt="ContactUs" width="800" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Transforming Kotlin Collections - Functions with Examples</title>
      <dc:creator>Ali Eren Şen</dc:creator>
      <pubDate>Thu, 13 Oct 2022 07:07:23 +0000</pubDate>
      <link>https://dev.to/appcircle/transforming-kotlin-collections-functions-with-examples-21ao</link>
      <guid>https://dev.to/appcircle/transforming-kotlin-collections-functions-with-examples-21ao</guid>
      <description>&lt;p&gt;Knowing about the standard library functions in Kotlin saves a lot of time while working on complex data structures. Whether you are mapping the API response model into your business model or you are sorting, filtering, and manipulating data; knowing  these operation on Kotlin collections come really handy.&lt;/p&gt;

&lt;p&gt;In this post, we are gonna go through some collection transformation operations that I use frequently.&lt;/p&gt;

&lt;h2&gt;Kotlin Collections - Transformation Operations&lt;/h2&gt;

&lt;h2&gt;1. Mapping&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mapping means to modify each item in a collection by applying a transformation lambda which results in the creation of another collection.&lt;/p&gt;

&lt;p&gt;If you are working on lists of data that you need to transform from one model into another or if you want to convert the API response model into a domain layer model you should use mapping operations in Kotlin.&lt;/p&gt;

&lt;h3&gt;.map()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
Using the &lt;code&gt;.map()&lt;/code&gt; function is the most common way to convert a collection of items into another. It applies the given transform lambda to each of the items of the receiver collection and yields them into a newly created list.&lt;/p&gt;

&lt;h3&gt;.mapIndexed()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also need the index of each item when transforming them, you can use the &lt;code&gt;.mapIndexed()&lt;/code&gt; function. It will feed the index of each item to the transform lambda so that you can utilize the order of the items.&lt;/p&gt;

&lt;h3&gt;.mapNotNull()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FMapping4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another convenient mapping function is &lt;code&gt;.mapNotNull()&lt;/code&gt;. You can use it if you want to filter out null items after the conversion.&lt;/p&gt;

&lt;p&gt;For example, if you have a list of objects which may or may not have text property, you can use &lt;code&gt;.mapNotNull()&lt;/code&gt; to get a list of texts without any nulls being in it.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Kotlin's standard library also has &lt;code&gt;.mapIndexedNotNull()&lt;/code&gt; method which combines &lt;code&gt;.mapIndexed()&lt;/code&gt; and &lt;code&gt;.mapNotNull()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also you can find &lt;code&gt;.mapKeys()&lt;/code&gt; and &lt;code&gt;.mapValues()&lt;/code&gt; methods which are defined on &lt;code&gt;Map&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Please check out the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#map" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; if you need more information on the topic.&lt;/p&gt;

&lt;h2&gt;2. Zipping&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you have two lists of the same size and you want to merge each item from the first list with the corresponding item coming from the second list you want zipping.&lt;/p&gt;

&lt;p&gt;Kotlin standard library has convenient functions to zip and unzip collections including &lt;code&gt;List&lt;/code&gt;s, &lt;code&gt;Array&lt;/code&gt;s, and &lt;code&gt;Sequence&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Let's take a look at what we have:&lt;/p&gt;

&lt;h3&gt;.zip()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;.zip()&lt;/code&gt; without any transformation to create a list of pairs. The pairs have their first item from the receiver list and the second from the argument. If you want to combine two different data sources into one and if the sources has the same number of items, the function &lt;code&gt;.zip()&lt;/code&gt; is really useful.&lt;/p&gt;

&lt;h3&gt;.zip() with transform lambda&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't need pairs but you want to define your own zipping logic, good news: &lt;code&gt;.zip()&lt;/code&gt; can also take a transform lambda as an argument. So you don't need to chain a &lt;code&gt;.zip()&lt;/code&gt; command with a &lt;code&gt;.map()&lt;/code&gt;. Instead, pass a lambda and combine two items coming from two data sources in a way you would prefer.&lt;/p&gt;

&lt;h3&gt;.unzip()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FZipping4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another great function in Kotlin is the &lt;code&gt;.unzip()&lt;/code&gt;. The name gives it all away: it does the opposite of &lt;code&gt;.zip()&lt;/code&gt;. If you have a list of pairs and want to create two lists that contain the firsts and seconds of each item, then just &lt;code&gt;.unzip()&lt;/code&gt; it!&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you want to see some examples please check out the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#zip" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's check out another group of transformation operations:&lt;/p&gt;

&lt;h2&gt;3. Association&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Association is when you want to traverse a &lt;code&gt;List&lt;/code&gt; and convert it into a &lt;code&gt;Map&lt;/code&gt; by associating each item with one of its properties. Understanding association operations is easier to show than tell, so let's take a look at what sort of functions we have in the standard library:&lt;/p&gt;

&lt;h3&gt;.associateWith()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.associateWith()&lt;/code&gt; function, structures the items of the List as keys of a &lt;code&gt;Map&lt;/code&gt;. The values for each key are computed by running the given lambda on the item. Please note that maps cannot have duplicate keys, so if the receiver collection has repetitive items, only the last one will remain in the map.&lt;/p&gt;

&lt;h3&gt;.associateBy()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kotlin also has &lt;code&gt;.associateBy()&lt;/code&gt;, which functions almost the same. The difference is items of the receiver collections are not used as keys but values.&lt;/p&gt;

&lt;p&gt;That means if the lambda returns the same values for different items, only the last one will be present in the resulting map.&lt;/p&gt;

&lt;h3&gt;.associate()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FAssociation4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last associating function in the standard library is &lt;code&gt;.associate()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using this function, you can define the logic of building the map. You need to pass a lambda that returns &lt;code&gt;Pair&lt;/code&gt;s and a &lt;code&gt;Map&lt;/code&gt; will be built for you using these &lt;code&gt;Pair&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Please note that this function has some performance implications since it generates &lt;code&gt;Pair&lt;/code&gt;s as an intermediate step.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you want to learn more on association you can take a look at the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#associate" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's see how we can flatten collections:&lt;/p&gt;

&lt;h2&gt;4. Flattening&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Flattening in general is removing the nestedness in a collection. Consider you are given a list of lists. If you want to remove all child lists and get their elements into one single-level list, you need to flatten that list.&lt;/p&gt;

&lt;p&gt;Let's begin with:&lt;/p&gt;

&lt;h3&gt;.flatten()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the most simple way of flattening a list of lists into just list. Just call &lt;code&gt;.flatten()&lt;/code&gt; on the receiver collection to have a flat list.&lt;/p&gt;

&lt;h3&gt;.flatMap()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or, if you want to apply some kind of transformation whilst flattening, you can use &lt;code&gt;.flatMap()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please note that &lt;code&gt;.flatMap()&lt;/code&gt; is just a shorter form of &lt;code&gt;.map().flatten()&lt;/code&gt; chain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FFlattening4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you want to see some code examples, you may check the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#flatten" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; on flattening.&lt;/p&gt;

&lt;p&gt;Now let's check out last chapter:&lt;/p&gt;

&lt;h2&gt;5. String Representation&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString1-1-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString1-1-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are generating user-visible text out of Kotlin collections or trying to log an internal state you will need to represent collections as strings. I really liked when I learned that Kotlin standard library has a function just for this reason:&lt;/p&gt;

&lt;h3&gt;.joinToString()&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString2-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString2-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If don't pass any parameters to &lt;code&gt;.joinToString()&lt;/code&gt;, string representations of each items will be concatenated in a string and separated by commas with spaces by default.&lt;/p&gt;

&lt;h3&gt;Customizing the separator, prefix and postfix strings&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString3-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString3-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, if you need to change the separator strings or add some more useful information to the start or to the end you can pass some arguments for &lt;code&gt;separator&lt;/code&gt;, &lt;code&gt;prefix&lt;/code&gt; and &lt;code&gt;postfix&lt;/code&gt; parameters.&lt;/p&gt;

&lt;h3&gt;The limit and truncated arguments&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString4-1030x515.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2022%2F10%2FString4-1030x515.png" alt="" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.joinToString()&lt;/code&gt; also support limiting and truncating the list. If you have a long list and don't want to print everything and make a mess, you can limit how many elements you want in the resulting string and what string to use in the place of an ellipsis.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Finally, it also supports passing a transform lambda if you also want to define how each item will be converted into a string.&lt;/p&gt;

&lt;p&gt;You can study the &lt;a href="https://kotlinlang.org/docs/collection-transformations.html#string-representation" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; to learn more about the topic.&lt;/p&gt;




&lt;p&gt;That was it! Now you have learned how to transform Kotlin collections using a handful of convenience functions.&lt;/p&gt;

&lt;p&gt;If you like the article please share in your social media and if you want to learn more on Kotlin's standard library functions, let us know!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What Is The Alternative To Xcode For Windows For Mobile App Archive, Sign And Simulation?</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Wed, 08 Sep 2021 16:37:46 +0000</pubDate>
      <link>https://dev.to/appcircle/what-is-the-alternative-to-xcode-for-windows-for-mobile-app-archive-sign-and-simulation-bho</link>
      <guid>https://dev.to/appcircle/what-is-the-alternative-to-xcode-for-windows-for-mobile-app-archive-sign-and-simulation-bho</guid>
      <description>&lt;p&gt;&lt;a href="https://appcircle.io/blog/alternative-xcode-for-windows-app-archive-sign-simulation/" rel="canonical noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fac.appcircle.io%2Fwp-content%2Fuploads%2F2020%2F04%2FXcode-for-Windows-2.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reading Time: 2 minutes&lt;br&gt;
People frequently ask, “How to download and install Xcode on Windows for iOS development?” or similarly “Xcode on Linux”. The volume of queries to find a working Xcode for Windows has recently been more augmented as people are forced to work from home with no access to their macOS devices.&lt;/p&gt;

&lt;p&gt;You can still do iOS development on Windows with code editors in a crude way or by using the cross-platform frameworks, but you would be missing out crucial Xcode features such as iPhone and iPad simulators and archiving and signing iOS applications on Windows.&lt;/p&gt;

&lt;p&gt;There are certain technical workarounds to use Xcode for Windows as we mention in other posts, but each has their own complexities regarding building, previewing and distributing mobile applications.&lt;/p&gt;

&lt;p&gt;Moreover, you will encounter additional issues if you want to use multiple Xcode versions such as beta or if you are using a cross-platform framework to develop your iOS app, which requires specific dependencies besides Xcode itself, so you would also be looking to seek an alternative to use such dependencies on Windows.&lt;/p&gt;

&lt;p&gt;Instead of struggling with all of these issues, you can use Appcircle for an automates and simple mobile CI/CD experience on any environment.&lt;/p&gt;

&lt;p&gt;Appcircle is a complete DevOps platform that can replace many of the post-development operations done with Xcode, from app builds to simulators.&lt;/p&gt;

&lt;p&gt;What is the Advantage of Appcircle as an Alternative to Xcode for Windows?&lt;br&gt;
You can just connect your git repository without the need for Xcode and Appcircle will handle the full CI/CD processes of your app in your browser, whether you are using Windows or Linux or any other operating system. Appcircle even works on tablets so in a way, you can use Xcode on iPad for app signing and previews.&lt;/p&gt;

&lt;p&gt;Get started with Appcircle right away for archiving, signing and submitting iOS apps along with running apps on simulators.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/contact?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=what_is_the_alternative_to_xcode_for_windows_for_mobile_app_archive_sign_and_simulation" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9pfolgwlhw0k8nzem9v.png" alt="ContactUs" width="800" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>xcode</category>
      <category>appcircle</category>
      <category>mobile</category>
      <category>devops</category>
    </item>
    <item>
      <title>What is Noops And How to Achieve Noops in Mobile App Development?</title>
      <dc:creator>Sophie @Appcircle</dc:creator>
      <pubDate>Wed, 08 Sep 2021 16:37:02 +0000</pubDate>
      <link>https://dev.to/appcircle/what-is-noops-and-how-to-achieve-noops-in-mobile-app-development-5b03</link>
      <guid>https://dev.to/appcircle/what-is-noops-and-how-to-achieve-noops-in-mobile-app-development-5b03</guid>
      <description>&lt;p&gt;&lt;a href="https://appcircle.io/blog/what-is-noops-and-how-to-achieve-noops-in-mobile-app-development/" rel="canonical noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fappcircle.io%2Fwp-content%2Fuploads%2F2019%2F08%2FWhat-is-Noops-845x321.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reading Time: 3 minutes&lt;/p&gt;

&lt;p&gt;As enterprises are embracing DevOps and realizing its benefits, especially in their well-established software stacks, they are challenged with another question with the increasing prominence of DevOps in the cloud applications supported with automation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The question can be expressed as "why don't we fully streamline the DevOps processes even further since it is more or less consist of tasks in a highly structured flow?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The primary hurdle is the presence of physical hardware that requires maintenance in any case, but moving to the cloud and taking advantage of SaaS (Software as a Service) or PaaS (Platform as a Service) products eliminates this layer of complexity and automated DevOps starts to make more sense.&lt;/p&gt;

&lt;p&gt;And this concept actually has a recently coined name of "NoOps", which is gaining foothold in parallel with the cloud adoption.&lt;/p&gt;

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

&lt;p&gt;In the simplest way, NoOps can be considered as integrating and automating (wherever possible) DevOps processes. In this sense, it is perceived as an alternative to DevOps or sometimes even as "DevOps" killer, but, it is more like an extension and further streamlining of the DevOps concept.&lt;/p&gt;

&lt;p&gt;The term is first identified by Forrester and they emphasize that&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"NoOps means that application developers will never have to speak with an operations professional again."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Indeed, when NoOps is implemented and used in the right way and in the right conditions, it is as beneficial and productive as the name suggests.&lt;/p&gt;

&lt;p&gt;However, it requires the right tools and preferably a full cloud presence and it should not be considered as a silver bullet for DevOps needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/wp-content/uploads/2019/08/cloud-image.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fappcircle.io%2Fwp-content%2Fuploads%2F2019%2F08%2Fcloud-image.png.webp" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the advantage of the cloud, NoOps eliminates the hassle of integration and upload/download operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps vs. NoOps
&lt;/h2&gt;

&lt;p&gt;There are certain fields where you have an established DevOps culture and an "Ops" team, such as maintaining critical backend applications, which may include dealing with locally installed hardware and software.&lt;/p&gt;

&lt;p&gt;However, in emerging technologies such as mobility, it is not as easy as to find and maintain internal resources for DevOps or you might not have the operations experience that you have already gained in backend applications for decades.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/wp-content/uploads/2019/08/DevopsvsNoops.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fappcircle.io%2Fwp-content%2Fuploads%2F2019%2F08%2FDevopsvsNoops.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  DevOps in Enterprise Mobility
&lt;/h2&gt;

&lt;p&gt;Due to its nature, mobility has its own DevOps challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Requiring a binary to be installed on mobile devices&lt;/li&gt;
&lt;li&gt;  Device and operating system fragmentation making coding, testing and distribution processes demanding&lt;/li&gt;
&lt;li&gt;  Binary distribution regulations to mobile devices&lt;/li&gt;
&lt;li&gt;  Strict app signing requirements&lt;/li&gt;
&lt;li&gt;  Issues with keeping signing identities safe, secure and accessible&lt;/li&gt;
&lt;li&gt;  Complex app signing and submission processes that force the use of specific hardware and software.&lt;/li&gt;
&lt;li&gt;  Lengthy and complex store submission and review processes causing issues in maintenance of the apps after production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this reason, we highlight the fact that mobile app development is only the tip of the iceberg and the lifecycle management of mobile apps (the "Ops" part) is as important as the development itself, if not more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/wp-content/uploads/2019/08/Lifecycle.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fappcircle.io%2Fwp-content%2Fuploads%2F2019%2F08%2FLifecycle.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Typical Mobile App Lifecycle&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching From DevOps to NoOps in Mobile App Development
&lt;/h2&gt;

&lt;p&gt;Achieving NoOps in mobile app development is more difficult but also more important than many other fields due to the problems outlined in the previous section.&lt;/p&gt;

&lt;p&gt;We developed Appcircle for enterprises to embrace the NoOps approach in enterprise mobility. You can consider Appcircle like an automated production line, where everything is transferred automatically between stations.&lt;/p&gt;

&lt;p&gt;Appcircle automates DevOps processes to achieve NoOps to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  streamline mobile CI/CD&lt;/li&gt;
&lt;li&gt;  deliver mobile apps faster&lt;/li&gt;
&lt;li&gt;  increase productivity&lt;/li&gt;
&lt;li&gt;  automate mobile app releases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://appcircle.io/contact?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=what_is_noops_and_how_to_achieve_noops_in_mobile_app_development" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9pfolgwlhw0k8nzem9v.png" alt="ContactUs" width="800" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>noops</category>
    </item>
  </channel>
</rss>
