<?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>Forem: Artem Goncharov</title>
    <description>The latest articles on Forem by Artem Goncharov (@artem_goncharov_e0b3f99d2).</description>
    <link>https://forem.com/artem_goncharov_e0b3f99d2</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%2F902561%2Ff3339beb-5eac-41d5-b76b-800e8b61f93d.jpeg</url>
      <title>Forem: Artem Goncharov</title>
      <link>https://forem.com/artem_goncharov_e0b3f99d2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/artem_goncharov_e0b3f99d2"/>
    <language>en</language>
    <item>
      <title>MR/AR devices as the next generation of exocortexes</title>
      <dc:creator>Artem Goncharov</dc:creator>
      <pubDate>Tue, 29 Nov 2022 07:55:43 +0000</pubDate>
      <link>https://forem.com/artem_goncharov_e0b3f99d2/mrar-devices-as-the-next-generation-of-exocortexes-4349</link>
      <guid>https://forem.com/artem_goncharov_e0b3f99d2/mrar-devices-as-the-next-generation-of-exocortexes-4349</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The next gen exocortex would proactively help us to do whatever we do by offloading some work to itself without us telling it to do so. The future App Store would be the Skill Store — we will be able to download skills right into our MR/AR devices, which are the best-equipped computing devices to be the next gen exocortex.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an exocortex?
&lt;/h2&gt;

&lt;p&gt;An exocortex is an external information processing system that augments the brain’s biological high-level cognitive processes. &lt;a href="https://transhumanism.fandom.com/wiki/Exocortex"&gt;[1]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Wikipedia, there is no such article and I’m being redirected to the page about BCI (brain-computer interface) &lt;a href="https://en.m.wikipedia.org/wiki/Brain"&gt;[2]&lt;/a&gt; –computer_interface which is a bit different from the notion of exocortex and describes the interface between two computing devices — the brain and the exocortex itself.&lt;br&gt;
Strictly speaking, we can say that exocortex is any external system that enhances our learning or thinking process. A notepad is one of the examples: when we write, think, read what we write, then write again — we use the simplest exocortex ever.&lt;/p&gt;

&lt;p&gt;Currently, any personal electronic device is an exocortex, especially a mobile phone. We offload a lot of storage tasks to our phones, and we use it as a notepad, as a scheduling tool, it helps with learning and solving simple tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an exocortex consists of?
&lt;/h2&gt;

