اپلیکیشن‌های موبایلی آینده‌نگر

اپلیکیشن‌های موبایلی آینده‌نگر

Forward Compatible Mobile Applications

تغییرات

همه‌ی ما میدونیم که همه اپلیکیشن‌ها و سازمان‌ها به مرور زمان نیاز دارن که تغییراتی رو توی خدماتی که ارائه می‌کنن و یا نحوه‌ی ارائه‌ی اون‌‌ خدمات داشته باشن. این چیزی که بالاخره اتفاق میافته و نمی‌شه ازش فرار کرد.

ولی ما میخوایم اپلیکیشنی داشته باشیم، که نه تنها نسبت به این تغییرات مقاومه و از کار نمیفته، بلکه حتی بتونه تا حد قابل توجهی از امکاناتی که بعدا به سرویس اضافه خواهد شد رو هم پشتیبانی کنه.

قبل از بررسی این موضوع بذارید باهم ببینیم اصلا تغییرات یعنی چی:

بطور کلی تغبیرات رو میتونیم به ۳ دسته تقسیم کنیم:
۱.  ممکنه ما بخوایم تغییری رو  توی یکی از امکاناتی که درحال حاضر داریم بدیم.
۲. ممکنه بخوایم یک امکان کاملا جدید رو  به خدماتمون اضافه کنیم.
۳. یا تصمیم بگیریم دیگه خدمتی رو ارائه ندیم  و یه چیزی رو حذف کنیم.

باید با هر کدوم از این تغییرات به نحوی برخورد کنیم که کمترین ریسک و سختی رو برای کاربرمون داشته باشه! خب حالا ما چجوری باید این تغییرات رو به کاربرمون برسونیم؟ برای کاربر چقدر هزینه داره که به این تغییرات جدید برسه؟ اگر هدفمون وب‌سایت یا PWA باشه خیلی سادست: F5. با فشار دادن یه دکمه همه چی به روز میشه.

اما ما درمورد موبایل اپلیکیشن صحبت می‌کنیم! اپلیکیشن نیتیو که مستقیما روی CPU اجرا میشه، نه روی مرورگر! اپلیکیشنی که:

  • همیشه توی جیب کاربر و در دسترسه! حتی آفلاین!
  • حافظه داره و اطلاعاتی که توش وارد شده رو رمزنگاری شده و داخل خود دستگاه نگه میداره.
  • حتی با اینترنت ضعیفی مثل EDGE هم به راحتی کار می‌کنه.
  • با ۱۲۰ فریم بر ثانیه بدون هیچ معطلی اسکرول میشه.
  • با یه پوش نوتیفیکیشن ساده کاربرمون رو برگردونه و همیشه درحالت اجرا باشه.

ما درمورد اپپلیکیشن نیتیو صحبت می‌کنیم. آپدیت کردن اپلیکیشن نیتو برای کاربر کم هزینه نیست! از هزینه‌هاش میتونم به این اشاره کنم که:

  • ممکنه حجم نسبتا زیادی داشته باشه.
  • ممکنه مشکلاتی برای دانلودش وجود داشته باشه. مثل وقتی که به VPN نیازه.
  • ممکنه کسب و کار اصلا دیگه نتونه به روزرسانیش رو عرضه کنه! فکر می‌کنم هممون در مورد اپل و وضعیت آپدیت اپپلیکیشن‌های iOS میدونیم!
  • تایید اپ‌استور‌ها ممکنه خیلی زمانبر باشه. حتی بعضی وقتا برای استورهای داخلی‌ که از خود استورهای اصلی هم بیشتر طول میکشه!
  • حتی ممکنه کاربر بخاطر دلایل شخصی آپدیت نکنه! مثلا نخواد ترافیکشو مصرف کنه! 🤷🏻‍♂️
  • یکی از بدترین! اتفاق‌‌هایی که میتونه بیفته اینه که کاربر اپپلیکیشن رقیب ما رو روی گوشیش داشته باشه! به راحتی اپمون رو پاک میکنه و از اپلیکیشن رقیب استفاده میکنه و برگردودنش واقعا میتونه سخت باشه...

