Къде е да по-добре да направим проверката за property-то ?


0

Здравейте, имаме основен клас GSM, който има полета model и manufcaturer, които са от тип стринг и полето Battery, което е отделен клас. Класът Battery има поле hoursIdle от тип int. Всички полета си имат и пропърти.Та въпросът ми е следният. Искам да хвърля exception, когато някой се опита да въведе негативно число за hoursIdle - къде е по-добре да се направи проверката - в пропъртито на HoursIdle в класа Battery или в пропъртито Battery в класа GSM ? Ето какво имам предвид: http://pastebin.com/BCksw3dT. Закоментираният код е вторият вариант 


в C# OOP от Hachiko (380 точки)


Отговори



2
Здравей,
Хвърли грешката в пропъртито в класа Battery - Там ти е полето, там трява да се грижиш за коректността на данните запазени в полето. В пропъртито Battery, спрямо контекста на класа GSM може да проверяваш дали някой не ти подава батерия от тип null.
Поздрави!

от nikolaikolarov (2177 точки)


1
Здравей, струва ми се че не трябва да имаш две свойства на battery. В класа Battery си правиш пропъртита на отделните елементи, хвърляш си изключения, а в класа GSM, трябва просто да инициализираш нов обект от тип Battery.

от wooden_jesus (2128 точки)


1
Правиш проверката и съответно хвърлянето на изключение само в класа батерия, който притежава hoursIdle поле, енкапсулирано в свойството HoursIdle (където реално трябва да ти е проверката). Обработването на грешката (try { ... } catch { ... }) се прави в Main метода на програмата и не в класа GSM. :)

от vlad_karamfilov (4595 точки)


0
А ако програмата няма Main метод, какво правим ? Например е ASP уеб приложение.

от yonchoy (2134 точки)

0
Там, където използваш логиката на пропъртито, трябва да хванеш грешката. Ако няма Main метод и е ASP.NET приложение, работата да хванеш грешката и да я обработиш е в controller-a/code-behind-a. ;)

от vlad_karamfilov (4595 точки)



0

Обикновено си слагам валидацията в set-а на полето. По този начин съм сигурен, че всеки път то ще ми върне валидирани данни. Ето например в конструктора na  Battery вместо   this.HoursIdle = hoursIdle; Ще направя setHoursIdle(hoursIdle).


от yonchoy (2134 точки)


0
Естествено че в пропъртито.А if (this.battery.HoursIdle < 0) тука трябва да е if (value < 0) иначе то си е null и няма да можеш да му сложиш стойност никога.

от IceElementor (398 точки)


0
Не трябва ли щом имаме поле да му направим и пропърти? В нашия случай в класа GSM имаме поле от тип Battery и за това му правим и пропърти или греша ? А ако е така както казва wooden_jesus, как тогава ще покажа на външния свят типът батерия и неговите характеристики като нямам пропърти за него в класа GSM и полето ми е private ?

от Hachiko (380 точки)


0
Да, но е хубаво да се отбележи, че писането на: private Battery gsmBattery; public Batter GsmBattery { get { return this.gsmBatter; } set { this.gsmBattery = value; } }
е напълно аналогично с: public Battery GsmBattery { get; set; } реално CLR си създава частно служебно поле, където записва стойността, а така дефинираното пропърти просто ни спестява писане (и даже изглежда по-пригледно и лесно четимо)

от gallumbits (2371 точки)

0
Значи в крайна сметка трябва да имам и пропърти за полето Battery. Всъщност сега се сетих, че в Main метода, когато си създаваме обект от тип GSM, трябва да си създадем и обект от тип Battery, който ще е един от аргументите на GSM конструктора: Battery nokiaBattery = new Battery(10); GSM nokia = new GSM("3310", "Nokia",nokiaBattery); Ако искаме да вземем информацията за батерията на този обект nokia можем или чрез обектът nokiaBattery или чрез свойството от тип Battery на класа GSM -кое е по-добрият вариант ?

от Hachiko (380 точки)



0
Kak ще хвърлите в пропърти ексепшън бе колеги?
на 2 места могат да се въведът грешни данни
1. В конструктора
2. В сетъра(сет метода) на полето батерия
там трябва да са и проверките и хвърлянето на ексепшън

от bgotov (1559 точки)


