سئوالات و مباحث WPF

the_king

مدیرکل انجمن
استاد میگم Visual Studio 2022 که استفاده از رم اش زیادتر شد (که احتمالا بخاطر 64 بیتی بودنش و شاید هم ارتقاء های دیگه اش هست) ، پروژه های WPF هم که وقتی در حالت Edit و کد نوشتن در Visual Studio هستیم هم که رم بیشتری مصرف میکنن مخصوصا اگه از Visual Studio اجرا بشن (که همون مشکل نسخه ی قبل که انگار نشت داده در رم هست ، هنوز درست نشد و در هر بار اجرا و بستن برنامه از Visual Studio ، یه مقداری از داده رم پاک نمیشه) ، حالا هم که Resharper را هم نصب کردم ، همه ی اینها باعث شدن Visual Studio به معنی واقعی کلمه ، رم رو ببلعه . :green:
اینقدر از ویژوال استدیو 2022 تعریف نکنید :green: اینها که میگید همه شون بدیهی ئه، معمولا هر نسخه جدید از محصولات نرم افزاری از نسخه قبلی منابع بیشتری لازم داشته، مجهز تر و عملا کند تر بوده و در عین حال برای بهینه سازی و افزایش کارایی اش تبلیغ شده.
در ضمن در سیستم عامل 64 بیتی پروسه های 32 مصرف حافظه بیشتری نسبت به همون پروسه های 32 در بیتی در ویندوز 32 بیتی دارند :
یعنی اینکه یک برنامه 64 بیتی بشه الزاما به این معنی نیست که مصرف حافظه اش حتما خیلی بیشتر بشه یا اصلا دو برابر بشه. این رو می توانید خودتون در آزمایش عملی موقع تغییر بین 32 بیتی و 64 بیتی بودن فایل اجرایی ببینید.
این پروژه که این طوره ، پس پروژه های بزرگ (با WPF) ، چقدر رم مصرف میکنن!
آدم یاد نرم افزار افترافکت میافته :green:
میزان مصرف منابع برای اغلب شرکت های نرم افزاری فاکتور مهمی ئه، مخصوصا وقتی پردازش اصلی نرم افزار شون منابع زیادی بخواد، برای همین معمولا سراغ واسط های کاربری خیلی سنگین و کند نمی روند. برای همینه که محصولات متعارف زیادی نمی بینید که با WPF طراحی شده باشند. من اگر جای طراحان مایکروسافت بودم برای خود محیط ویژوال استدیو هم یک واسط کاربری سبک و سریع بکار می بردم.

استاد ، اگه نشت داده برای پروسه ای وجود داشته باشه ، سیستم عامل مگه به پای اون پروسه نمینویسه؟
آخه وقتی Visual Studio باز بود ، مصرف کل حافظه ی فیزیکی 8.3GB بود در صورتی که پروسه های مربوط به Visual Studio (در سربرگ اولِ Task Manager) را مقدار 3.4GB نشون میداد .
وقتی که Visual Studio را بستم ، مقدار مصرفیِ کلِ حافظه ی فیزیکی ، 3.3GB شد .
این که اختلافش 5 گیگ میشه . پس چرا پروسه ی Visual Studio را 3.4GB نوشته بود داره حافظه ی فیزیکی رو مصرف میکنه؟
داستانش چجوریه؟!
الزاما یک پروسه که نیست، مجموعه ای از فایل های اجرایی است که هر کدوم حافظه میخوان و ممکنه بعد از بسته شدن ویژوال استدیو هم بعضی هاشون همچنان باز باشند. در ضمن حواس تون باشه که دارید کدوم مشخصه از حافظه رو بررسی می کنید. بهتره با مقدار Commit ارزیابی کنید، نه چیزی مثل Working Set
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اینقدر از ویژوال استدیو 2022 تعریف نکنید :green:

سلام استاد .
خیلی ممنون .

این بار ، عیب اش را گفتم که . مصرف حافظه ی زیادتر که عیبش بود :green:

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

آها ممنون .
البته منظورم ، خودِ ویژال استودیو 2022 بود که حافظه ی زیادتری انگار نسبت به نسخه های قبل استفاده میکنه .
منظورم ، برنامه ام نبود . هر چند برنامه ام ، در ویندوز 64 بیتی ، بصورت 64 بیت و در ویندوز 32 بیتی ، بصورت 32 بیتی اجرا میشه .

میزان مصرف منابع برای اغلب شرکت های نرم افزاری فاکتور مهمی ئه، مخصوصا وقتی پردازش اصلی نرم افزار شون منابع زیادی بخواد، برای همین معمولا سراغ واسط های کاربری خیلی سنگین و کند نمی روند. برای همینه که محصولات متعارف زیادی نمی بینید که با WPF طراحی شده باشند.

البته منظورم فقط مصرف حافظه ی ویژال استودیو 2022 بود که بالاتره . منظورم خودِ برنامه مون نیست .
سرعت ویژال استودیو 2022 چندان فرقی نداشت و در اغلب اوقات نسبت به نسخه ی قبلی بالاتر بود (بدون Resharper که تست کردم و قبلا گزارش را دادم . با Resharper تست نکردم) .

اما برنامه ی wpf مون که جداگانه ، هم سرعت خوبی داره و هم حافظه ی کمی اشغال میکنه . زمان اجرای برنامه مون ، مقدار Commit اش ، حدود 72 مگابایت بود .

من اگر جای طراحان مایکروسافت بودم برای خود محیط ویژوال استدیو هم یک واسط کاربری سبک و سریع بکار می بردم.

سرعت ویژال استودیو بد نیست ها .
من که سیستم ام تقریبا داره قدیمی میشه ، خوب اجرا میکنه . البته الان Resharper ، سرعتش را بصورت محسوس کم کرد .
سیستم من پردازنده 4460 با 12 گیگ رم دارم . پروژه را هم از روی hdd اجرا میکنم (هر چند ویندوز و ویژال استودیو توی ssd نصب و از اونجا اجرا میشن) .
فکر کنم شما لپتاپ دارین و تا جایی که یادمه ، i7 نسل 4 دارین درسته؟
لپتاپ ها معمولا در فرکانس پایین تر کار میکنن و کلا یه کم از دسکتاپ سرعت شون پایین تر هست .
هر چند 4460 هم جزء یکی از رده پایین ترین و کم فرکانس ترین i5 ها در نسل 4 دسکتاپ هست .

اما لپتاپ های نسل جدیدتر ، این اختلاف را به شدت کم کردن و با سرعت و فرکانسِ به مراتب بالاتری کار میکنن .
البته خودتون استادین (فقط بصورت کلی خواستم بگم) .

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

البته من این آمار را از ستون Memory در سربرگ Process ئه Task Manager دادم . که مقدار حافظه ی فیزیکی ای که فقط مخصوص همین پروسه هاست که بصورت مشترک با بقیه ی پروسه ها استفاده نمیشن .
شما درست میگین ، باید آمار را از ستون Commit ئه سربرگ Memory در Resource Manager میدادم که مقدار حافظه ی مجازی مربوط به اون پروسه هست .

برنامه ی خوب ، باید برنامه ای باشه که بعد از بسته شدن ، همه ی پروسه هاش بسته شه دیگه .
برنامه ی جاسوسی نیست یا باگ نداره که .
بعد از بسته شدن ، در ظاهر ، انگار همه ی حافظه های مربوط بهش پس گرفته میشه . نمیدونم باز .

در ضمن حواس تون باشه که دارید کدوم مشخصه از حافظه رو بررسی می کنید. بهتره با مقدار Commit ارزیابی کنید، نه چیزی مثل Working Set

تشکر

استاد ، در پست بعدی (پست پایین) ، یه بحث دیگه میکنم (که قبلا یه تیکه اش را بحث کردیم) ، بی زحمت دقت کنید .
این پست چون زیاد شد ، اون را چون بحث جداگانه ای هم هست ، در پست بعدی طرح میکنم (نوشتن اش طول میکشه احتمالا) .
تشکر استاد
 

the_king

مدیرکل انجمن
سلام استاد .
خیلی ممنون .

این بار ، عیب اش را گفتم که . مصرف حافظه ی زیادتر که عیبش بود :green:



آها ممنون .
البته منظورم ، خودِ ویژال استودیو 2022 بود که حافظه ی زیادتری انگار نسبت به نسخه های قبل استفاده میکنه .
منظورتون رو متوجه شدم. اینکه مصرف حافظه زیادتری داره ارتباط مستقیمی با 64 بیتی بودنش نداره. نرم افزار 64 بیتی قطعا میتونه از سیستم حافظه بیشتری دریافت کنه اما اینکه حداقل حافظه مورد نیازش خیلی بیشتر از نسخه های 32 بیتی قبلی باشه ربطی به 64 بیتی بودنش نداره.
برنامه ی خوب ، باید برنامه ای باشه که بعد از بسته شدن ، همه ی پروسه هاش بسته شه دیگه .
نه. همچین تعریفی نداریم، از خودتون ملاک اختراع کردین. یکسری نرم افزار ها که اصلا از وقتی ویندوز بالا اومد پروسه یا سرویس پشت پرده شون شروع به کار میکنه تا سریعتر بالا بیان. یکسری نرم افزار ها هم وقتی پنجره شون رو بستید یکسری عملیات بهینه سازی و ذخیره سازی و ... دارن که تا مدتی بعد بسته شدن ادامه پیدا میکنه. Microsoft Office و Google Chrome از اینجور نرم افزار ها هستند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد استاد
خیلی ممنون از توضیحات پست بالاتون .
استاد ، در لینک زیر :


متدِ FillComboBoxByDriveInfos را به نام SetFixedDriveComboBoxItemsProperty تغییر دادم که بدنه اش را در زیر مینویسم (این متد ، در کلاس PoshtibangirToloUI هست که جزء لایه ی View محسوب میشه . وظیفه ی این متد هم پر کردنِ پروپرتی ای بنام FixedDrivesCustomItems که از نوع List<ItemsControlCustomItem> هست ، هست و این متد ، در متد سازنده ی کلاس ، فراخونی میشه . پروپرتیِ FixedDrivesCustomItems هم یکبار مقداردهی میشه و لیست درایوهای ثابت یا همون درایوهای هارد اینترنال را داره که کمبوباکس هایی که لازم هست که لیست درایوهای ثابت را داشته باشن ، به این پروپرتی ، Binding میکنن) :

C#:
        private void SetFixedDriveComboBoxItemsProperty()
        {
            DriveInfo[] driveInfos = ExtensionMethodViewModel.GetFixedNtfsDrives();
            if (driveInfos == null || driveInfos.Length < 1)
                return;

            this.FixedDrivesCustomItems = new List<ItemsControlCustomItem>();
            foreach (DriveInfo driveInfo in driveInfos)
            {
                string driveInfoFormatted = this.ExtensionMethodViewModel.DriveInfoFormatted(driveInfo);
                ItemsControlCustomItem comboBoxCustomItem = new ItemsControlCustomItem(driveInfoFormatted, driveInfo);
                this.FixedDrivesCustomItems.Add(comboBoxCustomItem);
            }
        }

همونطور که قبلا در لینک بالا صحبت کردیم ، یکی از دو موضوع ام در این پست ، نقش شی کلاس DriveInfo در این متد هست (این متد بالا هم که در View هست) .
هر چند در اون پست که در بالا لینک دادم ، گفتم :
"ولی بالاخره DriveInfo که جزء لایه ی Model ام نیست ."

و DriveInfo در دات نت موجود هست ، و شاید این دلیلی باشه که بشه از شیِ DriveInfo در View هم استفاده و فراخونی کرد ، اما با این حال ، شاید بیشتر ، بشه برای شیِ DriveInfo ، نقشِ Model را متصور بود (هر چند در اعضای پروپرتی ای در View استفاده بشه) .
موافقید؟

اگه تا اینجا را درست بگم ، پس این پروپرتیِ FixedDrivesCustomItems ، بهتره که در لایه ی ViewModel مقدار دهی و پر بشه . یعنی بهتره که این متدِ SetFixedDriveComboBoxItemsProperty را به لایه ی ViewModel منتقل کنم . درست میگم؟

-------------------

حالا مشکل اینه که توی ViewModel که به پروپرتیِ FixedDrivesCustomItems (که در View هست) ، دسترسی ندارم ، چجوری از اونجا مقدار جدیدی بهش بدم (فقط نمیخوام دسترسی داشته باشم ، بلکه میخوام مقدار جدیدی به پروپرتی از ViewModel بدم) ؟

جوابش هم اینه که در ورودی این متد ، بصورت ref ، شیِ فیلدِ مربوط به این پروپرتی را بدم (چون خودِ پروپرتی که نمیشه بصورت ref پاس داد) .

مشکل دیگه اینکه اگه این پروپرتیِ FixedDrivesCustomItems ، متد RaisePropertyChanged (که با پیاده سازیِ اینترفیس IPropertyChanged انجام شد) را فراخونی کرد ، چون فیلدش را بصورت مستقیم در ViewModel مقداردهی کردیم و بنابراین قسمت set ئه پروپرتی مون با مقداردهیِ فیلدش اجرا نمیشه ، یا دسترسیِ این متدِ RaisePropertyChanged را public میگیریم و شیِ View مون را به این متد در ViewModel ارسال میکنیم و بعد از مقداردیِ فیلدش ، متدِ RaisePropertyChanged ئه PoshtibangirToloUI که جزء View محسوب میشه را فراخونی میکنیم یا حالا یه دلیگیتی پاس میدیم به همین متدِ SetFixedDriveComboBoxItemsProperty در ViewModel یا یه رویدادی یا از این قبیل کارها میکنیم برای اجرای متد RaisePropertyChanged .

درسته؟


====================================================================