پس به عنوان یک مدیر محصول، مالک محصول، طراح، توسعه‌دهنده یا هر شخص دیگه‌ای که روی تجربه کاربر تاثیر داره، وقتی تصمیم به تغییرات میگیریم، اولین چیزی که باید بهش توجه کنیم چیه؟

سازگاری

معمولان وقتی‌ کسی‌ درمورد compatibility با ما صحبت می‌کنه منظورش درواقع backward compatibility هست. backward compatibility یعنی‌ چی‌؟  یعنی‌ الان مجموعه‌ای از فرآیندها وجود دارن که دارن استفاده میشن و هرگونه تغییر ممکنه استفاده کننده از اون سرویس رو دچار مشکل کنه.

بذارید چنتا مثال بزنیم از چیزایی که میتونه باعث incompatibility یا ناسازگاری بشه:

  • تغییر روشی‌ که کاربر باهاش لاگین میکرده. (تا الان ورود فقط با شماره ایران بوده ولی قراره از این به بعد بشه با شماره‌های خارجی هم لاگین کرد.)
  • تغییر فرمتی که برای مدیاهامون قبول می‌کنیم. (ممکنه کاربرمون بخاطر فرمتی که ما تا الان ازش میخواستیم‌ حتی یه دستگاهی رو خرید باشه و این تغییر بهش ضرر بزنه! این مثال واقعیه و یه بار کاربر با ما تماس گرفت و با نارحتی این موضوع رو مطرح کرد! البته ما براش درستش کردیم ولی یه درس بزرگ گرفتیم.)
  • تغییر دادن دیتا تایپ بعضی‌ از داده ها! (تا الان امتیاز رو با عدد نشون میدادیم، حالا میخوایم با خوب و بد و متوسط نشون بدیم. اگر کلاینت از اون عددها به عنوان منطق پر کردن اون ستاره‌های امتیاز استفاده کرده باشه چی؟ 🤷🏻‍♂️)
  • ممکنه یسری اطلاعات که کاربر تولید کرده رو بخوایم از دسترسش خارج کنیم! (مثل بوکمارک‌ها، سیوها...)
  • شاید یه روز تصمیم بگیریم تعداد چیزایی‌ که برمیگشته سمت اپلیکیشن رو تغییر بدیم. (یه امکان جدیدی رو به لیست امکانتمون اضافه کنیم یا یکی رو حذف کنیم.)
  • شاید هم بخوایم یکی‌ از سرویس‌هایی‌ که داریم ازش استفاده می‌کنیم رو تغییر بدیم. (برای نگهداری از عکس‌هامون از یه سرویس third party جدید استفاده کنیم.)