0
Мястото да се хвърли ексепшън СПОРЕД мен е точно в пропъртито. От отговора ти оставам с впечатление, че си писал на други езици, в които се използват get/set методи (или бъркаш терминологията field (поле) / пропърти (свойство)). В C# не е приета практиката за гетъри и сетъри (гет и сет методи) вместо това се предоставя много по гъвкав синтаксис чрез така наречените пропъртита, които имат get и set (да приликата е голяма). Тези пропъртита енкапсулират данните на полетата и предоставят възможност да се валидират, да се ограничава достъпа и т.н.
Дали проверката за валидност на данните трябва да се извърши в конструктора или в пропъртито е спорен въпрос. Има хора, които го правят и на двете места дори, но това в почти всички случаи е излишно повтаряне на код. Най-добрия вариант СПОРЕД мен е данните да се валидират в set-а на пропъртито и всеки път когато се променят тези данни да се минава през него. Когато ти подават данни в конструктора минава през пропъртитата, когато променяш данните в някой метод минаваш през пропъртитата и т.н.

от westi3m (5621 точки)


2
Винаги когато можеш да избягаш от ползването на try/catch е за предпочитане. Проверки могат да се правят и без него. Примерно с xxx.TryParse(). Всеки метод който има входящи данни е добре да си ги проверява и да хвърля exception, но този който му ги дава трябва да прави прости проверки с if/else/TryParse за да е сигурен, че дава верните данни. По-добре е в else да изпише грешка на екрана от колкото да създаде условия за exception който да го хване с try/catch и пак да изпише на екрана същата грешка.
 
Твоя конкретен случай е невалиден:
GSM asdf = new GSM("3310""Nokia"new Battery(-1));
Тези данни идват от някъде. Системата едва ли някога ще и хрумне сама да си ги генерира. Ако се въвеждат от конзолата още тогава трябва да се проверява дали са валидни или не и да се изпише грешка, че не може да се приеме отрицателната стойност. Ако идват от базата когато са били вкарвани там се прави това, ако е asp.net те пак от някъде са дошли. Така се прескача възможноста за създаване на exception и съответно хвашането му в try/catch
 
След време като почнете да учите технологиите ще видиш, че в 80% от случайте се ползват автоматични пропъртита. Проверките се правят на други места в метод или конструктор преди информацията да стигне до тези пропертита.
 
Твоя конкретен случай аз бих ползвал автоматични протъртита и проверките ще сложа в конструкторите на съответните класове.  Ако проверката за батерия е при ГСМ и хванеш да преместиш този клас Батерия в друг проект кой ще прави за нея проверка? За това всеки клас си проверява собствените си пропъртита.

от saykor (8845 точки)


0
Не учихме ли точно в темата за exceptions, че е грешно да изписваме на конзолата с Console.WriteLine грешката, а правилният цивилизован начин е да хвърлим ексепшън и с него да изпишем какво става. Ако не е така за какво са ексепшъните

от Hachiko (380 точки)

0
Не забравяй, че на конзола се учите. Никой в днешно време не пише конзолни програми. Когато почнеш да пишеш нормални приложения дето се ползват от хора нещата са различни. Потребителя салбо го интересува какъв е ексепшъна. Той не може да го прочете и не трябва да му се показва. На него му подаваш user friendly message за да може човека да си разбере грешката и да я оправи.
Хвърлянето на ексепшън се ползва от програмиста да му гръмне хубаво у главата за дето не си е проверил входните данните. Програмиста чете ексепшъна, не потребителя на програмата. Ексепшъна ти дава на теб полезна инфромация да знаеш какво се е случило което не би трябвало да става.
Тук има една много тънка разлика в нещата. Класа не му е работа да знае какво е конзола и да пише по нея. Той хвърля ексепшън. Метода който проверява входящите данни обикновенно е част от клиентското приложение и знае как да изпише на потребителя нормално разбираемо съобщение.
В конкретния случай дето си дал би трябвало Main метода да приема данни от потребителя, да ги провери и ако не са валидни да му каже. Той знае какво е Console.
Но ако същите класове ги преместиш в Windows Phone приложение там няма Consola и самите класове си хвърлят ексепшън. Но там също ще имаш логика която да проверява входните данни и да изведе на потребителя на телефона му нормално съобщение за грешка. Така ти като програмист пазиш потребителя да не пише каквото си иска, а само това което е вярно. В същото време избягваш създаването на ексепшън и проверки с try/catch.

от saykor (8845 точки)