<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jorge Castro</title>
    <description>The latest articles on DEV Community by Jorge Castro (@keozdev).</description>
    <link>https://dev.to/keozdev</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%2F260791%2Ff7979832-d47c-4603-be99-04c45fea7238.jpeg</url>
      <title>DEV Community: Jorge Castro</title>
      <link>https://dev.to/keozdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/keozdev"/>
    <language>en</language>
    <item>
      <title>What I Stand for in 2023</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sun, 01 Jan 2023 21:33:59 +0000</pubDate>
      <link>https://dev.to/keozdev/what-i-stand-for-in-2023-3fff</link>
      <guid>https://dev.to/keozdev/what-i-stand-for-in-2023-3fff</guid>
      <description>&lt;p&gt;&lt;strong&gt;Sharing what I stand for in 2023.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Because I believe the only way we will make it through the current state of issues as humanity, is if more people stand by the right things, not because it is wrong not to, or want to change your mind, but because together, if we have shared concerns we may stand a chance.&lt;/p&gt;

&lt;p&gt;Call me “woke” if you wish, but at least I will try, sharing or putting some energy into a cause this year, even if the only thing I can give is sharing and some of my time or money. We have to put ourselves out there and be more vulnerable, I care more about the human behind a brand, and you should too, this is part of my identity.&lt;/p&gt;

&lt;p&gt;First and foremost, I &lt;a href="https://twitter.com/hashtag/StandWithUkraine"&gt;#StandWithUkraine&lt;/a&gt;. It is crucial that &lt;strong&gt;Ukraine win&lt;/strong&gt; against the invaders and terrorists occupying their land, it is a fight for freedom that humanity simply cannot afford to lose, if we lose, not only Russia, others will try to impose their will by holding others hostage enabled by their energy resources, and remain unaccountable for their actions, what kind of future is that? &lt;/p&gt;

&lt;p&gt;This leads me to my second stance, we need to develop or provide access to better &lt;strong&gt;energy technologies open to everyone&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;For this, I have been following the work from &lt;a href="https://twitter.com/DrStevenGreer"&gt;Dr. Steven Greer&lt;/a&gt;, as in his &lt;a href="https://twitter.com/DrStevenGreer/status/1604891839366152192"&gt;latest statements&lt;/a&gt; I think we are closer to having an open and accessible source of energy. A lot has to be done, but I don't know anyone else who seems committed to this and other humanity survival goals in the context of the rest of civilizations in the universe, which will take more and more importance, perhaps this year there is a breakthrough in this subject, and yes, I believe this is not science fiction, but the future of science as we know it.&lt;/p&gt;

&lt;p&gt;This will also immediately impact climate change crisis, there is no time left to waste, or we are closer to the point of no return.&lt;/p&gt;

&lt;p&gt;Third, COVID has become the ultimate threat to our quality of living, you simply do not need to catch a virus that causes potentially so much &lt;a href="https://twitter.com/HallwayOrchard/status/1601315839034023936"&gt;vascular damage&lt;/a&gt; and inflammation all over your body, and neither be disabled from long covid: &lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;
    &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__two-pics"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HVxGL7Nm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/FmX0o1jaMAAJTgd.jpg" alt="unknown tweet media content"&gt;
    &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--iEWi-0MO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1589325138960318464/2OwvQAWC_normal.jpg" alt="Eric Topol profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Eric Topol
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @erictopol
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Our comprehensive review of &lt;a href="https://twitter.com/hashtag/LongCovid"&gt;#LongCovid&lt;/a&gt; has just been published&lt;br&gt;&lt;a href="https://t.co/EgO7gtFvoe"&gt;nature.com/articles/s4157…&lt;/a&gt;&lt;br&gt;Phenomenal work by &lt;a href="https://twitter.com/ahandvanish"&gt;@ahandvanish&lt;/a&gt; &lt;a href="https://twitter.com/LisaAMcCorkell"&gt;@LisaAMcCorkell&lt;/a&gt; &lt;a href="https://twitter.com/juliamv"&gt;@juliamv&lt;/a&gt; &lt;br&gt;&lt;a href="https://twitter.com/NatureRevMicro"&gt;@NatureRevMicro&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      18:26 PM - 13 Jan 2023
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1613965639609372673" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1613965639609372673" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1613965639609372673" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Plenty of scientific evidence has given us the tools to fight it, spread is not unstoppable, is freaking physics and evidence-based science, just facts. Our tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/joeyfox85/status/1553901870774640640"&gt;Air Quality indoors&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/jeffgilchrist/status/1602994049815908353"&gt;Proper masking&lt;/a&gt; oh and WHO also &lt;a href="https://www.who.int/news/item/13-01-2023-who-updates-covid-19-guidelines-on-masks--treatments-and-patient-care"&gt;recommends masks&lt;/a&gt; go figure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/jljcolorado/status/1601078099071815685"&gt;Germicidal UV&lt;/a&gt; / &lt;a href="https://twitter.com/joeyfox85/status/1608674677177880581"&gt;Far-UV&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vaccinations and common sense&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thereby &lt;strong&gt;I stand for eradicating the virus spread&lt;/strong&gt;, every action counts, specially spreading the knowledge societies terribly lack of thanks to governments agendas and weak journalism.&lt;/p&gt;

&lt;p&gt;We start the year as 2020 started, restricting flights from China in places and pretending the virus has magically vanished with wishful thinking, as if we knew nothing of how the virus spreads, after 3 years, mind-boggling to say the least, but misinformation is people in power's agenda.&lt;/p&gt;

&lt;p&gt;I hope we don't repeat the same mistakes, but the situation calls for a better organized society to act, it is our health, any government will try to save face first before admitting mistakes on handling the pandemic. Another fight we cannot afford to lose, and we are.&lt;/p&gt;

&lt;p&gt;More on how to stop the spread &lt;a href="https://twitter.com/PeteUK7/status/1589096183515185152"&gt;here&lt;/a&gt; and &lt;a href="https://twitter.com/joeyfox85/status/1554939526560333825"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, &lt;strong&gt;I stand for a plant-based diet&lt;/strong&gt;, it is the best way we can take care and protect our bodies against disease or at least getting less sick and protect your brain too!&lt;/p&gt;

&lt;p&gt;Follow &lt;a href="https://twitter.com/nutrition_facts"&gt;NutritionFacts&lt;/a&gt; from Dr. Michael Greger author of “How not to die” book series, a great pool of resources for a plant-based diet following the science and evidence.&lt;br&gt;
Follow &lt;a href="https://www.instagram.com/thebraindocs/"&gt;TheBrainDocs&lt;/a&gt; for great information on nutrition focused on brain health, which of course impacts directly overall body health.&lt;/p&gt;

&lt;p&gt;By having a healthy diet, you may improve your immune system for easier recovery from Covid or avoid underlying conditions that could aggravate your health. Furthermore, reduces your carbon footprint, is the least you can do to do your part about the climate crisis.&lt;/p&gt;

&lt;p&gt;Perhaps I should change my blog to another site or create my own to share this, we will see. But I also know that even if we are technical people in this community, we should be aware and have some convictions in life, is not just politics, it is about being a human that cares for others and where you live and how you live.&lt;/p&gt;

</description>
      <category>2023</category>
    </item>
    <item>
      <title>[WIP] The unique journey from .NET mobile (Xamarin) to Kotlin / KMM</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Mon, 05 Sep 2022 18:51:01 +0000</pubDate>
      <link>https://dev.to/keozdev/wip-the-unique-journey-from-net-mobile-xamarin-to-kotlin-kmp-4865</link>
      <guid>https://dev.to/keozdev/wip-the-unique-journey-from-net-mobile-xamarin-to-kotlin-kmp-4865</guid>
      <description>&lt;p&gt;This is a work in progress…&lt;/p&gt;

&lt;p&gt;…and just like life, change is essential to improve, in my work life, I have taken the decision to transition from .NET as a mobile platform to the remarkable and ever surprising Kotlin ecosystem.&lt;/p&gt;

&lt;p&gt;This is my journey of discovery, this is my story, I will make the best out of this so is something worth sharing, hope you enjoy it as much as I'm enjoying it.&lt;/p&gt;

&lt;h1&gt;
  
  
  How it all started
&lt;/h1&gt;

&lt;p&gt;I have been working most of my career as a .NET Developer, and as of this writing, I have accumulated 14 years of experience to be precise, perhaps not so challenging experience I'd say, but good to be competitive with .NET.&lt;/p&gt;

&lt;p&gt;In retrospective, that is a lot, and I have written mostly consumer-facing apps for desktop, web, and mobile platforms most recently, and some server backend apps as well.&lt;br&gt;
Perhaps not a super spiced experience, mostly aligned to everyday coding and applications not too large to face scalability challenges. &lt;/p&gt;

&lt;p&gt;But I have always tried to improve upon my previous solutions with an improved on the next time I find similar problems. Not often I write two similar pieces of software with the same code, I always think how things can be improved from what I have done before.&lt;/p&gt;

&lt;p&gt;This challenges me to find better ways of coding. Some of those better ways of doing things has led me to learn, for example, the principles in the Pragmatic Programmer book which is a must-read for every developer, and the Reactive and Functional paradigms, still with C# which is object-oriented, but I have tried to squeeze as much as possible out of it.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Discovery
&lt;/h1&gt;

&lt;p&gt;I found myself in a position where I entered a team where Xamarin native was being used for writing apps. Later on, after some time, I was presented with the current state of the art in native Android development thanks to a colleague.&lt;/p&gt;

&lt;p&gt;To my surprise (because I was quite off touch with the pure native ecosystem) a lot has improved and went into, if I can summarize it, into the reactive paradigm, just different flavors of it. &lt;/p&gt;

&lt;p&gt;Later also discovered that web development has been all over it and functional programming since React.js was conceived, which also blew my mind, for reference, look at Honeypots's &lt;a href="//youtube.com/watch?v=8pDqJVdNa44"&gt;documentary on React.js&lt;/a&gt; and go down the rabbit hole a bit.&lt;/p&gt;

&lt;p&gt;In any case, a trend I discovered was obvious. In .NET community, Rx and functional programming has been always an afterthought, something few developers, in proportion, ever adopt or put in practice, even though Rx.net was one of the first libraries created to adopt the reactive paradigm, and Java/JS followed after and other platforms.&lt;/p&gt;

&lt;p&gt;I always find it challenging, and I believe other reactive practitioners find it too, to introduce this paradigm to other developers in the same .NET ecosystem, it shouldn't be, even today is something you have to deal with.&lt;/p&gt;

&lt;p&gt;So, I have been studying how Kotlin's Flow and Coroutines have evolved Rx to levels .NET can only dream of now, .NET folks and leadership have abandoned Rx, and instead we get things like IAsyncEnumerable or INPC that is the same old paradigms plus wrappers of the same old we have had since decades now. As much as I love ReactiveUI for example, it is also wrappers around the same old bindings and commands paradigms.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Learnings
&lt;/h1&gt;

&lt;p&gt;What follows is just a bunch of learnings I have encountered in this journey, so beware, it may be gibberish and nonsense, but is my evolving understanding of the technologies involved matching with my experience. I don't mind being corrected, even better, just be mindful this is a real-time prediction of things I learn that may change for the most part.&lt;/p&gt;

&lt;h2&gt;
  
  
  KMP and friends
&lt;/h2&gt;

&lt;h3&gt;
  
  
  View Model and State
&lt;/h3&gt;

&lt;p&gt;I have been digging into how KMP or KMM for that matter, shares state and view models to iOS. Considering that Android uses the native Flow and friends to compose UI state, I have found that in iOS you can use Combine framework, which is yet another Rx flavor for Swift.&lt;/p&gt;

&lt;p&gt;So, this way in Swift UI you can basically wrap Flows into Publishers and Subscribe to state change, very similar to how you would do it with LiveData, and then you can also "dispose" the subscription and clear the Coroutine scope coming from Kotlin when the view is gone.&lt;/p&gt;

&lt;p&gt;I know this and was very easy to identify because I happened to participate in an internal port of LiveData to Xamarin using Rx.net at my job, which turned out to be phenomenal to ditch MVVMCross Bindings and use UDF to manage our state. Hopefully, we would be able to open source it some day, at least for historical purposes, is a good way to document the transition that no one in .NET community has figured out from classic state management to UDF, again born 10+ years ago in React.js, and is still, the way to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  KotlinConf 2023
&lt;/h2&gt;

&lt;p&gt;I was highly anticipating this conference, and now I could attend my first KotlinConf, this was for me a way to commit to transition from being a .NET Developer to a Kotlin developer if all went well, and it has!&lt;/p&gt;

&lt;p&gt;These are some of the insights I gained from attending KotlinConf in April. This is from the perspective of evaluating the technology, and focuses on the aspects that we may be most interested in as .NET developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Regarding the future of Kotlin
&lt;/h3&gt;

&lt;p&gt;From the keynote, we can grasp what are the focus areas for the JetBrains team for the development of Kotlin and its sustainable future.&lt;/p&gt;

&lt;p&gt;In a nutshell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Expanding the reach of Kotlin Foundation, intended to secure the future development of Kotlin, where many groups are supporting and securing the continuation of its development, including Google, Gradle, Shopify and TouchLab. Also assisting library authors with grants, focusing on expanding multiplatform reach and sustainable development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It shows a clear direction of Kotlin to become the language running on top of every platform, massive focus on Multiplatform, Compose Multiplatform and WebAssembly integration as the driving technologies of Kotlin ecosystem going forward, this creates a better environment to improve tooling for mobile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Focus on tooling for developers, as always has been from JetBrains, and K2 compiler will enable faster and better features and tooling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The stable label to KMP will be added this year, but is production ready and already used by many large organizations, this is to focus on better developer experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Over 23% of the top 1k Android apps use Jetpack Compose, which is more than double the number from last year. 95% of the top 1k apps use Kotlin.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essential to watch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=c4f4SCEYA5Q"&gt;Video: KotlinConf 2023 Keynote&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Summary blog post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.jetbrains.com/kotlin/2023/04/kotlinconf-2023-opening-keynote/"&gt;KotlinConf 2023: A look at the Opening Keynote&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Regarding the present of Kotlin
&lt;/h3&gt;

&lt;p&gt;Kotlin Native is a consolidated multi-platform technology that has been constantly improving since 2018 when it started to mature. Currently, there are many companies who demonstrated Kotlin Multiplatform Mobile (KMM) maturity by implementing their solutions using this tech, many seen at the conference like CashApp, MeetUp, Google (Workspace apps), TouchLab, Xebia and Umain (McDonalds app) sharing their experience working in production with the technology. Some other case studies, including Netflix case, can be found here &lt;a href="https://kotlinlang.org/lp/mobile/case-studies/"&gt;https://kotlinlang.org/lp/mobile/case-studies/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably the most important presentation regarding the adoption of KMM as a platform for mobile dev is the following. And even though there is a lot of information regarding how real-world teams work, we can get a gist of what it takes to put a KMM workflow into production and what to consider for each kind of workflow. This is from the experience of a team helping put projects in production since the conception of KMM:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/-tJvCOfJesk?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;KotlinConf Video: Kotlin Multiplatform Mobile for Teams&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are the key aspects to consider when adopting Kotlin right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As a native-first technology, KMM requires expertise in at least one of the target platforms, which is often referred to as a “three-platform tech”. To leverage the technology fully, it is important to have a good understanding of native Android and Compose, as well as a good understanding of iOS and Swift (including SwiftUI) and the Kotlin features that facilitate code sharing across platforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We have to consider what workflow would work best. Given that the nature of .NET/Xamarin teams in general is that we all contribute to both platforms and shared code, perhaps the Workflow Mode 2 or Shared Architecture approach (as mentioned in the linked talk above) is not limiting as we all would contribute to the Kotlin core library in some capacity. Mode 1 as a Shared Module with an exposed framework could also work with dedicated iOS developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are some limitations in tooling subject to improvements, for example considerations in generic interfaces, async cancellation, and enumerations translated to iOS through Obj-C, and tooling to enable more integrated workflows instead of framework based workflows. There are workarounds and community solutions already in use, things will improve with Swift interop and SPM investments this year by JetBrains.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While there is an ever-increasing set of libraries targeting KMP as stated in the Keynote (check also &lt;a href="https://github.com/terrakok/kmm-awesome"&gt;https://github.com/terrakok/kmm-awesome&lt;/a&gt;), we have to consider there may be some differences with Android libraries, like instead of Retrofit, we may use Ktorfit, instead of Dagger/Hilt we may use Kotlin-inject, and so on, however is built on top of the stability of the KMP approach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The so-called “Reactive Interop” has some natural walls due to the fact we cannot translate asynchronous and concurrent approaches from Kotlin (Coroutines and Flow) to Swift directly (Tasks/Actors/Async and Combine) in the output end or consuming part of these APIs, like UI State where we should consider some wrappers. The hardest mapping setbacks have already been resolved either by community, tooling and broad documentation. In Android, everything in the standard Kotlin works, so no need for a wrapper, but is constantly evolving and is essential to understand how the building blocks work in Kotlin and in Swift and be aware of the new developments as they come. The technology is only going to get more accessible and improve, but not going to solve all problems, we have to still deal with Swift for UI at least.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UI sharing through Compose is still in development, but it can be leveraged now in a progressive and optional manner. It's worth considering that this approach may very well be the future of UI, not just in Kotlin, but across other languages as well. The language, approach, and tooling all matter, and it’s clear this ecosystem is fully committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The approach for KMM is different from other technologies. Optional add-ons building blocks to native-based development, from little code sharing to full UI sharing, Kotlin Multiplatform is designed for this kind of flexibility. It is not an all-in solution like Flutter, Maui or React-Native, we choose what to share, and we can always have the flexibility to fall back to fully native solutions in a much more frictionless fashion with full API availability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The more code we share for iOS like use cases, view models and state management, the less we would encounter Obj-C interop limitations, we can get to an 80/20 shared architecture / not shared + ui code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Other relevant presentations
&lt;/h4&gt;