هر کدوم از اینا میتونه مشکلی‌ ایجاد کنه که به اندازه‌ی خودش برامون مهمه:

  • بعضیاشون ممکنه گیچ کننده باشن!
    یعنی‌ اگه ما تعداد انتخاب‌هایی که میفرستیم رو مثلا کم کنیم، ممکنه کاربر ندونه کجا باید دنبالش بگرده یا اگه بدون اینکه UI این امکان رو داشته باشه که نشونش بده زیادش کنیم، کاربرمون که اتفاقا کاربر سایتمون هم هست، به این فکر می‌کنه که چرا تو سایت مثلا ۳ گزینه داره میبینه، ولی‌ تو اپ ۲ تا؟؟؟ 🤔
  • بعضیاشون آزار دهندن. کاربرا خودشون رو با اپپلیکیشن‌های ما عادت میدن. هر تغییری میتونه منجر به ترک عادت بشه و ترک عادت هم که موجب مرض است.
  • حتی این آزار دهندگی میتونه در حد کرش کردن اون سرویس یا حتی کرش کردن کل اپپلیکیشن بشه! 😱
    کرش کردن سرویس، جدا از تجربه‌ی خیلی‌ بعدی که برای کاربرمون داره احتمالا به بلاک شدنش هم منجر می‌شه. یعنی حتی ممکن کرش هم نکنیم ولی‌ تغییری که دادیم یا روشی‌ که انتخاب کردیم باعث بلاک شدن کاربر بشه و نتونه فرآیندی که می‌خواد رو انجام بده! حالا تصور کنید که اگر این داستان همون اول اپ، یعنی‌ مثلا توی لاگین یا توی درخواست کانفیگ اتفاق بیفته چی‌ می‌شه. دیگه کلا طرف نمیتونه از برنامه استفاده کنه!
  • فقط کافیه که این بلاک شدن در مورد دسترسی کاربر به اطلاعات شخصیش باشه. اونجاست که دیگه اعتماد کاربرمون و سال‌ها تلاشیمون برای جذب اون کاربر کاملا از دست میره و باید منتظر عصبانی شدنشون باشیم.
  • البته سازگار کردن بعضی‌ از این ناسازگاری‌ها، احتمالا فقط  باعث هزینه اضافی برای خود شرکت می‌شه.
  • مثلا جدیدا فهمیدیم که سرویس third party X چقدر کارآمده و میخوایم ازش استفاده کنیم. ولی چون URL هامون دارن توی اپلیکیشن تولید میشن، مجبوریم سرویس Storage پرهزینه و درِپیت خودمونو هم نگه داریم. اینا همش هزینست!

با خیلی‌ از مالکین محصول، UX دیزاینرها یا حتی صاحبین کسب‌و کار که صحبت می‌کنیم و بهشون در مورد این خطرات میگیم راه حلشون چیه؟

به روز رسانی اجباری

ولی ما راجب هزینه‌های به‌‌روزرسانی صحبت کردیم! تازه! طبق تحقیقات در بهترین حالت فقط ۵۰٪ کاربرها به موقع آپدیت میکنن! در حالت عادی که این عدد حدود ۲۰٪ هست! حالا اگه این آپدیت اجباری باشه چی میشه؟ هیچی! کاربرامون رو از دست میدیم! به همین راحتی! پس Force Update راه حل مناسبی نیست و تا جای ممکن نباید ازش استفاده کنیم. البته نمیگم هیچ وقت! مثلا وقتی که یه مشکل امنیتی پیش اومده، حتما باید Force Update انجام بشه! ولی باز همونم فقط برای نسخه‌های مشکل دار! یعنی با توجه به ورژنشون! نه برای همه! یا مثلا وقتی که دقیقا با آمار مطمئنیم که فقط درصد کمی از کاربرامون از نسخه‌های قدیمی ای که میخوایم فورس کنیم دارن استفاده میکنن.

ولی میدونین چرا فقط Force Update رو راه حل مشکل میدونن؟ چون چیزی که که افراد کمی‌ بهش توجه می‌کنن اینه که Backward Compatibility درواقع فقط نصفی از از مفهوم بزرگتری  به اسم Full Compatibility هست و نصف دیگش رو بهش میگن:

Forward Compatibility

یعنی‌ ما بتونیم پیشبینی‌ کنیم که کدوم قسمت از سرویسمون قراره در آینده تغییر کنه یا چه چیزی قراره بهش اضافه بشه و از الان براش یجور راه حل آینده‌نگارنه‌‌ی دینامیک در نظر بگیریم که بتونیم بدون نیاز به آپدیت کردن اپلیکیشنمون و مشکلاتی که راجبشون صحبت کردیم، این تغیراتو رو به کاربرامون برسونیم.

اما این داینامیک بودن، پویایی رو چجوری بدست بیاریم؟ از کجا بفهمیم که چقدر باید ادامه بدیم؟ البته که تجربه مهمترین مقیاس برای این اندازه‌گیری محسوب میشه، اما بیاید یه ارتباط منطقی براش پیدا کنیم.