یه مسئله ی دیگه و مهمتر اینکه ، من یه user control به نام DriveBackupUserControl دارم میسازم که از لحاظ ظاهری ، قراره خیلی شبیه به کنترلی که در My Computer (همون This PC) که آیکون و آیتم و نوشته ها و اطلاعات مربوط به یک درایو را نشون میده ، باشه . منتها این user control ، علاوه بر این اطلاعات ، اطلاعات بکاپ های اون درایو را نشون میده .

در واقع این user control ، اطلاعات بکاپ ها را نشون میده و همچنین بعضی از اطلاعات درایوها (که در My Computer) هست را نشون میده .

حالا من در یکی از کلاس های لایه ی Model ام ، پروپرتی ای بنام BackupStatus دارم که وضعیت بکاپ را بصورت enum ذخیره میکنه (که بکاپ در حالت عادی هست ، یا اینکه بکاپ نداره یا اینکه در شرایط هشدار دادن قرار داره) .
این پروپرتی ، برای کلاسی هست که اطلاعات کل و همه ی درایوها را ذخیره میکنه . یعنی فرضا اگه طرف 5 تا درایو داشت که وضعیت بکاپ 3 تاشون عادی بودن و یکی شون در حالت هشدار و یکی دیگه بکاپ نداشت ، این پروپرتی در این کلاس ، بدترین حالت را برمیگردونه که یکی از درایوها بکاپ نداشت (را برمیگردونه) .


اما بجز این ، مجددا همین پروپرتیِ BackupStatus در کلاسِ مجزای دیگه ای که اطلاعات بکاپِ تک تکِ درایوها را برمیگردونه ، استفاده میشه (هنوز واسه ی این کلاس ها اسم مشخص نکردم واسه ی همین اسم شون را ننوشتم) .

----------

این DriveBackupUserControl هم که کلاسی هست که مربوط به هر درایو میشه ، از پروپرتیِ BackupStatus ای که مربوط به هر درایو مجزا هستن میخواد استفاده کنه .

حالا چون این DriveBackupUserControl ، قراره که اطلاعات را توی خودش داشته باشه و کلا یه کلاس هست ، به نظرتون تکلیفش را با پروپرتیِ BackupStatus (که از نوعِ enum هست و در Model تعریف شده) ، چی کار کنم؟

این رو از این جهت میگم که قبلا چون از این پروپرتی ، برای تعیین شکل آیکون اصلی برنامه در پروپرتیِ Icon ئه TaskbarIcon میخواستم استفاده کنم ، گفتید مستقیما بیام و به پروپرتیِ BackupStatus ئه Model ام Binding کنم .
خوب اونجا که من کلاس TaskbarIcon را ایجاد نکرده بودم یا کلاسی ننوشته بودم که ازش ارث بری کنه و چندان هم نیاز نبود که در View ام ، یه پروپرتیِ BackupStatus مجددا تعریف کنم که به پروپرتیِ BackupStatus ئه Model ام Binding کنم .

----------

اما در این کلاسِ DriveBackupUserControl ، داشتنِ همچین اطلاعاتی و همچین پروپرتی هایی که شامل اطلاعات مختلفی از درایو باشه ، کاملا نیازه .
یعنی فرضا نمیتونم مثل قبل ، برای این User Control ، مستقیما Binding به Model ام انجام بدم . چون :

اولا فرضا اگه پروپرتی هایی برای این کار (پروپرتی های مربوط به اطلاعات درایو و بکاپ) را در این کلاس اش تعریف نکنم و مستقیما به پروپرتی های Model ام (که یک نمونه اش پروپرتیِ BackupStatus بود) ، Binding کنم ، فرضا اگه به پروژه ی دیگه ای بخوام این کنترل را منتقل کنم ، دردسرهای بسیار بزرگی داره و از اول باید براش به ازای هر پروژه ای که منتقل میکنم ، بجای مقداردهی پروپرتی ، از اول Binding هاش را درست کنم .

و دوما اگه پروپرتی هایی را در این کلاس اختصاص ندم و نخوام هم کنترل های مورد نظرم در این user control را توسط Binding مقداردهی کنم ، در این صورت ، هم دسترسی های اون کنترل هایی که درون user control تعریف کردم را باید public کنم که این وجهه ی خوبی نمیده و اصولی نیست و هم کد را زیاد و پیچیدگی اش را بیشتر میکنه .

=========

اگه پروپرتی هایی نظیر این پروپرتی هایی که در Model هست را در User Control تعریف کنم ، دقیقا چی کار کنم؟

چون میگید که پروپرتی هایی که از نوع Model هستن (مثل پروپرتیِ BackupStatus که از نوعِ enum ئه شخصی ای بنام BackupStatus هست که در Model تعریف کردم) را در View بخاطر نقض MVVM استفاده نکنم .

پس در این صورت فرضا به همچین enum ای اگه نیاز دارم استفاده کنم ، چی کار کنم؟
فرضا آیا پیشنهاد میدید که یه enum ئه دیگه که شامل همون اعضای enum ئه BackupStatus هستن ، اما این بار در لایه ی View تعریف کنم و بعد Binding ای بین enum ئه BackupStatus در Model با enum ئه BackupStatus در View توسط Converter انجام بدم؟

ببخشید استاد که خیلی زیاد شد .
تشکر :rose:
 

the_king

مدیرکل انجمن
سلامی مجدد استاد
خیلی ممنون از توضیحات پست بالاتون .
استاد ، در لینک زیر :


متدِ FillComboBoxByDriveInfos را به نام SetFixedDriveComboBoxItemsProperty تغییر دادم که بدنه اش را در زیر مینویسم (این متد ، در کلاس PoshtibangirToloUI هست که جزء لایه ی View محسوب میشه . وظیفه ی این متد هم پر کردنِ پروپرتی ای بنام FixedDrivesCustomItems که از نوع List<ItemsControlCustomItem> هست ، هست و این متد ، در متد سازنده ی کلاس ، فراخونی میشه . پروپرتیِ FixedDrivesCustomItems هم یکبار مقداردهی میشه و لیست درایوهای ثابت یا همون درایوهای هارد اینترنال را داره که کمبوباکس هایی که لازم هست که لیست درایوهای ثابت را داشته باشن ، به این پروپرتی ، Binding میکنن) :

C#:
        private void SetFixedDriveComboBoxItemsProperty()
        {
            DriveInfo[] driveInfos = ExtensionMethodViewModel.GetFixedNtfsDrives();
            if (driveInfos == null || driveInfos.Length < 1)
                return;

            this.FixedDrivesCustomItems = new List<ItemsControlCustomItem>();
            foreach (DriveInfo driveInfo in driveInfos)
            {
                string driveInfoFormatted = this.ExtensionMethodViewModel.DriveInfoFormatted(driveInfo);
                ItemsControlCustomItem comboBoxCustomItem = new ItemsControlCustomItem(driveInfoFormatted, driveInfo);
                this.FixedDrivesCustomItems.Add(comboBoxCustomItem);
            }
        }

همونطور که قبلا در لینک بالا صحبت کردیم ، یکی از دو موضوع ام در این پست ، نقش شی کلاس DriveInfo در این متد هست (این متد بالا هم که در View هست) .
هر چند در اون پست که در بالا لینک دادم ، گفتم :
"ولی بالاخره DriveInfo که جزء لایه ی Model ام نیست ."

و DriveInfo در دات نت موجود هست ، و شاید این دلیلی باشه که بشه از شیِ DriveInfo در View هم استفاده و فراخونی کرد ، اما با این حال ، شاید بیشتر ، بشه برای شیِ DriveInfo ، نقشِ Model را متصور بود (هر چند در اعضای پروپرتی ای در View استفاده بشه) .
موافقید؟
DriveInfo جزو واسط کاربری که نیست، ساختاری برای داده است. اما شما که تعریفش نمی کنید، جزئی از NET Framework. ئه، پس نمی توانید تعریفش رو به یک لایه خاص تخصیص اش بدهید. شما نمی توانید محل تعریف DriveInfo رو تغییر بدهید و بندازید داخل لایه فلان. ورای مدل پروژه شما است. در NET. Framework تعریف شده که بر اساس مدل MVVM هم نیست. برای همین یک تعریف خارج از پروژه شما است و اینکه در کدوم لایه ازش استفاده کنید به منطق روال تون بستگی داره وگرنه خودش در هر لایه ای میتونه مورد استفاده قرار بگیره. محدودیت چیه؟ محدودیت فقط اینه که DriveInfo مستقیم بین Model و View رد و بدل نشه. دقیقا همونطور که int نباید مستقیم به Model و View رد و بدل نشه.
اگه تا اینجا را درست بگم ، پس این پروپرتیِ FixedDrivesCustomItems ، بهتره که در لایه ی ViewModel مقدار دهی و پر بشه . یعنی بهتره که این متدِ SetFixedDriveComboBoxItemsProperty را به لایه ی ViewModel منتقل کنم . درست میگم؟
شما دارید بر شرایط DriveInfo نتیجه گیری می کنید، در حالی که DriveInfo جزئی از هیچ لایه MVVM ای نیست.
حالا مشکل اینه که توی ViewModel که به پروپرتیِ FixedDrivesCustomItems (که در View هست) ، دسترسی ندارم ، چجوری از اونجا مقدار جدیدی بهش بدم (فقط نمیخوام دسترسی داشته باشم ، بلکه میخوام مقدار جدیدی به پروپرتی از ViewModel بدم) ؟


جوابش هم اینه که در ورودی این متد ، بصورت ref ، شیِ فیلدِ مربوط به این پروپرتی را بدم (چون خودِ پروپرتی که نمیشه بصورت ref پاس داد) .

مشکل دیگه اینکه اگه این پروپرتیِ FixedDrivesCustomItems ، متد RaisePropertyChanged (که با پیاده سازیِ اینترفیس IPropertyChanged انجام شد) را فراخونی کرد ، چون فیلدش را بصورت مستقیم در ViewModel مقداردهی کردیم و بنابراین قسمت set ئه پروپرتی مون با مقداردهیِ فیلدش اجرا نمیشه ، یا دسترسیِ این متدِ RaisePropertyChanged را public میگیریم و شیِ View مون را به این متد در ViewModel ارسال میکنیم و بعد از مقداردیِ فیلدش ، متدِ RaisePropertyChanged ئه PoshtibangirToloUI که جزء View محسوب میشه را فراخونی میکنیم یا حالا یه دلیگیتی پاس میدیم به همین متدِ SetFixedDriveComboBoxItemsProperty در ViewModel یا یه رویدادی یا از این قبیل کارها میکنیم برای اجرای متد RaisePropertyChanged .

درسته؟
نه. شما اول یک محدودیت بی دلیل ایجاد می کنید که مشکل ایجاد می کنه و بعد دنبال راه حل برای مشکلی میگردید که از اساس نباید باشه.
یه مسئله ی دیگه و مهمتر اینکه ، من یه user control به نام DriveBackupUserControl دارم میسازم که از لحاظ ظاهری ، قراره خیلی شبیه به کنترلی که در My Computer (همون This PC) که آیکون و آیتم و نوشته ها و اطلاعات مربوط به یک درایو را نشون میده ، باشه . منتها این user control ، علاوه بر این اطلاعات ، اطلاعات بکاپ های اون درایو را نشون میده .

در واقع این user control ، اطلاعات بکاپ ها را نشون میده و همچنین بعضی از اطلاعات درایوها (که در My Computer) هست را نشون میده .

حالا من در یکی از کلاس های لایه ی Model ام ، پروپرتی ای بنام BackupStatus دارم که وضعیت بکاپ را بصورت enum ذخیره میکنه (که بکاپ در حالت عادی هست ، یا اینکه بکاپ نداره یا اینکه در شرایط هشدار دادن قرار داره) .
این پروپرتی ، برای کلاسی هست که اطلاعات کل و همه ی درایوها را ذخیره میکنه . یعنی فرضا اگه طرف 5 تا درایو داشت که وضعیت بکاپ 3 تاشون عادی بودن و یکی شون در حالت هشدار و یکی دیگه بکاپ نداشت ، این پروپرتی در این کلاس ، بدترین حالت را برمیگردونه که یکی از درایوها بکاپ نداشت (را برمیگردونه) .

اما بجز این ، مجددا همین پروپرتیِ BackupStatus در کلاسِ مجزای دیگه ای که اطلاعات بکاپِ تک تکِ درایوها را برمیگردونه ، استفاده میشه (هنوز واسه ی این کلاس ها اسم مشخص نکردم واسه ی همین اسم شون را ننوشتم) .

----------

این DriveBackupUserControl هم که کلاسی هست که مربوط به هر درایو میشه ، از پروپرتیِ BackupStatus ای که مربوط به هر درایو مجزا هستن میخواد استفاده کنه .

حالا چون این DriveBackupUserControl ، قراره که اطلاعات را توی خودش داشته باشه و کلا یه کلاس هست ، به نظرتون تکلیفش را با پروپرتیِ BackupStatus (که از نوعِ enum هست و در Model تعریف شده) ، چی کار کنم؟
این DriveBackupUserControl یک کنترل مستقل ئه، اصول برنامه نویسی شی گرا رو باید رعایت کنید. باید وظایف و کارکردش مستقل باشه، اونقدر که راحت بشه به پروژه دیگری منتقلش کرد، پس اینکه برای کارکردش یک Enum مستقل در خودش یا کنارش داشته باشه خیلی طبیعیه. حالا میخواهید شبیه این Enum در Model باشه تا برای ساختار داده Model بکار بره؟ خوب باشه. چه ایرادی داره؟ اینکه شبیه اون Enum در Model حتی با مقادیر مشابه تعریف شده باشه که نظم جهان هستی رو بهم نمی زنه. ViewModel میتونه با یک cast ساده این Enum رو به اون یکی Enum تبدیل کنه.
اگه پروپرتی هایی نظیر این پروپرتی هایی که در Model هست را در User Control تعریف کنم ، دقیقا چی کار کنم؟
نیاز های View شما ابدا ربطی به نیاز های Model شما نداره و برعکس. برای اینکه شرایط رو درک کنید تصور کنید UserControl شما رو تیم برنامه نویسی A سه سال پیش در سنگاپور طراحی کرده و Model شما رو هفته پیش تیم برنامه نویسی B در اوگاندا که اصلا از همدیگه خبری ندارند. اگر چیزی برای ذخیره سازی یا نگهداری داده لازمه در Model تعریف کنید و اگر چیزی برای کارکرد UserControl تون لازمه در View تعریف کنید. اگر کسی خواست از UserControl تون در پروژه دیگری استفاده کنه نباید لازم باشه چیزی از Model یا ViewModel رو بخواد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
DriveInfo جزو واسط کاربری که نیست، ساختاری برای داده است. اما شما که تعریفش نمی کنید، جزئی از NET Framework. ئه، پس نمی توانید تعریفش رو به یک لایه خاص تخصیص اش بدهید. شما نمی توانید محل تعریف DriveInfo رو تغییر بدهید و بندازید داخل لایه فلان. ورای مدل پروژه شما است. در NET. Framework تعریف شده که بر اساس مدل MVVM هم نیست. برای همین یک تعریف خارج از پروژه شما است و اینکه در کدوم لایه ازش استفاده کنید به منطق روال تون بستگی داره وگرنه خودش در هر لایه ای میتونه مورد استفاده قرار بگیره.