&lt;p&gt;I think the modern exocortex is a computing device with an interface to our internal computing device (brain). So, very high level there are three parts it contains:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The computing device is just a CPU/GPU + memory. Nothing interesting here.&lt;/li&gt;
&lt;li&gt;Interfaces to other computing devices, including the human brain are very diverse — starting from Wi-Fi, mouse, keyboard, and monitor for PC, and touchscreen for mobile phones and ending with BCI ( that interacts with brain neurons directly.&lt;/li&gt;
&lt;li&gt;Model — it’s a tricky thing. The models inside the exocortex are being computed with the computing device and should imitate models in our brain on multiple layers. One of the layers is a communication layer and here an interaction design can be used &lt;a href="https://en.m.wikipedia.org/wiki/Interaction_design"&gt;[3]&lt;/a&gt;. The core part of the model in the device is the set of very high-level abstractions that have counterparts in our brain — we name them applications. For instance, let’s take the application “Notes” — it models the notes catalog, it means in the brain we have a model/idea of the catalogue/list of notes, where each note is a piece of content about something. So the exocortex supports our brain by helping to offload computations of some models to itself and provides the result of computations using a protocol (interaction design) over the interface from (2).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How exocortex works?
&lt;/h2&gt;

&lt;p&gt;The main process looks like this: our brain gets some input from the external world or from the internals of the brain itself, then it decides to activate the exocortex, sends some info to the exocortex using available interfaces, the exocortex makes some models calculations and then returns the result of the calculations, which our brain uses for its own calculations.&lt;/p&gt;

&lt;p&gt;There are a lot of moving parts. The brain needs to switch between different activities here — thinking about a problem, deciding to use the exocortex, deciding what interface to use, encoding the data to be processed, passing the encoded data to the exocortex, then periodically checking if the results are already available, decoding the results. Of course, our brain is super adaptable and we usually don’t notice all those activities — they just occur. However, there is a cognitive power we spend on these activities anyway, any switch means losing focus and increased chances to be distracted by something else (new message from a friend while translating the word in the translate app).&lt;/p&gt;

&lt;h2&gt;
  
  
  v How to make a better exocortex?
&lt;/h2&gt;

&lt;p&gt;I believe the fewer moving parts we have the more efficiently we use our exocortex and the more enjoyable is the process. It’s one of the reasons we start using phones as an exocortex — switch time is lesser than when we use a PC, the same is for the voice assistants which make switch for some tasks super quick. &lt;br&gt;
For a PC or a notebook one needs to turn it on, find the app, run it, use mouse and keyboard as a rather slow input. For mobile phones usually, there is no hassle of finding the device and turning it on, the input is quicker in some tasks and slower in others. For voice assistant there is almost no time for a switch — just ask the question (yes, we still need encoding, communicating, and decoding but for most of people speech is faster than typing + no need to run the specific app).&lt;/p&gt;

&lt;p&gt;What would be the next steps to make the exocortexes even more efficient? I see two ways of doing it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We can continue optimizing interfaces to be less disruptive, probably the final target here is neural BCI which connects the brain and exocortex directly. However, we would still need to have an interactions layer and a high level protocol that connects models in a brain and in a computing device. So it could turn out that we will not save a lot of time because of this direct interface.&lt;/li&gt;
&lt;li&gt;We can make exocortex to be proactive, driven by its own AI. In this case, the exocortex should have the same inputs as our brain and then it would predict the tasks our brain is trying to solve and proactively pre-calculate some models and provide the results to the brain. Of course, the AI should learn to provide what is really needed for this particular brain at this particular moment. This way can considerably decrease the switch time or even get rid of it completely!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The next gen exocortex
&lt;/h2&gt;

&lt;p&gt;I think the second way is very promising. Just imagine, you are somewhere in France in a bakery shop and want to buy a loaf of artisan bread, but unfortunately, you can’t speak French, however, your AI driven exocortex can easily understand what task you are working on (buying bread) and proactively provides you with some phrases that can be of use now. You choose and say one of them — AI understands what phrase you use and learn from this fact, making the following advice even more accurate. The way it works looks super useful to me.&lt;/p&gt;

&lt;p&gt;The only problem with the second way is that the exocortex device should have the same input your brain has + the output/results of models calculations should be available to our brain constantly. Obviously, the future MR/AR devices &lt;a href="https://www.intel.co.uk/content/www/uk/en/tech-tips-and-tricks/virtual-reality-vs-augmented-reality.html"&gt;[4]&lt;/a&gt; are the best equipped for this task as they see and hear the same as you do + the results of models calculations are available to you any time as an overlay above the real world.&lt;br&gt;
Interestingly, in this case, the models (or apps) would be very different from the current apps that we see every day in our phones or PCs. The future models would more resemble the real models in our brain that are being activated by specific contexts automatically — so it could be that multiple models would be activated by the same context and will fight for the chance to provide help. It resembles one of the models of consciousness (Global Workplace Therory) where different object on the scene of our view fight for the attention of different parts of our brain areas and one with the largest number of activated areas wins the attention &lt;a href="https://www.frontiersin.org/articles/10.3389/fpsyg.2021.749868/full"&gt;[5]&lt;/a&gt;. For instance, when you cook, two models, for cooking and for healthy habits could fight each other because the context activates both of them. In this case, you would get help from both or from one that wins.&lt;/p&gt;

&lt;p&gt;The result would be that the App Store for MR/AR devices as an exocortex will look like &lt;strong&gt;the Skill Store&lt;/strong&gt;: users would install models that support the required activity to their exocortex (MR/AR device) — one for translating, one for calculating, one for drawing, one for woodworking, one for management and so on.&lt;/p&gt;

&lt;p&gt;For example, I’m going to learn to play the guitar, I open the Skill Store and choose the skill “guitar playing “ — it’s downloaded to my brand new MR device and once I take a guitar and look at the strings the new skill is being activated. It starts showing me accords right on the guitar, drums the beat and attracts my attention to mistakes, and provides some help to fix them.&lt;/p&gt;

&lt;p&gt;Another example: when I install the skill “bouldering”, go to an indoor bouldering center and start climbing, my AR device starts helping me by counting the climbs and their complexity, highlighting the holds in the route, and letting me know about breaks when my heart rate is spiking.&lt;/p&gt;

&lt;h2&gt;
  
  
  A new way of developing models for the next gen exocortex
&lt;/h2&gt;

&lt;p&gt;The way the models/apps/skills are being developed would change as well. Skills are not the mobile apps, they are much more complex and we may need to change our thinking process in order to learn how to develop skills for the next gen exocortex.&lt;/p&gt;

&lt;p&gt;For instance, we may apply systems thinking and notice that if we use the usual exocortex, like a mobile phone or assistant, we use it as a technology in one of our practices. However, if we use an exocortex that is equipped with AI, we can consider the exocortex as the active team member, which at each moment of time knows what practice we are doing, what the lifecycle of the outcome of the practice is, and proactively plays some sub-roles of our role, does its practices and provides outcomes of those practices, so once we need them — they are already ready.&lt;/p&gt;

&lt;p&gt;Systems thinking can help us to understand what practices the exocortex would help us with, what would be the lifecycle of the outcome for each practice and how we may split the models in the most efficient way.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href="https://transhumanism.fandom.com/wiki/Exocortex"&gt;Exocortex | Transhumanism Wiki | Fandom&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://en.m.wikipedia.org/wiki/Brain"&gt;Brain — Wikipedia&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://en.m.wikipedia.org/wiki/Interaction_design"&gt;Interaction design — Wikipedia&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://www.intel.co.uk/content/www/uk/en/tech-tips-and-tricks/virtual-reality-vs-augmented-reality.html"&gt;Virtual Reality vs. Augmented Reality vs. Mixed Reality — Intel&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://www.frontiersin.org/articles/10.3389/fpsyg.2021.749868/full"&gt;Frontiers | Global Workspace Theory (GWT) and Prefrontal Cortex: Recent Developments&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some resources about systems thinking: isss.org, eem.institute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; &lt;em&gt;Opinions expressed in this article are solely my own and do not express the views or opinions of any company including my previous or current employers.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>exocortex</category>
      <category>augmented</category>
      <category>systems</category>
    </item>
    <item>
      <title>Future of E2E testing</title>
      <dc:creator>Artem Goncharov</dc:creator>
      <pubDate>Sun, 07 Aug 2022 14:26:56 +0000</pubDate>
      <link>https://forem.com/artem_goncharov_e0b3f99d2/future-of-e2e-testing-4p33</link>
      <guid>https://forem.com/artem_goncharov_e0b3f99d2/future-of-e2e-testing-4p33</guid>
      <description>&lt;ol&gt;
&lt;li&gt;What do we want from E2E testing?&lt;/li&gt;
&lt;li&gt;E2E testing outcome&lt;/li&gt;
&lt;li&gt;Current situation with E2E testing&lt;/li&gt;
&lt;li&gt;Problems we have now with E2E testing&lt;/li&gt;
&lt;li&gt;One ideal solution&lt;/li&gt;
&lt;li&gt;The ideal solution outcome&lt;/li&gt;
&lt;li&gt;Virtual users solution&lt;/li&gt;
&lt;li&gt;Would the outcome be the same as in the ideal solution?&lt;/li&gt;
&lt;li&gt;Some words about the design and implementation of the virtual users&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this article I’m trying to anticipate the evolution of End-to-End (E2E) testing in the near future.&lt;/p&gt;

&lt;p&gt;There is a lot of info about E2E testing, for example, &lt;a href="https://www.browserstack.com/guide/end-to-end-testing"&gt;this one&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do we want from E2E testing? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;By using E2E testing we want to make sure that from the real user perspective all flows in our application work fine and that the user can successfully reach their goal using the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  E2E testing outcome &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As a result of testing we would have the following artefacts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the testing scenarios with the % of testers/runs who successfully finish them.&lt;/li&gt;
&lt;li&gt;Bug reports with enough info to reproduce the bugs.&lt;/li&gt;
&lt;li&gt;Using the above outcome we can decide if the new version of our app is ready to be released in production and give us enough info to understand in which system we have bugs and how to repro them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Current situation with E2E testing &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Currently, in order to implement E2E testing, we need to prepare/update the testing scenarios, prepare test data (test accounts, test cards, etc), ask manual testers to test the application using the testing scenarios, or automate running those scenarios using different tools and methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems we have now with E2E testing &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are quite a few problems with E2E testing. We can enlist some:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Considerable efforts to keep testing scenarios up to date every time a new version is being released or some code changes are being done.&lt;/li&gt;
&lt;li&gt;In the case of manual testing, we have to sacrifice some combination of user parameters like country, language, etc., in order to reduce the number of testing hours that can make the results of testing not so reliable.&lt;/li&gt;
&lt;li&gt;In the case of automation, there are a lot of technical challenges on each platform, especially on mobile, mostly related to the way of searching the proper UI elements and reliability of interaction with them and with device/browser.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  One ideal solution &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Then the question is how the ideal solution could look like. How do we see the perfect E2E testing?&lt;/p&gt;

&lt;p&gt;What if we can have all our real users use our application, do whatever they need, and report to us if they find a bug or inconvenience. They should not stop using the app or leave a bad rating in stores or call our support, instead, they should just send us well-prepared reports with enough info to reproduce and fix bugs.&lt;/p&gt;

&lt;p&gt;This approach definitely satisfies the definition of the E2E testing and it doesn’t have those problems from the previous chapter and actually, it sounds like perfect E2E testing, at least from my point of view.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ideal solution outcome &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In the case of the ideal solution we would have the same artefacts as from the usual E2E testing plus some more:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By using the business analytics and metrics that we anyway should have in our application we would know how many users participated, how many of them successfully do what they want, how many errors were caught, and a lot of other product specific metrics that we would not have in case of usual E2E testing.&lt;/li&gt;
&lt;li&gt;Bug reports with enough info to reproduce the bugs.&lt;/li&gt;
&lt;li&gt;Reports about services load from our backend.&lt;/li&gt;
&lt;li&gt;Reports about any errors in our systems, especially on the boundaries of the systems.&lt;/li&gt;
&lt;li&gt;We even can make some A/B testing before officially releasing the app :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sounds rather cool. Of course, there are its own difficulties around usage of special environments and organisation of the process but it seems possible to solve them as we’ve already done that for the usual E2E testing.&lt;/p&gt;

&lt;p&gt;The next question is how we can make that dream come true without bothering our real users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual users &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;What if we can invent a virtual user (AI driven) who would install our application or open our website and use it as the real user with a purpose in their mind (or maybe more correct — in our Neural Network). Then we summon as many such users as we need and they will be doing exactly what we described in the ideal solution.&lt;/p&gt;

&lt;p&gt;However, there are two requirements that make the task rather hard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Those users should behave differently in order to imitate the diversity in the real users. And they shouldn’t behave chaotically, they should be trying to reach their goal (buy a chair, search for a movie, or anything else).&lt;/li&gt;
&lt;li&gt;In order to reduce the load to our environment and to the machinery that emulate those virtual users we’d like to make their number as small as possible but enough to cover all the functionality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One way of solving the both above requirements is to set up different types of users that will match the different groups of the real users. For example, our app is a mega online store, so we can, probably, define the following groups of users using their intentions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for one specific thing a lot, add many options in the basket, then choose one and buy it (intent to choose one thing from one category and buy it ASAP)&lt;/li&gt;
&lt;li&gt;Search for a group of similar things, rarely add something to the basket, almost never buy (intent to explore a broad category of goods)&lt;/li&gt;
&lt;li&gt;Come by a direct link from outside and immediately buy smth (intent to buy the specific thing)&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m not an expert in user behaviour, it’s just what comes to my mind first.&lt;/p&gt;

&lt;p&gt;The main idea is that there are some common behavior patterns and they can be reproduced by our virtual users. However, the above patternd are not the testing scenarios. The testing scenarios are hardcoded and should give the tester or testing pipeline clear instructions: tap this, input that, check this, and so on. On the contrast the behaviors or patterns are very general, they are on a higher level of abstraction: “search for black office chair under 100 pounds with an overall rating bigger than 4.5 and check all reviews so there are no any injures mentioned, then buy it using {card} and {address}”.&lt;/p&gt;

&lt;p&gt;A virtual user will then imitate the real users — trying to understand UI, find the needed elements on the screen, and interact with them in the same way the real users do.&lt;/p&gt;

&lt;p&gt;Using this approach we can summon few virtual users per group and “ask” them to use our app in the same way the real users do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would the outcome from the virtual users solution be the same as in the ideal solution? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The outcome would be pretty much the same, so we will have the same stats about users who participated and successfully reached their goals, the same reports about any bugs that prevent our virtual users to reach their goals, reports about backend errors that didn’t impact user experience, and so on.&lt;/p&gt;

&lt;p&gt;What will be missing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Load testing.&lt;/strong&gt; It depends on the capacity of our environment and testing pipeline actually, so theoretically we can summon thousands or millions of virtual users but the costs of such testing would be super high.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proper business metrics about the real users’ behavior&lt;/strong&gt;. There are a lot of factors that impact the real users’ behavior — from the political situation in the world to the weather and modern trends. But nothing impacts our virtual users — they will behave almost the same way every time we summon them. Sure thing we can re-train them if something really important changes in the world. Thus the data about virtual users behavior can’t help product owners to evolve the product but &lt;strong&gt;it can help them to measure how easy using our application is by measuring the time the virtual users spend to reach their goals&lt;/strong&gt;. It’s, actually, a really interesting idea to use the virtual users in order to do UX research of our apps. If an image on a button is not easily understandable for the virtual user it will be the same for the real one.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Some words about the design and implementation
&lt;/h2&gt;

&lt;p&gt;How would we implement the virtual users?  &lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s see what would we need to make the virtual users do what we want.&lt;/p&gt;

&lt;p&gt;There could be the following layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;[UI] UI that we should already have in the app&lt;/li&gt;
&lt;li&gt;[UI Parser] A system that understands the UI. So it can extract all the UI elements, be able to interact with them, and understand their purpose using text or images on elements. Ideally it shouldn’t rely on any knowledge about the internals of the UI — it should analyse a plain picture of the interface in the same way a real user does it.&lt;/li&gt;
&lt;li&gt;[Solver] A system that can expand the goal into a series of steps to reach it. If you want to buy a black chair you need to search for one first, you want to use filters and keywords, then you want to check it out and finally pay for it.&lt;/li&gt;
&lt;li&gt;[Goal setter] The very high-level system that translates the pattern or the needed behavior in a text form into the virtual user’s goal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can think of layer 3 as a core of the system, layer 4 as an input, layer 2 as an adapter from core to any UI (web, mobile, PC apps, or even something special like medical equipment with touch screens or industrial monitoring systems with hardware buttons).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g3EvoilE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gekvfjbof3bhsjafs6ax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g3EvoilE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gekvfjbof3bhsjafs6ax.png" alt="High level diagram" width="880" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How could the above example &lt;em&gt;"Buying a black office chair"&lt;/em&gt; work here?&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 4
&lt;/h3&gt;

&lt;p&gt;Layer 4 gets the text input, analyzes and extracts all the important features from it. It could look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main goal: buy&lt;/li&gt;
&lt;li&gt;Subject: chair&lt;/li&gt;
&lt;li&gt;Subject properties: black, office&lt;/li&gt;
&lt;li&gt;Limitations: price (100 pounds), rating (better than 4.5), reviews (not contain injures). &lt;/li&gt;
&lt;li&gt;Account: …&lt;/li&gt;
&lt;li&gt;Card: …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I suppose the best way to do that is to use machine learning and train it to extract the meaning from the text, probably, there are already some on the market.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3
&lt;/h3&gt;

&lt;p&gt;This one is a bit tricky. It should look like a problem solver and for each task provides the algorithm or the sequence of steps to solve it. In our example, the steps could look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the search page&lt;/li&gt;
&lt;li&gt;Search for a subject “chair” with keywords: black and office.&lt;/li&gt;
&lt;li&gt;Check the list of options, if there is none -&amp;gt; return error&lt;/li&gt;
&lt;li&gt;Filter out all the items with a price bigger than 100 and rating less than 4.5&lt;/li&gt;
&lt;li&gt;Iterate the list and choose the first one where reviews don’t contain keyword injures&lt;/li&gt;
&lt;li&gt;Proceed to checkout of the chosen item&lt;/li&gt;
&lt;li&gt;If it’s available buy it using credentials {card}&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can see two ways of implementing this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the real users’ analytics data, label a lot of different funnels and user’s journeys with goals and properties, and then use this data to train NN that can do the opposite — using a goal and properties suggests the sequence of events that lead to the goal.&lt;/li&gt;
&lt;li&gt;Once layers 1 and 2 are ready we can use reinforcement learning to train NN to reach different goals in the real application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I appreciate that I don't have much knowledge in machine learning and maybe there are many other ways to implement this layer but I’m sure that the task is very interesting, challenging, and, what is more important, promising as the results can be reused in many other fields like robotics, game AI and many more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2
&lt;/h3&gt;

&lt;p&gt;This layer is very important as it gives us the real interface to any application. What I mean here is that UI is rather different in web, mobile apps, and PC apps and the way we can interact with the UI is different too. Layer 2 abstracts it and provides us with something more high level.&lt;/p&gt;

&lt;p&gt;In our example, Layer 2 will be constantly analyzing the page it sees (using screenshots, some special tools like ‘adb’ for android or something else), extract all UI elements, and “understand” them, so when it receives command “Open search page” from Layer 3 it looks up something that has the meaning of search — button with the text “Search”, magnifying glass icon, menu with the text “Search”, etc, and then activates it by tapping on it (using special tools or just tapping on screen using elements coordinates).&lt;/p&gt;

&lt;p&gt;This layer alone can be rather useful for UI testing as it gives the opportunity to interact with any UI universally and does not depend on special ‘ids’ of elements or special tooling for interacting with internal UI representation.&lt;/p&gt;

&lt;p&gt;We have already made a PoC for this layer and it looks very promising. Hopefully, in the next articles, we can reveal more about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1
&lt;/h3&gt;

&lt;p&gt;This is just the UI of our app and the implemetation of a bidirectional way of interacting with it. We already mentioned some options in the previous section — like taking screenshots and tapping on screen using coordinates of the UI elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary  &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this article, we discussed one possible way of E2E testing evolution and suggested some ways of going there.&lt;/p&gt;

&lt;p&gt;We think that the future of E2E testing in the hands of virtual users (AI) who can test our apps in the same way our real users use them every day.&lt;/p&gt;

&lt;p&gt;It’s definitely the challenge to make that AI work but each step to the end state can bring its own value and can reveal new unknown ways of testing, using the apps, and even thinking about the apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First of all, I’m super happy that somebody reaches this far and I’ll be even happier to discuss this topic in comments to the article or in any other appropriate place.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feel free to share your ideas, critics, and comments.&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Three things you didn’t know about exception handling in Dart and Flutter</title>
      <dc:creator>Artem Goncharov</dc:creator>
      <pubDate>Sat, 06 Aug 2022 18:23:04 +0000</pubDate>
      <link>https://forem.com/artem_goncharov_e0b3f99d2/three-things-you-didnt-know-about-exception-handling-in-dart-and-flutter-4jgd</link>
      <guid>https://forem.com/artem_goncharov_e0b3f99d2/three-things-you-didnt-know-about-exception-handling-in-dart-and-flutter-4jgd</guid>
      <description>&lt;ul&gt;
&lt;li&gt;What is an exception?&lt;/li&gt;
&lt;li&gt;Exceptions handling in different languages&lt;/li&gt;
&lt;li&gt;Exception handling in Dart and Flutter&lt;/li&gt;
&lt;li&gt;* Synchronous code
&lt;/li&gt;
&lt;li&gt;* Asynchronous code
&lt;/li&gt;
&lt;li&gt;* Zones and runZonedGuarded
&lt;/li&gt;
&lt;li&gt;* Error handling in streams
&lt;/li&gt;
&lt;li&gt;* Unhandled exceptions
&lt;/li&gt;
&lt;li&gt;Wrap up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sorry for the clickbait title of the article, I’m experimenting with different styles… But I’d like to not disappoint you and will provide all those 3 things :)&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an exception? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are two types of exception definition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An exception is an inability of an operation to fulfill its contract&lt;/li&gt;
&lt;li&gt;An exception is an unexpected behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It seems that the first definition can include the second one as the unexpected behavior can be one of the reasons why the operation couldn’t fulfill its contract. The other reasons could include more or less expected problems — like connection loss, corruption of the file, and so on.&lt;/p&gt;