ما باید بین حالتی که اپلیکیشنمون کاملا استاتیکه و برای کوچکترین تغییر (مثلا به خاطر متن یه خطا) مجبوریم آپدیت بدیم و حالتی که کاملا دینامیکه و کلا نیازی به آپدیت نداره( مثل Server-Driven UI اپلیکیشن‌ها که شاید تحت عنوان اپلیکیشن ساز هم دیده باشیدشون که کل UI رو از سمت سرور ارسال میکنن) بیشترین میزان تغییر‌پذیری اما با هزینه‌ی معقول رو انتخاب کنیم. چون میدونیند که آخرین درجه به خاطر هزینه‌ و فشار خیلی زیادی که با خودش میاره، همیشه بهترین گزینه نیست! حتی توی دور موتور ماشین رسیدن به آخرین حد، ممکنه کلا موتور ماشین رو از کار بندازه!

پس بهترین انتخاب نه حالت کاملا hardcode و استاتیکه و نه حالت کاملا داینامیک و سرور دریون! یه جایی نزدیک به انتهاست که ماشین بازا و گیمر‌ا بهش میگن پرفکت شیفت!

خب حالا از کجا شروع کنیم؟

Error Handling

اگه ما همه‌چیزمون Hard Code و Static باشه، احتمالا هر تغییری که بدیم یه مشکلی‌ پیش میاد، یعنی‌ یه اتفاقی‌ میافته که پیشبینی‌ نشده بوده. و به خطا میخوریم. درسته؟ پس اولین کاری که باید بکنیم اینه که یه فکری برای Error هایی که قراره در آینده بهشون بخوریم بکنیم! اگر میخوایم اپلیکیشنی داشته باشیم که با تغییرات آینده سازگاره، کاری که باید بکنیم اینه که یک سیستم جامع برای هندل کردن ارور هامون درست کنیم. مستقل از تمام قسمتهای دیگه‌ی سیستم.
این سیستم باید حداقل شامل این ۳ تا بخش باشه:

  • چیزی که دولپر باید بدونه. البته میتونه روی سرور پروداکشن که رفت دیگه برنگرده سمت کلاینت. میتونه بجاش لاگ بشه.
  • چیزی که ماشین باید بدونه. این مورد حتما، حتما، حتما، باید همیشه برگرده! و حتما کلاینت باید بر اساس این کد تصمیم بگیره! من یه دفه دیدم که کلاینت داشت براساس پیغامی که برای کاربر ( به فارسی!) و نوشته شده بود تصمیم میگیرفت! که البته ۱۰۰٪ اشتباهه! یه کانونشن خیلی خوب برای این کدها استفاده از استاتوس کدهای html هست.
  • و در نهایت خطایی که کاربر باید ببینه. که میتونه درقالب یه نوتیفیکشن بنر ساده باشه.

Notification

صحبت از نوتیفیکشن شد. مگه کلا نوتیفیکشن‌ همون چیزی نیست که میخوایم کاربرمون ببینه؟ پس چرا خودمون رو محدود کنیم به error؟

چرا کلا Message رو جدا نکنیم  و هرجا که خواستیم به کاربرمون چیزی نشون بدیم چه error، چه success، چه info، چه promotion، و چه هرچیز دیگه، از همون ساختار استفاده کنیم؟