سلامی مجدد استاد .
خیلی ممنون .
پس ، هر نوعی که در Model ام تعریف نشده باشه (فرضا در .Net یا .Net Framework یا کتابخونه ی دیگه ای تعریف شده باشه) ، محدودیت استفاده در لایه ی خاصی از اون نوع را ندارم .

محدودیت چیه؟ محدودیت فقط اینه که DriveInfo مستقیم بین Model و View رد و بدل نشه. دقیقا همونطور که int نباید مستقیم به Model و View رد و بدل نشه.

مگر اینکه روال عادی که در MVVM ، باید بین عضوی در Model هست که از اون نوع مورد نظر هست ، با View و برعکس ، ارتباط مستقیم وجود نداشته باشه (حتی نوع int و هر نوع دیگه ای) (یا از طریق Binding عمل بشه) که مشخص هست .

شما دارید بر شرایط DriveInfo نتیجه گیری می کنید، در حالی که DriveInfo جزئی از هیچ لایه MVVM ای نیست.

نه. شما اول یک محدودیت بی دلیل ایجاد می کنید که مشکل ایجاد می کنه و بعد دنبال راه حل برای مشکلی میگردید که از اساس نباید باشه.

بله .

این DriveBackupUserControl یک کنترل مستقل ئه، اصول برنامه نویسی شی گرا رو باید رعایت کنید. باید وظایف و کارکردش مستقل باشه، اونقدر که راحت بشه به پروژه دیگری منتقلش کرد، پس اینکه برای کارکردش یک Enum مستقل در خودش یا کنارش داشته باشه خیلی طبیعیه. حالا میخواهید شبیه این Enum در Model باشه تا برای ساختار داده Model بکار بره؟ خوب باشه. چه ایرادی داره؟ اینکه شبیه اون Enum در Model حتی با مقادیر مشابه تعریف شده باشه که نظم جهان هستی رو بهم نمی زنه. ViewModel میتونه با یک cast ساده این Enum رو به اون یکی Enum تبدیل کنه.

خیلی ممنون استاد .
پس اگه اشتباه نکنم ، نکته اینجاست که هر وقت در View مون ، به نوعی که در Model مون تعریف شده ، نیاز داشتیم ، کلا باید یکی از 3 کار زیر را کنیم تا MVVM نقض نشه :

1 - یا مجددا ، شبیه نوعی که در Model تعریف شده را در View مون تعریف میکنیم (که حالا بعدش با Binding و توسط Convert اش ، این نوع ها را به هم تبدیل میکنیم یا حالا هر روش دیگه ای) .

2 - یا از View ، به Model مون Binding انجام میدیم (که قبلا مفصلا توضیح دادید) .

3 - یا توسط ViewModel ، بصورت غیر مستقیم ، فراخونی و استفاده میکنیم (که قبلا مفصلا توضیح دادید) .

درسته دیگه؟

نیاز های View شما ابدا ربطی به نیاز های Model شما نداره و برعکس. برای اینکه شرایط رو درک کنید تصور کنید UserControl شما رو تیم برنامه نویسی A سه سال پیش در سنگاپور طراحی کرده و Model شما رو هفته پیش تیم برنامه نویسی B در اوگاندا که اصلا از همدیگه خبری ندارند. اگر چیزی برای ذخیره سازی یا نگهداری داده لازمه در Model تعریف کنید و اگر چیزی برای کارکرد UserControl تون لازمه در View تعریف کنید. اگر کسی خواست از UserControl تون در پروژه دیگری استفاده کنه نباید لازم باشه چیزی از Model یا ViewModel رو بخواد.

پس با این حالت ، میتونم اگه نیاز داشتم ، بجای زمانی که پروپرتیِ Icon ئه Window ام یا پروپرتیِ IconSource ئه TaskbarIcon ام را که به پروپرتیِ BackupStatus ئه Model ام (که از نوعِ enum ئه شخصی در Model تعریف شده) ، Binding کردم ، بیام و بجاش یه enum ئه شخصیِ دیگه ی BackupStatus اما این بار در View تعریف کنم و پروپرتی ای از نوعِ این enum را این بار در کلاس Window ام (منظورم فرزندِ Window هست) تعریف کنم و بعد پروپرتیِ Icon ئه Window ام یا پروپرتیِ IconSource ئه TaskbarIcon ام ، از این enum ئه BackupStatus ای که در View تعریف شده استفاده کنن و بعد من هم بین پروپرتیِ BackupStatus ای که در Window تعریف کردم ، با پروپرتیِ BackupStatus ئه Model ام ، Binding ای با Convert انجا بدم .

متوجه ی منظورم شدید؟
درست میگم؟
اگه آره ، شما کدوم روش را بهتر میپسندین؟
تشکر استاد :rose:
 

the_king

مدیرکل انجمن
پس اگه اشتباه نکنم ، نکته اینجاست که هر وقت در View مون ، به نوعی که در Model مون تعریف شده ، نیاز داشتیم ، کلا باید یکی از 3 کار زیر را کنیم تا MVVM نقض نشه :

1 - یا مجددا ، شبیه نوعی که در Model تعریف شده را در View مون تعریف میکنیم (که حالا بعدش با Binding و توسط Convert اش ، این نوع ها را به هم تبدیل میکنیم یا حالا هر روش دیگه ای) .

2 - یا از View ، به Model مون Binding انجام میدیم (که قبلا مفصلا توضیح دادید) .

3 - یا توسط ViewModel ، بصورت غیر مستقیم ، فراخونی و استفاده میکنیم (که قبلا مفصلا توضیح دادید) .

درسته دیگه؟
بله.
پس با این حالت ، میتونم اگه نیاز داشتم ، بجای زمانی که پروپرتیِ Icon ئه Window ام یا پروپرتیِ IconSource ئه TaskbarIcon ام را که به پروپرتیِ BackupStatus ئه Model ام (که از نوعِ enum ئه شخصی در Model تعریف شده) ، Binding کردم ، بیام و بجاش یه enum ئه شخصیِ دیگه ی BackupStatus اما این بار در View تعریف کنم و پروپرتی ای از نوعِ این enum را این بار در کلاس Window ام (منظورم فرزندِ Window هست) تعریف کنم و بعد پروپرتیِ Icon ئه Window ام یا پروپرتیِ IconSource ئه TaskbarIcon ام ، از این enum ئه BackupStatus ای که در View تعریف شده استفاده کنن و بعد من هم بین پروپرتیِ BackupStatus ای که در Window تعریف کردم ، با پروپرتیِ BackupStatus ئه Model ام ، Binding ای با Convert انجا بدم .

متوجه ی منظورم شدید؟
نه، متوجه نشدم پروپرتی ها برای چیه. شما یک Enum در Model دارید و یک Enum در View دارید و View یک مبدل میخواد که مقدار این Enum رو تبدیل کنه به آیکون متناظرش و یک مبدل در ViewModel برای تبدیل مقدار بین Enum ئه View و Enum ئه Model
اما به هر حال هر کاری میخواهید بکنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
خیلی ممنون استاد .
استاد ، در اون نمونه کدِ پروژه ی MVVM ئه Student که قبلا از اینترنت گرفته بودم و اینجا گذاشته بودم (و در جریانید) ، اگه یادتون باشه ، در لایه ی ViewModel اش ، شی ای از Student (که Model اش هست) ساخت و بعد توی همون لایه ی ViewModel ، به پروپرتی هایی که اعضای Student اش بودن ، مقدار داد .
یعنی مقداردهیِ اعضای Model را درون ViewModel انجام داد .

حالا سئوالم اینجاست که مقداردهیِ اعضای Model ، در درون ViewModel ، تا کجا درست هست؟ یعنی محدودیتی برای مقداردهیِ اعضای Model ، در درون ViewModel هست یا نه؟

چون اون پروژه ، مقداردهیش ساده بود .
اما پروژه که سنگین بشه ، در خیلی از مواقع ، مقداردهیِ پروپرتی های Model ، نیاز به محاسبات (ئه ریاضی یا فراخونیِ متدها و کلا اعضای مختلف در اون کلاسِ Model یا حتی در کلاس های مختلف در لایه ی Model) داره .
اگر این طور پیچیدگی داشت ، برای مقداردهیِ اون عضو از پروپرتیِ Model ، باز هم میتونیم از درون ViewModel مقداردهی کنیم یا نه؟

یا فرضا یه متدی در اون کلاس از Model بنویسیم (در اینجا ، فرضا در کلاسِ Student اون متد را بنویسیم) که این محاسبات را انجام بده و اون پروپرتی را مقداردهی کنه (فرضا اون متد ، محاسبات ریاضی یا فراخونیِ اعضای های مختلفی از لایه ی Model که برای مقداردهیِ اون پروپرتی نیاز هست را انجام بده و پروپرتیِ مورد نظر در کلاسِ Student را مقداردهی کنه) و بعد ما از درون ViewModel ، فقط اون متد در Student را فراخونی کنیم تا اون پروپرتی ، به این طریق ، مقداردهی بشه .

یا اینکه یه کلاسِ دیگه ای در Model بسازیم (فرضا کلاسی بنام Manager بسازیم) که در اون ، از کلاسِ Student مون شی بسازیم و محاسبات را برای مقداردهیِ اعضای پروپرتیِ شیِ Student را توش انجام بده و بعد در ViewModel ، با شیِ کلاسِ Manager ارتباط داشته باشیم؟
کدوم یکی از روش ها؟

کلا برای این نوع مواردی که برای مقداردهیِ پروپرتی های Model ، نیاز به محاسبات های مختلف داره ، باید چی کار کنیم؟
تشکر استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد .
استاد ، در اون نمونه کدِ پروژه ی MVVM ئه Student که قبلا از اینترنت گرفته بودم و اینجا گذاشته بودم (و در جریانید) ، اگه یادتون باشه ، در لایه ی ViewModel اش ، شی ای از Student (که Model اش هست) ساخت و بعد توی همون لایه ی ViewModel ، به پروپرتی هایی که اعضای Student اش بودن ، مقدار داد .
یعنی مقداردهیِ اعضای Model را درون ViewModel انجام داد .

حالا سئوالم اینجاست که مقداردهیِ اعضای Model ، در درون ViewModel ، تا کجا درست هست؟ یعنی محدودیتی برای مقداردهیِ اعضای Model ، در درون ViewModel هست یا نه؟
وظایف شون رو درست تفکیک کنید، وظایف لایه ها ناحیه اشتراکی ندارند، هیچ کاری نیست که هم بتونه وظیفه Model باشه و هم وظیفه ViewModel که سردرگم باشید که به کدوم یکی بسپارید، همچین چیزی نباید پیش بیاد.
Model هر چیزی که به خارج از Model ارائه میکنه یا رابط خروجی برای دریافت داده واکشی شده است یا رابط ورودی برای ارسال داده جهت ذخیره سازی ئه. نه روال تبدیل داده و محاسباتی به بیرون از خودش ارائه میکنه و نه اهمیتی میده که View چه نوع داده ای لازم داره.
هر رابطی از بیرون Model قابل دسترسی است برای استفاده در ViewModel ئه. اگر غیر از این باشه اشتباهه.
Model نباید کاری انجام بده که مربوط به تبدیل داده به قالب مناسب برای View باشه، و ViewModel نباید کاری رو انجام بده که مربوط استخراج داده، تحلیل داده، ذخیره سازی داده و ... باشه، ViewModel فقط باید رابط باشه، داده بین View و Model رو سازگار کنه، تبدیل کنه.
اگر ViewModel محاسباتی انجام میده، صرفا برای اینه که قالب داده View رو با قالب داده Model سازگار کنه، از این تبدیل کنه به اون و برعکس. ViewModel هیچ محاسباتی که مربوط به نمایش داده یا اعتبار سنجی ورودی کاربر، یا ذخیره سازی داده یا واکشی داده باشه انجام نمیده، اینکار ها یا وظیفه View بودن یا وظیفه Model.
چون اون پروژه ، مقداردهیش ساده بود .
اما پروژه که سنگین بشه ، در خیلی از مواقع ، مقداردهیِ پروپرتی های Model ، نیاز به محاسبات (ئه ریاضی یا فراخونیِ متدها و کلا اعضای مختلف در اون کلاسِ Model یا حتی در کلاس های مختلف در لایه ی Model) داره .
اگر این طور پیچیدگی داشت ، برای مقداردهیِ اون عضو از پروپرتیِ Model ، باز هم میتونیم از درون ViewModel مقداردهی کنیم یا نه؟
اینکه چند تا مشخصه مقدار دهی میشه یا چند تا متد فراخوانی میشه ابدا اهمیتی نداره، اما این مهمه که این رابطی که استفاده میشه لازم بوده در دسترس ViewModel باشه؟ یا روال داخلی Model ئه که اشتباها به بیرونش منتقل شده؟
به ViewModel ربطی نداره که Model در ساختار داخلی اش چه ارتباطاتی داره، اصلا نباید این ارتباطات داخلی از Model خارج بشه. رابط Model باید طوری باشه که در هر پروژه ای یک ViewModel نا آشنا بتونه به ساده ترین شکل ممکن داده رو به Model بده یا از Model داده بگیره. رابط خارجی Model باید ساده ترین شکل ممکن رو داشته باشه. Model زیر مجموعه ViewModel نیست که روال هاش رو به ViewModel ارائه کنه تا ViewModel در محاسباتش ازش استفاده کنه.