&lt;p&gt;As an example let’s consider this function:&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;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getRemainingAmount&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAcccountInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remainingAmount&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;This function returns the remaining money in our account. In order to do this, the function should hit our backend and request the account balance and this operation can fail because of various reasons — the network is down, the server is down, the contract between frontend and backend was changed, etc… All those reasons lead to an inability of our operation to fulfill its contract. However, all of those problems can be foreseen and we can add them to the contract. The only thing we can’t expect is unexpected behavior :). For instance, we anticipated all the problems except one: when backend in some cases returns text “negative” instead of the balance of our account — so this becomes unexpected for us (it’s a completely artificial example but just to give you an idea).&lt;/p&gt;

&lt;p&gt;The more we know about our system the less chance some unexpected behavior occurs.&lt;/p&gt;

&lt;p&gt;The next question is what we are going to do in all those exceptional cases. Do we want to react differently for each case or maybe we don’t care much if the server is down or returns some unexpected data? It’s the question of our system design but anyway we need a way to catch those exceptions separately or as a general exceptional situation so that we can respond accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exceptions handling in different languages &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The above considerations were taken into account differently in different programming languages. Let’s consider three approaches that Go, Rust and Dart use to handle exceptions (I'm not an expert in Go and Rust so feel free to comment if you found a problem with the code).&lt;/p&gt;

&lt;p&gt;Dart:&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="k"&gt;try&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;remaingAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;getRemainingAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;account:&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;displayAccountAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remaingAmount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;SocketException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;displayNoConnectionError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;logException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;exception:&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;stackTrace:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;rethrow&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;Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"math: square root of negative number"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&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;Rust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fn&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"main.jpg"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// main.jpg doesn't exist&lt;/span&gt;
   &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file found {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file not found &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;//handled error&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"end of main"&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;ol&gt;
&lt;li&gt;The most common approach which was used in C++ and is being used in Dart is to pay attention mainly to the happy path. So the code is rather easy to read and it’s not contaminated with many error branches. On the other side, it’s not that clear which block of code can cause an error and what kind of error it could be. For instance, in the above example, if you look inside the function getRemainingAmount you, most likely, will not be able to say if it would throw an exception or not.&lt;/li&gt;
&lt;li&gt;In Go it’s all the way around, the main focus is on error handling. So a function, besides a value, should return an error that has to be handled right after a function call. If the function can’t produce an error it should return a result only, and, it will clearly indicate that function is error-free. There is no way to silently ignore an error in a hope that upstream code will handle it — sure thing you can ignore an error but that error will not be automatically propagated to the upstream, you have to do it explicitly.&lt;/li&gt;
&lt;li&gt;In Rust, there is the third way of dealing with exceptions/errors. It looks similar to Go: function can return Either type with value OR error and then you can use pattern matching to understand if it’s value or error and what kind of error was returned. It’s not mandatory but there is no other way to throw an exception (except panic but it’s another story) so that you probably want to return Either type from all the functions that can cause errors. Code looks really readable and you can’t just pass exception/error upstream without handling it (only if the exception type is exactly the same as in an upstream function).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Any of those three approaches can be used in your code in Dart, you can return an object with value AND error, or result with Either value OR error, or use traditional try-catch blocks and other options Dart provides you out of the box.&lt;/p&gt;

&lt;p&gt;Let’s explore what exceptions handling options Dart provides us with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exception handling in Dart and Flutter &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;What are the situations where we need to use exception handling?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Synchronous code&lt;/li&gt;
&lt;li&gt;Asynchronous code&lt;/li&gt;
&lt;li&gt;Timers&lt;/li&gt;
&lt;li&gt;Streams&lt;/li&gt;
&lt;li&gt;Flutter app as a whole&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Synchronous code &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The main tool for handing the exceptions in Dart is &lt;code&gt;try-catch-finally&lt;/code&gt; construction — the same as in many other languages.&lt;/p&gt;

&lt;p&gt;In order to catch all the exceptions in a block of code you wrap the code in try block and use multiple &lt;code&gt;on-catch&lt;/code&gt; instructions to handle some specific exceptions, then use catch to handle all other unexpected exceptions, and finally use &lt;code&gt;finally&lt;/code&gt; to run the code that should be invoked after the code in try block and in any of the &lt;code&gt;catch&lt;/code&gt; blocks. Code in &lt;code&gt;finally&lt;/code&gt; will be called even if you return from &lt;code&gt;try&lt;/code&gt; or &lt;code&gt;catch&lt;/code&gt; blocks or &lt;code&gt;re-throw&lt;/code&gt; the exception in &lt;code&gt;catch&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;Instruction &lt;code&gt;rethrow&lt;/code&gt; helps you to throw the same exception after you handle it so the upstream code will take care 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="k"&gt;try&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;'Clean-up done 1'&lt;/span&gt;&lt;span class="p"&gt;);&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;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;FormatException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'format is wrong'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;FormatException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&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;'Format exceptions &lt;/span&gt;&lt;span class="si"&gt;$e&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="k"&gt;finally&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;'Clean-up done 2'&lt;/span&gt;&lt;span class="p"&gt;);&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;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&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;'Allocate something 3'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'Other error occurred'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;FormatException&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&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;'Format exceptions: &lt;/span&gt;&lt;span class="si"&gt;$e&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="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'Unknown exceptions: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;, with stack: &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;$s&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;rethrow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;'Clean-up something 3'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cant divide to zero
Clean-up done 1
Format exceptions FormatException: format is wrong
Clean-up done 2
Allocate something 3
Unknown exceptions: Other error occurred, with stack: 
#0      main (file:///Users/user/Downloads/dart_sample/bin/sync_exceptions.dart:26:5)
#1      _startIsolate.&amp;lt;anonymous closure&amp;gt; (dart:isolate-patch/isolate_patch.dart:299:32)
#2      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
Clean-up something 3
Unhandled exception:
Other error occurred
#0      main (file:///Users/user/Downloads/dart_sample/bin/sync_exceptions.dart:26:5)
#1      _startIsolate.&amp;lt;anonymous closure&amp;gt; (dart:isolate-patch/isolate_patch.dart:299:32)
#2      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that all three &lt;code&gt;try-catch&lt;/code&gt; blocks catch the exceptions and in the third block, the exception was &lt;code&gt;re-thrown&lt;/code&gt; after clean-up was done.&lt;/p&gt;

&lt;p&gt;This is pretty much it for the handling exceptions in synchronous blocks of code. You can check for more details here — &lt;a href="https://dart.dev/guides/language/language-tour#catch"&gt;https://dart.dev/guides/language/language-tour#catch&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous code &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s consider this example:&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&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;'Everything is fine!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;'Clean-up done'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Everything is fine!
Clean-up done
Unhandled exception:
IntegerDivisionByZeroException
#0      int.~/ (dart:core-patch/integers.dart:22:7)
#1      main.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/async_exceptions.dart:6:21)
#2      new Future.delayed.&amp;lt;anonymous closure&amp;gt; (dart:async/future.dart:325:39)
#3      Timer._createTimer.&amp;lt;anonymous closure&amp;gt; (dart:async-patch/timer_patch.dart:18:15)
#4      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#5      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#6      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’d like to handle the exception in the &lt;code&gt;Future&lt;/code&gt; delayed for one second. It’s natural that this code fails to catch the exception as the code in the &lt;code&gt;try-catch&lt;/code&gt; block just schedules the &lt;code&gt;_computation_&lt;/code&gt; (Futures callback/closure) to be invoked one second after &lt;code&gt;try-catch&lt;/code&gt; finishes its work.&lt;/p&gt;

&lt;p&gt;It would look something like this on a timeline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Em6HTngq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nmwzju7tqe9fq0svzn3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Em6HTngq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nmwzju7tqe9fq0svzn3g.png" alt="Catching exceptions in asynchronous code" width="880" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How to fix it? There are many ways of fixing it, for instance, by adding await instruction before the Future. It forces computation to be invoked inside the &lt;code&gt;try-catch&lt;/code&gt; and thus the &lt;code&gt;try&lt;/code&gt; block will be able to catch and handle the exception successfully.&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&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;'Everything is fine!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;'Clean-up done'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cant divide to zero
Clean-up done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it works fine, we managed to catch the exception and make a clean-up after it.&lt;/p&gt;

&lt;p&gt;We can represent the new code like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9j8Vewww--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yge0gg2f0y2ziyi5h9qe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9j8Vewww--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yge0gg2f0y2ziyi5h9qe.png" alt="code" width="880" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if we have a chain of futures? No problem at all, &lt;code&gt;try-catch&lt;/code&gt; will catch exceptions in all of them as long as we insert &lt;code&gt;await&lt;/code&gt; before the first of them.&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Its ok so far'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;value&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&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;'Everything is fine!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;'Clean-up done'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its ok so far
Cant divide to zero
Clean-up done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don’t like the above way of catching the exceptions you can use a dot syntax and &lt;code&gt;catchError&lt;/code&gt; function.&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Its ok so far'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;value&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;whenComplete&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Clean-up done'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its ok so far
Cant divide to zero
Clean-up done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, &lt;code&gt;catchError&lt;/code&gt; is an analog of &lt;code&gt;catch&lt;/code&gt; block and &lt;code&gt;whenComplete&lt;/code&gt; is an analog of &lt;code&gt;finally&lt;/code&gt; block. Function &lt;code&gt;catchError&lt;/code&gt; catches exceptions in all the code that located above it, so if you suspect that &lt;code&gt;whenComplete&lt;/code&gt; can throw an exception you can add one more &lt;code&gt;catchError&lt;/code&gt; after 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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Its ok so far'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;value&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;whenComplete&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Clean-up done'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'ss'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;'Oh, error in the finally block'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its ok so far
Cant divide to zero
Clean-up done
Oh, error in the finally block
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use exceptions matching using test parameter of a catchError function.&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Its fie so far'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&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;'Then started'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'random exception'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nl"&gt;test:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&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="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;'All other exceptions: &lt;/span&gt;&lt;span class="si"&gt;$error&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="nl"&gt;test:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&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="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;whenComplete&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Clean-up done'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its fie so far
Then started
All other exceptions: random exception
Clean-up done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks not super readable, right? That’s why a Dart code style recommends using &lt;code&gt;await&lt;/code&gt; (&lt;a href="https://dart.dev/guides/language/effective-dart/usage#prefer-asyncawait-over-using-raw-futures"&gt;code style guide&lt;/a&gt;)and thus &lt;code&gt;try-catch&lt;/code&gt; in such cases. It could look 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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Its fie so far'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Then started'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'random exception'&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="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'All other exceptions: &lt;/span&gt;&lt;span class="si"&gt;$e&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="k"&gt;finally&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;'Clean-up done'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its fie so far
Then started
All other exceptions: random exception
Clean-up done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From my personal point of view, it’s much clearer and more readable.&lt;/p&gt;

&lt;p&gt;Additionally, It has one more advantage — it can handle both synchronous and asynchronous code, so if you need to make some calculations between two asynchronous calls you don’t have to create additional synchronous Future (as you would have done in the case of dot syntax), just add this code into try block.&lt;/p&gt;

&lt;p&gt;Ooook, this was easy, right? What about this piece of code?&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Timer runs.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'[Timer] Bad thing happens!'&lt;/span&gt;&lt;span class="p"&gt;);&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;'Everything is fine!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;IntegerDivisionByZeroException&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;'Cant divide to zero'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;'Clean-up done'&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Everything is fine!
Clean-up done
Timer runs.
Unhandled exception:
Exception: [Timer] Bad thing happens!
#0      main.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/async_exceptions.dart:7:7)
#1      Timer._createTimer.&amp;lt;anonymous closure&amp;gt; (dart:async-patch/timer_patch.dart:18:15)
#2      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#3      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;:( (smile with crying). Yeah, bad things happen in timers too. And the above code is not good to deal with those bad things as again timer’s callback will be invoked not in the &lt;code&gt;try-catch&lt;/code&gt; block and we can’t fix it with await instruction as we can’t wait on Timer.&lt;/p&gt;