اگه بخوایم این نوتیفیکیشن رو که هرجایی قابل نمایشه و باید Forward Compatible باشه رو از سمت سرور تنظیم کنیم میتونیم:

  • زمانی‌ که روی صفحه میمونه رو تنظیم کنیم. اینجوری حتی میتونیم با طولانی کردنش کاری کنیم که تا زمانی‌ که کاربر شخصا دیسمیسش نکرده روی صفحه بمونه.
  • میتونیم استایلش رو انتخاب کنیم. مثلا Alert، Banner، Sheet یا هرچیز دیگه‌ای که برای اون پیغام مناسبتره.
  • البته که محتوای نوتیفیکیشن! که به صورت ساده شامل Title، Description و Media میشه.
  • میتونیم Theme ش رو نتظیم کنیم. اینجوری حتی میتونیم نوتیفیکیشن‌های مناسبتی داشته باشیم. مثلا برای پیام تسلیت از theme تیره استفاده کنیم.
  • اکشن‌هایی که اون نوتیفیکیشن انجام میده! که معمولا به صورت دکمه می‌‌بینیمشون! اما یادمون باشه که اکشن اصلی برای یه استایلی مثل بنر، با تاچ کردن خود بنر هم قابل دسترسیه. پس پیشنهاد میکنم که حداقل از یه Title و DeepLink استفاده کنید.
  • و مشخص کردن اتقاقی که بعد از بسته شدن این نوتیفیکشن میفته. به عنوان مثال اگر تنظیم کنیم که برنامه بسته بشه، عملا میتونیم حالت‌های فورس رو هم داشته باشیم. مثلا آلرتی اومده که روش نوشته آپدیت کن و وقتی میزنی، میره به صفحه‌ی استور و برنامه بسته میشه!
    یا حتی با ترکیبش با Duration صفر کاری کنیم که به صورت خودکار اکشنمون اتفاق بیفته و مثلا کاربر redirect بشه به جایی از flow که ما میخوایم. دقت کنید که این نوتیفیکیشن‌ها ممکنه هر جایی از API لازم بشن و فقط با Push notification نیست که بهشون میرسیم. پس بهتره که کالا پیام‌ها رو از لایه‌ی دیتا خارج کنیم و این امکان رو فراهم کنیم توی هر API call که خواستیم بتونیم چیزی که میخوایم رو به کاربر نشون بدیم:
{
    "notification": {
        "userMessage": "You are our favorite user ❤️",
        "developerMessage": "You are the reason that we can show this. Thanks.",
        "actions": [
            {
                "title": "Thanks",
                "link": "chenzook://achievements?id:lovedUser"
            }
        ]
    },
   "data": {
        "foo": "blah blah blah",
        "bar": "bloo bloo bloo",
    }
}

اگر این لینکی که توی اکشنه که  همون DeepLink هست رو درست تعریف کرده باشیم که بتونه به تمام قسمت‌های اپ حرکت کنه و یه صفحه‌ی WebView فول اسکرین ساده هم داخل اپلیکیشن وجود داشته باشه، عملا میتونیم هر صفحه‌ی جدیدی رو تا زمانی که کاربر اپلیکیشنش رو آپدیت نکرده "موقتا" به صورت وب بهش نشون بدیم.  دقت کنید که از این روش "موقتا" استفاده می‌کنیم و چون این صفحه در واقع داره داخل فضای اپلیکیشن اجرا میشه، ما دسترسی‌های خیلی بیشتری نسبت به PWA داریم.

خب حالا که دیگه به ارور نمیخوریم چی؟ یعنی دیگه چیزی به سرویسمون اضافه نمیشه؟

نه دیگه فقط همینه!

اجازه بدید به عنوان کسی که توی ۷ تا استارتاپ و چندیدن و چن شرکت بزرگ و کوچیک کار کرده و این جمله رو زیاد شنیده بهتون بگم که این جمله فقط یه دروغ بزرگه!

کلا جملاتی مثل:

این هیچ وقت تغییر نمیکنه...
این همیشه همین شکلیه...
این حالت هیچ وقت پیش نمیاد...
ما همه‌ی حالتاشو داریم پشتیبانی میکنیم...
سرویسی که ما استفاده میکنیم بهترینه...
کاربر اونو نمیبینه، یا روش نمیزنه، یا اصلا ازش استفاده نمیکنه...!

اینا همش دروغ‌هایی هستن که ما معمولا میشنویم یا گاهی هم خودمون میگیمشون. چون اولا ما هیچ وقت نمیتونیم کاملا از آینده مطمئن باشیم و کل این داستان Forward Compatiblity به خاطر همین عدم قطعیته. دوما چون بعضی از این تصمیمات وابسته به شرایطی هستن که ما روشون کنترلی نداریم. مثلا نمیدونیم که سرویس جدیدی میاد که ما ازش استفاده کنیم یا نه! ما نمیدونیم که قراره تحریم بشیم یا نه! و مهمترین چیز اینه که نباید قاطعانه به جای کس دیگه نظر بدیم! یا در واقع نباید نظر خودمون رو از طرف دیگران بگیم! مگر وقتی که اطلاعات واقعی ثبت شده داشته باشیم در موردش.