View هر ورودی ای که از سمت کاربر میاد رو اعتبار سنجی میکنه، با هر محاسباتی که مربوط به خودشه تبدیل به داده میکنه که مناسب خروج از View باشه، دیگه به بعدش که اون طرف ViewModel چیکار میکنه یا Model چه نوع داده ای میخواد کاری نداره.

Model برای چی محاسبات انجام میده؟ برای ایجاد داده خروجی یا برای ایجاد داده ای که میخواد ذخیره کنه، درسته؟ پس اینکار ابدا ربطی به ViewModel و وظایف ViewModel نداره. داخل خودش باید انجام بده و از رابط خروجی اش پنهان باشه.
یا فرضا یه متدی در اون کلاس از Model بنویسیم (در اینجا ، فرضا در کلاسِ Student اون متد را بنویسیم) که این محاسبات را انجام بده و اون پروپرتی را مقداردهی کنه (فرضا اون متد ، محاسبات ریاضی یا فراخونیِ اعضای های مختلفی از لایه ی Model که برای مقداردهیِ اون پروپرتی نیاز هست را انجام بده و پروپرتیِ مورد نظر در کلاسِ Student را مقداردهی کنه) و بعد ما از درون ViewModel ، فقط اون متد در Student را فراخونی کنیم تا اون پروپرتی ، به این طریق ، مقداردهی بشه .
بله.
یا اینکه یه کلاسِ دیگه ای در Model بسازیم (فرضا کلاسی بنام Manager بسازیم) که در اون ، از کلاسِ Student مون شی بسازیم و محاسبات را برای مقداردهیِ اعضای پروپرتیِ شیِ Student را توش انجام بده و بعد در ViewModel ، با شیِ کلاسِ Manager ارتباط داشته باشیم؟
کدوم یکی از روش ها؟
باید ساده ترین رابط خروجی Model رو بسازید. از هر روالی که رابط رو پیچیده کنه باید اجتناب بشه، ارتباط داخلی اجزاء لایه باید مربوط به داخل لایه بمونه، نباید ازش دربیاد. اگر پیچیدگی ای در Student هست که به واسطه Manager بتوانید از ViewModel پنهانش کنید اینکار رو بکنید. اما اگر فقط دارید رابط Model رو پیچیده تر می کنید نه.
کلا برای این نوع مواردی که برای مقداردهیِ پروپرتی های Model ، نیاز به محاسبات های مختلف داره ، باید چی کار کنیم؟
تشکر استاد .
خیلی ساده، اصول شی گرایی و تفکیک وظایف لایه ها در MVVM یا هر الگوی دیگری رو رعایت کنید. کلاس X، فضای نام N، لایه A و کلا هر ناحیه تعریف شده ای یک وظیفه مشخص داره، وظایف مشترکی با سایر ناحیه ها نداره و ابدا نباید ازش چیزی خارج بشه که وظیفه خودش بوده و به بیرون از خودش مربوط نیست و ابدا نباید کاری رو انجام بده که بهش مربوط نیست. هر وقت دیدید که سر اینکه a باید در اینجا باشه یا اونجا سردرگم شدید بدونید که تفکیک وظایف رو درست انجام نداده اید و مدل تون ایراد داره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام استاد .
خیلی ممنون
اول اینکه خیلی ممنون که نرم افزار Visio را برای ساخت دیاگرام معرفی کردین (نمیدونستم . کلا آفیس ام خیلی ضعیفه) .
نمیدونم قضیه ی دیاگرام برنامه ام ، به این تاپیک ها مربوط میشه و یا بهتره تاپیک مربوط به Visio را ایجاد کنم .
به هر حال ، فعلا این پست را اینجا میذارم و اگه اشتباه گذاشتم ، ببخشید (و بگید که در صورت ادامه ، تاپیک مجزا بزنم) .

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

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

============

الان در کلاس DriveVssBackupCollection که در دیاگرام مشخص هست (اعضای این کلاس هنوز تمام نشدن) ، به اعضایی رسیدم که نیاز به ارتباط با تنظیمات یا Setting ئه پروژه ی بکاپ ام دارن .
مثلا پروپرتیِ IsExceptionDrive ئه این کلاس که در دیاگرام مشخص هست ، نیاز به ارتباط با تنظیمات پروژه داره تا مقدارش را از تنظیمات پروژه بگیره .

--------

قبلا گفته بودین که برای اینکه میخوام تنظیمات را جوری طراحی کنم که وقتی کاربر فقط دکمه ی OK را کلیک کرد ، در صورت تغییر تنظیمات توسط کاربر ، اون بخش از تنظیمات (یا کل تنظیمات) اِعمال بشه ، گفته بودین که تنظیمات را توی استراکچری بریزم .

حالا میخوام بدونم که رابطه ی اعضای استراکچرِ تنظیمات ، با کلاس های پروژه (مثل کلاس DriveVssBackupCollection) بهتره که چجوری انجام بشه؟

چند مورد و سناریو به ذهنم برای ارتباط تنظیمات با کلاس ها و اعضاشون به نظرم میاد ببینین که آیا از بین اینها ، موردی را میپسندین یا اگه نه ، پس چی کار کنم؟ :

1) استراکچر تنظیمات را تعریف میکنیم (فرضا این استراکچر که نامش Settings هست ، فیلدی بنام exceptionDrives که لیستی از DriveInfo هست ، داره و لیست درایوهایی که کاربر ، مستثنی از بکاپ گیری میکنه را ذخیره میکنه) .

بعد ، در کلاس مورد نظر (فرضا در همین کلاس DriveVssBackupCollection) ، عضوِ معادلش که میخوایم از اون تنظیمات استفاده کنه را تعریف میکنیم (فرضا پروپرتیِ IsExceptionDrive در کلاس DriveVssBackupCollection) .

در پارامتر متد سازنده ی کلاس مورد نظری که میخوایم در اون کلاس ، از اعضای تنظیمات استفاده کنیم (در پارامتر متد سازنده ی DriveVssBackupCollection) ، شیِ مورد نظر از استراکچرِ تنظیمات را میگیریم و در فیلدی در کلاس ، ذخیره میکنیم (فرضا در فیلدی بنام currentSetting که از نوع استراکچر Settings هست و این فیلد ، در کلاس DriveVssBackupCollection تعریف شده ، ذخیره میکنیم) .

در متد سازنده ، ابتدا ، مقداردهی اولیه را از شیِ استراکچری (شیِ currentSetting) که ذخیره کرده بودیم ، پروپرتیِ مورد نظرمون (پروپرتیِ IsExceptionDrive) را ازش پُر میکنیم .

حالا میمونه وقتی که مقدار فیلد استراکچرمون (مقدار فیلد exceptionDrives در استراکچر Settings) تغییر کنه ، بعد ، کلاس و پروپرتیِ مورد نظرمون (کلاس DriveVssBackupCollection و پروپرتیِ IsExceptionDrive) از تغییر مقدارِ فیلدش مطلع بشن که شاید بشه با پیاده سازیِ اینترفیس INotifyPropertyChanged ، از تغییر مقدار فیلد exceptionDrives در استراکچر Settings مطلع شد (هر چند ، اون اینترفیس برای تغییر مقدار پروپرتی استفاده میشه ولی شاید بشه طرفندی زد ، نمیدونم) .
و اگه بشه ، با تغییر مقدار فیلد ، متدی را در کلاس مورد نظر (DriveVssBackupCollection) اجرا میکنیم که وظیفه اش Update کردنِ پروپرتی مورد نظرمون (پروپرتیِ IsExceptionDrive) باشه .

------

2) سناریو دوم را باید بیشتر فکر کنم . هنوز کامل نیست (فکر میکردم کامل هست تقریبا) :)

------

و بعد اینکه خود استراکچر تنظیمات ، با توجه به اینکه در تنظیمات ، هم چیزها و تنظیمات مربوط به Model و هم چیزها و تنظیمات مربوط به View هست و با توجه به اینکه تنظیمات هر پروژه ، مختص خودِ همون پروژه هست (یعنی در پروژه ی دیگه قابل استفاده و قابل انتقال نیست) ، این استراکچرِ تنظیمات ، در کدوم لایه باید تعریف بشه؟

طبق مواردی که اشاره شد ، به نظر میاد که استراکچرِ تنظیمات ، بهتره که در لایه ی ViewModel تعریف بشه . درست میگم؟

خیلی ممنون استاد :rose:
 

پیوست ها

  • Poshtibangir Tolo UML Diagram ( RoadMap ).rar
    89.9 کیلوبایت · بازدیدها: 5

the_king

مدیرکل انجمن
من در نرم افزار Visio ، برای پروژه ی بکاپ ام ، بخشی از دیاگرام ساختم .
پروژه ی Visio رو در این پست پیوست میکنم .
من نتوانستم از فایلی که پیوست کردید استفاده کنم، نمودار نمی بینم، صرفا یک متن طولانی می بینم که به دو قسمت تقسیم شده، شبیه هیچ دیاگرامی که میشناسم دیده نمیشه.
و بعد اینکه خود استراکچر تنظیمات ، با توجه به اینکه در تنظیمات ، هم چیزها و تنظیمات مربوط به Model و هم چیزها و تنظیمات مربوط به View هست و با توجه به اینکه تنظیمات هر پروژه ، مختص خودِ همون پروژه هست (یعنی در پروژه ی دیگه قابل استفاده و قابل انتقال نیست) ، این استراکچرِ تنظیمات ، در کدوم لایه باید تعریف بشه؟
تنظیمات بر اساس انتخاب کاربر تغییر می کنه؟ همچین تنظیماتی مربوط به View است، چون تاثیرش رو در عملکرد View میذاره و در View هم تغییر می کنه. Model صرفا ذخیره کننده یا واکشی کننده مقادیر تنظیمات از پایگاه داده است که اونم با همون ساختار تنظیمات در View منطبق نیست چون روال پایگاه داده قاعدتا متفاوت از اون ساختاری است که برای تنظیمات در View دارید، طبعا می توانید یک struct یا class مشابه در Model برای تجمیع این مقادیر و راحت تر کردن تبادل داده برای ModelView داشته باشید ولی این ساختار متناظر نباید ارتباطی با ساختار و روال در View داشته باشه. شما حتی ممکنه در پایگاه داده یک جدول به نام تنظیمات داشته باشید که دو ستون بیشتر نداره، عنوان و مقدار. اگر ده تنظیم هست، جدولش ده تا سطر داره. که میتونه هزاران تنظیم متفاوت رو بدون توجه به کاربردش نگهداری کنه. همچین ساختاری که نمیدونه شما در View چه تنظیماتی برای چه کاربردهایی دارید، فقط هر تنظیم رو در یک قالب ساده مثلا یک رشته ذخیره و واکشی می کنه.
پس ساختار تنظیماتی که در View دارید ربطی به Model نداره. اینکه در تنظیمات اش بخشی مربوط به Model رو داشته باشید ابدا منطقی نیست، اصلا نباید متوجه باشه که در Model چه هست و چه می گذره.
طبق مواردی که اشاره شد ، به نظر میاد که استراکچرِ تنظیمات ، بهتره که در لایه ی ViewModel تعریف بشه . درست میگم؟
بهتر یعنی بیشتر از یک حالت امکان پذیر باشه که بخواهید بین شون انتخاب کنید. در حالی که گفتم، نباید همچین دو راهی پیش بیاد.
اگر تنظیمات در ViewModel باشه معنی اش اینه که شما یک Model ای ساخته اید که فقط میتونه با این ViewModel خاص کار کنه چون بهش وابسته است و View ای ساخته اید که فقط میتونه با این ViewModel خاص کار کنه چون اونم بهش وابسته است. یعنی دیگه ViewModel رو از یک واسطه ساده تبدیل کرده اید که به مبنای ساختاری پروژه. یعنی انگار شما اول یک ViewModel داشته اید که آمده اید بر مبنای اون Model و View ای طراحی کرده اید که با ViewModel سازگار باشند. دیگه نه View قابلیت جایگزینی داره و نه Model، چون پایه و اساس سازگاری مدل اون ViewModel شده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
من نتوانستم از فایلی که پیوست کردید استفاده کنم، نمودار نمی بینم، صرفا یک متن طولانی می بینم که به دو قسمت تقسیم شده، شبیه هیچ دیاگرامی که میشناسم دیده نمیشه.

سلامی مجدد استاد .
خیلی ممنون .

من نمیدونم منظورتون از دیاگرام و این توضیحات که قرار بود در برنامه ی paint3D بنویسم و بجاش توصیه کردین که در Visio بنویسم ، چجوری هست .
توی paint3D هم قرار بود همینطوری بنویسم و با فِلِش ، کلاس ها و اعضای وابسته به همدیگه یا کلاس های والد و فرزند را مشخص کنم .
اما در Visio ، راحت تر و با جزئیات بیشتری میتونم این کار را کنم (همونطور که در اون فایل ، که کامل نشد و ادامه داره ، مشخص هست) .
دیگه منظورتون از نمودار را نمیدونم که باید چجوری رسم کنم و چه شکلی باشه؟

به هر حال ، مشکلم الان در قسمت عضوهایی هست که باید با مقدار و اعضای تنظیمات ، وابستگی داشته باشن . مثل عضو زیر :


