امید حدیدی
امید حدیدی
خواندن ۴ دقیقه·۳ سال پیش

یک اشتباه جزئی که روزها وقتم رو گرفت

سلام دوستای گلم دوباره بعد از مدت‌های یه تجربه دیگه رو اومدم با شما به اشتراک بزارم که مطمئنم میتونه بهتون کمک کنه و براتون جذاب باشه. شاید خیلی از شما به مشکلات کوچیکی برخورده باشید که سر بی دقتی خودتون یا اینکه یه سری مسائل پیش پا افتاده رو رعایت نکردن، براتون به وجود آوره.

اشتباهات توی دنیای برنامه نویسی موجب میشن که درک بهتری از یک زبان پیدا کنیم و همچنین بهمون کمک میکنه تا تجربه بیشتری توی اون زمینه پیدا کنیم و بعدا به اون مشکل نخوریم. ( بلاخره مار از یه سوراه دوبار گزیده نمیشه ?? )

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

تمامی لاگ‌ها نشون میدادن که بعد از آپلود شدن چند فایل اگه کاربر از صفحه آپلود خارج بشه برنامه بعد از آپلود شدن فایل نمیتونه اون رو از توی Queue در بیاره و برنامه بعد از مدتی کرش میکنه. ( اینم بگم که من توی لیمو با فلاتر برای ios برنامه مینویسم ??? )

دست به کار شدم، شروع کردم به زیر و رو کردن کدهای برنامه از قسمتهایی که ربطی به آپلود کردن نداشت تا lifecycle ویجت ها.

اولین اشتباهی که کرده بودم این بود که برای این قسمت از برنامه ( یعنی قسمت upload Management ) تست ننوشته بودم و درست متوجه کارش نبودم و نمیتونستم درست درکش کنم، پس شروع کردم به نوشتن تست‌ها.

عجب بود که تمامی تست‌هایی که مینوشتم داشت pass میشد!!? اما مشکل همچنان وجود داشت.

بعد از یکی دو روز کلنجار رفتن با برنامه به این قسمت رسیدم.


خوب همونطور که اسم تابع میرسونه، قرار بود که این تابع تمامی فایل‌هایی که توی صف آپلود قرار دارن رو اولا کنسل کنه و بعد هم از توی لیست پاکشون کنه. ( پاک کردن مشکلی نداشت و تابع cancelFileUpload، این کار رو انجام میده ? )

روند کاری تقریبا معلومه ( نیست خیلی کد تمیزه?? ) یه کپی از روی fileFuture درست میکنیم و از روش یه forEach میکنیم و به ازای هر key، مقدار داخل صف آپلود پاک میشه. ( fileFuture همون صف آپلوده)

به نظر همه چیز درست میاد کد باید مثل بچه آدم کار کنه اما، یه چیز خیلی مهم و ساختار شکنانه رو من رعایت نکردم.???

قطعا همه شمایی که برنامه نویسی کردید میدونید ( برای اونایی که نمیدونن میگم? ) زمانی که شما یک متغیر تعریف میکنید و مقداری به اون میدید میره توی حافظه ذخیره میشه و کار خودش رو انجام میده.

حالا این متغیر میتونه از نوع های اصلی باشه میتونه از نوع‌های فرعی باشه، اما یه فرقی بینشون هست. زمانی که شما از یک مقدار اصلی استفاده میکنید مثلا عدد ۵، آدرس این مقدار درون متغیره شما ذخیره میشه و میتونید ازش کپی بگیرید روی یک متغیر دیگه و بدون اینکه متغیر اولیه دست کاری بشه روی متغیر دستکاری شده تغییراتی رو اعمال کنید. اما برای کلاسها دیگه نه??!!

کلاسهایی که شما درست میکنید یا توسعه دهنده ها درست میکنن در هنگامی که شئ از روشون ساخته میشه یک آدرس یکتا میگیرن که اگه توی یک متغیر دیگه ازشون کپی بگیرید، هر عملی که بر روی متغیر کپی شده انجام بدید، روی متغیر اصلی هم اعمال میشه!?? ( یا خودی خدا‌، البته نمیدونم درست تونستم منظور رو برسونم و درست گفتم یا نه)

حالا این کد بالا نمایش میده منظور من چیه و خروجی چه تغییری میکنه. از یک متغیر که شئ person توش ریحته شده یه کپی گرفتیم و توی tempValue ریختیم. انتظار دارم که خروجی Ali, Omid باشه اما داستان متفاوت شد.??

حالا فکر کنم متوجه اشتباه من توی کدم شده باشید، نوع داده HashMap یک نوع کلاسه که من ازش استفاده کردم پس همینطوری الکی کشکی نمیتونم اون رو داخل یه متغیره دیگه بریزم و شروع کنم به تغییر دادن. ( دقیقا هر دو تا متغیر رو به فنا میدم. ?? )

پس باید چیکار کنم؟؟ معمولا کلاسهایی که توی Dart وجود دارن و توسعه دهنده ها اون رو ساختن یه سری متود مثل copyWith, from, ... دارن که میشه از یک کلاس کپی گرفت و ازش استفاده کرد.

پس حالا میتونیم کد درست رو بنویسیم و ازش استفاده کنیم.

حالا با این تغییر نسبتا ریز توی خط سوم کدها ( کامنتها رو در نظر نگرفتم ) برنامه به شکل کاملا درستی کار خواهد کرد و اون تستی هم که fail شده بود الان داره تیک سبز نشون میده. هوری هوریااااااا ???

خوب حالا اگه کلاس رو خودمون ساخته بودیم و این متودها رو نداشت چی ( دو دستی بزنیم تو سرمون؟ ?? )

خوب اینجا باید خودتون دست به کد بشید و یه متون مثل copyWIth توی کلاستون درست کنید. توی کد زیر من این متود رو درست کردم و زیرش هم براتون توضیح میدم که چی به چیه.

خوب اگه کدهای بالا رو یادتون باشه با کلاس person آشنایی دارید و حالا من این کلاس رو به این شکل بازنویسی کردم. یه متود ایجاد کردن توی این کلاس با عنوان copyWith و تمامی آپشنهایی که سازنده کلاس میگرفتن رو به این متود دادم و در آخر هم گفتم که یه کلاس جدید با این عنوان برای من برگردون تا بتونم ازش استفاده کنم. در ضمن این رو هم در نظر گرفتم که کاربر میتونه آرگمان خاصی به این متود نده که در این صورت می‌ره و از دیتاهای فعلی کلاس استفاده میکنه.

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


خوب امیدوارم که این مقاله تونسته باشه کمکتون کنه و تونسته باشم بهتون کمک کنم.

خوشحال میشم شما هم تجربیات جذاب خودتون رو این زیر برام کامنت کنید.


برنامه نویسیفلاترمشکلات برنامه نویسی
یه برنامه نویس پرتلاش و جستجوگر. عاشق برنامه نویسی و یادگیری چیزای جدید
شاید از این پست‌ها خوشتان بیاید