خب بالاخره چجوری؟ از کجا میتونیم مطمئن که یه جایی قراره تغییر کنه؟. به قول خالق لینوکس:

Talk Is Cheap.  Show Me The Code
― Linus Torvalds

کد هیچ وقت بهمون دروغ نمیگه و بهترین چیزی که کمکون میکنه قبل از اینکه به حالت تعریف نشده‌ای بخوریم، شناسایش کنیم، دیتاتایپه!

دیتا تایپ چیزیه که به جای اینکه بگه این متغیری که راجبش صحبت میکنیم چه مقداری خواهد بود، به ما میگه که اون متغیر چه مقداری میتونه باشه! یعنی تمام حالت‌های مقدار! نه اضافه‌تر نه کمتر!

اگر ما بتونیم همه‌ی حالت‌هایی که میتونه باشه رو هندل کنیم پس دیگه اصلا حالت تعریف نشده‌ای نمیمونه که بخوایم بعدا نگران backward compatibility باشیم! درسته؟ خب. بیاید سریع نکته‌های مهم هر کدوم بررسی کنیم:

Boolean

همه میدونیم Boolean چیه. صفر یا یک. صحیح یا ناصحیح. True یا False

خیلی راحت با یه if ساده میشه هندل میشه!

اما چیزی که خیلیا فراموشش میکنن ‌ کلمه‌ی ساده ولی مهم "یا" هست! به این مثال نگاه کنید:

if canAuthenticate {

    if canClaim {

        if canRegister {

            // Something

        } else {

            // Something else
            
        }
    }
}

این تیکه کد در عین سادگی میتونه در آینده مشکلات زیادی برامون درست کنه. چرا؟. مگه هر شرط ۲ حالت True یا False نداره؟ پس چرا تمام else ها رو هندل نکردیم؟

مشکل دوممون جایگشته!

  • اگه canRegister ترو باشه ولی canClaim فالس باشه چی میشه؟
  • اگه canAuthenticate فالس شد؟
  • اگه canClaim ترو شد؟ اینجور جاهاست که میشنویم:
این حالت هیچ وقت اتفاق نمیفته!
  • اصلا اگه یکش از سمت سرور برنگشت چی؟
  • یا یه شرط دیگه اضافه شد؟ اینجا جاییه که میگن:
همیشه فقط همین ۳ تاس!

ما به اینکه میشه یا نمیشه کاری نداریم! ما به اینکه میتونه بشه یا نه کار داریم. پس باید همه‌ی جایگشت‌‌ها رو در نظر بگیریم. ولی نمیتومیم برای کلید‌های key/value که بعدا اضافه میشن کاری کنیم! چون معمولا کلاینت کلید‌های جدید رو ignore میکنه! خب؟ راه حلمون چیه؟

Enum

استفاده از enum و switch case بجای boolean و if های تو در تو. Enum به ما این امکان رو میده که همه‌‌ی حالت‌ها رو ببینیم و switch برای این ساخته شده که تمام حالت‌های ممکن رو پوشش بده. اما اگر باز هم یه کیس جدید اضافه شد اون موقع چی میشه؟ سادست! با تعریف کیس default برای switch میتونیم یه فانکشن دیفالت داشته باشیم که برای هر حالت ناشخته‌ای کار میکنه!

خب باز به یه کانسپت خوب رسیدیم:

Defaults