&lt;p&gt;This is a curated list around KMM topic from the KotlinConf playlist, great content if you are eager to learn more. Full list here: &lt;a href="https://www.youtube.com/playlist?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;https://www.youtube.com/playlist?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/FWVi4aV36d8?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Compose Multiplatform for iOS&lt;/a&gt; - Great demo of Compose for iOS showing an image gallery with camera and map support! &lt;a href="https://github.com/JetBrains/compose-multiplatform/tree/master/examples/imageviewer"&gt;https://github.com/JetBrains/compose-multiplatform/tree/master/examples/imageviewer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/zDRlEp7r5i0?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Scale McDonald's with KMM&lt;/a&gt; - Interesting talk on implementing KMM at scale within a large consumer-facing app for over 60 markets globally!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/VtFam_D1USw?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Meetup with KMM Libraries&lt;/a&gt; - KMM at Meetup for Organizers app&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/uATlWUBSx8Q?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Confetti: building a Kotlin Multiplatform conference app in 40min&lt;/a&gt; - A fun ride with live coding an app using a GraphQL API and KMM&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/j-zEAMcMcjA?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Kotlin/Multiplatform for iOS developers : state &amp;amp; future&lt;/a&gt; - Implementing KMM from the perspective of introducing it to iOS developers and how to make their lives easier, limitations and recommendations of tools and practices&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/EKFdYgjCNOs?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Level up on Kotlin Multiplatform&lt;/a&gt; - Nice talk giving a broad overview on libraries and techniques applicable when using KMM&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/PbwFtqmbMuI?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Kotlin Multiplatform Conversions at Android Jetpack Scale&lt;/a&gt; - Case study of the experience converting some of the Jetpack libraries to Multiplatform&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/C9gCm51RhsU?list=PLlFc5cFwUnmwcJ7ZXyMmS70A9QFyUu1HI"&gt;Kotlin Multiplatform in Google Workspace&lt;/a&gt; - How Google is starting to leverage KMP to replace old tooling and share logic in Workspace apps&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=tplA17M9Y4Q"&gt;Arrow Trajectory&lt;/a&gt; - This shows how a community project is driven with such a great commitment and focus in this ecosystem. Because Kotlin allows and encourages a great functional development experience, the community has created this project to become the standard to enable better functional programming capabilities to Kotlin. This video shows Arrow history and future. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=tYcqn48SMT8"&gt;KotlinConf 2019 Asynchronous Data Streams with Kotlin Flow&lt;/a&gt; - This is an old one but was very relevant to me, showing the great investment in elevating the reactive and asynchronous paradigms in Kotlin when they introduced cold streams (Flow) and comparing it to classic Rx, something you don’t see at this level in .NET&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaways for the adoption of Kotlin Multiplatform
&lt;/h3&gt;

&lt;p&gt;Based on the facts above and having followed, studied and tried the platform for the latest few months from the perspective of a .NET Developer. I can conclude that Kotlin together with KMM is a proven technology to build cross-platform applications, the key differentiator is the approach as stated above, native first.&lt;/p&gt;

&lt;p&gt;Kotlin, as a language and platform, has quickly evolved into a pragmatic, declarative, and expressive language, takes some established practices and elevates them or balances them to integrate into the overall ecosystem very well. From day one, the developers have emphasized and elevated asynchronous, reactive, and functional paradigms in ways that cannot be found in the .NET ecosystem. This is because .NET's efforts are isolated and fragmented, or simply slow to improve due to neglect and lack of leadership, especially for native mobile development. As a .NET developer who has evaluated both approaches, it is a fact that Kotlin and its ecosystem has it all and the risks of adoption are very low.&lt;/p&gt;

&lt;p&gt;But it requires time and investment, specially if we aim to rewrite anything, I think the ROI is much higher than the expenses in the long term.&lt;/p&gt;

&lt;p&gt;[WIP]&lt;/p&gt;

</description>
      <category>xamarin</category>
      <category>xamarinforms</category>
      <category>kotlin</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Parte 4: La salida</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sun, 08 Aug 2021 19:02:16 +0000</pubDate>
      <link>https://dev.to/keozdev/parte-4-la-salida-4l0</link>
      <guid>https://dev.to/keozdev/parte-4-la-salida-4l0</guid>
      <description>&lt;h2&gt;
  
  
  El comienzo de una salida 🚪
&lt;/h2&gt;

&lt;p&gt;Entonces, qué hacer, ante esta situación de, francamente, esclavitud moderna, que se disfraza de empleo legal, y vaya que es apenas legal dadas las condiciones laborales. &lt;/p&gt;

&lt;p&gt;La realidad para muchos, es peor de la que te imaginas y si tu situación es similar o mejor has tenido "suerte", he leído casos donde la visa TN y otros tipos de visa se usa para literalmente esclavizar a personas que, por necesidad aceptan desde malos tratos hasta ser engañados en las actividades que les han dicho iban a hacer en su trabajo, personas que han sufrido amenazas y atentan contra sus derechos básicos. No creo que pase mucho en trabajo relacionado con tecnología, pero no es para nada ideal como ya te habrás dado cuenta.&lt;/p&gt;

&lt;p&gt;Hay una organización que lucha por los derechos de los trabajadores inmigrantes especialmente con los más desfavorecidos: &lt;a href="https://cdmigrante.org/"&gt;Centro de los Derechos del Migrante&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Realmente no sé de otras, pero debería haber más &lt;em&gt;awareness&lt;/em&gt; de este tipo de abusos, USCIS debería tener más facultades para abogar más por los derechos de los trabajadores visados, de la misma forma que EUA si pone presión sobre las condiciones de trabajo en empresas americanas con operación en México bajo el USMCA, desde mi punto de vista, no es tan importante para las autoridades americanas si no es tampoco visible para las autoridades mexicanas. En todo momento debe ser prioridad que las condiciones laborales sean las mejores posibles en los dos países. Aquí algo de como desde EUA se pide a México haga cumplir los acuerdos laborales: &lt;a href="https://www.bloomberg.com/news/articles/2021-05-12/u-s-asks-mexico-to-probe-gm-labor-rights-in-trade-pact-first"&gt;https://www.bloomberg.com/news/articles/2021-05-12/u-s-asks-mexico-to-probe-gm-labor-rights-in-trade-pact-first&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No he visto que desde México se haga mucho por los trabajadores mexicanos en EUA.&lt;/p&gt;

&lt;p&gt;En fin, una de las cosas que puedes empezar a hacer para evitar caer en alguna red de explotación es muy sencillo. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Busca tus propios proyectos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si, en LinkedIn, o en tu sitio de búsqueda de empleo favorito, ellos lo que hacen es algo muy similar, tienen redes con otras empresas que buscan recursos, estos son los 4th party, lo que también se llevan una rebanada de tu pastel como mencione en la Parte 3.&lt;/p&gt;

&lt;p&gt;Son los que simplemente hacen &lt;em&gt;staffing,&lt;/em&gt; o lo que es lo mismo, re-venta de recursos, reclutamiento que pudieran hacer directamente los clientes finales, sin embargo supongo tienen desinterés y mucha ignorancia sobre el tema, es verdaderamente absurdo que paguen a terceros cuando la mayoría de la gente es alcanzable, si no en LinkedIn, de otras formas &lt;em&gt;peer to peer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Así pues, tú puedes buscar una oferta interesante, contactarlos y preguntar algo sencillo y esencial: &lt;em&gt;¿Contratas Corp to Corp? (C2C)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A lo que responderán, si, o no. Muchas veces el No, es porque no son empresas que simplemente busquen re-vender, porque que son la alta gama de los staffers, ofreciendo una cierta "garantía" a los clientes finales o son consultorías que no se arriesgan al C2C porque pueden involucrarse con una empresa con prácticas no confiables o volátiles. &lt;/p&gt;

&lt;p&gt;El Quality of Service a los clientes finales es algo que es oro y no van a arriesgar su reputación por una relación C2C improvisada a menos que la posición sea urgente, claro que para tu sponsor lo esencial es que cumplas con el staffer porque es su "cliente" directo.&lt;/p&gt;

&lt;p&gt;Cuidado, no debes dar muchos detalles como tu salario actual o muchos detalles de tu sponsor, puede arruinar esa oportunidad.&lt;/p&gt;

&lt;p&gt;Cuando dicen que si trabajan C2C, bueno estás de suerte, les envías el contacto de tu sponsor y listo ellos se arreglan, tú no necesitas dar más detalles, ellos pedirán una entrevista contigo a través de ellos, a tu empleador solo diles que ellos te encontraron de alguna forma, tendrán los datos de algún lado. &lt;/p&gt;

&lt;p&gt;Aquí pongo un paréntesis, generalmente estos sponsors cuentan con que sus empleados no tengan contacto con otras empresas, obviamente porque es fácil ofrecerte trabajar para externos y que dejes de trabajar para el sponsor, porque no es tan difícil encontrar otras empresas que hagan sponsor en LinkedIn, de esto hablo más adelante, y generalmente son staffers, consultorías o empresas que tienen sus propios clientes aunque son menos. Al principio puede ser algo intimidante estas políticas y accedas a cosas absurdas como eliminar o poner privado tu perfil de LinkedIn, sí, son capaces. Puedes acceder en un principio por cordialidad, o miedo de perder el empleo, no lo hagas a largo plazo, por mi parte nunca lo hice, nunca fue algo que estuviera en el contrato, pero nadie tiene el derecho de forzarte a hacerlo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Mantén tu LinkedIn actualizado con los últimos proyectos en los que has estado, no menciones a tu sponsor, tu perfil es más atractivo conforme acumules experiencia en EUA.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Siguiendo con este tema, una vez que la negociación continua con el C2C, es posible que tu empleador también quiera ofrecerles alguien más barato y no a ti, al final a esta gente les conviene colocar a gente con menos experiencia con el mismo precio, esperaría que casi nunca lo logran, menos en tech, cuando pidan tu nombre, van a tener que darles tu información, véndete bien, ten un perfil atractivo para que no se vayan con cualquiera y paguen el extra de tener que ir C2C. Sobre todo, no pierdas contacto con el staffer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Dale seguimiento a las oportunidades que encuentras por tu cuenta&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Generalmente el staffer, cuando ya todo está bien y acepten las condiciones de tu sponsor, van a organizar una entrevista con alguien del cliente, o de la consultoría que trabaja para el cliente, o ambos (recuerda ya son 4 niveles involucrados incluyéndote) que te hará una o varias entrevistas, tu sponsor pasa mucho a segundo plano, ni los menciones, nunca han sido relevantes, solo enfócate en tu experiencia real.&lt;/p&gt;

&lt;p&gt;Tu sponsor, generalmente siempre permanecerá en la obscuridad, en el anonimato ante el cliente, ellos solo harán negocio con el staffer o la consultoría, y contigo, y harán todo para que no te intentes, digamos, pasar de listo.&lt;/p&gt;

&lt;p&gt;Si todo va bien, y haces match con el cliente final, te contrataran, recuerda que ellos estarán pagando bastante más de lo que tú estás recibiendo, sus expectativas sí, serán un poco más altas, pero si lo haces bien puedes estar en una posición favorable, hazte imprescindible aunque siempre lo seas y empezaras a tener una cierta estabilidad.&lt;/p&gt;

&lt;p&gt;Al final, tú elegiste esta oferta 😉 y eso trabajará a tu favor. &lt;/p&gt;

&lt;p&gt;Hasta el momento, esto es una opción viable si quieres mantener a tu empleador original y tener las mismas condiciones, es una opción de trabajo, segura hasta cierto punto, pero no tiene ningún crecimiento, si eres como yo, querrás buscar opciones mejores, y moverte hacia algo más estable y con mejores condiciones en todo sentido, te comento algunas.&lt;/p&gt;

&lt;h3&gt;
  
  
  #️⃣ Opción A - Busca ser contratado por el cliente
&lt;/h3&gt;

&lt;p&gt;Cada vez que te asignan a un cliente te pueden pedir que firmes un &lt;em&gt;non-compete agreement,&lt;/em&gt; esto esta ok, pero no aceptes condiciones descabelladas como no poder ser contratado hasta después de dos años por el cliente, de hecho una de las cosas que debes saber de tu empleador, es que si se presenta la oportunidad, si es negociable te liberen de tu contrato para ser contratado directamente por esa empresa, aunque es muy poco probable que tengan esa apertura. &lt;/p&gt;

&lt;p&gt;De cualquier forma, es mejor no te enganches con el cliente pues puede ser contraproducente, es mejor buscar esas oportunidades fuera del ecosistema de tu empleador.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Nunca dejes de buscar oportunidades de contrato directo por tu cuenta&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pero es una opción que no debes descartar, es la salida fácil, pero también depende que tanto te quiera ese cliente y lo que esté dispuesto a hacer por ti, incluso de enfrentar un proceso legal, que en realidad es solo sobre dinero, para poder contratarte directamente, porque claro ellos también tienen sus non-compete agreement con los staffers / consultorías, los cuales pueden ser más flexibles en este aspecto.&lt;/p&gt;

&lt;p&gt;Esta opción no aplica muy bien para ser contratado por los staffers, les conviene más mover gente rápidamente que comprometerse en un proceso contigo y de largo plazo.&lt;/p&gt;

&lt;h3&gt;
  
  
  #️⃣ Opción B - Busca empresas que te hagan sponsorship
&lt;/h3&gt;

&lt;p&gt;No solamente puedes buscar otras empresas que trabajen C2C con tu sponsor, que son las que generalmente postean trabajos en LinkedIn, en representación de algún cliente.&lt;/p&gt;

&lt;p&gt;Lo que puedes hacer es buscar entre las vacantes a clientes que puedan hacerte el sponsor de la visa, tienes que hacer un proceso totalmente aparte con ellos desde cero, pero al estar en EUA, no tendrías que salir ni hacer un proceso con las entrevistas, porque estarías haciendo un proceso de cambio de empleado, la visa y el permiso ya lo tienes, pero no puedes trabajar para otra empresa sin que te apruebe USCIS. Claro que si sales de EUA tendrías que hacer el proceso igual que al inicio como te lo explique en la Parte 1.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Busca oportunidades más allá de los staffers&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es un poco difícil encontrarlos, pero es cuestión de estar picando piedra constantemente. No tienen que ser empresas muy establecidas, hay más de lo que parece y tienen capacidad para buscar talento por su cuenta y para hacer un proceso de sponsor. Tienes que preguntar.&lt;/p&gt;

&lt;p&gt;Es posible también que no estén familiarizados con la Visa TN, o ninguna visa, pero que estén abiertos a que sea una posibilidad. Ofrece que busquen un abogado especializado en migración, aunque el proceso es sencillo es mejor que alguien con experiencia los guie sobre todo porque es algo que depende más de como lo ejecute la empresa que de ti.&lt;/p&gt;

&lt;p&gt;Hay quienes solo están familiarizados con la Visa H1B, pues es la más común para extranjeros, y entonces ya tienen gente dedicada a llevar procesos de visas. Lo cual puede ser mejor porque es más común que te ofrezcan un camino hacia residencia, pero la H1B lleva tiempo, les conviene también que los ayudes con el proceso de Visa TN primero para que mientras estas con TN puedan iniciar el trámite con H1B que es un paso más hacia la green card.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Busca que te ofrezcan siempre un camino a residencia permanente&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No dudo que haya empresas que también quieran abusar de esperanzar a empleados de llevarlos hacia la residencia, eso es muy común con los sponsors, ellos nunca lo harán, pero es más factible que un cliente con una reputación respetable si lo haga. Siempre puedes seguir buscando opciones y estar más cerca si tu objetivo es llegar a la residencia, que debería serlo porque solo así podrás decidir tú con quien trabajas en plena libertad. Y es la única forma de algún día hacerte ciudadano, si te convence la vida en EUA 🙂&lt;/p&gt;

&lt;h3&gt;
  
  
  #️⃣ Opción C - Hay un mundo allá afuera