&lt;p&gt;An obvious solution is to add &lt;code&gt;try-catch&lt;/code&gt; inside the timer callback but if we don’t want to contaminate the callbacks with exceptions handling or there is a much complicated asynchronous logic inside the timer’s callback and we want to handle exceptions from that logic in the place where we run timer?&lt;/p&gt;

&lt;h3&gt;
  
  
  Zones and runZonedGuarded &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;runZonedGuarded&lt;/code&gt; can help you with this and with more complicated cases too!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Zones&lt;/code&gt; (&lt;a href="https://api.flutter.dev/flutter/dart-async/runZonedGuarded.html"&gt;dart help&lt;/a&gt;) is a concept in Dart that helps to divide your code into error free zones where any exceptions in any pieces of asynchronous code will be handled in one place: zone’s uncaught error handler.&lt;/p&gt;

&lt;p&gt;How does it work? Each callback or computation in timers, microtasks, and &lt;code&gt;Futures&lt;/code&gt; is being wrapped into a special handler in the &lt;code&gt;Zone&lt;/code&gt;. The handler wraps the callback in &lt;code&gt;try-catch&lt;/code&gt; and if catch is being triggered &lt;code&gt;Zone&lt;/code&gt; invokes an uncaught error handler where you can handle those errors.&lt;/p&gt;

&lt;p&gt;Each piece of code is being run in some &lt;code&gt;Zone&lt;/code&gt;, even you don’t create your custom &lt;code&gt;Zone&lt;/code&gt; it would be invoked in the &lt;code&gt;Root Zone&lt;/code&gt; which means we are safe anyway!&lt;/p&gt;

&lt;p&gt;Let’s see how we can fix the problem with the timer:&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;runZonedGuarded&lt;/span&gt;&lt;span class="p"&gt;((){&lt;/span&gt;
    &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Timer runs.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'[Timer] Bad thing happens!'&lt;/span&gt;&lt;span class="p"&gt;);&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;'Everything is fine!'&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="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'Exception handled &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;$s&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Everything is fine!
Timer runs.
Exception handled Exception: [Timer] Bad thing happens!, 
#0      main.&amp;lt;anonymous closure&amp;gt;.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/async_exceptions.dart:7:7)
#1      _rootRun (dart:async/zone.dart:1182:47)
#2      _CustomZone.run (dart:async/zone.dart:1093:19)
#3      _CustomZone.runGuarded (dart:async/zone.dart:997:7)
#4      _CustomZone.bindCallbackGuarded.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1037:23)
#5      _rootRun (dart:async/zone.dart:1190:13)
#6      _CustomZone.run (dart:async/zone.dart:1093:19)
#7      _CustomZone.bindCallback.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1021:23)
#8      Timer._createTimer.&amp;lt;anonymous closure&amp;gt; (dart:async-patch/timer_patch.dart:18:15)
#9      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#10     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#11     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy! Just wrap your code into &lt;code&gt;runZonedGuarded&lt;/code&gt; and add an error handler. No exception can squeeze through this construct… until we will not throw the exception in the error handler itself as the error handler is being invoked in the parent zone, so, be careful.&lt;/p&gt;

&lt;p&gt;You can notice that the stack trace becomes longer as now async callbacks are wrapped into our &lt;code&gt;_CustomZone&lt;/code&gt; handlers.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Zones&lt;/code&gt; is a very powerful tool that can help you to isolate some parts of your complex asynchronous logic from the other parts of the app. As we will see later it’s also rather useful when you use streams and for handling unhandled exceptions in Flutter apps.&lt;/p&gt;

&lt;p&gt;If we would try to represent handling of exceptions is zones it could look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kf5yFub9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3q00118e8uf1qim8uqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kf5yFub9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3q00118e8uf1qim8uqm.png" alt="Handling exceptions with Zones" width="880" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the about image we can see that all the asynchronous callbacks are covered by the zone’s exception handling if we schedule those callbacks inside the zone.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;code&gt;Zones&lt;/code&gt; helps you to intercept the creation of timers and print operators, and, keep some parameters in the zone’s context (it’s a dictionary that you can pass to the zone while you creating it). All those advanced things are being used in tests mainly, as for my knowledge.&lt;/p&gt;

&lt;p&gt;This is an example of how we can use nested zones and zone’s context parameters — I added the parameter &lt;code&gt;ZoneName&lt;/code&gt; where I write &lt;code&gt;Zone&lt;/code&gt; name and display it in prints.&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Current zone start in: &lt;/span&gt;&lt;span class="si"&gt;${Zone.current.toString()}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;runZonedGuarded&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Current zone inside runZoned: &lt;/span&gt;&lt;span class="si"&gt;${Zone.current.toString()}&lt;/span&gt;&lt;span class="s"&gt; with name &lt;/span&gt;&lt;span class="si"&gt;${Zone.current['ZoneName']}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Timer runs.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'[Timer] Bad thing happens!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="n"&gt;runZonedGuarded&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="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;'Current zone (1) inside runZoned: &lt;/span&gt;&lt;span class="si"&gt;${Zone.current.toString()}&lt;/span&gt;&lt;span class="s"&gt; with name &lt;/span&gt;&lt;span class="si"&gt;${Zone.current['ZoneName']}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&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;'Timer 1 runs. '&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'[Timer 1] Bad thing happens!'&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="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'Current zone (1) inside catch: &lt;/span&gt;&lt;span class="si"&gt;${Zone.current.toString()}&lt;/span&gt;&lt;span class="s"&gt; with name &lt;/span&gt;&lt;span class="si"&gt;${Zone.current['ZoneName']}&lt;/span&gt;&lt;span class="s"&gt;'&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;'Exception handled (1) &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;$s&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="nl"&gt;zoneValues:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'ZoneName'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Second zone'&lt;/span&gt;&lt;span class="p"&gt;},&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;'Everything is fine!'&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="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'Current zone inside catch: &lt;/span&gt;&lt;span class="si"&gt;${Zone.current.toString()}&lt;/span&gt;&lt;span class="s"&gt; with name &lt;/span&gt;&lt;span class="si"&gt;${Zone.current['ZoneName']}&lt;/span&gt;&lt;span class="s"&gt;'&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;'Exception handled &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;$s&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="nl"&gt;zoneValues:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'ZoneName'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'First zone'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current zone start in: Instance of '_RootZone'
Current zone inside runZoned: Instance of '_CustomZone' with name First zone
Current zone (1) inside runZoned: Instance of '_CustomZone' with name Second zone
Everything is fine!
Timer runs.
Current zone inside catch: Instance of '_RootZone' with name null
Exception handled Exception: [Timer] Bad thing happens!, 
#0      main.&amp;lt;anonymous closure&amp;gt;.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/async_exceptions.dart:10:7)
#1      _rootRun (dart:async/zone.dart:1182:47)
#2      _CustomZone.run (dart:async/zone.dart:1093:19)
#3      _CustomZone.runGuarded (dart:async/zone.dart:997:7)
#4      _CustomZone.bindCallbackGuarded.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1037:23)
#5      _rootRun (dart:async/zone.dart:1190:13)
#6      _CustomZone.run (dart:async/zone.dart:1093:19)
#7      _CustomZone.bindCallback.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1021:23)
#8      Timer._createTimer.&amp;lt;anonymous closure&amp;gt; (dart:async-patch/timer_patch.dart:18:15)
#9      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#10     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#11     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
Timer 1 runs. 
Current zone (1) inside catch: Instance of '_CustomZone' with name First zone
Exception handled (1) Exception: [Timer 1] Bad thing happens!, 
#0      main.&amp;lt;anonymous closure&amp;gt;.&amp;lt;anonymous closure&amp;gt;.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/async_exceptions.dart:18:11)
#1      _rootRun (dart:async/zone.dart:1182:47)
#2      _CustomZone.run (dart:async/zone.dart:1093:19)
#3      _CustomZone.runGuarded (dart:async/zone.dart:997:7)
#4      _CustomZone.bindCallbackGuarded.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1037:23)
#5      _rootRun (dart:async/zone.dart:1190:13)
#6      _CustomZone.run (dart:async/zone.dart:1093:19)
#7      _CustomZone.bindCallback.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1021:23)
#8      Timer._createTimer.&amp;lt;anonymous closure&amp;gt; (dart:async-patch/timer_patch.dart:18:15)
#9      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#10     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#11     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above example, you can see that it’s rather convenient to use nested zones to divide your code into error free zones and, probably, use zone’s context to keep so useful info for logging purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error handling in streams &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I promised to reveal how zones can help with handling exceptions when we use streams.&lt;/p&gt;

&lt;p&gt;Let’s consider the simple code where one piece of code emits some events to the stream and another one consumes them.&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;'dart:async'&lt;/span&gt;&lt;span class="o"&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="kt"&gt;List&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;startListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getStream&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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;getStream&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;intsController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StreamController&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;broadcast&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;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;periodic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'[Stream] Bad thing happens!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;intsController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;intsController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&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;startListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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;ints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;event&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;event&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'[Listener] Bad thing happens!'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;43
Unhandled exception:
[Listener] Bad thing happens!
#0      startListener.&amp;lt;anonymous closure&amp;gt; (file:///Users/artemgoncharov/Downloads/dart_sample/bin/streams_exceptions.dart:23:7)
#1      _RootZone.runUnaryGuarded (dart:async/zone.dart:1384:10)
#2      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#3      _DelayedData.perform (dart:async/stream_impl.dart:611:14)
#4      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:730:11)
#5      _PendingEvents.schedule.&amp;lt;anonymous closure&amp;gt; (dart:async/stream_impl.dart:687:7)
#6      _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#7      _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#8      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#9      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:404:11)
#10     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#11     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
44
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know this code is not perfect at all :) but it demonstrate the problem — we would have an unhandled exception in the listener. An obvious solution is to add try-catch inside the listener. And again, it could be hard because there could be multiple listeners and some asynchronous logic in place and we may want to handle all the exceptions from the listeners and the business logic in one place.&lt;/p&gt;