1.JPG


که عضو IsExceptionDrive ، در کلاس DriveVssBackupCollection هست که مقدارش وابسته به عضو مورد نظر در استراکچر تنظیمات هست .

حالا سئوالم اینه که این نوع اعضا ، چجوری باید با عضو مورد نظرشون در تنظیمات ، رابطه داشته باشن؟
یعنی فرضا اون سناریویی که گفته بودم ، خوبه؟ (به نظر میاد که مشکل اون سناریو ، توی پیاده سازی اینترفیس IPropertyChanged باشه) .

اصلا لازمه که معادلِ عضوی که در استراکچر هست ، در کلاس مورد نظر هم همون عضو را در نظر بگیریم (مثل عضو IsExceptionDrive ئه DriveVssBackupCollection را لازمه در نظر بگیریم) یا بدون در نظر گرفتنِ این اعضا ، مستقیما از این کلاس ها (مثلا از کلاس DriveVssBackupCollection) ، با اعضای استراکچر ، ارتباط داشته باشیم؟
که البته باز هم در این حالت ، مشکل مطلع شدنِ کلاس DriveVssBackupCollection از تغییر مقدارِ اعضا یا تغییر مقدارِ خود استراکچر تنظیمات هست .

البته در نظر هم باشه که رویداد کلیک دکمه ی OK (در View) هست که با استراکچر میتونه سر و کار داشته باشه و مقادیرش را (حالا بصورت مستقیم یا غیر مستقیم) تغییر بده .
بنابراین همین View (و رویداد کلیک دکمه ی OK) هم میتونه یه سیگنال بده به کلاس مورد نظر (مثلا به کلاس DriveVssBackupCollection) که استراکچر ، یا عضوی از استراکچر ، تغییر کرد . درسته؟

یا کلا شما چه سناریویی را برای ارتباط اعضا و همچنین خود استراکچر ، با کلاس هایی (و شاید اعضایی از این کلاس ها) که میخوان از این استراکچر و اعضای استراکچر استفاده کنن ، چیه؟
سناریوی من را میپسندین؟ اگه نه ، پس چه سناریویی پیشنهاد میدین؟

تنظیمات بر اساس انتخاب کاربر تغییر می کنه؟

بله دیگه .
اصلا ذات تنظیمات ، قابلیت تغییر دادن شون هست دیگه .
تنظیمات ، 3 بخش داره که در عکس زیر ، اولی برای تنظیمات مربوط به عملکرد برنامه (Model) هست و دومی مربوط به تنظیمات ظاهر برنامه (View) هست و سومی هم که جزء ابزار محسوب میشه :


2.JPG


3.JPG


4.JPG

همچین تنظیماتی مربوط به View است، چون تاثیرش رو در عملکرد View میذاره و در View هم تغییر می کنه.

Model صرفا ذخیره کننده یا واکشی کننده مقادیر تنظیمات از پایگاه داده است که اونم با همون ساختار تنظیمات در View منطبق نیست چون روال پایگاه داده قاعدتا متفاوت از اون ساختاری است که برای تنظیمات در View دارید، طبعا می توانید یک struct یا class مشابه در Model برای تجمیع این مقادیر و راحت تر کردن تبادل داده برای ModelView داشته باشید ولی این ساختار متناظر نباید ارتباطی با ساختار و روال در View داشته باشه. شما حتی ممکنه در پایگاه داده یک جدول به نام تنظیمات داشته باشید که دو ستون بیشتر نداره، عنوان و مقدار. اگر ده تنظیم هست، جدولش ده تا سطر داره. که میتونه هزاران تنظیم متفاوت رو بدون توجه به کاربردش نگهداری کنه. همچین ساختاری که نمیدونه شما در View چه تنظیماتی برای چه کاربردهایی دارید، فقط هر تنظیم رو در یک قالب ساده مثلا یک رشته ذخیره و واکشی می کنه.
پس ساختار تنظیماتی که در View دارید ربطی به Model نداره. اینکه در تنظیمات اش بخشی مربوط به Model رو داشته باشید ابدا منطقی نیست، اصلا نباید متوجه باشه که در Model چه هست و چه می گذره.

بهتر یعنی بیشتر از یک حالت امکان پذیر باشه که بخواهید بین شون انتخاب کنید. در حالی که گفتم، نباید همچین دو راهی پیش بیاد.
اگر تنظیمات در ViewModel باشه معنی اش اینه که شما یک Model ای ساخته اید که فقط میتونه با این ViewModel خاص کار کنه چون بهش وابسته است و View ای ساخته اید که فقط میتونه با این ViewModel خاص کار کنه چون اونم بهش وابسته است. یعنی دیگه ViewModel رو از یک واسطه ساده تبدیل کرده اید که به مبنای ساختاری پروژه. یعنی انگار شما اول یک ViewModel داشته اید که آمده اید بر مبنای اون Model و View ای طراحی کرده اید که با ViewModel سازگار باشند. دیگه نه View قابلیت جایگزینی داره و نه Model، چون پایه و اساس سازگاری مدل اون ViewModel شده.

منظورتون استراکچر و اعضای این استراکچری که میخوام بنویسم و مربوط به ذخیره ی مقادیر تنظیمات میشه ، هست که میگین این استراکچر ، مربوط به View میشه (و در لایه ی View باید بنویسم) (منظور من ، همین استراکچر هست که باید در کدوم لایه بنویسم) ؛ یا اینکه منظورتون View ای هست که Window و کنترل های مربوط به تنظیمات را شامل میشه ، هست (که در عکس بالا گذاشتم) ؟

اگه منظورتون استاکچرش هست که باید در View تعریف بشه ، خوب قراره Model هم بهش دسترسی داشته باشه و از اعضاش استفاده کنه دیگه .
همچنان که قراره View هم از اعضای این استراکچر استفاده کنه و بهش دسترسی داشته باشه .
چون تنظیمات هر دوی View و Model توشون هست

تشکر استاد
 

the_king

مدیرکل انجمن
سلامی مجدد استاد .
خیلی ممنون .

من نمیدونم منظورتون از دیاگرام و این توضیحات که قرار بود در برنامه ی paint3D بنویسم و بجاش توصیه کردین که در Visio بنویسم ، چجوری هست .
شما در مورد دیاگرام UML تحقیقی کردید؟ وقتی در مورد چیزی مطالعه نکنید طبعا متوجه منظور من نمی شوید.
دیاگرام یعنی نمودار، یک متن طولانی که نمودار نیست. تصاویر UML Diagram رو جستجو کنید ببینید چه شکلی هستند. در نمودار های UML متن فقط اسامی ئه، عباراتی در حد یکی دو کلمه، مثلا اسامی موجودیت ها، فعالیت ها، متد ها و اینجور موارد. نه داخلش کد برنامه داره و نه جملات طولانی.
دیگه منظورتون از نمودار را نمیدونم که باید چجوری رسم کنم و چه شکلی باشه؟
یک راه حل بیشتر نداره، نمودار UML رو جستجو کنید.
به هر حال ، مشکلم الان در قسمت عضوهایی هست که باید با مقدار و اعضای تنظیمات ، وابستگی داشته باشن . مثل عضو زیر :


مشاهده پیوست 114765
که عضو IsExceptionDrive ، در کلاس DriveVssBackupCollection هست که مقدارش وابسته به عضو مورد نظر در استراکچر تنظیمات هست .
مقدار یک bool در کلاس DriveVssBackupCollection برای چی به اعضاء تنظیمات وابسته است؟ شما یک مقدار bool دارید که میتونه مستقیم از View به ViewModel یا برعکس یا مستقیم از Model به ViewModel و برعکس یا با واسطه ViewModel از Model به View و برعکس منتقل بشه، دیگه وابستگی اش برای چیه؟ شما فرضا با متد SetExceptionDrive(string name, bool value) در Model بهش اطلاع می دهید که مقدار فلان داده تغییر کرده تا در پایگاه داده ذخیره اش کنه، مثلا درایو فلان استثنا هست یا نیست، فقط همین. یا کل ساختار تنظیمات رو به ViewModel انتقال می دهید، ViewModel تبدیلش می کنه به یک رشته json یا XML یا INI یا هر ساختار سازگار دیگری با Model تا Model ذخیره اش کنه. Model هم دقیقا با همون قالب به ViewModel تنظیمات رو تحویل میده. دیگه کاری نداره که ساختار تنظیمات در View چیه.
به Model ربطی نداره که این داده برای تنظیمات View ئه یا کاربرد دیگری داره، کاربر تغییرش داده یا منطق View یا اصلا این تغییر چه تاثیری در کارکرد View داره.
منظورتون استراکچر و اعضای این استراکچری که میخوام بنویسم و مربوط به ذخیره ی مقادیر تنظیمات میشه ، هست که میگین این استراکچر ، مربوط به View میشه (و در لایه ی View باید بنویسم) (منظور من ، همین استراکچر هست که باید در کدوم لایه بنویسم) ؛ یا اینکه منظورتون View ای هست که Window و کنترل های مربوط به تنظیمات را شامل میشه ، هست (که در عکس بالا گذاشتم) ؟
مگر دو تا View متفاوت هست؟ اولی با دومی چه فرقی داره؟ منظورم هم اولی ئه و هم دومی چون هر دوشون توصیف یک مورد بیشتر نیست.
اگه منظورتون استاکچرش هست که باید در View تعریف بشه ، خوب قراره Model هم بهش دسترسی داشته باشه و از اعضاش استفاده کنه دیگه .
نه. قبلا بهتون گفتم شرایط رو چطور تصور کنید، یادتون که نرفته؟ Model رو کدوم تیم کی و در کجا نوشته بود؟ طراحی Model اصلا نمیدونه شما در View چه تنظیماتی دارید. View هم نمیدونه Model برای ذخیره سازی تنظیماتش چه روشی بکار میبره.
فرض کنید Model به شما این امکان رو داده که بتوانید تنظیمی با هر بخش و نام و مقدار دلخواهی مثلا section فلان، name بهمان و مقدار value مشخصی رو ذخیره کنید یا واکشی کنید. اگر فردا تنظیمات جدیدی به View اضافه شد، Model هیچ تغییری نخواهد کرد.
Model هیچ اطلاعی از معنی و کارکرد این بخش و name و مقدارش نداره، مثلا در پیاده سازی برای هر بخش یک جدول جداگانه داشته باشه، اما نمیدونه جدول a با جدول b چه تفاوت کارکردی داره. ممکنه برای نگهداری این مقادیر یک جدول یا فایل داشته باشه یا ده تا جدول و فایل یا اصلا همه رو خلاصه کنه در یک رشته یا آرایه باینری. هیچ کاری نداره که این مقادیر در تنظیمات View با چه ساختار و کارکردی استفاده میشن. فقط مقادیری که روی نحوه واکشی یا ذخیره سازی خود Model تاثیر داره رو در خود Model مدیریت می کنه، اصلا به اینکه بیرون خودش مقادیر چه کارکردی دارند کاری نداره.

View هم درست برعکس، View میتونه به ViewModel کل شیء تنظیماتش رو یکجا یا بصورت جزء به جزء به هر طریقی که مناسب میدونه انتقال بده.
به چی ربط داره؟ به اینکه اینترفیس View چیه. View ممکنه یک دیکشنری از اسامی و مقادیر تحویل بده یا یک شیء از کلاس تنظیمات یا یکسری مشخصه یا یک رشته XML یا ...
حالا اینکه ViewModel به چه طریقی مقادیر رو به Model انتقال میده به چی بستگی داره؟ به اینترفیس Model. طراحی Model یک اینترفیسی در نظر گرفته که میگه این مدلی بهت داده تحویل میدم یا ازت داده میگیرم. فرضا Model میگه به من یک رشته json یا XML بده تا به عنوان تنظیمات ذخیره اش کنم، یا این مشخصه ها رو یکی یکی پر کن، یا مقادیر پارامتر های متد فلان رو مقدار دهی کن، یا ...
این دیگه وظیفه ViewModel ئه که اون مقادیری که از View تحویل گرفته رو با این اینترفیس هماهنگ کنه و برعکس.
اما به هر حال Model اینترفیس ای داره که ابدا کاری به ساختار تنظیمات View نخواهد داشت.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
شما در مورد دیاگرام UML تحقیقی کردید؟ وقتی در مورد چیزی مطالعه نکنید طبعا متوجه منظور من نمی شوید.
دیاگرام یعنی نمودار، یک متن طولانی که نمودار نیست. تصاویر UML Diagram رو جستجو کنید ببینید چه شکلی هستند. در نمودار های UML متن فقط اسامی ئه، عباراتی در حد یکی دو کلمه، مثلا اسامی موجودیت ها، فعالیت ها، متد ها و اینجور موارد. نه داخلش کد برنامه داره و نه جملات طولانی.

یک راه حل بیشتر نداره، نمودار UML رو جستجو کنید.

سلامی مجدد
خیلی ممنون استاد از توضیح خوب تون .

دیاگرامه دیگه . مثل این در اینترنت :

Class-diagram.jpg


هدفم اینه که میخوام بعدا یادم بمونه .
من هم همینطور رسم کردم دیگه . اگه منظورتون متن های اضافی هست ، چون هر بخش اش را ممکنه فاصله ی زمانی زیادی بین شون برای پیاده سازی طول بکشه و یادم بره ، همراه توضیحات و در بعضی هاش هم صرفا قسمت کلی کد (نه جزئی اش) مثل اینکه چه متدی (که مهم باشه) را فراخونی کنه و ... .