&lt;/h3&gt;

&lt;p&gt;Finalmente, no te cierres a quedarte en EUA, tampoco a resignarte a volver a México. Existen muchas posibilidades en otros ecosistemas muy atractivos y con incluso mejores condiciones que EUA.&lt;/p&gt;

&lt;p&gt;Últimamente, Canadá se está haciendo uno de los destinos de profesionales Mexicanos más demandado, con excelentes condiciones para desarrollar tu carrera y ser parte de esa sociedad. Solo es cuestión de que te sigas preparando, buscar oportunidades y seguir creciendo tu red de contactos.&lt;/p&gt;

&lt;p&gt;Tu experiencia en EUA, es una ventaja extraordinariamente importante para abrirte las puertas a otros países y un mundo de ofertas de trabajo.&lt;/p&gt;

&lt;p&gt;En mi experiencia personal, yo estaba buscando primero la Opción B. Tenía algunos prospectos de hecho que me podían hacer sponsor de visa TN y visa H1B, uno de ellos no tanto en el área de mi especialidad, pero seguía siendo tecnología y al ser directo pues no había nada que perder, que por cierto, fue a través de un contacto que después del proyecto en el que era mi manager, siguió contactándome cuando ya estaba en otra empresa buscando recursos, así que super importante que tu reputación siga siendo referencia después de los clientes que te asignan y mantener a los contactos en tu agenda.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Hazte alcanzable siempre a tus colaboradores del pasado, los que valen la pena, claro.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Y para cuando estábamos listos para negociar un inicio y poder renunciar con mi sponsor, surgió otra oportunidad que al final de cuentas me hizo dejar la del contacto que tenía y permanecer en EUA.&lt;/p&gt;

&lt;p&gt;Esta oportunidad fue de nada menos que de Dinamarca, la verdad no tenía muchas expectativas, pero fue creciendo la posibilidad de que me contrataran, es algo de lo que ya contaré más cuando termine estas series seguramente :) &lt;/p&gt;

&lt;p&gt;El punto es que como verás, el mundo se abre conforme vas ganando experiencia aunque tengas la limitadísima visa TN, si no te conformas, crecerán tus herramientas para poder llegar al siguiente nivel, y poder encontrar la oportunidad que estabas esperando.&lt;/p&gt;

&lt;p&gt;Con esto concluyo esta Parte 4, a fin de prólogo voy a escribir un poco más en una parte final sobre la forma de vida en EUA y cosas generales para tomar en cuenta en tu vida diaria. ¡Hasta la próxima!&lt;/p&gt;

&lt;p&gt;Recuerda unirte a &lt;a href="https://www.facebook.com/groups/238451871803891"&gt;Mexpats&lt;/a&gt;, un grupo de Facebook donde podrás compartir experiencias y conectar con otras personas que también hayan vivido la experiencia de vivir en otro país o que están interesados.&lt;/p&gt;

</description>
      <category>visatn</category>
      <category>eua</category>
      <category>mexico</category>
      <category>immigration</category>
    </item>
    <item>
      <title>Parte 3: El trabajo</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sun, 20 Jun 2021 19:50:20 +0000</pubDate>
      <link>https://dev.to/keozdev/parte-3-el-trabajo-21bl</link>
      <guid>https://dev.to/keozdev/parte-3-el-trabajo-21bl</guid>
      <description>&lt;p&gt;Esta es la tercera parte de mi serie de blogs donde publico mi experiencia en EUA con la Visa TN, si quieres interactuar con otros expats que han vivido esta experiencia o que están interesados en hacerlo únete a nuestro grupo en Facebook &lt;a href="https://www.facebook.com/groups/238451871803891"&gt;Mexpats&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ahora sí, a trabajar, pero...
&lt;/h2&gt;

&lt;p&gt;No te podría decir que mi experiencia fue como lo esperaba, mi error fue no haber manejado mis expectativas correctamente.&lt;/p&gt;

&lt;p&gt;En esencia, yo esperaba que mi trabajo fuera similar al que tenía en México, una consultoría con diversos clientes, al menos eso parecen describir estos empleadores en sus cartas dirigidas a los cónsules de la embajada.&lt;/p&gt;

&lt;p&gt;Si podía esperar que tuviera que ir al lugar donde estuviera el cliente, pero no estaba preparado para la modalidad de trabajo con la que operan este tipo de empresas que a mi parecer son "barely legal".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Haz tu investigación de la forma en la que trabaja tu empleador&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Evitarás sorpresas desagradables si sabes a lo que vas, aun así, es manejable, solo debes estar preparado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Forma de trabajo
&lt;/h3&gt;

&lt;p&gt;Lo que quiero decir, es que no es cómo se venden, la empresa no tiene absolutamente ningún cliente, si como lo lees, lo único que hacen es conectarte con clientes "potenciales" con los que puedes o no trabajar, de que depende, de tu entrevista con ese cliente.&lt;/p&gt;

&lt;p&gt;Básicamente venden tus servicios aunque se escuche feo. Vaya ni siquiera son reclutadores contratados por los clientes, nunca supe exactamente como ellos encontraban las entrevistas, creo también tienen una red de similares o peers que les pasan contactos, pero es tan fácil como ir a la publicación de una oferta (de un verdadero reclutador) y preguntar si aceptan trabajar C2C (Corp to Corp).&lt;/p&gt;

&lt;p&gt;El C2C, es simplemente una subcontratación, no te contratan a ti, pero a la empresa y ellos firman el contrato, tú solo tienes que pasar la entrevista con el cliente final, tú ya estás contratado por quién te trajo, tu sponsor.&lt;/p&gt;

&lt;p&gt;Entonces si este es tu caso, tenemos que a ti te contrata el sponsor, al sponsor lo contrata un reclutador, al reclutador muchas veces lo contrata una consultoría o fábrica de software, y a este último lo contrata el cliente final. 🤷‍♂️&lt;/p&gt;

&lt;h3&gt;
  
  
  El reparto de tu sueldo
&lt;/h3&gt;

&lt;p&gt;Así de absurdo como se oye, en 3 o 4 porciones se reparte el pastel del cliente, lo que debiera ser un sueldo pagado directamente a ti se reparte entre todos estos digamos clases de &lt;em&gt;parásitos&lt;/em&gt; de este sistema que se abusa demasiado. &lt;/p&gt;

&lt;p&gt;Porque claro, el cliente paga tu valor completo, pero a ti te toca un 50% de eso si bien te va, muchas veces va a ser menor, por eso es importante negociar bien el sueldo inicial.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Negocia tu sueldo inicial de USD $60,000 anuales o más&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esto es un sueldo promedio, hay mucha gente que sobrevive con mucho menos que eso, pero tú debes valorar tu trabajo, los sueldos de ingeniería son fácilmente mínimo USD $80,000 para residentes o ciudadanos que van iniciando y llegan hasta $150,000 o más dependiendo si es management o posiciones senior.&lt;/p&gt;

&lt;p&gt;Es importante que también en tu contrato especifique cuando y de cuanto van a ser tus aumentos de sueldo, generalmente es 10% cada año, pero si puedes negociar más mejor.&lt;/p&gt;

&lt;p&gt;Todos los sueldos son anuales, y en estas empresas generalmente pagan al mes y tardan hasta 7 días en depositar lo cual es un abuso.&lt;/p&gt;

&lt;p&gt;Considera también el sueldo neto, dependiendo del estado también te descuentan un impuesto. En general te descuentan entre 20 al 30 por ciento.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Intenta calcular tu sueldo neto en el estado donde te paguen para planear adecuadamente&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  De uno a otro cliente
&lt;/h3&gt;

&lt;p&gt;Hablando de clientes, como ya comenté, está modalidad hace que tu contrato no sea indefinido, el contrato se acaba básicamente cuando el cliente lo decida, eso puede ser cualquier día, si así lo han acordado con tu sponsor, o el tercero del tercero. &lt;/p&gt;

&lt;p&gt;Regularmente se hacen contratos de 6 meses hasta un año con renovación de meses dependiendo la estabilidad el proyecto.&lt;/p&gt;

&lt;p&gt;En mi experiencia ningún proyecto fue realmente estable, dependía mucho de los recursos con los que contaba el proyecto o la empresa.&lt;/p&gt;

&lt;p&gt;Casi siempre, la percepción es que tú como &lt;em&gt;contractor&lt;/em&gt; estas para apoyar al equipo base, o fijo, de la empresa y eres prescindible, de hecho claro, nunca tendrás todos los beneficios de un empleado permanente, de igual forma como nunca tendrás los beneficios de un ciudadano o residente permanente.&lt;/p&gt;

&lt;p&gt;Como diría una de los tantos clientes que te tratan como cualquier recurso prescindible: "Life of a contractor"&lt;/p&gt;

&lt;p&gt;Si, esas fueron las últimas palabras del cliente que me dijo el mismo día que pensaban terminarme, que ese era mi último día. Resultó ser una estancia de unos 3 meses. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 No esperes el cliente tenga consideraciones contigo, actúa en consecuencia&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Actuar en consecuencia, significa que debes siempre estar preparado para todo, si termina tu contrato tienes o te tienen que buscar inmediatamente otro proyecto, no es tan sencillo buscar alguno en la misma ciudad, por lo tanto, de nuevo, tienes que estar preparado con el lugar que elijas para vivir y si vivir ligero o no, los contratos punitivos pueden a acabar con tu economía.&lt;/p&gt;

&lt;p&gt;Tu sponsor te podría apoyar a buscar rápidamente algo, pero a veces la espera puede ser larga, y claro mientras esperas no recibes sueldo. Te recomiendo negocies una cláusula para tener un sueldo mínimo en estos lapsos, sabiendo que está es la forma de trabajo, a mí me ofrecían $50 por semana lo cual es humillante por decir lo menos, afortunadamente no fue más de 2 o 3 semanas antes de empezar con otro proyecto.&lt;/p&gt;

&lt;p&gt;Como verás, esta percepción de ser prescindible es algo cultural que también se vive en México, pero en EUA es algo aún más marcado para inmigrantes que solo pueden ser sub-contratados. El nunca alcanzar el sentido de pertenencia a un grupo de trabajo, es algo a lo que nunca me acostumbre, es tal vez lo que más pesa en esta experiencia o en la mía al menos. Aun cuando siempre tuve la disposición de dar el 100% realmente no es suficiente con las circunstancias tan cambiantes de las que no tienes ningún control, pertenecer a este sub-grupo de una organización hace que tu voz sea fácilmente apagada y tu impacto sea menos, aun cuando tus compañeros te aprecien y sepan el valor de tus aportaciones.&lt;/p&gt;

&lt;p&gt;La cultura americana tan jerárquica y orientada a servicio se presta a que empresas con una cultura no desarrollada o tóxica no sepan como manejar sus recursos eficientemente y que se premien actitudes individualistas y egocéntricas en detrimento del equipo en una buena parte de estas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 No gastes tu energía mental en cosas que no puedes controlar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con esta descripción de la agria experiencia de un contratista en EUA termino esta parte, en las siguientes explicaré como puedes salir de este círculo vicioso de un sponsor inicial.&lt;/p&gt;

</description>
      <category>visatn</category>
      <category>eua</category>
      <category>mexico</category>
      <category>immigration</category>
    </item>
    <item>
      <title>Parte 2: Esenciales de EUA</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Tue, 25 May 2021 17:23:18 +0000</pubDate>
      <link>https://dev.to/keozdev/visa-tn-esenciales-de-eua-38fl</link>
      <guid>https://dev.to/keozdev/visa-tn-esenciales-de-eua-38fl</guid>
      <description>&lt;p&gt;Esta es la segunda parte de mi serie de blogs donde publico mi experiencia en EUA con la Visa TN, si quieres interactuar con otros expats que han vivido esta experiencia o que están interesados en hacerlo únete a nuestro grupo en Facebook &lt;a href="https://www.facebook.com/groups/238451871803891"&gt;Mexpats&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Esenciales de EUA
&lt;/h2&gt;

&lt;p&gt;Aquí te explico algunos elementos esenciales que debes tramitar y obtener a tu llegada. Seguramente tu empleador te dará algunas direcciones similares.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Seguridad" social
&lt;/h3&gt;

&lt;p&gt;Tal vez el trámite más importante si ya tienes tu hospedaje resuelto es obtener tu número de seguridad social (SSN). Con él básicamente puedes hacer todo lo que un ciudadano legal tiene acceso de forma sencilla como trabajar (en el caso de TN solo para tu empleador sponsor), crédito, licencia, seguro médico, etc. excepto votar. Tengo entendido que tu número es permanente incluso si sales de EUA.&lt;/p&gt;

&lt;p&gt;Para obtener tu tarjeta SSN desde el día 1 tienes que hacer una cita en la oficina más cercana de citizen services USCIS, el proceso no es muy tardado y solo verifican tu status migratorio e identidad con pasaporte y visa.&lt;/p&gt;

&lt;p&gt;Algo importante es que tienes que dar un domicilio, si puedes da el de un conocido, si no alguno que puedas acceder tu mismo o el de la empresa, ahí llegará tu tarjeta. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Obtén tu SSN inmediatamente&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Al salir te darán una constancia de que tú SSN está en trámite, esto te servirá para sacar tu cuenta en el banco, así que paso #2 ve inmediatamente al banco. &lt;/p&gt;

&lt;h3&gt;
  
  
  Banking
&lt;/h3&gt;

&lt;p&gt;Hay muchas opciones, pero es recomendable un banco establecido que no sea local o de cooperativa financiera porque tienes que acceder a servicios de banco en el lugar donde estés, yo elegí Chase y siempre me funcionó perfectamente, he escuchado Bank of America también es "immigrant friendly".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Corre a sacar tu cuenta de banco&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Obviamente sin cuenta no te paga nadie, es probable que batalles un poco sin tener antes el SSN o ITIN (número de identificación para contribuyentes) pero deben poder crearte una cuenta con la constancia, si ves difícil a la gente simplemente ve a otra sucursal o habla con el gerente u otro banco.&lt;/p&gt;

&lt;p&gt;Pide a tu empresa te facilite una carta que acredite tu empleo también y salario para que sea más ágil tu trámite.&lt;/p&gt;

&lt;p&gt;Lo más importante aparte de tu tarjeta de débito es tu número de cuenta (routing + account number) que le tienes que dar a tu empleador para que te pague.&lt;/p&gt;

&lt;h3&gt;
  
  
  Crédito
&lt;/h3&gt;

&lt;p&gt;Algo menos esencial, pero que no deja ser importante es que establezcas tu historial crediticio lo antes posible.&lt;/p&gt;

&lt;p&gt;Tener un score crediticio bueno (arriba de 600) te ayudará a tener mejores ofertas para no pagar tanto en depósitos de compra o arrendamiento de todo tipo, y tener acceso a créditos de más riesgo.&lt;/p&gt;

&lt;p&gt;Establecer un buen historial crediticio lleva al menos 2 años porque una de las cosas que más afectan tu score es la antigüedad de tus cuentas, como acabas de llegar claro no es como que puedas tener un score como el de muchos ciudadanos americanos, pero la ventaja es que no tendrás deudas, ten cuidado de no acumular deudas en EUA, no sabes cuando puedas necesitar ese score asociado a tu número de seguro social.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Obtén una tarjeta de crédito&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una de las mejores opciones para empezar a generar historial de crédito es con tarjetas de crédito de prepago, esto es, que no te dan una línea de crédito, tú tienes que hacer un depósito de unos USD $500 mínimo para que te llegue una tarjeta con ese monto, ese es tu crédito disponible, pero la tarjeta funciona normal como cualquier otra, tienes que pagar lo que gastas.&lt;/p&gt;

&lt;p&gt;Yo usé esta opción de tarjeta con Discover, es una muy buena opción, después de 6 meses o un año de buen comportamiento con ese crédito inicial, te aumentan la línea de crédito sin que tengas que depositar algo más.&lt;/p&gt;

&lt;p&gt;Una de las cosas que más afecta tu historial será que no tienes muchas cuentas abiertas y son de poco tiempo de apertura, pero ayuda mucho que no tengas retrasos en tus pagos y que no trates de abrir muchas cuentas dentro del plazo de un año. También mantén tu uso de crédito abajo del 50% para que no se vea afectado tu score.&lt;/p&gt;

&lt;p&gt;Otra de las cosas que te ayuda es si rentas un departamento, algunas empresas pueden reportar tu historial de renta como una cuenta crediticia.&lt;/p&gt;

&lt;p&gt;Una cuenta para arrendar un auto también cuenta para tu historial, solo ten cuidado de no retrasarte en los pagos de estas considerables inversiones porque los retrasos afectan mucho tu historial.&lt;/p&gt;

&lt;p&gt;Entre mejor &lt;em&gt;score&lt;/em&gt; tengas menos serán los depósitos y &lt;em&gt;down payments&lt;/em&gt; que tengas que hacer en un auto o rentas inmobiliarias, y tener acceso a créditos con mejores beneficios y menos intereses si son pagos por mensualidades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registro como empleado
&lt;/h3&gt;

