سلام دوستان! امروز میخوایم با هم یه نگاهی بندازیم به یکی از الگوهای مهم به نام UDF یا همون Unidirectional Data Flow که در Jetpack Compose هم کاربرد داره. شاید اسمش به نظرتون پیچیده بیاد، ولی نگران نباشید، قدم به قدم با هم جلو میریم و با مثال توضیح میدیم.
اول از همه، بذارید ببینیم UDF اصلاً چی هست و چرا باید ازش استفاده کنیم. UDF یا همون جریان دادهی یکطرفه، یه الگوی معماریه که توش دادهها فقط در یک جهت جریان دارن. به زبون سادهتر، فانکشن های کامپوزی ما، state ها رو به فاکنشن های زیرین خودشون پاس میدن (در صورت نیاز و وجود داشتن child function) و اون child function ها event ها رو به فانکشن های بالایی خودشون بر میگردونن.
توی مثال بالا، ما یک parent داریم که یک state داره که به child خودش اونو پاس داده. و فانکشن فرزندش هم به ازای هر تغییر، به parent خودش اطلاع میده (onTextChange).
در مثال بالا، اگر از UDF استفاده نمیکردیم و state رو داخل تابع فرزند تعریف میکردیم، دیگه تابع parent خبری از مقدار text نداشت. حالا اگر مقدار text در تابع parent برامون مهم باشه و نیازش داشته باشیم چی ؟؟؟ احتمالا به فکرتون میرسه که viewmodel رو به فانکشن پاس بدیم، اما آیا پاس دادن viewmodel به همه ی فانکشن ها کار خوبیست ؟ خیر!
نکتهی مهم دیگه اینه که با این کار قابلیت Reusability رو افزایش میدیم. اینطوری میتونیم یه تابع بنویسیم و توی جاهای مختلف ازش استفاده کنیم، مثل همهی Custom Function هایی که شاید تا الان برای Button ها یا TextField هاتون نوشتید.
** ازینجا به بعد مقاله باید درباره Mvi هم اطلاعات داشته باشین. **
خب تا اینجا فهمیدیم چرا باید از UDF استفاده کنیم و شاید تا الان هم استفاده میکردین.
اما خیلی از فانکشن هایی که مینویسیم نیازی به قابلیت استفاده مجدد ندارن و صرفا مختص همون صفحه ای که داریم طراحی میکنیم هستن. آیا توی این موارد هم همه دیتا ها رو باید اینجوری هندل کنیم؟
عکس زیر رو نگاه کنید:
تقریبا میشه گفت که توی MVI با همچین چیزی سروکار داریم. یه data class برای نگهداری مقادیر لازم هر صفحه و یک seald class برای مدیریت کردن event هامون. در viewmodel هم احتمالا یک فانکشن دارین که با دریافت event، مقادیر data class رو آپدیت میکنه.
توی این سناریو فرض کنیم قراره که یک صفحه لاگین درست کنیم، پس ui شما تقریبا یه همچین چیزی میشه :
توی این مثال ما فقط دوتا متغیر داریم و به ازای اون دوتا ما مجبور شدیم دوتا تابع لامبدا بنویسیم تا بتونیم مقادیر جدید یوزرنیم و پسورد رو به viewmodel پاس بدیم:
onUsernameChange: (String) -> Unit,
onPasswordChange: (String) -> Unit
ولی برای صفحه هایی که خیلی مقادیر بیشتری دارن چطور؟ مثلا صفحه ثبت نام کاربر که ممکنه کلی پارامتر داشته باشه! و مجبور بشیم برای تک تک اونها لامبدا بنویسیم.
یا ممکنه عمق فانکشن های ما زیاد باشه. مثلا:
خب توی اینجا ما مجبوریم همه اون لامبدا ها رو برای هر فانکشن بنویسیم.
راه حل خیلی سادس با اضافه کردن یه خط کد:
typealias OnAction = (LoginUiEvent) -> Unit
خب حالا ازین به بعد به جای پاس دادن توابع لامبدای هر متغیر، OnAction رو به childها پاس میدیم و در اونجا مستقیما LoginUiEvent مدنظرمون رو به OnAction میدیم. ینی این شکلی:
تو زبون کاتلین، typealias به ما اجازه میده که برای یک نوع (type) موجود، یه نام جدید تعریف کنیم. این کار به ویژه وقتی مفیده که:
البته که میتونیم خود نوع رو ینی
(LoginUiEvent) -> Unit
رو هم به فانکشن هامون پاس بدیم ولی با typealias هم کدمون قشنگ تر میشه هم ساده تر.
فقط باید حواستون باشه که برای توابعی این کارو انجام بدین که مطمئن هستین جای دیگه نمیخواین ازش استفاده کنین. چون این شکلی Reusability اون فانکشن رو از دست میدین.
همین! توی این مقاله با هم یاد گرفتیم که UDF چیه و چطوری میشه با استفاده ازش، کدهای خواناتر و بهتری بنویسیم. دیدیم که UDF چطور میتونه به ما کمک کنه تا دادههامون رو بهتر مدیریت کنیم و از پیچیدگیهای غیرضروری جلوگیری کنیم. همچنین، فهمیدیم که توی پروژههای واقعی چطوری میتونیم راحتتر از UDF استفاده کنیم تا کدهای کمتری بنویسیم و کارمون رو سادهتر کنیم.
امیدوارم این آموزش براتون مفید بوده باشه و بتونید از این نکات توی پروژههاتون استفاده کنید. اگر سوالی داشتید یا نکتهای براتون مبهم بود، حتماً بپرسید.
ارادت ✌🏻
لینک منبع قسمت دوم آموزش: