باسلام

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

روش معمولی که در این گونه پروژه‌ها در حال استفاده هست اینه که یک کلاس سینگل تون ایجاد میشه و هرکجا لازم باشه لاگ در لاگر نوشته میشه اما خب این روند بدی های زیادی داره از جمله مشکلاتی که الگوی طراحی singletone برای unit testing پیش میاره پس به ذهنم رسید که باید روش بهتری هم برای انجام این کار باشه از قبل میدونستم میشه streambuf رو ریدایرکت کرد پس گفتم بذار ببینم راهی برای ریدایرکت کردن استریم بافر هست که بشه توی یک  مثلا تکست بروزر ازش استفاده کنم ؟ با جستجو به این لینک رسیدم std::cout to QTextBrowser و با کمی تغییر سعی کردم کاری بکنم که لاگ رو توی رنگ های متفاوتی داشته باشیم و موفق هم شدم توی کد پایان پست میتونید نتیجه رو ببینید. اما بعدش رفتم دنبال روشی که بتونم خروجی qDebug و موارد دیگه کیوت رو برای دادن خروجی به این شکل در بیارم ولی به دلیل بد ساختاری کیوت در این زمینه راهی که فراهم کرده اینه که یک تابع استاتیک رو به عنوان هندلر بافر میگیره و این باعث میشه نتونیم مثل cout خروجی رو به راحتی با یک کلاس هندل کنیم و وقتی توی ساختارش بریم نیاز هست که باز کلاس سینگلتون رو داشته باشیم که من دیگه روی این روش ادامه ندادم.

دقت کنید مشکل اصلی که الان با لاگر معمولی داشتم این بود که یا باید یک کلاس سینگلتون ازش میساختیم و همه جا استفاده میکردیم که خیلی بود بود و برای یونیت تستینگ هم به مشکل میخوردیم یا باید لاگر رو عادی تعریف میکردیم و توی MainWindow برنامه نشون میدادیم و هرکجا بهش نیاز داشتیم اون رو به عنوان ورودی میفرستادیم که این باعث میشود بایندینگ بین لایه های مختلف پروژه از بین برود چون شی لاگر یک شی گرافیکی و از لایه view برنامه است و پاس دادن آن به لایه‌های business logic باعث بهم خوردن معماری می‌شد بنابر این نیاز به روش بهتری بود تا این مشکل رو حل کنیم.

روندی که الان پیاده کردم بدون نیاز به کلاس سینگلتون و ارسال کلاس لاگر به لایه های پایین برنامه میتونه برامون لاگ رو توی لاگر با رنگ های مختلف نشون بده من برای cout رنگ مشکی رو در نظر گرفتم و برای clog زرد و برای cerr رنگ قرمز اما مشکل دیگه ای که وجود داره در مورد raise لاگرمون هست به این معنی که توی روش قبلی که خود لاگر ارسال می‌شد ما میتونستیم وقتی پیامی رو توی لاگر ست میکنیم اون رو raise کنیم تا محتویاتش رو به کاربر نشون بده چون لاگر رو همیشه کاربر نیاز نداره میتونه اون رو ببنده یا اندازش رو کوچک کنه پس اگر اروری داشته باشیم شاید با توجه به کارکرد برنامه لازم باشه لاگر رو باز نشون بدیم اما این روند الان میتونه با throw کردن حل بشه به این شکل که اگر اروری که داریم از ارور های استاندارد هست میتونیم از std::exception استفاده کنیم و در صورتی که ارور خاصی هست میتونیم از این کلاس به ارث ببریم و ارور خودمون رو بسازیم و وقتی مشکل توی لایه های پایین به وجود اومد اون رو throw کنیم و در MainWindow یا کلاس‌های کنترلر بالاتر از لایه business logic که توان امیت کردن سیگنال را دارند با استفاده از try این ارور ها را هندل کنیم و در صورت نیاز سیگنالی را امیت کنیم که در MainWindow آن را به Raise کردن لاگر متصل کنیم.

با این روند میتوانیم بدون ارسال آبشاری شی به پایین و بدون استفاده از کلاس سینگلتون یک لاگر تمیز و کامل مطابق با اصول معماری نرم افزار داشته باشیم.

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

 

لینک پروژه در Github