&lt;p&gt;Otra cosa no menos importante es que tu empleador debe haberte registrado como empleado a través de las formas W8 y la I9, me parece está última es para extranjeros y la primera es para todos los trabajadores en EUA.&lt;/p&gt;

&lt;p&gt;Así que tienes que estar atento y hacerlo cuánto antes, tu estancia legal depende que estés haciendo lo que tú visa y registro dice que haces.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡Pide el original de estos documentos firmado por tu empleador para tus registros.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Impuestos basicos
&lt;/h3&gt;

&lt;p&gt;Algo importante es que al tener el SSN, estás obligado a reportar tus impuestos, lo que se le llama el &lt;em&gt;tax return filing&lt;/em&gt; de que cada año entre febrero y abril.&lt;/p&gt;

&lt;p&gt;Tu empleador te debe enviar lo que se llama el formato W2 donde dice exactamente cuanto te pagaron, y cuanto te descontaron de tus impuestos, así como toda la información de tu empleador. &lt;/p&gt;

&lt;p&gt;Tengo entendido que donde trabajas declaras impuestos también, pero no todos los estados requieren declares impuestos si estás en esa situación. Si debes de declarar de donde te pagan, que es el estado donde reside la empresa.&lt;/p&gt;

&lt;p&gt;A mí me sirvió TurboTax para hacer esto cada año, es sencillo y rápido.&lt;/p&gt;

&lt;p&gt;Al final lo más seguro es tengas un saldo a favor y te regresen parte de tus impuestos pagados a tu cuenta de banco. &lt;/p&gt;

&lt;p&gt;Si vas con tu pareja tienen que declarar impuestos en conjunto, a menos que tenga su propia visa TN, pero supongo es más fácil sea juntos aun así. Tu pareja debe hacer su registro ante el IRS y obtener su número ITIN para declarar impuestos aunque no trabaje.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Tu pareja debe obtener su propio ITIN&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sabiendo todo esto, en general, creo podrías ya estar listo para empezar a hacer lo que viniste a hacer, trabajar, en la siguiente parte hablo al respecto de mi experiencia como desarrollador de software. Como comente antes, cada quien puede tener una experiencia muy diferente a la mía porque cada industria es diferente y las circunstancias son diferentes, te puede ir mejor o peor, pero creo hay comunes denominadores, que desde mi punto de vista muy personal, pueden reflejar los problemas de la legislación laboral para migrantes en EUA.&lt;/p&gt;

&lt;p&gt;Mientras tanto únete a nuestro grupo de Facebook &lt;a href="https://www.facebook.com/groups/mxpats"&gt;Mexpats&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gracias por leer&lt;/p&gt;

</description>
      <category>visatn</category>
      <category>eua</category>
      <category>mexico</category>
      <category>immigration</category>
    </item>
    <item>
      <title>Mi experiencia en EUA y la Visa TN de trabajo</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Mon, 10 May 2021 17:38:42 +0000</pubDate>
      <link>https://dev.to/keozdev/mi-experiencia-en-eua-y-la-visa-tn-de-trabajo-2c6n</link>
      <guid>https://dev.to/keozdev/mi-experiencia-en-eua-y-la-visa-tn-de-trabajo-2c6n</guid>
      <description>&lt;p&gt;En este post comparto mi experiencia como programador en Estados Unidos, una historia que comienza en 2016 y que terminó en 2020.&lt;/p&gt;

&lt;p&gt;Voy a omitir algunos detalles y nombres por obvias razones pero la intención es que mi experiencia sirva para otros profesionales que están empezando a dirigir su carrera fuera del país hacia EUA muy probablemente a través de la Visa TN.&lt;/p&gt;

&lt;p&gt;Esta es la primera entrega de una serie de posts que haré sobre mi experiencia, esta primera parte es una introducción a la Visa y comparto la primera etapa de mi estancia en EUA.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;La Visa TN te puede abrir muy fácilmente una puerta en EUA, sí.&lt;/p&gt;

&lt;p&gt;Pero, tienes que ver la Visa TN como un medio para proyectar tu carrera, no como un fin.&lt;/p&gt;

&lt;p&gt;Parece fácil, pero tienes que enfrentarte a muchos retos, los beneficios son muy buenos si los sabes sobrellevar, aquí te comento de algunos si quieres seguir leyendo.&lt;/p&gt;

&lt;p&gt;Si te interesa unirte a nuestra nueva comunidad &lt;strong&gt;Mexpats&lt;/strong&gt; y conectarte con más gente que esté en el extranjero, estamos en Facebook y pronto en Discord: &lt;a href="https://www.facebook.com/groups/238451871803891"&gt;www.facebook.com/groups/mxpats&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Y por qué? 🤔
&lt;/h2&gt;

&lt;p&gt;A veces se juzga a las personas que deciden salir del país para buscar nuevas oportunidades por no "buscarle lo suficiente" cuando hay todo en México. La verdad es que no siempre la oportunidad encuentra la circunstancia, o no para todos. A veces no es suficiente con "echarle ganas" y no te tienes que sentir culpable de querer buscar algo mejor.&lt;/p&gt;

&lt;p&gt;Todo es muy circunstancial, diferentes factores te pueden llevar a tomar la decisión, la situación país, la oferta de trabajo, la oferta económica del extranjero, la cultura laboral en tu industria, y ahora ya es menos factor tu lugar de residencia, especialmente en Tecnologías de Información, donde 2020 y en adelante reforzará el teletrabajo como nunca antes pero aún así, la experiencia de forma integral, no se compara en lo más mínimo con salir del país.&lt;/p&gt;

&lt;p&gt;Si a mi me preguntas si recomendarías a alguien salir del país (no solo a EUA) mi respuesta siempre será: SÍ, y cuanto antes mejor. El mundo es muy diferente afuera, y en el dia a dia te das cuenta de más cosas que si fueras solo de visita, tendrás una visión más amplia de lo que sucede y poder mirar en retrospectiva todo lo que está mal en México con una perspectiva, que en el mejor de los casos, te darán ganas de llevar a México de regreso.&lt;/p&gt;

&lt;p&gt;Un día estaba pensando con mi esposa, qué pasaría si tan solo en México existiera un transporte público al menos el 50% de lo eficiente, y seguro, como en las ciudades en los que hemos estado 🚌, y con esa puntualidad y comodidad. Cambia todo, parece simple y mundano pero para que sucediera eso tendría que haber muchos cambios de fondo y le daría un cambio de vida radical a los habitantes de cualquier ciudad de México. Algo que dan por hecho afuera y parece común, y para los mexicanos algo a lo que te tienes que resignar, no hay de otra pues el subdesarrollo solo se combate con la unión de muchas voluntades que buscan cambios.&lt;/p&gt;

&lt;p&gt;Bueno pues lo que quiero es que si haya de otra, no nos conformemos, y quiero ayudar a que los estudiantes y profesionales aspiren a más, y si quieren salir que lo hagan y mejoren su calidad de vida, y si puedo ayudar, quiero hacerlo, esa es mi visión, y este es el comienzo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Las circunstancias
&lt;/h2&gt;

&lt;p&gt;Dónde y cuándo empieza todo, pues en mi querido México, claro. Y uno nunca deja de ser mexicano, a pesar de todo, es siempre nuestro puerto seguro, donde si todo se complica podremos volver. &lt;/p&gt;

&lt;p&gt;En mi caso, los factores que me llevaron a tomar la decisión en el año 2016 fueron a grandes rasgos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decepción de no encontrar una oferta adecuada con mi experiencia e intereses, en ese momento por ejemplo era más difícil encontrar una oferta atractiva con desarrollo para apps móviles con Xamarin que ahora.&lt;/li&gt;
&lt;li&gt;El querer salir de mi actual lugar de trabajo después de varios años donde la relación iba degradándose cada vez más, a pesar de que en algún momento lo consideré el trabajo ideal, y por lo cual puse todo de mi parte pero no sirvió, no estaba ya en mi control, tenía que dejarlo ir.&lt;/li&gt;
&lt;li&gt;Y finalmente, la sorpresivamente accesible y atractiva 💸 oferta que me habían hecho en EUA, incluso esta empresa la que llamaré de aquí en adelante, sponsor o empleador, esperó un buen tiempo para preparar mi salida, pero eso no tenía nada que ver con mi experiencia, después me di cuenta que sería yo una mercancía, y no bien pagada, por lo cual no importa cuanto tuvieran que esperar, esto es a lo que se dedican y son expertos en atraer gente a EUA.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Visa TN
&lt;/h2&gt;

&lt;p&gt;Lo que te ofrecen los sponsor es la visa TN, si estas leyendo esto muy probablemente ya sepas de que vá, pero en resumen, es un tipo de visa de trabajo a la que tenemos acceso Canadienses y Mexicanos mediante el tratado de comercio USMCA, antes NAFTA. &lt;/p&gt;

&lt;p&gt;El nombre de la visa no cambió al cambiar de nombre, casi que pasa desapercibida, según entiendo lo relacionado a esta visa se mantuvo igual. A mi parecer, debería tener una relevancia mucho más importante y central en las relaciones comerciales entre los 3 países, con un enfoque en proteger los derechos de los trabajadores, honestamente no es un tema central de ningún lado esta visa, eso debería cambiar, podría ser un instrumento clave para la cooperación bilateral entre México y EUA.&lt;/p&gt;

&lt;p&gt;De hecho debería ser parte central en la estrategia para resolver la crisis migratoria en la frontera, si no esta visa, sí similares, que tal por ejemplo, visas de capacitación con opción de trabajo.&lt;/p&gt;

&lt;p&gt;El talento mexicano que le hace falta a EUA podría ser convenientemente aprovechado si hubiera reglas más claras y condiciones de trabajo mejores para los mexicanos, y que no se tratara como empleos temporales sin acceso a una ruta hacia residencia, supongo también es un tema del que se habla poco en EUA por la tendencia conservadora de no incluir a más migrantes en el sistema laboral, que no quepa duda alguna, siempre van a necesitar lo que se les llama &lt;em&gt;skilled workers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Y de eso, México tiene mucho. Y la Visa TN tiene un amplio rango de profesiones con las que se puede aplicar entre ingeniería, medicina, ciencias y educación, aquí &lt;a href="https://www.nafsa.org/_/file/_/amresource/8cfr2146.htm"&gt;la lista completa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con todo esto, pues entonces para los sponsors, es muy sencillo tramitar la visa para los mexicanos, debería ser sencillo no solo para los sponsors, sino para cualquier empresa americana, solo que no saben como hacerlo o le tienen miedo a ese tipo de trámites, algo que solo empresas grandes o bien que les interesa atraer talento a pesar de las trabas burocráticas lo hacen.&lt;/p&gt;

&lt;p&gt;Por lo tanto esto crea una demanda de talento proveniente de las empresas que aprovechan estas reclutadoras como mi sponsor.&lt;/p&gt;

&lt;p&gt;En resumen el proceso de trámite de visa es así:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Llenas el formulario DS-160, la llamada Online Nonimmigrant Visa Application, en el sitio de &lt;a href="https://travel.state.gov/content/travel/en/us-visas/visa-information-resources/forms/ds-160-online-nonimmigrant-visa-application.html"&gt;travel.state.gov&lt;/a&gt; con los datos de la empresa que te va a contratar, también para tu familia, que tendrían una visa TD, con aun menos derechos pero bueno al menos puedes llevar a tu familia.&lt;/li&gt;
&lt;li&gt;El empleador tiene que hacer un requerimiento por medio de la forma I-129, no estoy seguro si otra cosa más, pero bueno, no es mucho más que eso, de hecho es el mismo proceso para extensión de visa.&lt;/li&gt;
&lt;li&gt;Para tener acceso a la cita para la visa tienes que registrarte en &lt;a href="https://ais.usvisa-info.com/es-mx/niv"&gt;usvisa-info&lt;/a&gt; que es el que ya se conoce para las visas de turista también y tienes que pagar, creo son $160 dólares por aplicación.&lt;/li&gt;
&lt;li&gt;Se hace la cita para la visa, que incluye biométricos y entrevista en embajada si es primera vez, cuando es renovación generalmente puedes omitir la entrevista.&lt;/li&gt;
&lt;li&gt;A la entrevista y biométricos debes llevar una carta de tu empleador, con su firma, sobre la petición e intención de contratarte mencionando que es mediante el tratado de comercio del USMCA y básicamente un choro de la "estabilidad" de la empresa y exactamente el trabajo que vas a desempeñar.&lt;/li&gt;
&lt;li&gt;A la entrevista también tienes que llevar documentos que avalen tu experiencia o tus estudios, si no tienes titulo, puede ser carta de recomendación o CV, te dirá el cónsul si te aprueba o no y en una semana o máximo 2 te llega la visa estampada en tu pasaporte.&lt;/li&gt;
&lt;li&gt;A algunos si se la dan por 3 años pero en mi caso tuve que renovar cada año, solo me la daban por uno. Pero después de esto ya puedes volar, tiempo de decir adiós.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Esta visa no te da oportunidad de obtener residencia permanente en el corto plazo, pues es una de las visas &lt;em&gt;non-immigrant&lt;/em&gt;, lo que quiere decir que es de las más temporales. &lt;/p&gt;

&lt;p&gt;Aquí encuentras más información sobre la visa y el proceso en &lt;a href="https://travel.state.gov/content/travel/en/us-visas/employment/visas-canadian-mexican-nafta-professional-workers.html"&gt;travel.state.gov&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo mejor es tener una H1B en el corto plazo después de obtener la TN, pero es más costosa y difícil de obtener porque tiene un número limitado al año y su proceso es más largo, esta visa es para inmigrar y te da acceso a la residencia después de un tiempo.&lt;/p&gt;

&lt;p&gt;De nuevo, es una visa que no te ofrece cualquier empresa, generalmente startups y empresas grandes lo hacen, los reclutadores de TN solo te la van a prometer, pero no por escrito. Hablando de lo que deben ofrecerte por escrito, hablemos un poco del contrato.&lt;/p&gt;

&lt;h2&gt;
  
  
  El contrato 📝
&lt;/h2&gt;

&lt;p&gt;Regresando un poco atrás, antes de iniciar a trabajar (y de hacer el viaje claro) debes tener un contrato, pero que clase de contrato es el que te van a ofrecer es algo que debes ver antes de llegar a EUA, en mi caso si pues lo leí y todo y firme y fue entonces que se tramitó la visa.&lt;/p&gt;

&lt;p&gt;En su momento no me pareció descabellado, aunado a que tenía ya muchos anhelos de trabajar allá o tal vez más el irme de México, que después en retrospectiva pienso en cómo fue una firma peligrosa, había cláusulas que nadie debería aceptar en su sano juicio, otro de mis grandes errores.&lt;/p&gt;

&lt;p&gt;Es posible que hubiera podido negociar las cláusulas inquisitivas y abusivas pero en ese momento se me hizo fácil y no podía pagar un abogado que me ayudara con esto.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Primer tip: Revisa bien el contrato, negocia el quitar cláusulas absurdas y contacta a un abogado si tienes dudas&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para no entrar mucho en detalle, prácticamente tenía que pagarles si me iba antes de 2 años y tenía que avisarles 4 semanas antes de irme si no quería tener una penalización, voy a retomar esta parte después para explicar mi salida, pero así entre otras cosas más para protegerse ellos de cualquier cosa, seguramente es una práctica de muchas de estas empresas que traen mexicanos, y latinos, a EUA. Mucho ojo 👀&lt;/p&gt;

&lt;p&gt;Es difícil también que estas empresas tengan por escrito el &lt;em&gt;path de citizenship&lt;/em&gt; o residencia donde puedas pasar de una TN a una H1B, si es posible puedes pedir sea por escrito que después de un año, inicien el trámite de H1B y si no, puedes salir del contrato sin penalización.&lt;/p&gt;

&lt;p&gt;Está de más decir que, eso yo no lo pedí 🙂  pues no tenía en ese entonces mucha información al respecto, pero sí pensaba exigir lo hicieran si las cosas salían bien. Al final no salieron tan bien.&lt;/p&gt;

&lt;h2&gt;
  
  
  La travesía de emigrar 🧳
&lt;/h2&gt;

&lt;p&gt;Con visas listas, es tiempo de partir.&lt;/p&gt;

&lt;p&gt;En un comienzo, parecía no tan compleja la travesía de tener que vender, tirar, empacar y mudar las cosas que habíamos ido acumulado en los 4+ años de estar viviendo juntos, mi ahora esposa y yo.&lt;/p&gt;

