به عنوان کسی که تجربه خیلی زیادی نداره؛ بنظرم تا الان سخت ترین کاری که کردم هماهنگی اطلاعات کاربر بوده (هم سمت کاربر و هم سمت سرور). حالا چرا این قضیه برای من اینقدر سخت بوده و اشک ام رو هر سری دراورده؟
۱ - تجربه و دانش کم
خب همونطوری که گفتم من تجربه خیلی زیادی ندارم و اونقدری هم که بنظرم برای این کارها لازمه دانش نداشتم ولی متاسفانه با اینکه این مسئله رو میدونستم مستقیم شروع به کد زدن کردم که خیلی بهتر میشد اگر حداقل ۲ ساعت قبلش تحقیق میکردم که ببینم اصلا کلا جریان چیه و در این مورد بیشتر میخوندم. بنظرم خیلی بهتر میشد اگه قبل از اینکه برم سراغ کد زدن حداقل یکبار مسئله رو پیش خودم حل میکردم و مطمئن میشدم که راه حلی که من انتخاب کردم مسئله رو برطرف میکنه و بعد میرفتم سراغ کد زدن. (در مورد این قضیه، این مقاله خیلی بدردم خورد)
۲- مشخص نبودن دقیق نیازمندی(ها)
این البته مربوط به شرکت ها و کارفرماهایی که من باهاشون کارکردم نمیشه و اینجوری که فهمیدم تقریبا بیشتر جاها این مشکل کم و بیش وجود داره. برای من چندبار تاحالا پیش اومده که یک شرایطی رو ازم خواستن بعد من رفتم پیاده سازی کردم و وسطش یک حالت دیگه ای رو گفتن اضافه کن که اضافه کردن اون یک مورد ساختار اون بخش رو عوض کرده. بنظرم بهتر میشد اگر نیازمندی رو با تیم پروداکت (و حتی یک دبل چک با تیم QA) نهایی میکردم و بهشون میگفتم نمیشه وسط پیاده سازی این فیچر، چیزی بهش اضافه بشه.
۳ - در نظر نگرفتن تمام حالتها
بنظرم چیزی که توی این قضیه خیلی مهمه تست های مختلف نوشتنه که خب متاسفانه من توی اکثر موارد یا تست نمینوشتم یا تست های کم و ساده ای مینوشتم که همهی شرایط و همهی کد ها رو پوشش نمیاد. بنظرم خیلی لازمه که قبل از شروع یک دور اکثر حالت هایی که ممکنه پیش بیاد رو یک جایی بنویسید و براشون برنامه داشته باشید و از قبل بدونید که فلان شرایط رو قراره چجوری هندل کنید. مثلا از اینکه اگه فلان وب سرویس http جواب داد و فلان وب سوکت بشه شد چیکار باید کرد تا اینکه اگه یکی از کلاستر های مختلف یکی از اینها جواب نداد ولی چیزی که بهش وابسته است جواب میداد باید چیکارش کرد تا کاربر بتونه به حداقل دیتایی که میخواد برسه. کلا خیلی حالت های مختلفی به وجود میاد چون معمولا با دو یا بیشتر از دو تا پروتکل یا دیتابیس یا وب سرویس یا وب سوکت یا … داریم کار میکنیم. جلوتر بعضی از حالت هایی که برای من پیش اومد و هندلشون نکرده بودم رو میگم.
۴ - شاخص نگه داشتن حداقل یک مقدار تا آخرین قطرهی خون!
همونطوری که گفتم توی این چیزها معمولا با دو یا بیشتر از دوتا "چیز" مختلف سروکار داریم پس حتما همیشه لازم داریم که یک چیز شاخصی داشته باشیم تا بتونیم بفهمیم که الان با کی کار داریم. مثال خیلی ساده و اولیه این ماجرا میشه هماهنگ کردن آنلاین و آفلاین. مثلا حالتی رو در نظر بگیرید که کاربر دو سه تا کار انجام داده و حالا بعد از یک اکشنی یا بعد از یک زمانی میخوایید این اطلاعات رو بفرستید سمت سرور. خب اول طبیعتا میدونید که این کاربر علیه پس uuid علی رو یک جایی و یک طوری دارید. بعد حالا علی میاد یک کاری میکنه و لازم میشه که اطلاعات اش بره برای سرور ولی ای بابا علی رفت تو تونل حکیم و اینترنتش قطع شد (حالا فرض میکنیم که علی وقتی میاد بیرون هم اینترنت نداره و فردا دوباره میاد تو برنامه. منظورم اینه که اون ریکوئست دوباره یا چندباره تکرار نمیشه). حالا آیا ما اطلاعات علی رو بیخیال میشیم؟ آیا به علی میگیم دمت گر و بوس بهت و خدافظ؟ هرگز، ما تا آخرین اطلاعات علی رو میخواییم :)) پس باید اطلاعات علی رو یک جایی با یک چیز شاخصی مثل uuid نگه داریم تا بدونیم که بعدا این اطلاعات در مورد علی بوده. وقتی علی آنلاین شد میگیم عه علیییههه و به سرور میگیم این سشنی بود که باز داشتی با این uuid که دیتاش رو فلان روز نصفه فرستادم برات؟ اونم میگه عه علییییی، خب خب؟ بهش میگی بیا اینم بقیه دیتاش. (این در حالتیه که علی لاگین نکرده و بحث های احراز هویت سروری وجود نداره)
این ها چیزهایی بوده که من توی این جور کارها رعایت نکردم یا حداقل درست رعایت نکردم.
کارهای اینجوریه که کردم و به مشکل خوردم و اینکه چجوری حلشون کردم:
۱ - هماهنگی لاگین در همه جا (یک بار لاگین برای همه جا) ( single sign-on | sso)
اول یک توضیحی کوچیکی بدم که این قضیه کجاها کاربرد داره و حدودا چجوری کار میکنه. البته ویکیپدیا خیلی بهتر و کامل تر توضیح داده.
فرض کنیم که شما سایت ممد و سایت جاسم رو دارید که جفت سایت ها نیاز به ورود و اینا داره. حالا میخوایید وقتی یک کاربری تو سایت ممد عضو شد بتونه با همون یوزنیم و پسورد تو سایت جاسم هم وارد بشه. این یک حالت خیلی اولیه از این قضیه است.
من یک پروژه ای داشتم که کارفرما گفته بود میخوام کاربرهایی که توی فروشگاه ام عضو هستن بتونن با همون اطلاعات کاربری توی اون یکی فروشگاه هم وارد بشن. خب طبیعتا دوتا فروشگاه مال خودش بود و اطلاعات جفتش رو داشت. من اون موقع باید میگفتیم که خب الان سایت اول مثلا ۲هزارتا کاربر داره و سایت دوم مثلا ۳هزارتا و باید یک جوری کاربرهایی که الان هم تو سایت اول ثبت نام کردن بتونن برن تو سایت دوم. ولی خب متاسفانه این حالت رو درنظر نگرفته بودم و رفتم و این حالت رو برای کاربرهای جدید توسعه دادم و درست هم کارمیکرد. بعد چند روز کارفرما گفت که کاربرهایی که قبلا بودن چی میشن؟ شرایط خیلی سخت تر شد چون یک جوری نوشته بودم که واقعا حالتی برای کاربرهای قبلی درنظر نگرفته بودم. کدی که اول نوشته بودم رو تقریبا پاک کردم و از اول نشستم فکر کردم که باید چیکار کنم و اینبار تمام حالت های ممکن رو درنظر گرفتم و فهمیدم که فراموشی پسورد هم برای کاربرهای قدیمی درست نکردم. مثلا از ۵۰۰ خط کدی که نوشته بودم ۲۰ خطش رو نگه داشتم و تمامش رو از اول نوشتم. sso هم خیلی بستگی داره که دقیقا نیازمندی چیه و میشه خیلی مدل های مختلفی پیاده سازی اش کرد. ممکنه فقط قضیه احزار هویت باشه که خب الان خیلی سرویس ها هستن که کار احراز هویت رو انجام میدن (مثل ثبت نام با گوگل) یا حتی سرویس های واسطی که اینارو هندل کردن مثل auth0.com ولی اگر قرار باشه اطلاعات کاربرها مثل سفارش ها و سبدخرید و ... هم هماهنگ باشه دیگه لازمه که دیتابیس یک طور خاصی که با هردوتا سایت هماهنگ طراحی بشه و ...
۲ - هماهنگی وب سوکت (یا sse) با http
فرض کنید شما یک اپلیکیشن مانیتورینگ دارید که یک دیتای مهم هرلحظه باید مانیتور بشه. خب طبیعتا راه حل درست استفاده از سوکت یا چیز شبیه به اونه تا هروقت تغییری دردیتا به وجود اومد در لحظه شما با خبر بشید و تو اپلیکیشن تغییر رو نشون بدید. حالا درنظر بگیرید که این دیتای حساسی که داره نشون داده میشه باید با یک دیتای دیگه جمع بشه که اون یکی دیتا روزانه عوض میشه و نیازی به سوکت براش نیست. تا اینجا شما یک سوکت دارید که دیتا رو بعد هر تغییر برای شما میفرسته و یک وب سرویس http که هربار دیتا رو ازش میگیرید و با دیتا سوکت جمع میکنید. خب تا اینجا بنظر چیز خیلی خاصی وجود نداره و خیلی راحت میشه همه چیز رو درست و مرتب جلو برد. حالا فرض کنید که به شرایط قبلی یک متغییر دیگه هم اضافه میشه که باید با رقم نهایی جمع بشه و بعد از اون برای سوکت هم فرستاده بشه که بقیه هم بفهمن.
بیایید از یک فرض محال استفاده کنیم. فرض کنیم که قیمت گوشت توسط سازمان مربوطه اش داره هرلحظه برای همهی قصابی ها فرستاده میشه تا همه یک قیمت باشن و مثل قیمت دلار هم خداروشکر لحظهای بالا و پایین میشه. حالا فرض کنیم فقط سه تا چیز تو قیمت اثر میذاره. اولی قیمت گوسفند و گاو و گوساله و ایناست که هرلحظه از یک جایی توسط سوکت برای ما میاد. دومی سود واسط و نرخ تورم و فلان و ایناست که هربار میتونیم مثلا از بانک مرکزی با http قیمت جدیدش رو بگیریم. سومی هم مثلا یک کامران نامی نشسته پشت پنل ادمین و هر رقمی دلش بخواد وارد میکنه و قیمت رو کم یا زیاد میکنه.
خب تقریبا اساسی ترین مسئله همون چیزیه که آخر سر با قیمت جمع میشه. اول اینکه باید تمام حالت های ممکن درنظر گرفته بشن مثل این حالت که اگر سوکت بشه شد ما به کاربر نهایی بگیم که اطلاعات جدید دیگه برات نمیاد و این اطلاعات مربوط به ساعت فلانه یا بگیم سرور خراب شده دوباره بیا یا حتی بک اند برامون یک سرویس آماده کرده باشه که اگه سوکت خراب شد تو یک دوره زمانی به اون ریکوئست بزنیم و اطلاعات سوکت رو از اون بگیریم و کلی حالت دیگه که باید قبل از شروع کار حتما باید اونارو در نظر گرفت. طبیعتا من اون اول اینکارو انجام دادم و باز هم چندین و چند خط کد الکی نوشتم و در نهایت تبدیل شد به یک فانکشن خیلی خیلی ساده که تقریبا پنجاه خط کد بود.
در نهایت امیدوارم دیگه از این کارا نکنم :)) سعی میکنم هروقت به هر مسئلهای برخورد کردم قبل از شروع به کد زدن مدت زمان بیشتری رو به اون مسئله فکر کنم.