مقدار یک bool در کلاس DriveVssBackupCollection برای چی به اعضاء تنظیمات وابسته است؟ شما یک مقدار bool دارید که میتونه مستقیم از View به ViewModel یا برعکس یا مستقیم از Model به ViewModel و برعکس یا با واسطه ViewModel از Model به View و برعکس منتقل بشه، دیگه وابستگی اش برای چیه؟ شما فرضا با متد SetExceptionDrive(string name, bool value) در Model بهش اطلاع می دهید که مقدار فلان داده تغییر کرده تا در پایگاه داده ذخیره اش کنه، مثلا درایو فلان استثنا هست یا نیست، فقط همین. یا کل ساختار تنظیمات رو به ViewModel انتقال می دهید، ViewModel تبدیلش می کنه به یک رشته json یا XML یا INI یا هر ساختار سازگار دیگری با Model تا Model ذخیره اش کنه. Model هم دقیقا با همون قالب به ViewModel تنظیمات رو تحویل میده. دیگه کاری نداره که ساختار تنظیمات در View چیه.
به Model ربطی نداره که این داده برای تنظیمات View ئه یا کاربرد دیگری داره، کاربر تغییرش داده یا منطق View یا اصلا این تغییر چه تاثیری در کارکرد View داره.

مگر دو تا View متفاوت هست؟ اولی با دومی چه فرقی داره؟ منظورم هم اولی ئه و هم دومی چون هر دوشون توصیف یک مورد بیشتر نیست.

نه. قبلا بهتون گفتم شرایط رو چطور تصور کنید، یادتون که نرفته؟ Model رو کدوم تیم کی و در کجا نوشته بود؟ طراحی Model اصلا نمیدونه شما در View چه تنظیماتی دارید. View هم نمیدونه Model برای ذخیره سازی تنظیماتش چه روشی بکار میبره.
فرض کنید Model به شما این امکان رو داده که بتوانید تنظیمی با هر بخش و نام و مقدار دلخواهی مثلا section فلان، name بهمان و مقدار value مشخصی رو ذخیره کنید یا واکشی کنید. اگر فردا تنظیمات جدیدی به View اضافه شد، Model هیچ تغییری نخواهد کرد.
Model هیچ اطلاعی از معنی و کارکرد این بخش و name و مقدارش نداره، مثلا در پیاده سازی برای هر بخش یک جدول جداگانه داشته باشه، اما نمیدونه جدول a با جدول b چه تفاوت کارکردی داره. ممکنه برای نگهداری این مقادیر یک جدول یا فایل داشته باشه یا ده تا جدول و فایل یا اصلا همه رو خلاصه کنه در یک رشته یا آرایه باینری. هیچ کاری نداره که این مقادیر در تنظیمات View با چه ساختار و کارکردی استفاده میشن. فقط مقادیری که روی نحوه واکشی یا ذخیره سازی خود Model تاثیر داره رو در خود Model مدیریت می کنه، اصلا به اینکه بیرون خودش مقادیر چه کارکردی دارند کاری نداره.

View هم درست برعکس، View میتونه به ViewModel کل شیء تنظیماتش رو یکجا یا بصورت جزء به جزء به هر طریقی که مناسب میدونه انتقال بده.
به چی ربط داره؟ به اینکه اینترفیس View چیه. View ممکنه یک دیکشنری از اسامی و مقادیر تحویل بده یا یک شیء از کلاس تنظیمات یا یکسری مشخصه یا یک رشته XML یا ...
حالا اینکه ViewModel به چه طریقی مقادیر رو به Model انتقال میده به چی بستگی داره؟ به اینترفیس Model. طراحی Model یک اینترفیسی در نظر گرفته که میگه این مدلی بهت داده تحویل میدم یا ازت داده میگیرم. فرضا Model میگه به من یک رشته json یا XML بده تا به عنوان تنظیمات ذخیره اش کنم، یا این مشخصه ها رو یکی یکی پر کن، یا مقادیر پارامتر های متد فلان رو مقدار دهی کن، یا ...
این دیگه وظیفه ViewModel ئه که اون مقادیری که از View تحویل گرفته رو با این اینترفیس هماهنگ کنه و برعکس.
اما به هر حال Model اینترفیس ای داره که ابدا کاری به ساختار تنظیمات View نخواهد داشت.

خیلی ممنون استاد از توضیح خوب تون .
هر چند ، منظور من یه چیز دیگه بود و شما بیشتر ، روال دیتابیس را توضیح دادین (که فعلا مد نظرم نبود) ، اما این توضیح تون باعث شد ، سناریویی که توی ذهنم بود ، تغییراتی کنه و یا بشه گفت یه سناریوی جدیدتر به ذهنم برسه که این رو در Visio (با اندکی کد و توضیحات در اعضا) نوشتم که در این پست پیوست میکنم (حالا اگه خواستین ، توضیحات و اون یه کم کد را نخونین و صرفا نام اعضاش را بخونین) و در ادامه توضیح میدم .

بی زحمت چک کنین ببینین سناریویی که برای زمانی که مقدار تنظیمات تغییر کنه (برای آپدیت کردن پروپرتیِ مورد نظر در کلاس های مختلف) نوشتم ، همون چیزیه که تایید میکنید یا مد نظرتون هست یا این سناریو (در کلیات کار) مشکلی نداره؟

طبق نظر شما ، استراکچر تنظیمات (بنام ProgrameSettings) را در لایه ی View آوردم . اما هنوز شک دارم که این لایه ، جای مناسبی برای استراکچر تنظیمات باشه .
چون فرضا در Model ، یه عضو از نوعی که در خودِ Model تعریف بشه (مثلا نوعِ enum ئه BackupStatus) ، و فرضا در صورتی که اون نوع ، معادلش در View تعریف نشده باشه (که حالا ViewModel بخواد بین این دو نوع در View و Model ، تبدیلی انجام بده) (یعنی این نوع فقط در Model تعریف شده باشه) و در تنظیمات هم فیلدی با این نوع نیاز باشه ، در این صورت که لایه ی View مناسب قرار گرفتنِ استراکچرِ تنظیمات نیست .
واسه ی همین میگم لایه ی ViewModel ، بهترین مکان برای تعریف استراکچر تنظیمات هست .

=========

توضیحات درباره ی کلاس های Model ای که در این فایل نوشته شده اینکه :

کلاس ProgrameManager : بالاترین سطح کلاس در Model هست و ViewModel ، بصورت مستقیم با این کلاس ارتباط داره . همچنین فرضا اگه بعدا کلاس های بیشتری در قسمت Model اضافه بشه که نیاز به ارتباط با بالاترین لایه داشته باشن ، با این لایه ارتباط خواهند داشت .

کلاس InternalHardDriveCollection : (ایندکسرش) مجموعه ای از کلاس DriveVssBackupCollection هست .
همچنین اطلاعات مربوط به کل درایوها (نه یک درایو) را داره .

کلاس DriveVssBackupCollection : (ایندکسرش که در این فایل Visio نشون داده نشد) مجموعه ای از VssBackup هست .
همچنین اطلاعات مربوط به یک درایو را در خودش داره .

=========

در این کلاس ها ، فقط پروپرتی هایی که مقدارشون را از تنظیمات میگیرن و همچنین اعضای دیگه ای که برای مقداردهی و کارهای مربوطه ، مربوط میشن در این فایل از Visio آوردم (تا ساده ترین حالتش بشه) .

و همینطور که در این فایل قابل مشاهده هست ، طرح و سناریوی کلی اینه که در View ، وقتی دکمه ی کلیک دکمه ی تنظیمات کلیک شد و بسته شد ، وقتی این رویداد ، مقادیر جدید و تغییر یافته در تنظیمات را گرفت ، متدی در ViewModel ، و بعد ViewModel هم تک تک متدهایی که در هر کلاس در لایه ی Model ، برای آپدیت کردنِ پروپرتی های مربوط به تنظیمات (و همچنین ذخیره در دیتابیس) در همون کلاس نوشته شدن را فراخونی میکنه .

اگه متوجه ی توضیحات در اینجا نشدین ، فکر کنم این فایل ، طرح کلی اش واضح باشه اگه نگاه کنین . اگه متوجه هم شدین ، بی زحمت اون فایل را نگاه کنین شاید من بصورت کلی اشتباهی کنم که چون این طرح ، بصورت کلی هست ، اشتباه کوچیکش ، باعث خیلی اشتباهاتِ ریزِ دیگه در پیاده سازی اش میشه چون هر کدوم ده ها عضو و متد دیگه دارن و این فقط طرح و سناریوی کلی هست .

تشکر استاد :rose:
 

پیوست ها

  • Setting Diagram.rar
    62.9 کیلوبایت · بازدیدها: 1

the_king

مدیرکل انجمن
دیاگرامه دیگه . مثل این در اینترنت :

Class-diagram.jpg
چیزی که شما طراحی کردید مثل اینه؟
بی زحمت چک کنین ببینین سناریویی که برای زمانی که مقدار تنظیمات تغییر کنه (برای آپدیت کردن پروپرتیِ مورد نظر در کلاس های مختلف) نوشتم ، همون چیزیه که تایید میکنید یا مد نظرتون هست یا این سناریو (در کلیات کار) مشکلی نداره؟
شما یکسری تنظیمات دارید مثل exceptionDrives (بماند که نمیدونم چرا صرفا یک نمونه DriveInfo تعریفش کرده اید، Drives قاعدتا مجموعه چندین درایو ئه). حالا نقش این DriveInfo در Model چه خواهد بود؟ اینکه نام درایو ذخیره یا واکشی بشه، نه حجم اش و نه فضای خالی اش و ... در جایی ذخیره نخواهد شد. بنابر این برای Model وجود DriveInfo لازم نیست، DriveInfo اگر کاربردی داره در View است، در Model یک رشته یا مجموعه رشته ای میتونه مجموعه درایو های exceptionDrives رو مشخص کنه، مثل ":E:|F:|G"

طبق نظر شما ، استراکچر تنظیمات (بنام ProgrameSettings) را در لایه ی View آوردم . اما هنوز شک دارم که این لایه ، جای مناسبی برای استراکچر تنظیمات باشه .
چون فرضا در Model ، یه عضو از نوعی که در خودِ Model تعریف بشه (مثلا نوعِ enum ئه BackupStatus) ، و فرضا در صورتی که اون نوع ، معادلش در View تعریف نشده باشه (که حالا ViewModel بخواد بین این دو نوع در View و Model ، تبدیلی انجام بده) (یعنی این نوع فقط در Model تعریف شده باشه) و در تنظیمات هم فیلدی با این نوع نیاز باشه ، در این صورت که لایه ی View مناسب قرار گرفتنِ استراکچرِ تنظیمات نیست .
واسه ی همین میگم لایه ی ViewModel ، بهترین مکان برای تعریف استراکچر تنظیمات هست .
از طرف دیگه یک BackupStatus دارید، تاثیر مقدار این BackupStatus در Model چیه؟ یعنی اگر مقدار BackupStatus از x به y تغییر کنه، چه تاثیری در روال و عملکرد Model میذاره؟ فرضا یک if یا switch ای دارید که بگه اگر فلان بود فلان کار رو بکن که عملکرد متفاوتی رو بوجود بیاره؟ یا صرفا مقدار BackupStatus رو بدون تاثیر عملکردی ذخیره و واکشی می کنه؟ اگر مقدارش از enum ئه به int تغییر کنه، چه اتفاقی در عملکرد Model می افته؟ اگر Model صرفا مسئول نگهداری مقادیر یک تنظیم باشه، دلیلی نداره که برای تفکیک مقادیرش enum داشته باشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
چیزی که شما طراحی کردید مثل اینه؟

سلامی مجدد استاد
خیلی ممنون

حالا توضیحات اضافی داره :green:

الان استاد ، پس کلیات کار که نوشتم ، درسته؟
یعنی روالی که در متد SendUpdateSettingToModel ئه ProgrameManagerViewModel نوشتم که از همین متد ، تمام متدهایی که در هر کلاس از Model بودن را فراخونی میکردم (که اون متدها ، وظیفه ی به روزرسانیِ پروپرتی های مربوط به همون کلاس را انجام میداد) ، این روش درسته؟
همونی که با فِلِشِ سبز رنگ در فایل Visio مشخص کردم را میگم .

و در کل ، روال کلی اش درسته؟
چون در ادامه ی توضیحات تون ، هیچ ایرادی از روال کلی نگرفتین .

شما یکسری تنظیمات دارید مثل exceptionDrives (بماند که نمیدونم چرا صرفا یک نمونه DriveInfo تعریفش کرده اید، Drives قاعدتا مجموعه چندین درایو ئه).

اشتباه تایپی بود . چون توی ویژال استودیو ننوشتم . مستقیم توی Visio مینوشتم .
exceptionDrives از نوعِ List ای از DriveInfo هست .

حالا نقش این DriveInfo در Model چه خواهد بود؟ اینکه نام درایو ذخیره یا واکشی بشه، نه حجم اش و نه فضای خالی اش و ... در جایی ذخیره نخواهد شد. بنابر این برای Model وجود DriveInfo لازم نیست، DriveInfo اگر کاربردی داره در View است، در Model یک رشته یا مجموعه رشته ای میتونه مجموعه درایو های exceptionDrives رو مشخص کنه، مثل ":E:|F:|G"

حالا نوعِ DriveInfo را که قبلا گفته بودید چون توی دات نت هست ، پس مشکلی نداره در View یا Model و ViewModel استفاده بشه . یعنی باعث نقض MVVM نمیشه .

حالا اینکه چرا نوع DriveInfo میگیرم ، میگم اگه احتمالا توی اون کلاس ، یه وقتی نیاز شد که به اطلاعات بیشتر از اون درایو دسترسی داشته باشم ، مجددا نیام از رشته ی نام درایو ، شیِ DriveInfo بسازم .

از طرف دیگه یک BackupStatus دارید، تاثیر مقدار این BackupStatus در Model چیه؟ یعنی اگر مقدار BackupStatus از x به y تغییر کنه، چه تاثیری در روال و عملکرد Model میذاره؟ فرضا یک if یا switch ای دارید که بگه اگر فلان بود فلان کار رو بکن که عملکرد متفاوتی رو بوجود بیاره؟ یا صرفا مقدار BackupStatus رو بدون تاثیر عملکردی ذخیره و واکشی می کنه؟ اگر مقدارش از enum ئه به int تغییر کنه، چه اتفاقی در عملکرد Model می افته؟ اگر Model صرفا مسئول نگهداری مقادیر یک تنظیم باشه، دلیلی نداره که برای تفکیک مقادیرش enum داشته باشه.