&lt;p&gt;Pero nos dimos cuenta que en este corto tiempo si teníamos muchas cosas que tendríamos que dejar atrás para volver a empezar 🙄. Volver a empezar se dice fácil pero no es tan fácil desprenderse de las cosas, y es algo a lo que es posible te tengas que acostumbrar a hacer constantemente por la cambiante situación a la que te podrás enfrentar en EUA.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Es mejor vivas ligero, casi nada te vas a llevar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En ese año tuvimos muchos gastos pero sobre todo teníamos deudas que aún no teníamos saldadas, y aún así gastábamos en cosas muchas veces innecesarias, otras si con miras a establecernos más en México, pero ya no íbamos a tenerlas al menos por un tiempo, algunas las vendimos, otras las regalamos y unas pocas las guardamos. &lt;/p&gt;

&lt;p&gt;El problema, que aún no veíamos tan claro, era que íbamos a ir a Estados Unidos con deuda y peor aún, ¡Sin tener ahorros!&lt;/p&gt;

&lt;p&gt;Si, esto ya parece una locura, pensábamos que con el sueldo y siendo más austeros podríamos solventar rápidamente nuestra estabilidad económica, se vale soñar 🙂&lt;/p&gt;

&lt;p&gt;Por cierto, parece obvio pero no está de más, tu sponsor debe pagar el 100% de tu vuelo de ti y tu familia, además de reembolsarte los gastos que hiciste para el trámite de visa y traslados durante los primeros días.&lt;/p&gt;

&lt;h2&gt;
  
  
  Economía 101 y llegando a EUA
&lt;/h2&gt;

&lt;p&gt;Ok, ya tienes todo arreglado, organizado, te despediste, hiciste fiesta o algo, hora de empacar con lo que te quedó e iniciar la aventura. ✈️&lt;/p&gt;

&lt;p&gt;Nadie puede estar preparado para esta experiencia pero generalmente cometemos muchos errores y somos muy impulsivos, entre más jóvenes aún más.&lt;/p&gt;

&lt;p&gt;Una de las cosas que me di cuenta tarde es que mi esperanza de recuperarme económicamente no fue tan fácil y rápido como pensé.&lt;/p&gt;

&lt;p&gt;Otro de mis grandes errores entonces, fue haberme ido con deuda de México. Si, debía mucho, como comente antes y fui acumulando gastos en tarjeta y préstamos del banco que iban generando intereses, aparte del gasto de haberme casado en ese año 💒&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 No te vayas sin haber pagado tus deudas &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Supongo que muchas personas pasan por lo mismo, y si bien mi deuda era manejable, me enfrenté a muchos obstáculos al inicio de este viaje. Fue un inicio con demasiada turbulencia, y peor aún sin ahorros.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Lleva dinero ahorrado 💰&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esta situación era por demás arriesgada por lo que podrás darte cuenta, empecé a acumular gastos rápidamente pero ahora en dólares y no en pesos.&lt;/p&gt;

&lt;p&gt;Tienes que pagar comida, hospedaje, transporte y seguir pagando lo que aún debas, si bien la empresa que me trajo podía "adelantarme" sueldo y pago las 2 primeras semanas de hospedaje, no es suficiente y no es una buena posición para pedir aún más prestado, aparte que se paga nómina mensualmente por lo general. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Exige el 100% de tu hospedaje los primeros meses 🏨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;De nuevo, si es por escrito en el contrato, mejor, o la otra opción, tu vuelo debe incluir hospedaje de al menos 4 semanas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hospedaje
&lt;/h2&gt;

&lt;p&gt;Ya que hablamos de hospedaje, yo cometí mi primer error en EUA, confiar en que mi estancia en la ciudad donde llegué a trabajar sería larga, no contaba con que en la modalidad que te contratan estas empresas, tienes que moverte a donde el cliente esté.&lt;/p&gt;

&lt;p&gt;Fue así que después de estar en un par de Airbnb's durante 3 semanas pensé que sería buena idea buscar un departamento donde vivir "más estable". &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Permanece en Airbnb's u hoteles de larga estancia el mayor tiempo posible hasta que estés seguro de tu estabilidad laboral&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tu empleador, como la mayoría, te empleará como contratista por proyecto, y no te va a garantizar que puedas permanecer en el mismo lugar por largo tiempo, eso lo debes evaluar tú. A menos que estés empleado en una empresa que te emplee directamente. Hablaré sobre esto más adelante.&lt;/p&gt;

&lt;p&gt;Mi recomendación es que si la ciudad donde vives tiene buena actividad en la industria en la que trabajas y en tu especialidad es más probable que encuentres proyectos más estables o con mucha demanda.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Evalúa la demanda de la ciudad donde estás antes de comprometerte a una renta de largo plazo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El permanecer en Airbnb también claro te puede traer experiencias diversas, en general te recomiendo busques solo Super Hosts, aunque sea más caro, si te da una tranquilidad que no tendrás sorpresas, tal vez viviendo solo no sea un problema pero cuando viajas con tu familia, si lo vas a pensar dos veces.&lt;/p&gt;

&lt;p&gt;Mi experiencia en Airbnb antes de "establecerme" finalmente en Houston fue bastante interesante. Tuvimos la oportunidad de conocer a personas con diferentes historias, formas de vida y cultura. En  especial el último hospedaje fue una vivencia muy agradable, aprendimos a convivir con una familia americana que nos recibió extraordinariamente, nos integraron en parte de su vida diaria y nos apoyaron de diversas formas para sentirnos un poco seguros en medio de tanta inestabilidad. Algo que siempre estaré muy agradecido.&lt;/p&gt;

&lt;p&gt;En retrospectiva, creo pudimos haber aprovechado más todas esas interacciones, pero también, es complicado pues tienes que pensar constantemente en cómo darle la vuelta a tu situación y buscar tu propia forma de vida y estabilidad, no es como si estuvieras de vacaciones, pero es frustrante sentirte como una especie de refugiado del sistema.&lt;/p&gt;

&lt;p&gt;Cómo encontrar tu camino, es algo de lo que hablaré más adelante. Antes hablemos de algunos temas técnicos esenciales aparte del hospedaje que deberás tener en cuenta al llegar a EUA.&lt;/p&gt;

&lt;p&gt;En una segunda parte, te comentaré más sobre los esenciales al llegar a Estados Unidos y acciones para ayudarte a tener una mejor estabilidad laboral.&lt;/p&gt;

&lt;p&gt;Si te interesa conectarte con gente que ha tenido experiencias similar, no solo en EUA, te invito al grupo de Facebook que estamos iniciando: &lt;a href="https://www.facebook.com/groups/238451871803891"&gt;www.facebook.com/groups/mxpats&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;¡Gracias por leer!&lt;/p&gt;

</description>
      <category>visatn</category>
      <category>eua</category>
      <category>mexico</category>
      <category>immigration</category>
    </item>
    <item>
      <title>Azure Functions hacks</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Mon, 29 Mar 2021 20:17:44 +0000</pubDate>
      <link>https://dev.to/keozdev/azure-functions-hacks-p7</link>
      <guid>https://dev.to/keozdev/azure-functions-hacks-p7</guid>
      <description>&lt;p&gt;This is just a collection of mini-hacks to fix problems I've faced during development of Azure Functions, maybe it can help anybody out there. I'm a total newbie in Azure so if you have some insights on these issues you are welcome to show me the way of the light.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development storage failing to start
&lt;/h2&gt;

&lt;p&gt;When starting a functions app with &lt;code&gt;func start&lt;/code&gt; locally, maybe you got it working at the beginning but suddenly you can get this cryptic unhelpful message&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There was an error performing a read operation on the Blob Storage Secret Repository. Please ensure the 'AzureWebJobsStorage' connection string is valid."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And you have no idea because the storage in dev used to work and you have your &lt;code&gt;"UseDevelopmentStorage=true"&lt;/code&gt; in place, fear not, just go to your Server Explorer in VS, go to Storage and Blobs, there may be a couple of records there for &lt;code&gt;azure-webjobs-hosts&lt;/code&gt; so maybe those are conflicting don't know 🤷‍♂️ for sure so just delete them and you should be good to go.&lt;/p&gt;

&lt;p&gt;Looks like these deletions are not needed if you use files storage, use file storage for secrets storage type, in local.settings.json you have to add&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"AzureWebJobsSecretStorageType": "files",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also every time you start development with &lt;code&gt;func start&lt;/code&gt; remember to kick off Azure Storage Emulator from program files and make sure to Start Storage Emulator from the commands or status icon in Windows&lt;/p&gt;

&lt;h2&gt;
  
  
  SignalR Serverless
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Method not found (404)
&lt;/h3&gt;

&lt;p&gt;When you start development with SignalR you may find yourself not finding the broadcast method to invoke via&lt;br&gt;
&lt;code&gt;await _connection.InvokeAsync("broadcast", "message" );&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This maybe due the negotiate function having a &lt;code&gt;[SignalRConnectionInfo(HubName = "hubname")]&lt;/code&gt; attribute&lt;/p&gt;

&lt;p&gt;If you don't want to send to a hub at the beginning then just remove the hub linked connection :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Failure to deserialize the json message
&lt;/h3&gt;

&lt;p&gt;If your &lt;code&gt;HubConnection.On&amp;lt;T&amp;gt;&lt;/code&gt; method fails to deserialize and only works with &lt;code&gt;object&lt;/code&gt;, it may be because you need the parameterless constructor but also a public setter for your properties.&lt;/p&gt;

&lt;p&gt;I think there is a way to pass the properties values through a constructor which is much better than having public properties but haven't looked into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debug your function while running your app
&lt;/h3&gt;

&lt;p&gt;Say you have your functions and app in same solution&lt;/p&gt;

&lt;p&gt;If you are running locally using &lt;code&gt;func start&lt;/code&gt; you can simply attach the debugger to the func.exe process and you get debugging side to side with your app :D&lt;/p&gt;

</description>
    </item>
    <item>
      <title>México y la competitividad de talento [spanish]</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Mon, 15 Feb 2021 18:55:49 +0000</pubDate>
      <link>https://dev.to/keozdev/mexico-y-la-competitividad-de-talento-spanish-25jp</link>
      <guid>https://dev.to/keozdev/mexico-y-la-competitividad-de-talento-spanish-25jp</guid>
      <description>&lt;p&gt;Quiero compartir este video sobre una plática que organizó &lt;a href="https://twitter.com/RevistaSG"&gt;@RevistaSG&lt;/a&gt; junto con Claudio Cossio, Sergio Nouvel, Jesús Ramos, y  del staff SG, esto porque considero se habla de uno de los problemas más importantes para la industria en México y del que creo lamentablemente no es tema tan central y por lo tanto asumo es limitado alcance lo que se hace para remediarlo.&lt;/p&gt;

&lt;p&gt;Siento que esté en FB pero bueno lo importante es que hubo argumentos importantes.&lt;br&gt;
&lt;a href="https://fb.watch/3x2PeJG0B2/"&gt;https://fb.watch/3x2PeJG0B2/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En estos días he estado pensando al respecto y tengo unos apuntes que me gustaría compartir y también a manera de una humilde opinión y al final me atrevo a sugerir algunos call to action.&lt;/p&gt;

&lt;p&gt;En específico el tema de la cultura en las empresas es muy importante, y ahora más, cuando ha cambiado muchísimo o se ha obligado a cambiar a la industria y esto le ha pegado a la retención y atracción de talento no solo en México y LATAM, pero en el mundo.&lt;/p&gt;

&lt;p&gt;Sin embargo algo que hace que le afecte más a México, es el tema de la competitividad de las empresas, pero para competir con otras organizaciones, se necesita contar con competitividad para atraer talento, lo cual evidentemente le pega a México porque es muy difícil retener y atraer talento ante una oferta globalizada donde el trabajo remoto se ha vuelto esencial y hace que los talentos mexicanos sean extremadamente accesibles. Como dato, en el &lt;a href="https://gtcistudy.com/the-gtci-index/#gtci-rankings-table"&gt;Global Talent Competitiveness Index 2020&lt;/a&gt; se puede notar que México no está bien posicionado para atraer talento.&lt;/p&gt;

&lt;p&gt;Pero esto ya pasaba antes de 2020, para quien realmente quisiera, buscaba y encontraba oferta fuera del país, aunque casi ni se habla de la oferta en EUA, es una oferta de buen tamaño y hay muchas posibilidades para trabajar allá. Mucho menos se habla de la oferta en Europa que es muy interesante en mi opinión, algo que me gustaría tocar más a fondo después.&lt;/p&gt;

&lt;p&gt;En cara al 2021, esta tendencia seguirá y se reforzará, una de las buenas cosas que nos dejó una pandemia, el costo ha sido demasiado grande y hubiera sido mejor tener mecanismos para una transición previendo este cambio en la cultura hacia aprovechar el trabajo remoto, en cambio en muchos casos propicio tanto buscar más formas de &lt;em&gt;micro-management&lt;/em&gt; como &lt;em&gt;burnout&lt;/em&gt; por exceso de horas de trabajo, un desastre, pero porque no tenemos esa cultura de work-life balance. Por otro lado, como mencionan, muchas empresas sí han empezado a derribar barreras y prejuicios a fin de atraer y retener talento y buscando ser más competitivos adaptándose de forma adecuada.&lt;/p&gt;

&lt;p&gt;La situación económica de México tampoco ayuda, difícilmente podrás atraer talento para moverse a México puesto que no se puede ofrecer una calidad de vida como la de EUA, Canadá o de muchos países de Europa. Mucho menos sin un sistema de migración que lo facilite, otros países como Barbados, hasta permiso específicamente para trabajo remoto ofrecen, que claro no es lo mismo que puedas ir a plantarte a un país y hacerlo de alguna forma que haya programas que lo promuevan y obviamente este rollo solo es posible que sea atractivo con reglas accesibles en los sistemas tributarios, todo esto es algo que México no tiene.&lt;/p&gt;

&lt;p&gt;Considero que hay más temas de fondo como el hecho que no hay suficientes políticas públicas que promuevan la atracción de talento a México, pero sin una estabilidad social ni económica, que no se puede negar es un problema, no hay mucho que hacer, son cosas de fondo que el gobierno debe de atender y nosotros como ciudadanos exigir resultados.&lt;/p&gt;

&lt;p&gt;Mientras tanto esto mejore, tendremos que ponernos creativos para ayudar y promover a que la industria se adapte a estos nuevos tiempos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cultura y valor
&lt;/h2&gt;

&lt;p&gt;Algo que menciona Sergio es clave, la cultura de los equipos es la que tiene que cambiar para atraer talento, las empresas no podrán competir en compensación, muchas veces puede ser imposible, pero puede ofrecer valor ofreciendo algo más cercano al individuo como impacto local, y también un mindset de work-life balance, una mentalidad más abierta a operar con mucho más flexibilidad, es algo que por ejemplo países nórdicos tienen muy presente localmente. Es algo que concuerdo en que puede atraer a la gente con experiencia.&lt;/p&gt;

&lt;p&gt;Como dice Claudio, la organización debe operar pensando en pro del individuo, cualquier organización que no ponga de frente el desarrollo del individuo no vale la pena, creo desde ahi empieza la raíz o el ancla de la cultura de una empresa, es con lo que se va a poder competir y tener mucha transparencia en tus opciones de desarrollo.&lt;/p&gt;

&lt;p&gt;Una cultura que gane talento, innovadora, creativa y dinámica siempre será una cultura inclusiva y diversa como también mencionan en el video, congruente con los valores que profesa hacia afuera sean aún más parte de su cultura interna. Otra oferta de valor.&lt;/p&gt;

&lt;p&gt;También hay que tener cuidado con las prácticas abusivas donde extranjeros miran el talento mexicano como recursos explotables y mano de obra barata porque pueden, debemos denunciar esas prácticas porque no aportan nada y solo promueven culturas tóxicas que obstruyen el desarrollo individual, suficiente tenemos con locales que mucho daño hacen y no aportan valor de vuelta.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Como mexicano me ocupa este tema, y como mexicano en el extranjero creo que me da una perspectiva más amplia de lo que sucede. A todos nos debería interesar que México progrese y sea más competitivo, lamentablemente no veo que sea un tema de mucho interés, al final, todos estamos en modo supervivencia. Pero creo podemos hacer algo desde nuestra trinchera, si algo que concuerdo que también se menciona en el video, se puede compartir el conocimiento y empezar a crear comunidades y redes para promover el talento mexicano y sembrar la cultura para dar valor y contenido de valor de vuelta a la comunidad. &lt;/p&gt;

&lt;p&gt;En conclusión, creo que debemos hacernos a la idea que la industria en México, ya no existe solo en México, que México está dónde estén los mexicanos, debemos crear una especie de conciencia colectiva y global con miras a aportar algo para la población mexicana y promover que existan mas y mejores oportunidades tanto para los que están en el país, como para los que no estamos, y obviamente quitarnos la idea nacionalista donde no permitir que exista la mal llamada fuga de talento, al contrario, que no exista tal "fuga" y mejor guiar a la gente para que pueda desarrollarse donde mejor pueda.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debemos construir puentes, y dejar de ponernos muros, seamos ciudadanos del mundo.&lt;/strong&gt; Desarrollemos nuestro potencial mirando hacia adelante, pero nunca dejemos de mirar hacia atrás y contribuir a la sociedad de dónde venimos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Call to action
&lt;/h2&gt;