&lt;p&gt;We wrap listeners creation into one zone and producers creation in another one, and, now we can handle all the exceptions from both sides and log them and/or recover in one place that is very convenient:&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;'dart:async'&lt;/span&gt;&lt;span class="o"&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="kt"&gt;List&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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;stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;runZonedGuarded&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getStream&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="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'PRODUCER ZONE Exception handled: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;$s&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="n"&gt;runZonedGuarded&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;startListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&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="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;'CONSUMER ZONE Exception handled: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;$s&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="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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;getStream&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;intsController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StreamController&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;broadcast&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;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;periodic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;seconds:&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="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'[Stream] Bad thing happens!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;intsController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;intsController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&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;startListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&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;ints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;event&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;event&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="s"&gt;'[Listener] Bad thing happens!'&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;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;43
44
CONSUMER ZONE Exception handled: [Listener] Bad thing happens!, #0      startListener.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/streams_exceptions.dart:35:7)
#1      _rootRunUnary (dart:async/zone.dart:1206:13)
#2      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#3      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
#4      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#5      _DelayedData.perform (dart:async/stream_impl.dart:611:14)
#6      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:730:11)
#7      _PendingEvents.schedule.&amp;lt;anonymous closure&amp;gt; (dart:async/stream_impl.dart:687:7)
#8      _rootRun (dart:async/zone.dart:1182:47)
#9      _CustomZone.run (dart:async/zone.dart:1093:19)
#10     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
#11     _CustomZone.bindCallbackGuarded.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1037:23)
#12     _rootRun (dart:async/zone.dart:1190:13)
#13     _CustomZone.run (dart:async/zone.dart:1093:19)
#14     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
#15     _CustomZone.bindCallbackGuarded.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1037:23)
#16     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#17     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#18     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#19     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:404:11)
#20     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#21     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
45
PRODUCER ZONE Exception handled: [Stream] Bad thing happens!, #0      getStream.&amp;lt;anonymous closure&amp;gt; (file:///Users/user/Downloads/dart_sample/bin/streams_exceptions.dart:24:18)
#1      _rootRunUnary (dart:async/zone.dart:1198:47)
#2      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#3      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
#4      _CustomZone.bindUnaryCallbackGuarded.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1042:26)
#5      _rootRunUnary (dart:async/zone.dart:1206:13)
#6      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#7      _CustomZone.bindUnaryCallback.&amp;lt;anonymous closure&amp;gt; (dart:async/zone.dart:1026:26)
#8      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#9      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Warning!&lt;/strong&gt; I’m not saying we have to give up handling errors as close to the place where they can arise, I’m just saying that sometimes it’s very useful to wrap the complex features to zones in order to catch and properly log the errors that sometimes squeeze through all our downstream bastions.&lt;/p&gt;

&lt;p&gt;On this optimistic note, I’m going to get into the last topic: Unhandled exceptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unhandled exceptions &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As we saw before all the unhandled exceptions are intercepted by the zone the code is being invoked in. So that if you’d like to log the unhandled exceptions in you flutter app you need just wrap your &lt;code&gt;runApp&lt;/code&gt; call into the &lt;code&gt;runZoneGuarded&lt;/code&gt; and add logging in the error handler. If you do something else in main function — create providers or singletons — you may want to wrap them to the &lt;code&gt;runZonedGuarded&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;This helps you to be aware of any unhandled exceptions in your app.&lt;/p&gt;

&lt;p&gt;You may argue that you can see all of them in the terminal when you debug your app. This is super convenient for debugging but it has two nuances:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you debug your app directly on a device (not on Simulator) you will not be seeing the exceptions in the asynchronous code (unless you use &lt;code&gt;runZonedGuarded&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;In release builds, I’m sure, you want to be aware of all the unhandled exceptions even if it seems that app is working fine. So that you need to add &lt;code&gt;runZonedGuarded&lt;/code&gt; and log all the exceptions to your backend or Firebase/Sentry, or whatever system you use for remote logging&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, &lt;code&gt;runZoneGuarded&lt;/code&gt; can’t help you with the exceptions which were already handled by the Flutter framework.&lt;br&gt;
All those exceptions can be logged using &lt;code&gt;FlutterError.onError&lt;/code&gt; callback. If you add logging to this callback then anytime Flutter catches an error with rendering or anything in widgets it will reach that callback and will be logged by you. Don’t forget to &lt;code&gt;WidgetsFlutterBinding.ensureInitialized()&lt;/code&gt; before adding the &lt;code&gt;onError&lt;/code&gt; callback.&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;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;WidgetsFlutterBinding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureInitialized&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="n"&gt;FlutterError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlutterErrorDetails&lt;/span&gt; &lt;span class="n"&gt;errorDetails&lt;/span&gt;&lt;span class="p"&gt;)&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;"onError Exception: &lt;/span&gt;&lt;span class="si"&gt;$errorDetails&lt;/span&gt;&lt;span class="s"&gt; was caught by Flutter framework - redirect to Sentry or Firebase."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="n"&gt;runZonedGuarded&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;createProviders&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyApp&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="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&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;"Synchronous or Asynchronous Exception: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt; (stack &lt;/span&gt;&lt;span class="si"&gt;$s&lt;/span&gt;&lt;span class="s"&gt;) was caught in our custom zone - redirect to Sentry or Firebase."&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;
  
  
  Wrap up &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;It seems that brevity is not one my features but I hope the article was still useful and can be of help for you.&lt;/p&gt;

&lt;p&gt;Additionally, if you still haven’t forgotten about the 3 things from the title, here they are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There are many ways of dealing with exceptions in different languages, try-catch is not the only one, and, it depends on your design what exception handling method you want to use — in Dart you can implement many of them&lt;/li&gt;
&lt;li&gt;Use runZoneGuarded to catch exceptions in the complex asynchronous code, streams, and in a whole Flutter app too&lt;/li&gt;
&lt;li&gt;Unhandled exceptions in asynchronous code can be silently swallowed (not printed in the terminal) if you debug your app on the real device&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This article was written after my presentation (&lt;a href="https://www.youtube.com/watch?v=yAxHWK-UzsA"&gt;YouTube link&lt;/a&gt;) in Singapore Flutter Meetup which you can find here: &lt;a href="https://www.meetup.com/Singapore-Flutter-Meetup/events/276139032/"&gt;https://www.meetup.com/Singapore-Flutter-Meetup/events/276139032/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;List of sources&lt;br&gt;
&lt;a href="https://api.flutter.dev"&gt;https://api.flutter.dev&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dart.dev/get-dart"&gt;https://dart.dev/get-dart&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/flutter/flutter"&gt;https://github.com/flutter/flutter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Yet another mobile architectures comparison</title>
      <dc:creator>Artem Goncharov</dc:creator>
      <pubDate>Sat, 06 Aug 2022 17:02:08 +0000</pubDate>
      <link>https://forem.com/artem_goncharov_e0b3f99d2/yet-another-mobile-architectures-comparison-5pd</link>
      <guid>https://forem.com/artem_goncharov_e0b3f99d2/yet-another-mobile-architectures-comparison-5pd</guid>
      <description>&lt;p&gt;There are a lot of articles about different architecture patterns for mobile applications which try to convince you that this or that architecture pattern is the best one. Sure thing, we all know that there is no a silver bullet… unfortunately. However, it’s a very good exercise to compare the most popular mobile architecture patterns (&lt;strong&gt;MVC, MVP, MVVM, VIPER, Riblets and Redux&lt;/strong&gt;) and find out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what we can learn from them, &lt;/li&gt;
&lt;li&gt;how they can help us to design our app architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Multitier architecture
&lt;/h2&gt;

&lt;p&gt;In order to compare the above mentioned architecture patterns we need a baseline. I chose the multitier (actually 5 tier) architecture as it’s very popular, universal and has tiers/layers that are in fact very high level abstractions so we can use them to understand the abstraction level of the layers in mobile architecture patters.&lt;/p&gt;

&lt;p&gt;There are a lot of information about the multitier architecture [1], depending on the type of system some authors find 3 layer (pure backend — Data, Business Logic, Presentation), some 4 or 5.&lt;/p&gt;

&lt;p&gt;Each layer is a high level abstraction and the architecture has only one restriction: components in the layer can interact only to the components from the neighbour layers. It allows to decrease the coupling between parts of the application and keep a dependency graph in a manageable state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--arciXCrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmuw1ofv5962jxlbajdi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--arciXCrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmuw1ofv5962jxlbajdi.png" alt="The multitiered architecture" width="880" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let’s map each mobile architecture pattern to our baseline and see what we can find out.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVC
&lt;/h3&gt;

&lt;p&gt;Let’s start from MVC: View can be easily mapped to the View layer, Controller we can map to Presentation layer, and Model then should span over the rest of layers and it depends on your product whether you need them or not (in most cases you do). So MVC adds nothing to the multitier architecture and actually just simplifies it a bit.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVP
&lt;/h3&gt;

&lt;p&gt;Next is MVP. We can map it in the same layers as MVC — just change Controller to Presenter. Additionally, MVP restricts interactions between components so that Model can interact only with Presenter and View can interact only with Presenter as well. In the multitier architecture we have the same restrictions, so MVP again adds nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVVM
&lt;/h3&gt;