نه .
BackupStatus ، را مثال زدم . وگرنه الان که نوعی از BackupStatus در تنظیماتم ندارم .احتمالا همه شون از نوع های بولین و عدد و رشته و اینها خواهند بود .
مثال زدم که فرضا در نسخه های دیگه ی این نرم افزار ، یا کلا هر نرم افزاری که به هر دلیلی نیاز باشه که در تنظیماتش ، فیلدی از نوعی که در Model اش نوشت داشته باشه ، در اون صورت ، پس بهترین مکان برای تعریف استراکچر تنظیمات ، لایه ی ViewModel نیست؟


یا اینکه مجددا در View اش ، نوعی شبیه به اونی که در Model اش تعریف کرد ، تعریف کنه (یعنی فرضا یک نوعِ BackupStatus را در Model و یک نوعِ دیگه از BackupStatus را در View تعریف کنه) و در ViewModel ، تبدیل بین این دو انجام بده؟ (اگه این کار را بخواد کنه ، بهتر نیست که مستقیما استراکچر تنظیمات را در ViewModel تعریف کنه که لازم به تعریف مجددِ یک نوع در دو لایه و بعد هم نیاز به تبدیلش در ViewModel نباشه) ؟

تشکر استاد .
 

the_king

مدیرکل انجمن
سلامی مجدد استاد
خیلی ممنون

حالا توضیحات اضافی داره :green:

الان استاد ، پس کلیات کار که نوشتم ، درسته؟
یعنی روالی که در متد SendUpdateSettingToModel ئه ProgrameManagerViewModel نوشتم که از همین متد ، تمام متدهایی که در هر کلاس از Model بودن را فراخونی میکردم (که اون متدها ، وظیفه ی به روزرسانیِ پروپرتی های مربوط به همون کلاس را انجام میداد) ، این روش درسته؟
همونی که با فِلِشِ سبز رنگ در فایل Visio مشخص کردم را میگم .

و در کل ، روال کلی اش درسته؟
چون در ادامه ی توضیحات تون ، هیچ ایرادی از روال کلی نگرفتین .
اولا من قصد ندارم ایراد بگیرم، قبلا هم این رو گفتم. ثانیا کلیات و روال بعدا که نوشتینش مشخص میشه، الان ارتباط ها مشخص نیست.
حالا نوعِ DriveInfo را که قبلا گفته بودید چون توی دات نت هست ، پس مشکلی نداره در View یا Model و ViewModel استفاده بشه . یعنی باعث نقض MVVM نمیشه .
نه مشکلی نداره، فقط اینترفیس رو بدون دلیل موجه پیچیده تر می کنه. اگر Model یا View در اینترفیس شون از DriveInfo استفاده می کنند، باید دلیلی باشه که حتما DriveInfo لازم باشه. فرضا اگر Model صرفا به نام درایو نیاز داشته باشه و شما بجای string از نوع داده پیچیده تری مثل DriveInfo استفاده کنید، اینترفیس رو بدون نیاز موجه بیخودی پیچیده کرده اید.
حالا اینکه چرا نوع DriveInfo میگیرم ، میگم اگه احتمالا توی اون کلاس ، یه وقتی نیاز شد که به اطلاعات بیشتر از اون درایو دسترسی داشته باشم ، مجددا نیام از رشته ی نام درایو ، شیِ DriveInfo بسازم .
این چیزی که میگید خلاف اصول مبنایی شیء گرایی است. در ضمن شما وقتی اینترفیس Model رو طراحی می کنید بر اساس روال داخل View تصمیم می گیرید؟ قرار نیست بدونید در داخل View چه میگذره. Model چرا باید به اطلاعات بیشتری بجز نام درایو نیاز داشته باشه؟
BackupStatus ، را مثال زدم . وگرنه الان که نوعی از BackupStatus در تنظیماتم ندارم .احتمالا همه شون از نوع های بولین و عدد و رشته و اینها خواهند بود .
مثال زدم که فرضا در نسخه های دیگه ی این نرم افزار ، یا کلا هر نرم افزاری که به هر دلیلی نیاز باشه که در تنظیماتش ، فیلدی از نوعی که در Model اش نوشت داشته باشه ، در اون صورت ، پس بهترین مکان برای تعریف استراکچر تنظیمات ، لایه ی ViewModel نیست؟
باز که میگید بهترین. این وظیفه مشترکی که بین لایه MVVM تصور کرده اید چیه که بشه یک مورد هم در این لایه و هم در اون لایه قرار بگیره که حالا یکی شون بهتر باشه؟
خیلی مساله ساده ای است. شما یک Model دارید که داخلش یک نوع داده اختصاصی داره. که طبعا در اینترفیس اش ازش استفاده شده که اجازه دسترسی خارجی بهش داده وگرنه که نباید همچین دسترسی ای باشه. این Model مستقل کامپایل شدنی ئه، هر چی لازم داره در خودش هست. مشابه هر Model و View ای که در مدل MVVM میتونه باشه. حالا اگر بخواهید از این Model در یک پروژه همراه یک View استفاده کنید چه چیزی لازمه؟ یک ViewModel که بین این Model و View واسطه باشه و اون نوع داده رو به داده متناسب با اینترفیس View تبدیل کنه و برعکس. همین. اگر این Model رو ببرید در یک پروژه دیگه قرار بدهید موقع کامپایل خطا میده؟ نمیده. چون نه به ViewModel خاصی وابسته است و نه به View. هر چه نیاز داره داخل خودشه، چیزی در اینترفیس اش نداره که در ViewModel یا View تعریف بشه. برای View هم همینطور. این مگر ویژگی MVVM نیست که بشه View و Model رو تعویض کرد یا در پروژه دیگری استفاده مجدد کرد؟
وظیفه ViewModel چیه؟ اینکه واسطه بین View و Model باشه. یعنی در یک پروژه View و Model ای قرار بگیره و بعد ViewModel ای طراحی بشه که واسطه بشه. ViewModel که ماهیت مستقل نداره، هم به View وابسته است و هم به Model. اما View و Model رو میشه از این پروژه برداشت و در پروژه دیگری استفاده کرد، به اون ViewModel خاص که وابسته نیستند.

در حالی که شما همچین مدلی رو توصیف می کنید: یک ViewModel ای دارید که داخلش یک نوع داده اختصاصی داره و اینترفیس View و Model وابسته به این نوع داده هستند. اینترفیس View و Model بدون اون نوع داده معنی داره؟ نه. یعنی بخشی از کد View و Model رو داخل ViewModel نوشته اید که بدون وجودش ناقص می شوند. یعنی تفکیک لایه های MVVM رو بهم زده اید. حالا شما می توانید بر مبنای مدل MVVM این View یا Model رو در پروژه دیگری بکار ببرید؟ نه. چون وابسته شده اند به ViewModel و اون نوع داده. بدون وجود اون ViewModel اصلا معنی ندارند، کامپایل نمیشن. قابل جایگزینی و استفاده مجدد نیستند. این که MVVM ای نیست که نوع داده واسط کاربری Model و View داخل ViewModel باشه. در نمودار مدل MVVM اون لایه ViewModel جزئی از Model و View ئه که ناحیه مشترک داشته باشند؟ کاملا مجزا و تفکیک شده هستند. ViewModel قرار نیست کد اینترفیس View و Model رو تکمیل کنه. فقط باید واسطه باشه. View و Model باید بدون ViewModel هم اینترفیس و استقلال خودشون رو داشته باشند، نباید ناقص بشوند.
یا اینکه مجددا در View اش ، نوعی شبیه به اونی که در Model اش تعریف کرد ، تعریف کنه (یعنی فرضا یک نوعِ BackupStatus را در Model و یک نوعِ دیگه از BackupStatus را در View تعریف کنه) و در ViewModel ، تبدیل بین این دو انجام بده؟ (اگه این کار را بخواد کنه ، بهتر نیست که مستقیما استراکچر تنظیمات را در ViewModel تعریف کنه که لازم به تعریف مجددِ یک نوع در دو لایه و بعد هم نیاز به تبدیلش در ViewModel نباشه) ؟
اولا نیاز Model و View کاملا متفاوت هستند، چون وظایف شون متفاوت ئه، برای همین به ندرت ممکنه همچین حالتی پیش بیاد که نوع داده ترکیبی مشابهی در اینترفیس شون لازم داشته باشند. داخلشون هم که اصلا به بیرون شون ربطی نداره. اینکه در View یا Model چه انواع داده داخلی استفاده شده ابدا به لایه های خارجی شون ربطی نداره. ثانیا اگر چنین حالتی هم پیش بیاد که شبیه اون نوع داده رو ایجاد کنید، نیاز خودشونه، ایجادش می کنید. ربطی به لایه های دیگه نداره. فرضا اگر Model یا View به یک نوع داده خاص شبیه هم نیاز دارند، برای اینه که خودشون نیاز دارند، پس برای خودشون هم تعریفش می کنند. هر چیزی که Model نیاز داره برای خودش تعریف می کنه و هر چیزی که View لازم داره برای خودش تعریف می کنه و از همدیگه هم خبر ندارند. باز هم تکرار می کنم، شما معماری MVVM رو طوری طراحی می کنید که انگار دو تیم مستقل در زمان ها و مکان های تفاوت دارند لایه های View و Model رو بدون اینکه با هم ارتباط داشته باشند طراحی می کنند. نهایتا یک طراح این دو View و Model رو کنار هم قرار میده و ViewModel ای طراحی می کنه که بین شون واسطه باشه.
اگر بخواهید این تفکیک وظایف لایه ها رو بهم بزنید، پروژه تون کار می کنه اما دیگه MVVM نیست. قابلیت ها و خصوصیات MVVM رو هم نداره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اولا من قصد ندارم ایراد بگیرم، قبلا هم این رو گفتم.

ثانیا کلیات و روال بعدا که نوشتینش مشخص میشه، الان ارتباط ها مشخص نیست.

سلامی مجدد استاد .
خیلی ممنون از توضیح خوب تون .
ارتباطات رو مشخص کردم دیگه . توی همون فایل Visio ، هم ارتباطات و هم کلیاتش هست دیگه .
View ، با نوع استراکچر تنظیمات سر و کار داره (و فیلدی از این نوع داره) . بعد از کلیک روی دکمه ی OK در پنجره ی تنظیمات ، View ، مقادیر جدید از فیلدهای تنظیمات را به ViewModel (به متد SendUpdateSettingToModel در ViewModel که در تصویر زیر موجود هست) ارسال میکنه .
ViewModel هم تمام متدهایی که درهر کلاس از Model برای آپدیت پروپرتی هایی که در همون کلاس به تنظیمات وابسته هستن را فراخونی میکنه (نام این متدها ، UpdateSettingRelatedProperties هست) .

1.JPG

این چیزی که میگید خلاف اصول مبنایی شیء گرایی است.

در ضمن شما وقتی اینترفیس Model رو طراحی می کنید بر اساس روال داخل View تصمیم می گیرید؟ قرار نیست بدونید در داخل View چه میگذره. Model چرا باید به اطلاعات بیشتری بجز نام درایو نیاز داشته باشه؟

بله میدونم شی گرایی را .
منظورم این بود که مجددا شی ای که قبلا از DriveInfo را اگه درست کرده بودم و بهش نیاز داشته باشم ، در دسترسم باشه .

هر چند شیِ جدید از DriveInfo هم اگه درست کنم ، فرق خاصی نداره . چون اطلاعاتش مهمه که همه شون یکی هستن (یعنی نام درایو و فضای خالی و حداقل ، اغلب اطلاعات در همون درایو در چند شی از DriveInfo ، یکی هستن) .

باز که میگید بهترین. این وظیفه مشترکی که بین لایه MVVM تصور کرده اید چیه که بشه یک مورد هم در این لایه و هم در اون لایه قرار بگیره که حالا یکی شون بهتر باشه؟
خیلی مساله ساده ای است. شما یک Model دارید که داخلش یک نوع داده اختصاصی داره. که طبعا در اینترفیس اش ازش استفاده شده که اجازه دسترسی خارجی بهش داده وگرنه که نباید همچین دسترسی ای باشه. این Model مستقل کامپایل شدنی ئه، هر چی لازم داره در خودش هست. مشابه هر Model و View ای که در مدل MVVM میتونه باشه. حالا اگر بخواهید از این Model در یک پروژه همراه یک View استفاده کنید چه چیزی لازمه؟ یک ViewModel که بین این Model و View واسطه باشه و اون نوع داده رو به داده متناسب با اینترفیس View تبدیل کنه و برعکس. همین. اگر این Model رو ببرید در یک پروژه دیگه قرار بدهید موقع کامپایل خطا میده؟ نمیده. چون نه به ViewModel خاصی وابسته است و نه به View. هر چه نیاز داره داخل خودشه، چیزی در اینترفیس اش نداره که در ViewModel یا View تعریف بشه. برای View هم همینطور. این مگر ویژگی MVVM نیست که بشه View و Model رو تعویض کرد یا در پروژه دیگری استفاده مجدد کرد؟
وظیفه ViewModel چیه؟ اینکه واسطه بین View و Model باشه. یعنی در یک پروژه View و Model ای قرار بگیره و بعد ViewModel ای طراحی بشه که واسطه بشه. ViewModel که ماهیت مستقل نداره، هم به View وابسته است و هم به Model. اما View و Model رو میشه از این پروژه برداشت و در پروژه دیگری استفاده کرد، به اون ViewModel خاص که وابسته نیستند.