&lt;p&gt;Propongo las siguientes acciones para empezar a hacer o seguir haciendo en la medida que cada quien pueda, y darles voz y visibilidad a grupos y organizaciones que ya lo estén haciendo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crear y compartir contenido como dice Claudio, escribe, comparte lo que vas aprendiendo, incluso no solo aspectos técnicos, también sobre lo que piensas de tu entorno o temas como este, no importa la audiencia que tengas, todos podemos generar conversación y llegar a influir cambios, es ser un individuo consciente y que participa para mejorar su entorno, parte de lo que denomino un #AwareProgrammer&lt;/li&gt;
&lt;li&gt;Crear redes y apoyar esfuerzos que sirvan para empujar y promover talentos mexicanos tanto localmente como en el extranjero.&lt;/li&gt;
&lt;li&gt;Promover empresas con buena cultura y denunciar a las que promueven prácticas tóxicas, crear safety nets y apoyo adecuados para quienes lo denuncian, al menos no ignorarlos y generar una conversación.&lt;/li&gt;
&lt;li&gt;Desincentivar el uso de consultorías, reclutadores y staffers y promover el contrato directo y remoto, especialmente los que abusan para sacar más beneficio del trabajo de los empleados y sin ofrecer un plan de desarrollo.&lt;/li&gt;
&lt;li&gt;Aunque el offshore/nearshore es un mal necesario para la industria, a las empresas extranjeras con operaciones en México con la cultura adecuada, darles más visibilidad, que no se busque a los mexicanos para mano de obra barata o fácil de explotar por falta de regulación efectiva.&lt;/li&gt;
&lt;li&gt;Promover mecanismos para que empresas extranjeras atraigan a su país talento mexicano y sin intermediarios, un ejemplo, me sorprende que Dinamarca tenga reglas de permiso de trabajo más claras y ofrezca mejores condiciones para atraer talento que Estados Unidos, go figure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;¡Inglés!&lt;/strong&gt; Es esencial para tu competitividad e impulsar tu desarrollo.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/platzi"&gt;@Platzi&lt;/a&gt; tiene cursos de inglés y muchos cursos de calidad en español, el retorno de inversión si lo aprovechas es muy bueno.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/platzi"&gt;@io_exception&lt;/a&gt; tiene una iniciativa para practicar inglés en Discord y comparte también buen contenido.&lt;/li&gt;
&lt;li&gt;Las empresas que ofrecen certificación Cambridge CELTA para maestros de inglés últimamente ofrecen clases en línea gratuitas para que los maestros practiquen como dar clases, no se si en todas lados, pero uno de ellos es TeachingHouse, &lt;a href="https://www.teachinghouse.com/contact-us"&gt;contáctalos&lt;/a&gt; para que te den informes de las clases en línea.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Medita, para tu salud mental y para tu claridad de pensamiento, creo el mindfulness trae muchos beneficios, últimamente la app de Calm me ha ayudado a hacerlo un hábito diario. Y si lo emparejas con tener una vida activa mejor, puedes usar &lt;a href="https://www.calm.com/gp/9jkazn"&gt;este pase&lt;/a&gt; para acceder por 30 días gratis si eres de los primeros 5 en usarlo.&lt;/li&gt;
&lt;li&gt;Keep learning, lee mucho porque hay gente que ha puesto todo su esfuerzo y experiencia para compartir lo que sabe y plasmarlo en libros, que para mí es la máxima expresión de conocimiento. Un libro que considero esencial para nuestra profesión y nunca dejaré de recomendar es &lt;em&gt;The Pragmatic Programmer&lt;/em&gt;, hace poco publique un review &lt;a href="https://dev.to/keozdev/book-review-the-pragmatic-programmer-26h2"&gt;acá&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;¿Tú qué harías para mejorar?&lt;/p&gt;

&lt;p&gt;Únete a la conversación por acá&lt;br&gt;
&lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--jNgAVKha--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pbs.twimg.com/profile_images/1356655426830491650/3I7DQXlZ_normal.jpg" alt="Jorge C. #WearKN95s 🇲🇽🇺🇲🇩🇰 profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jorge C. #WearKN95s 🇲🇽🇺🇲🇩🇰
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/keozdev"&gt;@keozdev&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDgU_xDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Publique un blog: &lt;a href="https://t.co/Az7Zk6BplW"&gt;dev.to/keozdev/mexico…&lt;/a&gt; &lt;br&gt;&lt;br&gt;Comento acerca de la reciente plática que organizó &lt;a href="https://twitter.com/RevistaSG"&gt;@RevistaSG&lt;/a&gt; junto con &lt;a href="https://twitter.com/marayve"&gt;@marayve&lt;/a&gt;, &lt;a href="https://twitter.com/pedrogk"&gt;@pedrogk&lt;/a&gt;, &lt;a href="https://twitter.com/ccossio"&gt;@ccossio&lt;/a&gt;, &lt;a href="https://twitter.com/shesho"&gt;@shesho&lt;/a&gt; y &lt;a href="https://twitter.com/xuxoramos"&gt;@xuxoramos&lt;/a&gt; sobre cómo ven el 2021...
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      19:05 PM - 16 Feb 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1361753521528438797" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OXOJJiQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1361753521528438797" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--foTp-unf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1361753521528438797" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SFHqU4bF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


</description>
    </item>
    <item>
      <title>Book Review - The Pragmatic Programmer</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sun, 10 Jan 2021 14:02:04 +0000</pubDate>
      <link>https://dev.to/keozdev/book-review-the-pragmatic-programmer-26h2</link>
      <guid>https://dev.to/keozdev/book-review-the-pragmatic-programmer-26h2</guid>
      <description>&lt;h2&gt;
  
  
  In a nutshell, 🥜
&lt;/h2&gt;

&lt;p&gt;Empowering &lt;a href="https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/"&gt;book&lt;/a&gt; 💪&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4infH-p4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/tpp20.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4infH-p4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/tpp20.jpg" alt="Pragmatic Programmer" width="800" height="1046"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes this is one empowering book and is one of the books that should be bought with hard-cover and keep it close to you for reference and to read again a couple of times, or more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this all about? 🤷🏻‍♂️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/pragdave"&gt;David&lt;/a&gt; and &lt;a href="https://twitter.com/PragmaticAndy"&gt;Andrew&lt;/a&gt; take us in a journey to mastery, as the book says, from being just a programmer to becoming a pragmatic programmer, and pragmatism is all about using the tools that work best for you and your team to develop professional products and delight your users by helping them achieve their goals, delivering value at each step you take, value where you are aware of the larger context, beyond the immediate problems, and the approach you take to find efficient solutions to those problems with the right tools and practices. You make this an &lt;strong&gt;habit and an attitude&lt;/strong&gt; and you will see improvements in your productivity and career as developer.&lt;/p&gt;

&lt;p&gt;I wish I had someone pointing me to this book before, I just read the 20th anniversary edition! I wish I had some good mentors in my career that told me about it, but probably I also didn't worry too much about seeking mentorship, in part, I have been pragmatic "doer", pivoting around what works for me. Nonetheless, the more I learned the more I thought: there should be a less speculative and more proven and also practical way to do software. As years have passed, I am a more &lt;em&gt;aware programmer&lt;/em&gt; and I seek more knowledge from the people that have been through a lifetime of experience, and you should too, the earlier the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you care? 🤔
&lt;/h2&gt;

&lt;p&gt;The 53 topics presented conveying the 100 &lt;em&gt;maxims&lt;/em&gt; or tips 💡 in the book to me are the way foundational software development knowledge must have been passed through generations of programmers, but I have seen a handful times these concepts been overheard or taught or practiced, sometimes of course, they take different names, practices and entire paradigms, but &lt;strong&gt;the very essence of software development&lt;/strong&gt; is the same, and this book explains it all. These topics are a must to put in practice for every developer to &lt;em&gt;empower&lt;/em&gt; their career.&lt;/p&gt;

&lt;p&gt;You may also think, like some reviewers I have seen about this book, "oh yeah that sounds nice but I have known those things my whole career" 🤷🏻‍♂️, or "it's just obvious common sense, I'm beyond that" 💁🏻‍♂️, or "this is too basic for me" 🥱. Well more often than not, you may think you know a lot of this stuff, but do you really put all into practice? and within the proper context? or do you go beyond good wishes? Do you really take an active approach to &lt;em&gt;Don't Live with Broken Windows&lt;/em&gt; 💥 (Tip 5) to remove &lt;em&gt;Software Entropy&lt;/em&gt; (Topic 3) for instance. I'm afraid not, and if you do, maybe you haven't been able to pass that expertise wisdom to fellow developers and really influence the industry or your team. &lt;/p&gt;

&lt;p&gt;We have an industry lacking of so much leadership and examples of practices that came out of hard proven experience, because as developers we are arrogant animals, working in solo, reinventing the wheel every time we can pretending software is totally different than years or decades ago, while programming (and tech in general) is almost all the time a sharing and a team experience where you work surrounded by other people and discover 🔍, research 🧪 and learn 📚 all the time and evolve from learnings of the past. The best example nowadays I guess is Open Source Software and how more often than not, collaboration enables us to create better technology and deliver with more quality, still, some folks just don't get it.&lt;/p&gt;

&lt;p&gt;I understand that like any expertise, is hard to pass the knowledge of so many experiences in a single book, but I think the authors did a really great job abstracting very important concepts into these 53 topics and 100 tips💡. While some may be familiar to your own experience depending of your mileage, others will be new or refreshing points of view of, what should be considered, &lt;strong&gt;universal knowledge and skills in software development&lt;/strong&gt;. 🎓&lt;/p&gt;

&lt;p&gt;As an example, take the topics like &lt;em&gt;DRY - Don't repeat yourself&lt;/em&gt;, &lt;em&gt;Orthogonality&lt;/em&gt; and &lt;em&gt;Decoupling&lt;/em&gt; and you will end up mapping a lot of the advice to OOP practices like SOLID principles for instance, but in a more abstract and universally applicable way which to me is very useful so that the advice can be applied in any context, stack and paradigm 🤯. It's up to you really, to delve deeper within your own context and develop and practice in your craft beyond the &lt;strong&gt;thorough advice in the book&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Take also for example how &lt;em&gt;Agile&lt;/em&gt; practices have been transforming over the years but the essence of &lt;em&gt;Agility&lt;/em&gt; is more often than not, misunderstood, Andrew and Dave, who participated in the &lt;em&gt;Agile Manifesto&lt;/em&gt;, explains perfectly what is &lt;em&gt;The Essence of Agility&lt;/em&gt; (Topic 48), in a way that you can make it your anchor, no matter the context you are in because remember that &lt;em&gt;Coconuts Don't Cut It&lt;/em&gt; (Topic 50) and what works for one team may not work for other 🤹🏻‍♀️ to be able to &lt;em&gt;Deliver when users need it&lt;/em&gt; (Tip 88) operating with &lt;strong&gt;true Agility&lt;/strong&gt;. 🤸🏻‍♂️&lt;/p&gt;

&lt;h2&gt;
  
  
  A journey that never ends 🧗🏻‍♀️
&lt;/h2&gt;

&lt;p&gt;I just shed a light on why is so important for newcomers to software to start with this solid advice from really experienced programmers who have been through a lot. As for seasoned programmers, you will end up wanting to become more pragmatic and efficient at code and keep it as a good reference throughout your journey to mastery, &lt;strong&gt;a journey that never ends&lt;/strong&gt; thankfully and this is your &lt;em&gt;compass&lt;/em&gt; 🧭&lt;/p&gt;

&lt;p&gt;To me personally, the book gave me more to learn about and also sparked a renewed hope for programmers to be more pragmatic and unorthodox, less individualistic and philosophical, become active instead of passive agents of change, so that one really becomes part of the collaborative force of progress that technology is all about.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>wetware</category>
      <category>bookreview</category>
      <category>books</category>
    </item>
    <item>
      <title>UI Command Pattern : Part II</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sun, 29 Nov 2020 03:15:40 +0000</pubDate>
      <link>https://dev.to/keozdev/ui-command-patterns-part-ii-1poc</link>
      <guid>https://dev.to/keozdev/ui-command-patterns-part-ii-1poc</guid>
      <description>&lt;p&gt;This post is a continuation on the &lt;a href="https://dev.to/keozdev/ui-command-pattern-268n"&gt;UI Command Pattern : Part I&lt;/a&gt; where I go through different approaches for &lt;code&gt;ICommand&lt;/code&gt; implementation with pros and cons.&lt;/p&gt;

&lt;p&gt;I left out &lt;a href="https://www.mvvmcross.com/"&gt;MvvmCross&lt;/a&gt; Command implementation in that post but now I have updated the sample application with &lt;code&gt;MvxAsyncCommand&lt;/code&gt;. You can follow along with the same project from here: &lt;a href="https://github.com/keozx/CleanRx/tree/master/src/samples/Commands"&gt;https://github.com/keozx/CleanRx/tree/master/src/samples/Commands&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison
&lt;/h3&gt;

&lt;p&gt;Since my winner from last post is &lt;a href="https://dev.to/keozdev/ui-command-pattern-268n#option-4"&gt;ReactiveCommand&lt;/a&gt; I present a framework command comparison including &lt;code&gt;ReactiveCommand&lt;/code&gt;, &lt;code&gt;AsyncCommand&lt;/code&gt; and &lt;code&gt;MvxAsyncCommand&lt;/code&gt; given that to my surprise, MvvmCross has a very nice implementation of the Command, though still lacking of course the great versatility of &lt;code&gt;ReactiveCommand&lt;/code&gt; but nonetheless a good option.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Async&lt;/th&gt;
&lt;th&gt;MvxAsync&lt;/th&gt;
&lt;th&gt;Reactive&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Executes a simple bindable Action&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️ &amp;lt;T&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create from Task&amp;lt;T&amp;gt; (not async void)&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieve unhandled exceptions&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observes boolean changes for "CanExecute" behavior through INPC (not RaiseCanExecute)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️ *WhenAnyValue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observes IObservable ticks for "CanExecute" behavior&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guards against double execution (double tap)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Returns a &amp;lt;T&amp;gt; result at end of execution&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessible "CanExecute" state&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessible "IsExecuting" state&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subscribe to Completion and executes handler for &amp;lt;T&amp;gt; result&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;p&gt;The biggest downside of &lt;code&gt;MvxCommand&lt;/code&gt; is the lack of handling errors like &lt;code&gt;AsyncCommand&lt;/code&gt; does, so if we want to handle unhandled exceptions we have to wrap it ourselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;p&gt;There is an overload constructor that takes a &lt;code&gt;CancellationToken&lt;/code&gt; for the function being executed so you can cancel the task at a later point, this token is autogenerated so to cancel it from a button for example I think is not straightforward, still, this is not as interesting as the way &lt;code&gt;ReactiveCommand&lt;/code&gt; handles cancellation in a functional state pulling way.&lt;/p&gt;

&lt;p&gt;One of the great things of &lt;code&gt;MvxCommand&lt;/code&gt; and &lt;code&gt;MvxAsyncCommand&lt;/code&gt; is the ability to pass a boolean on instantiation, to indicate whether or not concurrent execution is allowed for a given command, this mimics &lt;code&gt;ReactiveCommand&lt;/code&gt; double tap protection. Unfortunately that's all the advantage we have over &lt;code&gt;AsyncCommand&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The ICommand implementation still has a winner in &lt;code&gt;ReactiveCommand&lt;/code&gt; even though all the features are only accessible through the base and not only the interface, I think all is moving away from ICommand anyway, just look at how things are going in MAUI + MVU for example, is time for new UI paradigms and more efficient patterns. This is an exciting time for innovation, in the meantime let's make it all reactive!&lt;/p&gt;

</description>
      <category>xamarin</category>
      <category>csharp</category>
      <category>mobile</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>UI Command Pattern : Part I</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sat, 19 Sep 2020 20:23:01 +0000</pubDate>
      <link>https://dev.to/keozdev/ui-command-pattern-268n</link>
      <guid>https://dev.to/keozdev/ui-command-pattern-268n</guid>
      <description>&lt;p&gt;This post is intended to discuss different Command pattern approaches when developing UI user interactions through &lt;code&gt;ICommand&lt;/code&gt; interface. &lt;/p&gt;

&lt;p&gt;You can follow along with the final code here:&lt;br&gt;
&lt;a href="https://github.com/keozx/CleanRx/tree/master/src/samples/Commands"&gt;https://github.com/keozx/CleanRx/tree/master/src/samples/Commands&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is important to analyze each approach and the differences among them so when it is adopted within a team is easier to break barriers of adopting one framework or the other or small part of it. Most organizations will stick to one framework but that is seldom efficient when you need the best tool to get the job done. In my opinion, contrary to common belief, mixing up frameworks is actually a good thing, linking and proper dependency management should remove the clutter around having many tools in a single code base.&lt;/p&gt;