&lt;p&gt;MVVM has a pretty similar mapping. View, as in the previous examples, can be mapped to View layer, View Model in this pattern usually maps to Presentation layer and Model is the rest. The only difference is in a more advanced decoupling between View and ViewModel — here ViewModel knows nothing about View and all interactions from ViewModel to View happen through the binding of UI elements in View layer components to exposed properties in ViewModel components. So MVVM adds conception of binding between View and Presentation layers to the multitier architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v3WojArm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bmnht8jvue8vusnifm2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v3WojArm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bmnht8jvue8vusnifm2s.png" alt="Mapping of MVC, MVP and MVVM to the multilayered architecture" width="880" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  VIPER
&lt;/h3&gt;

&lt;p&gt;What about VIPER? It looks like a different beast. View as always maps to View layer, Presenter and Router go to the Presentation layer, Interactor maps to Business logic, and, Entity spans over Service and Data layers. Thus VIPER adds Router layer that helps to extract routing business logic from Presentation layer. But, what is more important, VIPER introduces conception of VIPER modules and describes a universal structure for such a module in an app and by this it starts the confusion between layers and classes names (Interactor usually is a class name that doesn’t make sense as it this name can’t help us to understand the business logic inside the Interactor). Splitting the app to modules is a very useful concept but there is no clear understanding how those modules can interact with each other and moreover share some state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yYi0jSn5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz46hzzajur3mcam2zu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yYi0jSn5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz46hzzajur3mcam2zu9.png" alt="Mapping of VIPER to the multilayered architecture" width="880" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Redux
&lt;/h3&gt;

&lt;p&gt;Redux seems to be the only pattern that doesn’t cover View at all and concentrates mostly on Business logic as Reducers and State, and, Data + Service Layers as Middleware. Redux is a very good attempt to define the conception of building the “backend” part of our layered model(data, service and business+state layers). By introduction the concepts of state, subscriptions, reducers, actions and middleware Redux helps to fully decouple Business layer from Service and Data layers, and additionally, View + Presentation layers from all the other layers. So Redux doesn’t claim to be a universal architecture pattern, it just provides a way to organise interactions between the layers and keep them independent from each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sNIDB-hJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga1a6085womcgmncqxwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sNIDB-hJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga1a6085womcgmncqxwf.png" alt="Mapping of Redux to the multilayered architecture" width="880" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Riblets
&lt;/h3&gt;

&lt;p&gt;Lastly there is Riblets (or RIBs). This pattern can actually be 1–1 mapped to the layered model, Services maps to Data + Service layer, Interactor to Business logic layer, Model Stream looks like State inside Business layer, Presenter and Router maps to Presentation layer and View is actually View layer. Riblets looks very similar to the VIPER as it helps to split your application not only to the vertical layers but horizontally to modules as well. However Riblets fixes some VIPER problems and modules can be united to the hierarchical structure using Routers and communicate and share some state using Interactors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--96oxCk41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8676nf44lbs0ybi7ezy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--96oxCk41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8676nf44lbs0ybi7ezy.png" alt="Mapping of Riblets to the multilayered architecture" width="880" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;How this analysis can help us to choose or understand existed mobile architecture patterns? Good question.&lt;br&gt;
Firstly, we can see that not all the design patterns are on the same level of abstraction and moreover they have different intention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MVC and MVP&lt;/strong&gt; are very high level design patterns, they are on the same level of abstraction as the multilayered architecture and add nothing to it. So it worths to be aware that Model, View, Controller and Presenter are not the classes but rather abstract layers and you need to come up with the components, classes and interactions between them in each layer of the multitier architecture. They are just hints how you can split functionality of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MVVM&lt;/strong&gt; is more about interaction between ViewModel(Presenter) and View. If you want to isolate UI from components in Presenter layer — you can try the MVVM way of binding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIPER&lt;/strong&gt; might help you to divide your app into modules with the strictly defined structure and interactions between components in the module. So it’s a lower level of abstraction and it has less freedom and flexibility if you follow VIPER ideology but it’s good as a starting point to learn about modularisation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redux&lt;/strong&gt; is the only design pattern that takes the state and the business logic very seriously. Again Redux is located on the even lower level of abstraction and will considerably restrict you in a way of layers/components interaction if you chose it as it is. But Redux gives us an idea about the state and the business rules management and additionally it can be easily coupled with any of above patterns in this role (for instance, you may try to use Redux as a Model layer in MVP pattern).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Riblets&lt;/strong&gt; seems to be on the lowest level of abstraction and it dictates you how to make hierarchical modules in your app, how to build them, interact between components in a module and even tries to take care of the app state. So if you think of you application as a hierarchy of modules and you have no idea where to start — it’s time to learn Riblets and see how it’s done there.&lt;/p&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href="https://en.wikipedia.org/wiki/Multitier_architecture"&gt;https://en.wikipedia.org/wiki/Multitier_architecture&lt;/a&gt;, &lt;a href="https://www.researchgate.net/figure/The-5-tier-Architecture-model_fig1_280235378"&gt;https://www.researchgate.net/figure/The-5-tier-Architecture-model_fig1_280235378&lt;/a&gt;, &lt;a href="https://www.oreilly.com/library/view/core-j2eetm-patterns/0130648841/0130648841_ch06lev1sec1.html"&gt;https://www.oreilly.com/library/view/core-j2eetm-patterns/0130648841/0130648841_ch06lev1sec1.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>android</category>
      <category>mobile</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Grokking the Mobile System Design interview</title>
      <dc:creator>Artem Goncharov</dc:creator>
      <pubDate>Sat, 06 Aug 2022 14:21:59 +0000</pubDate>
      <link>https://forem.com/artem_goncharov_e0b3f99d2/grokking-the-mobile-system-design-interview-4ehm</link>
      <guid>https://forem.com/artem_goncharov_e0b3f99d2/grokking-the-mobile-system-design-interview-4ehm</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Purpose&lt;/li&gt;
&lt;li&gt;How mobile system design interview usually looks like&lt;/li&gt;
&lt;li&gt;Common recommendations&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proposed interview answer plan&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;Business idea&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;Requirements clarification&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;Mathematical model design (if needed)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;High level system design&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;API design&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;High level client side design&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;Detailed design of some modules&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;ul&gt;
&lt;li&gt;One complex case and detailed discussion&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Summary&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;References&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Purpose &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Being a mobile developer you may know that it’s a problem to find any preparation materials for mobile system design interview. There are plenty of videos about backend system design interviews and just few of them about mobile one. The same situation is with the articles, one can find a lot of articles and even courses that would help to be prepared to the backend system design interview and there is no articles at all about mobile system design interviews. That’s why I thought it would be great to share my experience of the preparation and passing the mobile system design interviews.&lt;/p&gt;

&lt;p&gt;Sure thing this article is just one way of grokking the interview, and the outcome will depend not only on information you’ve got from this article but on your knowledge, skills and on interviews skills and knowledge as well, so don’t consider this info as a silver bullet.&lt;/p&gt;

&lt;h2&gt;
  
  
  How mobile system design interview usually looks like &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;First let’s explore how mobile system design interview looks like, what are the input, the process and the expectations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;Usually the interview takes about 45 minutes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5 minutes - acquaintance&lt;/li&gt;
&lt;li&gt;5–10 minutes - defining the task&lt;/li&gt;
&lt;li&gt;25–30 minutes - solution&lt;/li&gt;
&lt;li&gt;5 minutes - your questions to an interviewer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Commonly your task is to design the mobile application or a part of the application and sometimes to design some part of backend that is relevant to the mobile application as well. An interviewer lets you know all the needed information during the second 5–10 minutes, the input can vary from company to company.&lt;/p&gt;

&lt;h3&gt;
  
  
  Input
&lt;/h3&gt;

&lt;p&gt;Let’s see what can be provided to you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The idea of the new feature or of the whole application. Usually it sounds like — “Let’s design the Instagram like application” or “Given you work in Twitter let’s add the the feature of combining some of your posts to stories”. Nothing more you commonly hear from the interviewer, all additionally info you need to get from them using properly formulated questions — the technique will be described later in the article.&lt;/li&gt;
&lt;li&gt;The sketches of the screens needed to implement the idea from the first item. It’s a very important piece of the information and you have to be very attentive in order to absorb all the nuances.&lt;/li&gt;
&lt;li&gt;Some requirements and limitations, like in what extent you need to design the system — mobile only, or mobile and API only, or mobile and backend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it, no more input you most likely have from the interviewer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expectations
&lt;/h3&gt;

&lt;p&gt;High-level expectations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ability to understand and solve complex problems&lt;/li&gt;
&lt;li&gt;Communicate clearly and effectively&lt;/li&gt;
&lt;li&gt;Having relevant experience and knowledge
The way of going deeper from this abstract definitions mainly depends on the interviewer, theirs skillset, experience and position in the company. They can define complex problems very differently, but we will try to formulate the most common concrete signals you should demonstrate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the first item, in order to show your ability to understand and solve complex problems, you should demonstrate the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ability to think about the business part of the task as this is the first step in understanding the problem and answering the question “Why?”. You would show the attitude to understand the business purpose of the feature or the whole application and apply this knowledge in the process of clarifying or generating the technical requirements.&lt;/li&gt;
&lt;li&gt;Working well with the vague requirements. The interviewer usually gives you very less information and this info is definitely not enough to even start designing, thus you should be able to ask proper questions in order to clarify the requirements. The requirements clarification process should be driven by definite and clear aims, questions shouldn’t be random, but should rather follow some system.&lt;/li&gt;
&lt;li&gt;Ability to synthesise the solution for a given problem. In the first two items you demonstrated ability to understand the problem, next step is to apply all the available knowledge and design a reasonable solution. You would synthesise the design using the “top to bottom” approach in order to provide the context and the main conceptions first, and then, using divide and conquer technics, gradually split the system to smaller and smaller pieces.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second item — effective and clear communication — could include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Voice communication. You should speak for about 30 minutes without any big pauses explaining all your solutions and ideas with enough confidence, knowledge and ability to defend your ideas&lt;/li&gt;
&lt;li&gt;Whiteboard communication. A whiteboard is super helpful to document all your thoughts so you can return back to any step and see what you decided earlier and whether all of your decisions are consistent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With regards to the relevant experience and knowledge:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have experience in the development of the huge mobile applications or better the whole client-server systems. You are expected to show the knowledge of the application to server communications design (one-way, two-ways, API design), pagination, cache and state management, modularisation techniques, different mobile application design patterns and their pros and cons. In addition here you can demonstrate knowledge of the most popular problems in mobile apps and methods of avoiding them (like state mutation, storing of the big images in the app state and overuse of singletons and god objects).&lt;/li&gt;
&lt;li&gt;Ability to foresee the problems or difficulties in the solution. Some solutions can be very hard to implement and you are expected to clearly communicate about it, explain where the possible problem or the trade-off is.&lt;/li&gt;
&lt;li&gt;Have experience working with the different quality assurance and risk mitigation techniques. Here you are expected to mention how you make your design good for testing, blue-green deployments, fail fast, etc.&lt;/li&gt;
&lt;li&gt;Ability to design the modules on the class level, awareness of the main principles and design patterns. Very unlikely you will have time to do this but still there is a chance the interviewer will ask you questions like “How would you implement updating of the unread messages count label?” — you will need to decide will it be observer pattern or delegate or polling or whatever else it could be and draw the simple diagram.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common recommendations &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Summarising the most popular recommendations companies provide before the interview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to gather as many requirements as possible from your interviewer before starting designing. Don’t hesitate to ask as many questions as needed.&lt;/li&gt;
&lt;li&gt;You should show your knowledge so it’s possible to start from the part of design you know the best.&lt;/li&gt;
&lt;li&gt;You shouldn’t be silent, speak all the time, communicate clearly, don’t wait for hints from the interviewer.&lt;/li&gt;
&lt;li&gt;Always provide information about the alternatives and defend your choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Proposed interview answer plan &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I believe that if in your company you have a good tradition to do a design review before implementation of any big (or cross team) feature you can notice that actually a system design interview looks like a complex design review along with the preliminary work when you gather the requirements, think about the design and draw diagrams.&lt;/p&gt;