در حالی که شما همچین مدلی رو توصیف می کنید: یک ViewModel ای دارید که داخلش یک نوع داده اختصاصی داره و اینترفیس View و Model وابسته به این نوع داده هستند. اینترفیس View و Model بدون اون نوع داده معنی داره؟ نه. یعنی بخشی از کد View و Model رو داخل ViewModel نوشته اید که بدون وجودش ناقص می شوند. یعنی تفکیک لایه های MVVM رو بهم زده اید. حالا شما می توانید بر مبنای مدل MVVM این View یا Model رو در پروژه دیگری بکار ببرید؟ نه. چون وابسته شده اند به ViewModel و اون نوع داده. بدون وجود اون ViewModel اصلا معنی ندارند، کامپایل نمیشن. قابل جایگزینی و استفاده مجدد نیستند. این که MVVM ای نیست که نوع داده واسط کاربری Model و View داخل ViewModel باشه. در نمودار مدل MVVM اون لایه ViewModel جزئی از Model و View ئه که ناحیه مشترک داشته باشند؟ کاملا مجزا و تفکیک شده هستند. ViewModel قرار نیست کد اینترفیس View و Model رو تکمیل کنه. فقط باید واسطه باشه. View و Model باید بدون ViewModel هم اینترفیس و استقلال خودشون رو داشته باشند، نباید ناقص بشوند.

اولا نیاز Model و View کاملا متفاوت هستند، چون وظایف شون متفاوت ئه، برای همین به ندرت ممکنه همچین حالتی پیش بیاد که نوع داده ترکیبی مشابهی در اینترفیس شون لازم داشته باشند. داخلشون هم که اصلا به بیرون شون ربطی نداره. اینکه در View یا Model چه انواع داده داخلی استفاده شده ابدا به لایه های خارجی شون ربطی نداره. ثانیا اگر چنین حالتی هم پیش بیاد که شبیه اون نوع داده رو ایجاد کنید، نیاز خودشونه، ایجادش می کنید. ربطی به لایه های دیگه نداره. فرضا اگر Model یا View به یک نوع داده خاص شبیه هم نیاز دارند، برای اینه که خودشون نیاز دارند، پس برای خودشون هم تعریفش می کنند. هر چیزی که Model نیاز داره برای خودش تعریف می کنه و هر چیزی که View لازم داره برای خودش تعریف می کنه و از همدیگه هم خبر ندارند. باز هم تکرار می کنم، شما معماری MVVM رو طوری طراحی می کنید که انگار دو تیم مستقل در زمان ها و مکان های تفاوت دارند لایه های View و Model رو بدون اینکه با هم ارتباط داشته باشند طراحی می کنند. نهایتا یک طراح این دو View و Model رو کنار هم قرار میده و ViewModel ای طراحی می کنه که بین شون واسطه باشه.
اگر بخواهید این تفکیک وظایف لایه ها رو بهم بزنید، پروژه تون کار می کنه اما دیگه MVVM نیست. قابلیت ها و خصوصیات MVVM رو هم نداره.

خیلی ممنون استاد .
بله درست میگید . چیزی که قبلا هم مفصلا گفته بودید .

پس شما میگید اگه استراکچر تنظیمات در ViewModel باشه ، حالا شیِ این استراکچر که یا در View و یا در Model و یا در هر دو که استفاده بشه ، باعث وابستگیِ View و Model ، به ViewModel میشه و بنابراین نمیشه View و Model را به پروژه های دیگه منتقل کرد (یا جایگزین شون کرد) .
و ضمن اینکه وظیفه ی ViewModel ، فقط انتقال داده بین View و Model هست . نه اینکه نوعی که در View یا Model استفاده میشه را در خودش تعریف کنه .

درست میگم؟
درست میگید . ببخشید . من از منظر دیگه ای نگاه کردم .

حالا میگم چطور شد که توی View میگید که استراکچر تنظیمات را تعریف کنیم؟
قبل از اینکه شما بگید ، حدس من این بود که استراکچر تنظیمات را توی Model تعریف کنم (چون فکر میکردم که بیشتر ، به Model مربوط بشه) .

تشکر استاد
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد استاد .
خیلی ممنون از توضیح خوب تون .
ارتباطات رو مشخص کردم دیگه . توی همون فایل Visio ، هم ارتباطات و هم کلیاتش هست دیگه .
View ، با نوع استراکچر تنظیمات سر و کار داره (و فیلدی از این نوع داره) . بعد از کلیک روی دکمه ی OK در پنجره ی تنظیمات ، View ، مقادیر جدید از فیلدهای تنظیمات را به ViewModel (به متد SendUpdateSettingToModel در ViewModel که در تصویر زیر موجود هست) ارسال میکنه .
ViewModel هم تمام متدهایی که درهر کلاس از Model برای آپدیت پروپرتی هایی که در همون کلاس به تنظیمات وابسته هستن را فراخونی میکنه (نام این متدها ، UpdateSettingRelatedProperties هست) .

مشاهده پیوست 114778





بله میدونم شی گرایی را .
منظورم این بود که مجددا شی ای که قبلا از DriveInfo را اگه درست کرده بودم و بهش نیاز داشته باشم ، در دسترسم باشه .
شیء ای که از x قبلا در کلاس A می سازید بر اساس نیاز کلاس A ئه، ربطی به نیاز کلاس B نداره. اگر کلاس B نیاز مشابهی داره برای خودش شیء خواهد ساخت. مبنای شی گرایی همینه. اگر غیر از این بود در NET. فرضا چند تا فیلد از اشیاء منابع بصری مرسوم طراحی می کردند تا همه کلاس کنترل ها از اون اشیاء استفاده کنند و هر کدوم برای موارد مشابه خودشون شیء مستقل نسازند.
حالا میگم چطور شد که توی View میگید که استراکچر تنظیمات را تعریف کنیم؟
نه همه تنظیمات.
Model هیچ اطلاعی از معنی و کارکرد این بخش و name و مقدارش نداره، مثلا در پیاده سازی برای هر بخش یک جدول جداگانه داشته باشه، اما نمیدونه جدول a با جدول b چه تفاوت کارکردی داره. ممکنه برای نگهداری این مقادیر یک جدول یا فایل داشته باشه یا ده تا جدول و فایل یا اصلا همه رو خلاصه کنه در یک رشته یا آرایه باینری. هیچ کاری نداره که این مقادیر در تنظیمات View با چه ساختار و کارکردی استفاده میشن. فقط مقادیری که روی نحوه واکشی یا ذخیره سازی خود Model تاثیر داره رو در خود Model مدیریت می کنه، اصلا به اینکه بیرون خودش مقادیر چه کارکردی دارند کاری نداره.
برای تک تک تنظیمات از خودتون سوال کنید، الزامی نیست که همه تنظیمات مربوط به یک لایه خاص باشند. سوال اینه. این تنظیم نرم افزار شما روی کارکرد کدوم لایه تاثیر داره؟ Model یا View؟ یا اصلا هر دو. Model قراره مقداری رو ذخیره و واکشی کنه که مربوط به تنظیمات ئه، اما اینکه true رو ذخیره کنه یا false یا 4 رو ذخیره کنه یا 10 روی کارکردش تاثیر داره؟ اگر مقدار تنظیمی از false به true تغییر کنه یا مقدار تنظیمی از ":E" به ":F" تغییر کنه، در عملکرد View و تعامل با کاربر تاثیر میذاره؟ جواب این سوالات مشخص می کنه که تنظیم متعلق به کدوم لایه است. مثال میزنم، فرضا شما یک تنظیم دارید به نام ConnectionString که برای ارتباط با پایگاه داده است، مشخص می کنه Model چطور و کجا به پایگاه داده متصل بشه. این تنظیم کارکرد Model رو تغییر میده، تغییر دادنش پایگاه داده رو تغییر میده، اما همچین تاثیری رو در View نداره. برای View صرفا یک مقدار برای نمایش و ویرایش ئه. اما مثلا یک تنظیم دیگه دارید به نام OutputFolder که وقتی View میخواد خروجی نرم افزار رو ایجاد کنه ازش استفاده خواهد کرد. تغییر مقدار این OutputFolder روی کارکرد Model تاثیری نداره، فقط رشته رو ذخیره و واکشی می کنه اما مقدارش کارکرد View رو تغییر میده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
شیء ای که از x قبلا در کلاس A می سازید بر اساس نیاز کلاس A ئه، ربطی به نیاز کلاس B نداره. اگر کلاس B نیاز مشابهی داره برای خودش شیء خواهد ساخت. مبنای شی گرایی همینه. اگر غیر از این بود در NET. فرضا چند تا فیلد از اشیاء منابع بصری مرسوم طراحی می کردند تا همه کلاس کنترل ها از اون اشیاء استفاده کنند و هر کدوم برای موارد مشابه خودشون شیء مستقل نسازند.

نه همه تنظیمات.

برای تک تک تنظیمات از خودتون سوال کنید، الزامی نیست که همه تنظیمات مربوط به یک لایه خاص باشند. سوال اینه. این تنظیم نرم افزار شما روی کارکرد کدوم لایه تاثیر داره؟ Model یا View؟ یا اصلا هر دو. Model قراره مقداری رو ذخیره و واکشی کنه که مربوط به تنظیمات ئه، اما اینکه true رو ذخیره کنه یا false یا 4 رو ذخیره کنه یا 10 روی کارکردش تاثیر داره؟ اگر مقدار تنظیمی از false به true تغییر کنه یا مقدار تنظیمی از ":E" به ":F" تغییر کنه، در عملکرد View و تعامل با کاربر تاثیر میذاره؟ جواب این سوالات مشخص می کنه که تنظیم متعلق به کدوم لایه است. مثال میزنم، فرضا شما یک تنظیم دارید به نام ConnectionString که برای ارتباط با پایگاه داده است، مشخص می کنه Model چطور و کجا به پایگاه داده متصل بشه. این تنظیم کارکرد Model رو تغییر میده، تغییر دادنش پایگاه داده رو تغییر میده، اما همچین تاثیری رو در View نداره. برای View صرفا یک مقدار برای نمایش و ویرایش ئه. اما مثلا یک تنظیم دیگه دارید به نام OutputFolder که وقتی View میخواد خروجی نرم افزار رو ایجاد کنه ازش استفاده خواهد کرد. تغییر مقدار این OutputFolder روی کارکرد Model تاثیری نداره، فقط رشته رو ذخیره و واکشی می کنه اما مقدارش کارکرد View رو تغییر میده.

سلامی مجدد
خیلی ممنون استاد .

پس ، در کل منظور شما اینه که ، استراکچر (یا کلاسِ) تنظیمات ، یا باید در View و یا در Model و حتی درون یک برنامه ، میتونه دو تا استراکچرِ تنظیمات باشه که یکی اش در View و یکی دیگه در Model باشه ؟
درست متوجه شدم؟

الان در عکس پست 932 که از برنامه گذاشتم ، عکسِ (سربرگِ) اول و سوم ، به Model ئه برنامه ام مربوط میشه و روی اونها تاثیر میذاره دیگه . درست میگم؟
هر چند Binding از View به Model ام انجام میشه تا مشخص بشه تنظیمات ، چطور تنظیم شدن (یعنی فرضا گزینه ی اول که "اجرای برنامه زمان شروع ویندوز" هست ، آیا تیک داره یا نه و ...) اما تنظیمات این دو سربرگ ، فقط جنبه ی نمایشی در View دارن اما تاثیرشون توی Model هست .
یعنی شما میگید برای این دو سربرگ ، استراکچری برای این تنظیمات (مربوط به این دو سربرگ) را در Model ایجاد کنم؟


و همچنین سربرگ (عکس) دوم ، توی ظاهر یا View ئه برنامه ام تاثیر داره (یعنی انتخاب استایل ، روی View ئه برنامه ام تاثیر داره) .
منظور شما اینه که یه استراکچرِ دیگه از تنظیمات ، درون لایه ی View برای سربرگ دوم ام بسازم؟

اگه آره ، این جوری ، کار یه کم پیچیده نمیشه؟

============

بعد اینکه استاد ، اول ، اصلا به نظرتون من معادل هر فیلد در استراکچرِ تنظیمات ، پروپرتیِ متناظرش را در کلاس مورد نظرم داشته باشم یا نه؟
فرضا (در اون فایل Visio) که پروپرتیِ ExceptionDrives در کلاسِ InternalHardDriveCollection بود ، من بیام در این کلاس ، پروپرتیِ ExceptionDrives تعریف کنم یا اینکه لازم نیست و مستقیما مقدارش را از استراکچرِ تنظیماتم در مواقع مورد نیاز فراخونی کنم؟
با توجه به اینکه اولا پروپرتی نیاز دارم تا این پروپرتی ام در Model را به View ام Binding کنم و دوما این پروپرتی ها (مثل پروپرتیِ ExceptionDrives در کلاسِ InternalHardDriveCollection) ، جزء مشخصه و ویژگیِ خودِ همون کلاس هست ، نظر خودم اینه که به همین منوال پیش برم . یعنی متناظرِ فیلدهای استراکچر ، پروپرتیِ مورد نظر را در کلاس مورد نظرم ایجاد کنم (نظرم ، همون روالی که در فایل Visio نوشتم ، هست) .
درست میگم؟


یه مورد دیگه این بود که فرضا بجای اینکه بیام در متد مورد نظر در هر کلاس (متد با نام UpdateSettingRelatedProperties در اون فایل Visio) ، بعد از به روزرسانیِ مقادیر پروپرتی مورد نظر در اون کلاس ، بعدش بیام این مقادیر را در این متد ، در دیتابیس ذخیره کنم ، بجاش یه متدی در خودِ استراکچرِ تنظیمات بسازم و از اونجا در دیتابیس ذخیره کنم .
نظرتون در این رابطه چیه؟ در استراکچر تنظیمات ، متدی بسازم یا در همون کلاس (با متد UpdateSettingRelatedProperties) برای ذخیره سازی در دیتابیس ؟
نظر من اینه که در همون کلاس این کار را انجام بدم (همون روالی که در اون فایل Visio نوشتم) .
 

جدیدترین ارسال ها

بالا