&lt;p&gt;This post is divided in 3 main sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The framework comparison below.&lt;/li&gt;
&lt;li&gt;Or, you can skip to the demo requirement here.&lt;/li&gt;
&lt;li&gt;Or, you can skip to the implementations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Command framework comparison
&lt;/h2&gt;

&lt;p&gt;In the following table I compare different Command frameworks out there, most of them of course are part of a bigger framework but focusing on one small piece at a time helps in making the right choice on your current situation. &lt;br&gt;
I chose to analyze what I think are the frameworks most commonly used, I'm missing MVVMCross for now as well as others, but I'll add them in following posts as soon as I have time to play around with them, in this first part I have included only these 4 approaches with the features I found relevant to consider, but this can change later and will update the post and code accordingly.&lt;/p&gt;

&lt;p&gt;A better visibility version can be found in my &lt;a href="https://keozx.github.io/CleanRx/ui_patterns/#command-framework-comparison"&gt;GitHub Page&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;XF&lt;/th&gt;
&lt;th&gt;Prism&lt;/th&gt;
&lt;th&gt;Async&lt;/th&gt;
&lt;th&gt;Reactive&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Executes a simple bindable Action&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️ &amp;lt;T&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create from Task&amp;lt;T&amp;gt; (not async void)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieve unhandled exceptions&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observes boolean changes for "CanExecute" behavior through INPC (not RaiseCanExecute)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️ *WhenAnyValue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observes IObservable ticks for "CanExecute" behavior&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guards against double execution (double tap)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Returns a &amp;lt;T&amp;gt; result at end of execution&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessible "CanExecute" state&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessible "IsExecuting" state&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subscribe to Completion and executes handler for &amp;lt;T&amp;gt; result&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✔️&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Xamarin.Forms &lt;code&gt;Command&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Based on above comparison, is there any reason to use XF Command? well only for a quick POC or if all you are really going to do is clicking a button and do something simple that does not require any other feature. However there may be some memory save if you are having a lot of simple buttons in a screen. A benchmark comparison coming soon.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.command-1?view=xamarin-forms"&gt;Xamarin Docs&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Prism &lt;code&gt;DelegateCommand&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;DelegateCommand&lt;/code&gt; is a better Command implementation because allows observing a boolean for 'CanExecute', but other than that, feels like a half-baked implementation of &lt;code&gt;ICommand&lt;/code&gt;, not really intended in my opinion for use in complex apps. &lt;a href="https://prismlibrary.com/docs/commanding.html"&gt;Prism Docs&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  AsyncAwaitBestPractices &lt;code&gt;AsyncCommand&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;AsyncCommand&lt;/code&gt; comes from package &lt;a href="https://github.com/brminnick/AsyncAwaitBestPractices"&gt;Async Await Best Practices&lt;/a&gt; which apart from giving an implementation of ICommand with error handling, prevents the use of async void. Also the library provides for other good stuff like &lt;code&gt;SafeFireAndForget()&lt;/code&gt; and &lt;code&gt;WeakEventManager&lt;/code&gt; so is a handy package for Task based programming.&lt;/p&gt;

&lt;p&gt;Unfortunately it does not provide &lt;code&gt;CanExecute&lt;/code&gt; observer pattern like &lt;code&gt;DelegateCommand&lt;/code&gt;, but is capable of catching exceptions if you provide an Error Handler parameter when creating the Command.&lt;/p&gt;
&lt;h3&gt;
  
  
  ReactiveUI &lt;code&gt;ReactiveCommand&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;From all, from what you can see in the table &lt;a href="https://www.reactiveui.net/docs/handbook/commands/"&gt;ReactiveCommand&lt;/a&gt; is your swiss army knife implementation of &lt;code&gt;ICommand&lt;/code&gt;, fully featured and rock solid, you can't go wrong with it, the flexibility of &lt;code&gt;IObservable&lt;/code&gt; as consumer and implementer gives us ultimate adaptability. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ReactiveCommand&lt;/code&gt; is also the only one capable of providing a generic typed result, additional to the default parameter in &lt;code&gt;ICommand&lt;/code&gt;, to allow to retrieve the execution output, this is useful for Unit Testing because often you would want to assert the outcome of an operation starting with the click of a button end to end.&lt;/p&gt;

&lt;p&gt;One thing that shines from the rest is also that it has built-in execution blocking so it won't allow double tap or double execution if already fired, whether is a Task or an Action. Also, you can retrieve &lt;code&gt;CanExecute&lt;/code&gt; and &lt;code&gt;IsExecuting&lt;/code&gt; states to have better awareness for other components that may need to know execution state.&lt;/p&gt;

&lt;p&gt;*While not directly capable of observing a boolean property, what RxUI Command offers is accepting the more robust &lt;code&gt;IObservable&lt;/code&gt; type parameter for &lt;code&gt;CanExecute&lt;/code&gt; behavior. You have to take an extra step to use &lt;code&gt;WhenAnyValue()&lt;/code&gt; extension to wrap the INPC events from a property into an observable but in a real world application you rarely just watch for a single source, you could chain different observables here without having to notify of Can Execute has changed, so this is handy when having to watch multiple states at once and calculate whether or not the Command should be enabled or disabled.&lt;/p&gt;

&lt;p&gt;In the following sections I go through a demo setup to analyze each one in deep.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up a meaningful use case 👨‍🏫
&lt;/h2&gt;

&lt;p&gt;Let's say we have a minimum requirement when we click a button in our app, simple but still a realistic requirement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We should be able to click a button in screen to execute an Important Task&lt;/li&gt;
&lt;li&gt;User can control whether or not the button should be enabled&lt;/li&gt;
&lt;li&gt;There may be an event that would make the button not available to click, when the event for disabling it happens we disable the button, then enable it with the following event&lt;/li&gt;
&lt;li&gt;Button should be enabled only when the user has manually enabled it and the event for enabling it occurs.&lt;/li&gt;
&lt;li&gt;Oh but also the Important Task shall not be executing while another Task is happening, this is an important Task!&lt;/li&gt;
&lt;li&gt;Important Task may error with an Exception, handle it&lt;/li&gt;
&lt;li&gt;Important Task takes a parameter from the Command execution.&lt;/li&gt;
&lt;li&gt;After Important Task finishes we may do some operation on the result, this handler may also cause an unexpected exception, handle it but this is an unrecoverable state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's explore our options for a minimum implementation of this, shall we?&lt;/p&gt;
&lt;h3&gt;
  
  
  Defining a simple View
&lt;/h3&gt;

&lt;p&gt;Here I'm using C# Markup extensions as of latest XF 4.8 (I don't think XAML is suited for UI code for reasons I'll explain in another post)&lt;/p&gt;

&lt;p&gt;Notice I declare the Parameter and Result types to pass a parameter and return a Result from the Task to execute.&lt;/p&gt;

&lt;p&gt;The view is simply a Button and a Switch to enable manually the the button, the command is bound to the View Model we define later here, the VM will handle results, errors and executability of the Command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MainPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;formsVm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FormsCmdViewModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;delegateVm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DelegateCmdViewModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;asyncVm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AsyncCmdViewModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rxVm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ReactiveCmdViewModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StackLayout&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Spacing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
                &lt;span class="p"&gt;{&lt;/span&gt; 
                    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContentView&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; 
                        &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formsVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StackLayout&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formsVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                            &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Forms Command"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formsVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FormsCommand&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                        &lt;span class="n"&gt;formsVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;parameterSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Parameter&lt;/span&gt;
                                        &lt;span class="p"&gt;{&lt;/span&gt;
                                            &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Forms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="p"&gt;}),&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Enable Command?"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formsVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&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="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContentView&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; 
                        &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delegateVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StackLayout&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delegateVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                            &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Delegate Command"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delegateVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DelegateCommand&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                        &lt;span class="n"&gt;delegateVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;parameterSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Parameter&lt;/span&gt;
                                        &lt;span class="p"&gt;{&lt;/span&gt;
                                            &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"DelegateCommand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="p"&gt;}),&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Enable Command?"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delegateVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&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="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContentView&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; 
                        &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StackLayout&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                            &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Async Command"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsyncCommand&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                        &lt;span class="n"&gt;asyncVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;parameterSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Parameter&lt;/span&gt;
                                        &lt;span class="p"&gt;{&lt;/span&gt;
                                            &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AsyncCommand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="p"&gt;}),&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Enable Command?"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&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="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContentView&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; 
                        &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rxVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;StackLayout&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;BindingContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rxVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;Children&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                            &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Reactive Command"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                        &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rxVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RxCommand&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                        &lt;span class="n"&gt;rxVm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="n"&gt;parameterSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Parameter&lt;/span&gt;
                                        &lt;span class="p"&gt;{&lt;/span&gt;
                                            &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ReactiveCommand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                        &lt;span class="p"&gt;}),&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Enable Command?"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rxVm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                            &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Parameter&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;h3&gt;
  
  
  Declaring the Important Task
&lt;/h3&gt;

&lt;p&gt;We simply define a Task with a Delay and randomly throwing an exception, a simple Result instance is returned from this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ImportantTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Command executed from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&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;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rnd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&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;rnd&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exception! Because it can happen"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&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="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Type&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;
  
  
  Commands Implementation
&lt;/h2&gt;

&lt;p&gt;Let's now explore our options to implement the Command execution and determining when is enabled or not, and also how to catch exceptions in each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Xamarin Forms &lt;code&gt;Command&lt;/code&gt; 🤦‍♂️
&lt;/h3&gt;

&lt;p&gt;Ok so let's firstly declare our command in the constructor of the FormsCmdViewModel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;FormsCmdViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_device&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DeviceService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;_device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;OnEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;FormsCommand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;OnClickAsyncVoid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CanExecute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;OnEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EnabledFromEvent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;_enabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Event triggered: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_enabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we use a timer to set &lt;code&gt;EnabledFromEvent&lt;/code&gt; property that will be a conditional to enable the &lt;code&gt;Command&lt;/code&gt; and hence, the button.&lt;/p&gt;

&lt;p&gt;Now let's define the &lt;code&gt;OnClickAsyncVoid()&lt;/code&gt; method &lt;a&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnClickAsyncVoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We have to await the Task and try/catch this async void,&lt;/span&gt;
    &lt;span class="c1"&gt;// otherwise we would not catch exceptions on the ImportantTask handler, &lt;/span&gt;
    &lt;span class="c1"&gt;// like when we don't change Enabled in the Main Thread, then our app wouldn't make a noise!&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;Enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ImportantTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;HandleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;InvalidOperationException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Expected Exception handled! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;}&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="c1"&gt;// If you did this you would run into threading exception,&lt;/span&gt;
            &lt;span class="c1"&gt;// shows our point above.&lt;/span&gt;
            &lt;span class="c1"&gt;// Enabled = true;&lt;/span&gt;
            &lt;span class="n"&gt;_device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginInvokeOnMainThread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Exception from handler! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// This is an unrecoverable state of the app!&lt;/span&gt;
        &lt;span class="k"&gt;throw&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;So as you can see is a very simple method that basically does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executes our &lt;code&gt;ImportantTask&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Calls the result handler through &lt;code&gt;HandleResult()&lt;/code&gt; method and catches the expected &lt;code&gt;InvalidOperationException&lt;/code&gt;, we simply log to console these for simplicity.&lt;/li&gt;
&lt;li&gt;Also. We catch unexpected exceptions happening inside the execution with the outer try catch, notice that setting &lt;code&gt;Enabled = true&lt;/code&gt; out of Main Thread would cause the exception, while you can remove it later after the code is safe, most of times you will want to keep a handler in cases an unexpected exception happens in more complex tasks, notice also that we crash the app as we don't know the state of the app if we ever get here!&lt;/li&gt;
&lt;li&gt;Lastly, it will disable the &lt;code&gt;Command&lt;/code&gt; at beginning of execution and at the end setting &lt;code&gt;Enabled&lt;/code&gt; property&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method completes our requirement, there is one thing we have to do so that our Button disables or enables as we operate the switch or a timed event happens, in our properties we need to call also &lt;code&gt;RaiseCanExecuteChanged()&lt;/code&gt; so the &lt;code&gt;Command&lt;/code&gt; evaluates &lt;code&gt;CanExecute&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_enabled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_enabled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;set&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;_enabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&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;FormsCommand&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;ChangeCanExecute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_enabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;EnabledFromEvent&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_enabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;set&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;_enabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&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;FormsCommand&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;ChangeCanExecute&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;This method will be also used for &lt;code&gt;DelegateCommand&lt;/code&gt;, for the &lt;code&gt;CanExecute()&lt;/code&gt; method we simply define that both booleans should be true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;CanExecute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;obj&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;Enabled&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;EnabledFromEvent&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;h3&gt;
  
  
  Option 2: Prism &lt;code&gt;DelegateCommand&lt;/code&gt; 💆‍♂️
&lt;/h3&gt;

&lt;p&gt;Well, I was thinking that&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;ObservesCanExecute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;canExecute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would accept the 2 conditions we have set up at once, but it will not, so only you can observe properties with &lt;code&gt;ObservesProperty()&lt;/code&gt;, however you can chain together several so in this case we would not need to call &lt;code&gt;RaiseCanExecuteChanged()&lt;/code&gt; which is analogue to XF Command's &lt;code&gt;ChangeCanExecute()&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;DelegateCommand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DelegateCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;OnForms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CanExecute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ObservesProperty&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ObservesProperty&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EnabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;ObservesProperty()&lt;/code&gt; method, allows us to save some code delegating the knowledge of when to call &lt;code&gt;RaiseCanExecuteChanged&lt;/code&gt; automatically, to the Command itself, instead of imperatively calling it in the properties! We sort of pull the state, not push it, which is one essential aspect of &lt;em&gt;Reactive paradigm&lt;/em&gt;, but this is not using &lt;em&gt;Reactive Extensions&lt;/em&gt; at all. Notice that this will tell when to call &lt;code&gt;CanExecute()&lt;/code&gt;, not really evaluating the properties altogether, so you can still have arbitrary logic in the &lt;code&gt;CanExecute()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;and that's it... the &lt;code&gt;OnClickAsyncVoid&lt;/code&gt; defined before is exactly the same, let's move on!&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: &lt;code&gt;AsyncCommand&lt;/code&gt; 🧰
&lt;/h3&gt;

&lt;p&gt;The most interesting use of &lt;code&gt;AsyncCommand&lt;/code&gt; is that it can handle passing Tasks for execution and a way to handling errors out of the box, that way we have the following declaration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;AsyncCommand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AsyncCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="n"&gt;OnClickAsyncTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CanExecute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows to convert our &lt;code&gt;OnClickAsyncVoid()&lt;/code&gt; to an &lt;code&gt;OnClickAsyncTask()&lt;/code&gt; &lt;a&gt;&lt;/a&gt; to be simplified a bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;OnClickAsyncTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&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="c1"&gt;// Ideally, we would return the Task instead of awaiting here,&lt;/span&gt;
                &lt;span class="c1"&gt;// but we would not be able to retrieve the Result at Command level&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ImportantTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nf"&gt;HandleResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;InvalidOperationException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Expected Exception handled! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;}&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="c1"&gt;// If you did this you would run into threading exception,&lt;/span&gt;
                &lt;span class="c1"&gt;// shows our point above.&lt;/span&gt;
                &lt;span class="c1"&gt;// Enabled = true;&lt;/span&gt;
                &lt;span class="n"&gt;_device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginInvokeOnMainThread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&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;This will remove some code from the method and remove the async void!&lt;/p&gt;

&lt;p&gt;However, we have to still call explicitly when we want it to evaluate the conditions for &lt;code&gt;CanExecute&lt;/code&gt; behavior contrary to &lt;code&gt;DelegateCommand&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AsyncCommand&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;AsyncCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;RaiseCanExecuteChanged&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And also explicitly enable and disable the button as all previous examples. But this can be done better!&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 4: &lt;code&gt;ReactiveCommand&lt;/code&gt; 👨‍🔬
&lt;/h3&gt;

&lt;p&gt;Let's declare our &lt;code&gt;ReactiveCommand&lt;/code&gt; functionality as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;RxCommand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReactiveCommand&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateFromTask&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ImportantTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;CanExecute&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;RxCommand&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HandleResult&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;RxCommand&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ThrownExceptions&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot is going on here! So let's demystify it. The first declaration is similar to others, we use the static &lt;code&gt;CreateFromTask()&lt;/code&gt; method to pass in this case not the &lt;code&gt;OnClickAsyncTask&lt;/code&gt; anymore, but the &lt;code&gt;ImportantTask&lt;/code&gt; directly. &lt;/p&gt;

&lt;p&gt;This saves us a lot of code because as you may remember, this command can take a Task but also the Command enables and disables when the Task starts and completes, respectively.&lt;/p&gt;