&lt;p&gt;So you can conduct design review for 3–5 times and it should be enough to understand the idea. But if you don’t have such an option let’s explore the good plan of your system design interview.&lt;/p&gt;

&lt;p&gt;This could be the high level plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Business idea (what we are selling to user?, usually it’s the services and the data) : 3–4 minutes&lt;/li&gt;
&lt;li&gt;Requirements clarification (5 dimensions to help with limitations) : 1–2 minutes&lt;/li&gt;
&lt;li&gt;Designing of a mathematical model (if needed) : 0–5 minutes&lt;/li&gt;
&lt;li&gt;Define how to split that state and functionality between the server and the client sides : 3–5 minutes&lt;/li&gt;
&lt;li&gt;API design : 7–10 minutes&lt;/li&gt;
&lt;li&gt;High level client side design (layered structure) : 4–5 minutes&lt;/li&gt;
&lt;li&gt;Detailed design of the one chosen module : 4–8 minutes&lt;/li&gt;
&lt;li&gt;One complex/tricky case and detailed discussion : 5–10 minutes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9f23RL0p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr76tzoeur5jhnh8lbe8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9f23RL0p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr76tzoeur5jhnh8lbe8.png" alt="Requirements per plan item" width="880" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s explore each item from the below plan in more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Business idea &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is mainly to understand the context, to formulate what exactly we are going to sell users (what kind of services and data) and to start thinking about the task from the very top. &lt;/p&gt;

&lt;p&gt;The outcome of this step is as the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The list of services we sell to our users&lt;/li&gt;
&lt;li&gt;The data entities access we sell to our users&lt;/li&gt;
&lt;li&gt;Understanding the main idea of the product or the feature (if you don’t understand something, don’t hesitate to ask all the needed questions. The more you know about the product the easier will be making decisions during the the rest of the process)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, if you were asked to design the simplified WhatsApp-like application without registering/login, groups, broadcast lists, E2E encryption and reading the status then the outcome of this step would be something like this:&lt;br&gt;
We sell the following services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Safely storing and providing read/write access to your address book
- Providing the ability to make/receive Audio and Video calls to contacts from your address book
- Providing the ability to send/receive text messages and images to contacts from your address book and safely store the history of all the chats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Services should be as independent from each other as possible so it will help you to design API faster. In our example all services depend on address book service but they are independent from each other.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We sell the access to the following data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Address book item:
- First name
- Family name
- Phone number
Chat history message:
- User opponent
- Inbound or outbound
- Date and time of the message
- Message text or Image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the above services list and the data entities (+ UI sketches commonly provided by the interviewer) form the basis for all your future work. The data entities are not the final ones and are not prepared to be stored or transferred by network, it’s just a high level description of the data mostly from the end-user perspective.&lt;/p&gt;

&lt;p&gt;You can start clarifing requirements right here, for instance you can ask whether we need to add user avatar image but in this case you should be ready to answer this question by your self since the interviewer can ask you back the same question and you should reason your choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements clarification &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It’s very important to gather all the possible requirements beforehand. We started doing that with the business requirements on the previous step, now we need to clarify the technical requirements, the limitations and the context. Why do we need it? Because your design should depend on the context, development processes and actually the ask from the customer/PO/interviewer.&lt;/p&gt;

&lt;p&gt;So the first question should be about the context, whether we have any in our task, whether we have the host application we’re adding new functionality to, whether we have backend already done for the web version, how big our team is and what their expertise is. In 99% of the cases I believe the interviewer will answer that there is no context at all and you should start from the scratch but these questions will show that you do care about the context and take it into account during the solution design process.&lt;/p&gt;

&lt;p&gt;Concerning the limitations I prefer to use a checklist for evaluation of the design solutions. The following list contains the checklist items and questions that can be asked regarding each of the item related to the mobile system design. You can come up with different questions and use another list, this one just for reminding you of the questions during the interview.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt; — are we designing MVP or PoC or full scale system? How big is the team which will implement my design?&lt;br&gt;
Testability — we can leave this dimension, we definitely need to think about some type of testing. No limitations here, just not to forget to mention about testing on the latest steps of you design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability/Performance&lt;/strong&gt; — here we can treat scalability as the scalability of our team — ability to reuse their code in different platforms and though we can ask about cross platform option since it can impact our design considerably. Also you can ask questions about some parameters that could impact the performance of the applications where performance is crucial and where it’s better to define limitations beforehand. For instance, if you are designing an application with recognition of many objects in the live video using ML you could mention that we limit our selves to the latest models of Android or iOS devices only. Otherwise we need to use third party libraries and use main processor for making all the calculation that can affect the battery life and the quality of recognition. This will not impact design so seriously but it’s worth mentioning since it shows your experience and an ability to foresee the problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt; — it’s very important to discuss the limitations caused by security reasons. Especially if you’re asked to store some information on the device, or if you should work with the Personally Identifiable Information (PII) or sensitive PII. So it’s better to clarify with the interviewer that persisting and transferring requested information should be safe and if you think it’s not safe you should suggest what have to be done to protect it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Availability&lt;/strong&gt; — here we can ask about the ability to work offline, probably limitations of OS versions, phone/tablet choice, using limited set of languages and screen sizes. Of course all those questions should be asked only if it’s relevant to your task.&lt;/p&gt;

&lt;p&gt;There is no need to enlist all the dimensions on the whiteboard as they work only as the keys to recall what should you think and ask about. Later on you can use the same dimensions if you will be asked to compare two solutions.&lt;/p&gt;

&lt;p&gt;It’s better to write all the answers to the above questions on the whiteboard so you can reference them later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Mathematical model design &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This step is relevant only to a limited subset of the tasks. Those tasks would sound like following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are a Facebook developer and you have to add new feature to show the two most popular posts at the top of the feed. In this case you need to clarify/come up with what it means — “most popular” and then describe how you can calculate it: should you use views or comments or likes in order to figure it out, should it be instant popularity or moving average and so on.&lt;/li&gt;
&lt;li&gt;You are a developer in a rapidly growing super hotel aggregator and your task is to develop a bot detection feature. Here you should define the input data you need to detect bots and come up with the algorithm and mathematical model of how to use this data in order to distinguish bots from the real users. For instance, you can calculate the requests rate using moving window and compare it to a given limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Outcome of this step would be a simple schema of the module with inputs, formula(s) inside and outputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X5r00uH8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsoe01ygjp2vjyj6e134.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X5r00uH8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsoe01ygjp2vjyj6e134.png" alt="Math model" width="880" height="378"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  High level system design &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Next step is to decide what part of the services and the data should be implemented/stored on the server and what part should be implemented/stored on the mobile device. Here you can use the output of the first step — list of services and data entities.&lt;/p&gt;

&lt;p&gt;Let’s consider previous example — WhatsApp-like app.&lt;/p&gt;

&lt;p&gt;Can we implement address book storage on device only? No, because we need to have one shared store so all the clients can use it in order to be able to contact to the needed correspondent (We don’t consider distributed storage schemes but you can think about it and compare with the above schema using dimensions from the second step).&lt;/p&gt;

&lt;p&gt;Can we implement Audio calls using client side only? Yes, but you need to let the interviewer know about all the tradeoffs in that case in comparison to the server side service (like E2E encryption, better scalability, worse availability because of NAT traversal and so on).&lt;/p&gt;

&lt;p&gt;For instance, you decide to put all the services to the server side, and so all the data will reside on the server as well.&lt;/p&gt;

&lt;p&gt;Then since all the data and services reside on the backend we need to choose the client-server communication type for each of them one by one.&lt;/p&gt;

&lt;p&gt;For WhatsApp-like application example, address book service can be easily implemented as a simple REST HTTP calls with JSON payload (given that each user can use only one device and so we don’t need server to client notifications about changes in the address book contacts), Audio/Video calls service would use its own communication interfaces — bidirectional TCP-based connection for a signal protocol (WebSocket probably) and UDP-based for the streaming of the data (RTP probably). On this step it should be enough to just mention type of communication (bidirectional or unidirectional, streaming or request-response-based, then more details — HTTP REST (simple, long-polling), web-socket, raw-socket, etc…)&lt;/p&gt;

&lt;p&gt;For the text/images chats service it is a bit harder to decide what communication channel to use. It could be REST HTTP + push notification or bidirectional web-sockets or custom TCP based channel or something else. All the options have their own pros and cons so you can choose any option, just let the interviewer know about the other alternatives and be ready to defend the chosen one.&lt;/p&gt;

&lt;p&gt;The outcome of this step should be something like on the following scheme where you define the place where the services and the data will reside + communication channels between the server and clients.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vCf0XBP6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehj8h45w2afzcfyaa7la.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vCf0XBP6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehj8h45w2afzcfyaa7la.png" alt="High level design schema" width="880" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the first very high level structure of our system and most likely it will be the only scheme where you draw any backend details.&lt;/p&gt;
&lt;h3&gt;
  
  
  API design &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This topic is rather controversial, there are a lot of ways to design the API, so you can use any of them, the only thing is to define all the exact data entities and API calls as an outcome of this step. Side effect of API design is the clarification of some server-side solutions.&lt;/p&gt;

&lt;p&gt;From my experience it’s good to start from the service and the data entity that other services/data entities depend on and expand it to one or more API calls. For instance, our first service is address book, so there would be 4 API calls:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;GET /address-book?page,limit -&amp;gt; [AddressBookItem]&lt;/em&gt;. Read the address book data with paging (it’s very important not to forget about paging — better if you consider paging by default to any call and then remove it if it’s not needed than to forget about it at all). I intentionally don’t mention any user identifier as we need to mention in the interview that all the requests should contain header with authorisation token which was received earlier during login procedure. If the interviewer wants to know more about login you can let him know one or more ways of the register/login implementation.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;POST /address-book?user_id,first_name,family_name,phone -&amp;gt; AddressBookItem&lt;/em&gt;. Add new record to the address book.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;PUT /address-book?usert_id,first_name,family_name,phone -&amp;gt; AddressBookItem&lt;/em&gt;. Update existed record in the address book.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;DELETE /address-book?user_id&lt;/em&gt;. Delete existed record from the address book.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Where &lt;em&gt;AddressBookItem&lt;/em&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddressBookItem:
    user_id: int64
    first_name: string
    family_name: string
    phone: string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read chat message API call would look like:&lt;br&gt;