Default ها رو باز میتونیم به دوسته‌ی کلی تقسیم کنیم:

  • Default case ها که مهمترین جاهایی که باید ازشون استفاده کنیم
  • Enum ها هستن
  • همینطور برای عددها و رنج‌ها
  • استرینگ‌‌ها و
  • آرایه‌های خالی
  • و البته خطاهای ناشناخته
  • و Default Value ها که مهمترین کاربردشون توی
  • آپشنال‌‌ها یا همون nullable ها دیده میشه
  • المان‌های ناشناخته که معمولا توی لیست‌ها میبینیمشون
  • و برای تمام منابعی که انتظار داریم از وب دانلود بشن و اونایی که به سخت افزار خاصی وابسته هستن. چون ممکنه اینترنت یا اون سخت افزار اون لحظه در دسترس نباشه و ما نمیخوایم کاربرمون رو به خاطر این موضوع بلاک کنیم. شاید در جریان باشید که چند وقت پیش یکی از بانک‌ها، امکان ورود با اثر انگشت رو به اپلیکیشنش اضافه کرد که خیلی هم خوبه. ولی همه‌ی اونایی که گوشیشون سنسور اثر انگشت نداشت دیگه نمیتونستن وارد بشن و بلاک شدن!

Blockers

رفع بلاکرها هم سادست. اگه به دو دسته تسقیمشون کنیم:

  • دسته‌ی اول میشن بلاکرهای آنی مثل:
  • بلاکرهای دیداری که نمیذارن کاربر المان مورد نظرش رو ببینه! مثلا hide کردن یه دکمه!
  • بلاکرهایی که نمیذارن اون المان‌ها کار کنه! مثلا dissable کردن یه روز توی تقویم!
  • یا validation های سمت کلاینت. مثلا اینکه شماره تلفن حتما باید با ۰۹ شروع بشه!
  • دسته‌ی دوم میشن  زمان کش‌‌ها! مثل
  • درخواست کانفیگ اول برنامه
  • یا لود کردن تبلیغات
  • یا منتظر شدن برای ریسپانس‌هایی که  برای کاربر بی ارزشه! مثلا ریسپانس لاگ اوت!
    به راحتی با داینامیک کردن شرط بلاکرهای آنی و اجرا کردن بلاکر‌های زمان کش توی بکگراند میتونیم ازشون جلوگیری کنیم.

نتیجه

خب! حالا اگه همه‌ی این نکات ساده رو رعایت کنم میتونیم برای هر تغییری که میدیم تصمیم بگیریم:

  • به کاربرمون درمورد آپدیت اطلاع بدیم . (ولی فورسش نکنیم)
  • یا گزینه‌‌ی ناشناخته‌ی جدیدمون رو به کمک defaul ولیو اضافه کنیم و به کمک default case ازش بخوایم که برای دیدن جزئیاتش، اگر دوست داره آپدیت کنه!
  • یا به کمک اکشن‌ها بفرستیمیش به صفحه‌ی متناسبش توی وب ویویی که داخل اپ باز میشه!
  • یا فقط به یه اطلاعیه‌ی کوچیک و ساده بسنده کنیم!

جمع‌بندی

بررسی کردیم و فهمیدیم که:

  • برای سازگاری کامل باید به هر دوی backward و forward کامپتیبیلیتی توجه کنیم.
  • فهمیدیم که تغییرپذیری ۱۰۰٪ الزاما راه حل مناسبی نیست و باید سطح درستی از داینامیک بودن رو انتخاب کنیم.
  • فهمیدیم که به عنوان اولین اصل، به فکرِ هندل کردن ارورها باشیم و نذاریمشون برای آخر کار.
  • دیدم که جدا کردن پیام‌‌هایی که میخوایم به کاربر نشون بدیم، صَرف نظر از خطا یا اطلاعیه بودنشون، چقدر میتونه در آینده کمکمون کنه.
  • قرار گذاشتیم که بجای احتمالات، به امکان داشتن یا نداشتن اون fact و بر اساس دیتا تایپ، توجه کنیم.
  • و هرجا که میتونیم و میدونیم، از مقادیر و کیس‌های پیش فرض استفاده کنیم.

امیدوارم که این مقاله نظرتون رو جلب کرده باشه.  میتونید با من مستقیما در ارتباط باشید. کافیه که عبارت  "Mojtaba iOS" رو توی گوگل سرچ کنید تا به راه‌های ارتباطی برسید.

ممنونم از توجهتون.