&lt;p&gt;Also, we don't need to wrap the Task calling into an &lt;code&gt;async&lt;/code&gt; method because we can simply &lt;code&gt;Subscribe()&lt;/code&gt; to the execution completion of the &lt;code&gt;ReactiveCommand&lt;/code&gt;, which allows to retrieve the result and pass it to our &lt;code&gt;HandleResult&lt;/code&gt; method or do something else as the command is an &lt;code&gt;IObservable&amp;lt;T&amp;gt;&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;Lastly, &lt;code&gt;ReactiveCommand&lt;/code&gt; provides a way to catch any thrown Exceptions through &lt;code&gt;ThrownExceptions&lt;/code&gt; observable. We pass the &lt;code&gt;OnError&lt;/code&gt; handler but as we don't have a way to filter through the exceptions, we simply type sniff the exception as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Expected Exception handled! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;}&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;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Exception from handler! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// This is an unrecoverable state of the app!&lt;/span&gt;
        &lt;span class="n"&gt;RxApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OnNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&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;This may not be ideal for more complex scenarios, in which case we can still keep a very slim version of &lt;code&gt;OnClickAsyncTask()&lt;/code&gt; while also keeping the unexpected exception handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;OnClickAsyncTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ImportantTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&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;InvalidOperationException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Expected Exception handled! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;default&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;We now don't have the side effects as in the previous method version, notice that even if is an async Task, it is a generic &lt;code&gt;Task&amp;lt;TResult&amp;gt;&lt;/code&gt; which the &lt;code&gt;ReactiveCommand&lt;/code&gt; can easily make available to us, something you simply can't do with any other Command, that however comes with a bit of a price, &lt;code&gt;ICommand&lt;/code&gt; is still an interface &lt;code&gt;ReactiveCommand&lt;/code&gt; implements but to handle result operations it also implements &lt;code&gt;IObservable&amp;lt;TResult&amp;gt;&lt;/code&gt;, so you will need to declare the command property differently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ReactiveCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;RxCommand&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All in all, this has allowed us to have a &lt;em&gt;Single Responsibility&lt;/em&gt; method, such as execute our Task and handle any errors coming from it, no need to care about the execution state of the Command or if there is another error down the road of execution that we can't handle. &lt;/p&gt;

&lt;p&gt;Lastly, let's explore the &lt;code&gt;CanExecute&lt;/code&gt; part, in order to mimic what DelegateCommand's &lt;code&gt;ObservesProperty()&lt;/code&gt; can do we have to pass an &lt;code&gt;IObservable&amp;lt;bool&amp;gt;&lt;/code&gt; to the command declaration, so we have to modify &lt;code&gt;CanExecute()&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IObservable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CanExecute&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAnyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Enabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enabledEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;enabledEvent&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;We use the &lt;code&gt;WhenAnyValue&lt;/code&gt; extension method from &lt;em&gt;ReactiveUI&lt;/em&gt; to observe the INPC events easily and at once for both properties &lt;code&gt;Enabled&lt;/code&gt; and &lt;code&gt;EnabledFromEvent&lt;/code&gt;, the third argument is a selector, so you can pass a custom logic to evaluate the two properties observed, in this case we simply want both to be true, but again, this is a powerful tool to enable complex logic as you can see.&lt;/p&gt;

&lt;p&gt;Note also, that even though we had to make this method return &lt;code&gt;IObsevable&amp;lt;bool&amp;gt;&lt;/code&gt;, it is now in a whole different league than just observing boolean properties, meaning you can chain other observables together to create complex pipelines. Plus we don't need to tell the command to evaluate imperatively this condition on each property setter, as it should be!&lt;/p&gt;

&lt;p&gt;Again, we don't need to tell the Command when it should enable through the properties, a function is responsible to evaluate it when something changes, we react.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus code! 🎁
&lt;/h3&gt;

&lt;p&gt;You may notice that for simple cases like ours, the &lt;code&gt;IObservable&amp;lt;bool&amp;gt;&lt;/code&gt; for &lt;code&gt;CanExecute&lt;/code&gt; parameter may be a bit hard to read specially since you are only evaluating 2 booleans. So what I did is try to mimic the way &lt;code&gt;DelegateCommand&lt;/code&gt; is able to observe properties with &lt;code&gt;ObservesCanExecute()&lt;/code&gt; in a compact way.&lt;/p&gt;

&lt;p&gt;While I'm a total newbie dealing with &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/"&gt;C# Expressions&lt;/a&gt;, I was able to come up with a quick and dirty extension method that will create our &lt;code&gt;IObservable&amp;lt;bool&amp;gt;&lt;/code&gt; for us, given 1 or 2 INPC enabled boolean properties. I give you 'WhenAnyValueMixin' class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WhenAnyValueMixin&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IObservable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ObservesProperty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;TSource&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;property1&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;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAnyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;GetExpression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IObservable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ObservesProperty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;TSource&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;property2&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;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAnyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
            &lt;span class="n"&gt;GetExpression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;GetExpression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;property2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetExpression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This expression is our goal for the ObservableForProperty():&lt;/span&gt;
        &lt;span class="c1"&gt;// Expression&amp;lt;Func&amp;lt;ReactiveCmdViewModel, bool&amp;gt;&amp;gt; target;&lt;/span&gt;
        &lt;span class="c1"&gt;// And this parameter is a MemberExpression (=&amp;gt; Enabled) (because is a member?)&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;property1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MemberExpression&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;    
            &lt;span class="c1"&gt;// Let user know if is not MemberExpression&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotSupportedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MemberExpression expected!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Expression for the Parameter type we need in the goal above, assuming we have a member on TSource.&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="c1"&gt;// Create Member Access Expression, as in vm =&amp;gt; vm.Enabled from the Member Info from the above of course.&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;memberAccess&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MakeMemberAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMemberInfo&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c1"&gt;// Create target expression from the member access and parameter expressions so we get vm =&amp;gt; vm.Enabled to get it's observable below&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lambda&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;memberAccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parameter&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;lambda&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Fpr reference, started with this&lt;/span&gt;
        &lt;span class="c1"&gt;// return this.ObservableForProperty(lambda,  false, false)&lt;/span&gt;
        &lt;span class="c1"&gt;//     .Select((change, i) =&amp;gt; change.Value);&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;As this is kind of out of scope for this post, I'll leave it to you to explore the code, which is not much, but this allows to declare our &lt;code&gt;CanExecute()&lt;/code&gt; this way!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IObservable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CanExecute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Mimicking DelegateCommand with WhenAnyValue here:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ObservesProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EnabledFromEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice also you only need to pass &lt;code&gt;CanExecute()&lt;/code&gt; to the Command, not the ObservesProperty in the Command declaration which is required for DelegateCommand, this is doing both evaluating CanExecute and Observing the properties for both being true in a single shot. Also, you can still attach a selector so you can do arbitrary logic on the 'ticked' values from the Observable.&lt;/p&gt;

&lt;p&gt;Pretty neat!&lt;/p&gt;

&lt;h2&gt;
  
  
  A winner? 🏆
&lt;/h2&gt;

&lt;p&gt;I have made up my mind, after trying out all of them now, to me there is not better implementation of &lt;code&gt;ICommand&lt;/code&gt; + &lt;code&gt;IObservable&lt;/code&gt; than Reactive UI, in my opinion we don't need any other implementation.&lt;/p&gt;

&lt;p&gt;Consider also how much we reduced our code footprint in each iteration!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;XF Command&lt;/th&gt;
&lt;th&gt;DelegateCommand&lt;/th&gt;
&lt;th&gt;AsyncCommand&lt;/th&gt;
&lt;th&gt;ReactiveCommand&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Enabled/EnabledFromEvent property setters lines&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OnClickAsyncVoid/OnClickAsyncTask executors lines&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;0-12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OnClick* cognitive complexity&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Readability weight (1-5)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last one may be subjective but I think the &lt;code&gt;ReactiveCommand&lt;/code&gt; version of the ViewModel is more readable, with less side effects and more scalable. This comes more evident as your complexity increases and you realize reactive programming is a natural fit for some advanced scenarios. Again, all this was all a simple example but is a good starting point for Reactive Extensions and ReactiveUI, one command to rule them all 😁&lt;/p&gt;

&lt;p&gt;I find it unfortunate that the Reactive Paradigm is just gaining momentum even though has more than a decade of existence, and that's why few frameworks are leveraging Reactive Extensions, using Rx super charges a tool and makes it more versatile to use; &lt;a href="https://github.com/shinyorg/shiny"&gt;Shiny&lt;/a&gt; is a good example of providing the flexibility of Reactive in a library and hope that's a trend.&lt;/p&gt;

&lt;p&gt;I also have started a project that tries to close the gap on examples (still being cooked!) using Reactive and also be useful as an Architecture guidance, &lt;a href="https://github.com/keozx/CleanRx"&gt;CleanRx&lt;/a&gt;&lt;/p&gt;

</description>
      <category>xamarin</category>
      <category>csharp</category>
      <category>mobile</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Book Review - Adaptive Code: Agile coding with design patterns and SOLID principles</title>
      <dc:creator>Jorge Castro</dc:creator>
      <pubDate>Sat, 25 Jul 2020 18:31:06 +0000</pubDate>
      <link>https://dev.to/keozdev/book-review-adaptive-code-agile-coding-with-design-patterns-and-solid-principles-4c82</link>
      <guid>https://dev.to/keozdev/book-review-adaptive-code-agile-coding-with-design-patterns-and-solid-principles-4c82</guid>
      <description>&lt;p&gt;Starting this blog with a book review, and what a book, probably one that influences greatly my career path ahead of me in years to come.&lt;/p&gt;

&lt;h3&gt;
  
  
  In a nutshell, 🥜
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Enlightening ⚡ &lt;a href="https://www.microsoftpressstore.com/store/adaptive-code-agile-coding-with-design-patterns-and-9781509302581"&gt;book&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4T56wSGa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/jotmw3643g8yrnycsfdg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4T56wSGa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/jotmw3643g8yrnycsfdg.jpg" alt="Alt Text" width="532" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/GaryMcLeanHall"&gt;Gary&lt;/a&gt; takes us in a journey through the seas of patterns and practices that helps us build quality software because it means with them we can write &lt;strong&gt;adaptable, maintainable, testable and even, readable code&lt;/strong&gt;, go figure! We all could use some of that.&lt;/p&gt;

&lt;p&gt;He explains with enough deepness, behavioral and architectural patterns (and anti-patterns) and demystifies SOLID principles to achieve all of this, and explains what Test Driven Development is all about and how to leverage it to write quality tests which leads to less technical debt.&lt;/p&gt;

&lt;p&gt;At the end, he shows how to put all things together with Dependency Injection. And also some guidance of metrics like Coupling, Cohesion, and &lt;a href="https://en.wikipedia.org/wiki/Connascence"&gt;Connascence&lt;/a&gt;, which I wish we could get more of it, because I believe the more we measure, the better we can see progress in our performance.&lt;/p&gt;

&lt;p&gt;He even dedicates and entire part of the book to Agile and Kanban because without proper execution, simply there is little you can do as developer when projects struggle to find proper management of work items, that however may deserve a deeper understanding and overall, practice, that more often than not, is not in control of the developers, but is our responsibility we are ready to use them and to encourage the use of proper Agile practices. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is all about how we deliver value and with how much quality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  But also, 🤷‍♂️
&lt;/h3&gt;

&lt;p&gt;Leaves me with more questions or adds more to all time questions I have had no answers in my 10+ years of experience as developer.&lt;/p&gt;

&lt;p&gt;It left me wanting more!&lt;/p&gt;

&lt;h3&gt;
  
  
  First of all, 📚
&lt;/h3&gt;

&lt;p&gt;Is this some kind of forbidden knowledge?&lt;/p&gt;

&lt;p&gt;Maybe, because too many people have tried to debunk these patterns and practices in order to do their own over or under engineered ideas?&lt;/p&gt;

&lt;p&gt;I mean, this is not new at all, even though I think Gary makes an excellent job at demystifying the core of the principles and patterns and have clear words on explaining a lot that otherwise may appear too abstract, the way most likely you find on the web.&lt;/p&gt;

&lt;p&gt;And, honestly you don't hear many co-workers talking about in the daily coding drill, I guess I've heard more of it in interviews 🤔&lt;/p&gt;

&lt;h3&gt;
  
  
  Are we experienced enough? 👴
&lt;/h3&gt;

&lt;p&gt;One thing is clear though, you don't get enlightenment out of this book if you are not an experienced developer who have gone through a lot.&lt;/p&gt;

&lt;p&gt;And by experience I don't mean doing the same way of years of crafting software over and over with the same company, same technology or architecture, or the same project, nor I mean you need 20+ years of experience; at least, 5 years involved in diverse projects for sure, small and large, with different approaches, with multi-cultural and interdisciplinary teams, small and large; facing the problems of, and not limited to, not testing, not properly abstracting, not using interfaces and patterns properly and constantly battling the technical debt left behind affecting the project health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is the only way you can appreciate what is exposed here.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Then we all have a story on failed projects 🌩
&lt;/h3&gt;

&lt;p&gt;Why the struggle of having to go through failed projects that have accumulated to much reckless technical debt that there is no recover from it? Too many broken windows that lead to unrecoverable trend downwards as explained in &lt;a href="https://www.amazon.com/dp/0135957052/ref=cm_sw_em_r_mt_dp_U_9i0gFbZGEKS0G"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Decision makers and leaders have to step up and take responsibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But how do you reverse this trend? Meanwhile we wander around with our own "good enough" implementations of code, not leaning towards an Agile ever changing environment, but heck, even Agile is more often than not an incomprehensible abstract, if that's what we got in the process, what can we expect from the ever hidden humble code only visible to the developers.&lt;/p&gt;

&lt;p&gt;Far too many projects and for far too long, Software Entropy in projects is still a constant.&lt;br&gt;
Why is it hard to come together and craft quality software? And who is held accountable for it?&lt;/p&gt;
&lt;h3&gt;
  
  
  Why is this even relevant? ╰（‵□′）╯
&lt;/h3&gt;

&lt;p&gt;While these software practices may have been forgotten for some, new to others, or misunderstood by the majority, and as new trends of creating software arise like Power apps, 0-code builders, or AI powered magic; we still have to build the systems that interact with or extend these &lt;em&gt;abstractions&lt;/em&gt; for generations to come, and how you &lt;em&gt;build&lt;/em&gt; it and how you &lt;em&gt;execute&lt;/em&gt; it, still matters.&lt;/p&gt;

&lt;p&gt;Tightly coupled is the way you manage or execute a project being Agile or otherwise, and how you code it through software practices that drive your craft.&lt;/p&gt;

&lt;p&gt;As engineering mindset or IT community have we really agreed upon a set of practices before moving on or try to avoid them?&lt;/p&gt;

&lt;p&gt;Have priorities got in our way, or time to market, or deadlines, or the process itself to deliver fast while compromising quality?&lt;/p&gt;
&lt;h3&gt;
  
  
  So, what are we missing? 🔎
&lt;/h3&gt;

&lt;p&gt;Is this science? 🧪 well yes Software Engineering is a branch of Computer Science right? but perhaps is just too hard to prove several practices usefulness until you really practice it, and put effort in understanding.&lt;/p&gt;

&lt;p&gt;Perhaps there are too little too few examples of success or real-world validation.&lt;br&gt;
Perhaps success stories exist in the world and in the knowledge of teams that will be archived or left out for others to learn their experience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Perhaps too much is left to each one of our egos and theoretical interpretation instead of relying on hard evidence, maturity or metrics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Is it a change of paradigm? pretty much like Reactive and Functional programming is to TPL and Imperative programming, why people will not invest on trying things out?&lt;/p&gt;

&lt;p&gt;Maybe what is lacking is &lt;strong&gt;how we communicate it all&lt;/strong&gt; in a efficient way, maybe we need more examples, or improve guidance and understanding of the advantages. Pretty much like everything else in software engineering.&lt;/p&gt;

&lt;p&gt;I'm willing to seek answers to these questions, even if it is the purpose or my entire career.&lt;br&gt;
I have seen enough, I'm done catching up and dealing with acquiring technical debt, being too many times close to failure due this, I want to change how things work for the better, even for a little, and I'll take the first of many steps with hopes of many to follow and learn with me, but I'm also open to join whoever share the same values; moreover, the same questions seeking answers.&lt;/p&gt;

&lt;p&gt;Thank you for reading my review but overall, I guess sharing with you the frustration I think many of us share. If you are interested, I am working on a humble open source effort regarding architecture and software practices using .NET in my GitHub to help me understand more about all of this, and hopefully help others:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/keozx"&gt;
        keozx
      &lt;/a&gt; / &lt;a href="https://github.com/keozx/CleanRx"&gt;
        CleanRx
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Clean Architecture Guidance to implement Clean Architecture on .NET Platforms with a focus on Mobile and the help of Reactive Programming
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;At the very least, I want to have some good examples of good design :)&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>solid</category>
      <category>agile</category>
      <category>engineering</category>
    </item>
  </channel>
</rss>