&lt;em&gt;GET /chat-history?user_id,page,limit -&amp;gt; [ChatMessage, ChatImageMessage]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Where &lt;em&gt;ChatImageMessage&lt;/em&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ChatImageMessage:
    user_id: int64
    msg_id: int64
    dt: timestamp
    is_inbound: bool
    img_url_thumb: string
    img_url_full_size: string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrote API calls in a custom form that is easy to show in one line, so question mark doesn’t mean we will use request path parameters, it’s just delimiter between the call name and parameters list. Moreover word “GET” doesn’t imply we will use HTTP requests, it could be WebSocket according to our high-level scheme and this API call can be encoded with Google Protobuf, for instance, but idea will remain the same — it should be an idempotent call with three input parameters that returns array of 2 types of chat messages (simple text message and image message).&lt;/p&gt;

&lt;p&gt;You can come up with your own format of writing API calls if you think it would better represent the call name, input and output data.&lt;/p&gt;

&lt;p&gt;At this step we define data with more details taking into account server side implementation and trying to foresee future problems. For instance, we added unique identifiers to users and messages and represent image as two direct links — one for a thumbnail and one for a full size image.&lt;/p&gt;

&lt;p&gt;Most likely in your task you will have to work with images so it’s better to think about the possible problems beforehand, like saving a lot of traffic for users by downloading only thumbnails and not the full size images. It sounds obvious but those small optimisations make your solution more interesting to design and discuss.&lt;/p&gt;

&lt;p&gt;Designing an API is an iterative process, you can change API later when you will be designing client-side and it’s OK. This step is rather important and hard since you need to think simultaneously about server-side design and client-side design trying to foresee future problems with the connection speed, throughput and usage convenience. The previous steps are intended to prepare you by providing with the services list, data entities and the type of communication channel between the client and the server.&lt;/p&gt;

&lt;p&gt;After finishing this step you can spend some time analysing the result — probably there are some obvious optimisations you can apply to the API, for example, you may want to merge some APIs to one, or split some of them, or even decide to change communication channel because, for instance, it turns out that bidirectional communication better suits for one of the cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  High level client side design &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, you can start drawing the client modules structure scheme. Layered design, commonly, the easiest way to organise modules in some meaningful groups in almost all Frontend applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dbzukofz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3ej5cexjj84hpifdsv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dbzukofz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3ej5cexjj84hpifdsv7.png" alt="Client side design diagram" width="880" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s better to start drawing this scheme from the central and most important part of it — the state and services that doesn’t related to sate. These are things you provide to your users, so let’s start designing from them. You can name this layer business entities or &lt;strong&gt;Business Layer&lt;/strong&gt; and then start going downwards in order to meet the server-side.&lt;/p&gt;

&lt;p&gt;The next layer could be &lt;strong&gt;Service Layer&lt;/strong&gt;, here I use name “service” in a different meaning than before— interval Services Layer helps to isolate concrete implementations of the low level communication and persistent modules (Data Layer) from the Business Layer. So Business Layer shouldn’t bother about the place where we get the data from — persistent storage or communication channels, and what kind of SDK we use to implement audio/video calls. Another purpose of the Service Layer is to convert data from multiple formats to the one Business Layer is using. At this step we don’t make any assumptions about implementation of the services — will it be the set of middleware in Redux or services distributed among VIPER modules or something else, we can just mention that our purpose is to make services stateless and to try to keep explicit state in the Business Layer only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Layer&lt;/strong&gt; contains SDKs, frameworks, libraries that provide your application with such features like network communication, local DB access, logging, or, complete fully functional features like Audio/Video calls. Of course you can split Data Layer to multiple internal layers if it makes sense, for instance if you develop some low level codecs you would have two layers in the Data Layer — one for high level orchestration and one for low level access to device hardware, but it should be hidden in the Data Layer and exposed only in Dependency Injection phase where we can define what kind of modules and codec should be used in Data Layer.&lt;/p&gt;

&lt;p&gt;Going upwards from business layer to meet user we should draw the &lt;strong&gt;Presentation Layer&lt;/strong&gt;. The main purpose of this layer is to prepare the data from Business Layer to be displayed to user in UI Layer. Again it worth to mention that we want to keep the Presentation Layer stateless.&lt;/p&gt;

&lt;p&gt;The last layer to draw on the high level design structure scheme is &lt;strong&gt;UI Layer&lt;/strong&gt;. It’s a very platform specific layer where the business data, converted by the Presentation Layer, is being displayed on the device screen using OS SDKs. The second purpose of this layer is to interact with the user and pass all those interactions throughout the Presentation Layer to the Business Layer and further if needed.&lt;/p&gt;

&lt;p&gt;This layered design can be mapped to any concrete architecture patterns like MVC, MVI, Redux, VIPER, RIBs, etc, but it’s very important to remain on the higher level of abstraction at this step and not to go deeper to those concrete patterns. You can mention such thing like “module” here but postpone the concrete definition of the “module” to the next step as module’s meaning depends on the architecture pattern you will choose later, for instance, module in VIPER lays horizontally and crosses all the layers except the Data Layer, so each module contain small piece if each layer. In opposite, Redux, usually, doesn’t have modules but more like features instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detailed design of some modules  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Here we should finally choose one feature/module and define the architecture pattern that suits it best in your opinion. Let’s consider the chat feature in a WhatsApp-like application. As the chat feature crosses all the layers, the chosen pattern will influence the whole application, so we need to think not only about chosen feature but rather about the app in a whole.&lt;/p&gt;

&lt;p&gt;Actually, our WhatsApp-like application works with rather limited types of data entities that are related to each other and all changes in the data should be immediately reflected in different part of the application as messages in the chat list and the chat screen, as a notification when user browses the other parts of the app and as a counter of the unread messages. It means we can have the one periodically updated state with the ability to subscribe to those state’s changes. Looks like Redux is a good option for the Business Layer + middleware as the Service Layer + MVP or MVVM or MVI patterns for the Presentation and UI layers with the Redux store playing the Model role. VIPER seems a bit excessive for just a few screens with minimum number of routes between them and RIBs is better suits very complex screens with many teams working on the same screen. Of course, you can choose any pattern or mention none of them, but then you would have to to explain where store/state should be placed, how it should work, how we would implement subscription for state changes, how services should be used and how they will update the state.&lt;/p&gt;

&lt;p&gt;I intentionally didn’t mention any concrete platform as it actually doesn’t matter if it’s Android or iOS as there are multiple implementations of Redux store and reactive frameworks for implementation of the MVVM/MVI for both platforms whereas MVP doesn’t need any.&lt;/p&gt;

&lt;p&gt;Let’s draw a possible structure scheme for the chat feature:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uO1P0ZhV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbk6nw6qndi6neioloa0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uO1P0ZhV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbk6nw6qndi6neioloa0.png" alt="Feature design schema" width="880" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here it’s important to describe how all the cycle of the data update would work, demonstrate the advantages of the pattern you have chosen and mention some tradeoffs and hard problems you would encounter during the implementation of this solution.&lt;/p&gt;

&lt;p&gt;For instance, we can enlist the following advantages of the chat feature’s Redux design using the previous dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: We fully decouple data receiving part (Data and Service Layer) and data consumer part (Presentation and UI Layer) using store with updates subscriptions, so it doesn’t matter from which source the data comes — from a persistent store or a network communication channel. It helps to change some parts of the app without impacting the others + reuse as much code as possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: The store could have multiple subscribers out of the box, so Presenter of our chat feature will be triggered and will pass the latest changes to View in order to display them + Presenter of the top panel, for instance, will be triggered as well and will update the counter of the unread messages. Adding one more subscriber is easy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt;: State is immutable and located in one place (not distributed across the app) which help to avoid many mistakes related to simultaneous changes of the state. Also it helps to test the app as you are sure that state can be changed only in reducers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployability&lt;/strong&gt; (and partly Maintainability): complex project structure and the tricky modularisation concept. In order to change something in the chat feature developers will have to make changes in many places — state, reducers, actions, middleware, Presenter, View. Moreover, all those places are spreader among the project (we can come up with a project structure that minimise this effect by uniting the most of the parts in one place but it could lead with the repeating code and problems with changing the other teams code) which makes modularisation a bit tricky. So every team will be most likely touching the store/state and it means rebuilding of all the modules as all the modules depend on the state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: the bigger become the application the bigger become the state. Usually we split it into sub-states so each feature has it’s own sub-state but anyway huge state could lead to performance and multithreaded access issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s worth mentioning that your pattern/approach/design is good for testing, for instance, in our example we can mention that we should test middleware, services, presenters and reducers and it’s very easy since they are stateless.&lt;/p&gt;

&lt;p&gt;Additionally, here you can demonstrate the skill of class diagrams designing. Specific implementation will depend on the platform (because, for instance, table rendering concepts are different in Android and iOS).&lt;/p&gt;

&lt;h3&gt;
  
  
  One complex case and detailed discussion  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;At this step you can show the knowledge of the platform and problem solving skill. It’s better to choose one interesting case that you met before and successfully resolved and softly lead the conversation to this case.&lt;br&gt;
For instance, you can say that it’s interesting problem of caching the images in the chats. Each image has direct link to it’s thumbnail and full size image and once image comes to the visible area of the screen it will be requested from, let’s say, an image download service which downloads image using those direct links. Weak point of such a solution is that if user has slow network connection images will appear too late, especially if user scrolls chat rather fast. Obviously we need a cache. The easiest solution is to add to the image download service a memory cache which represents the dictionary with keys as direct links and values as images but what will happen when we restart the app? All the text messages will be restored from the local DB (assume it) but should we save thumbnails and full size images in DB as well? Or should we save only thumbnails in DB and full size images in the file system? If we will save images in the filesystem how can we find them later on? How can we housekeep folder with images if for instance device, in case of iOS, asks to free some space up? There are a lot of questions and answering them could demonstrate your experience, knowledge of the platform and problem solving skills.&lt;/p&gt;

&lt;p&gt;So the trick here is to choose one common hard enough problem beforehand and lead the conversation to this problem. The interviewer can reject that and choose the random one, but still you will show that you aware of some problems and you would have a chance to talk a lot about the problem you know the best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary  &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Summarizing the above information I can say that it’s always better to elaborate a plan of the common system design interview beforehand, should it be like one I suggested in this article or another one. It doesn’t matter which plan you will chose but it should clearly demonstrate your ability to tackle a very big ambiguous problem — split it to some meaningful pieces, absorb them one by one, process that information and produce another type of relevant information as an outcome.&lt;/p&gt;

&lt;p&gt;Good luck at your interviews and don’t hesitate to write comments to this article or share your experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  References &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Layered architecture pattern: &lt;a href="https://towardsdatascience.com/software-architecture-patterns-98043af8028"&gt;https://towardsdatascience.com/software-architecture-patterns-98043af8028&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Architecture/systems quality attributes/dimensions: &lt;a href="https://sites.google.com/site/misresearch000/home/software-architecture-quality-attributes"&gt;https://sites.google.com/site/misresearch000/home/software-architecture-quality-attributes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;There are a lot of books about API Design, it does worth to read at least one&lt;/li&gt;
&lt;li&gt;Mobile Architecture patterns: MVC, MVP, MVVM, MVI, VIPER, REDUX, etc. It would be good to know about them and about the conceptions behind each of them even if you don’t want to mention any of them on the interview. It’s easy to find a lot of info about each of them.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>mobile</category>
      <category>ios</category>
      <category>interview</category>
    </item>
  </channel>
</rss>
