Loading...
Pe6o601 avatar Pe6o601 61 Точки

Впечатление от изпита по КПК (5/17/2015)

Искам да отбележа, че това е първата ми тема, която пускам във форума.

Искам да попитам кой освен автора на изпита се е опитал да го реши?

Много ми е интересно как може изпитите от предните курсове да се решават за 3 часа, а текущия "изпит" да не стигнат 6 за самото рефакториране. 

В моя защита ще отбележа, че задачата, която къдравия лектор (Данчо, нищо лично, просто така ти излезна прякора ) "реши" по време на "подготовката" не успя да я докара до макс точки.

До кога ще търпим изцепки и неработещи задачи, зле проведени лекции, неработещи тестове, сгрешени условия?

Да не говорим че ако се напишат нужните тестове за задачата judje няма да я приеме заради голям размер на архива.

 

П.С. Хора, успокойте се малко с това че искате да покажете, че знаете повече от нас. Не е това идеята а да ни научите.

 

 

Тагове:
45
C# OOP Advanced 17/05/2015 19:18:29
simeon.georgiev avatar simeon.georgiev 62 Точки

И в крайна сметка ще има ли някакъв официален отговор от страна на SoftUni екипа?

2
a.angelov avatar a.angelov 1316 Точки

И аз да си кажа - прекалено обемиста задача за 6 часа.

Съставителя на задачата вероятно е успял да я реши за доста по-малко, НО - предполагам първо я пише нормално, после я разваля и след това я решава. Съответно има привилегията да знае какво е писал, какви са уловките и какво е омазал и затова му убягва обективната оценка на задачата :)

Задачите от предните изпити са със значително по-малък обем и тяхното решаване в рамките на това време е нормално.

Определено е нужно след съставяне на изпитните задачи те да бъдат решавани от трети човек за да се прецени нивото им.

7
Achev avatar Achev 53 Точки

Напълно съм съгласен с колегите по-горе.

Изпита не беше труден, бих го решил, но в никакъв случай за по-малко от 6 часа. Имаше доста малоумни грешки от сорта на "Park" с "Р" на кирилица, което ми отне може би час и половина, добре, че го чух из залата, иначе нямаше да хвана и сегашните точки. Аз не смятам, че такива грешки трябва да има на изпит по КПК. До самата част с UNIT тестовете дори не можах да стигна.

Както и да е, надявам се да съм направил няколко точки да хвана някаква оценка, че на поправка въобще не ми се ходи. laugh

0
17/05/2015 23:19:06
StrahilRuychev avatar StrahilRuychev 117 Точки

Не е на кирилица колега, на "бразилица" е :)))

3
nedjo avatar nedjo 53 Точки

Напълно подкрепям. Задачата не беше много трудно, просто доста обемиста. Изгубих четири часа в рефакториране и оправяне на бъгове и тъкмо си помослих, че ще тръгне и Exeption на ExitVehicle. Стандартно си помислих, че някъде ще има кирилска буква или парсването на датата ще е проблемна. И до края се опитвах да разбера защо не влиза в метода. И грешката се оказа в "моя телевизор". Не съм и предполагал, че последният подаван параметър ще е със сгрешено пропърти. Не, че не го знам, просто съм зациклил и дотам. Не мисля, че трябва да има толкова много бъгове в задачата. А се дават много малко точки за това. Все пак за да разбереш как работи програмата, трябва да я изчистиш откъм бъгове, да дебъгнеш всички входове и да разбереш кое как работи. А имаше още какво да рефакторирам. Надявам се поне да съм го взел, че заради материал, който знам(не перфектно, но достатъчно за взимане на изпита с що годе добра оценка) не ми се блъска пак по пътищата до другия край на България.

1
iordan_93 avatar iordan_93 Trainer 407 Точки

Здравейте, колеги. Ще се опитам да отговоря на възможно най-много от въпросите / коментарите ви. Извинявам се за дългия пост (няма картоф накрая :)). Обръщам внимание, че отговарям от мое име, а не от името на СофтУни и коментарът ми може да не отразява позицията на СофтУни по въпроса.

Организация:

@Pe6o601: Никога не е била целта да търпим "изцепки и неработещи задачи", "зле проведени тестове" и "сгрешени условия". Екипът влага много старание в подготовката на лекциите и изпитите. Само че е като с програмирането: все изскача по някой бъг и то все, където най-малко очакваш :(. Най-доброто, което можеш да направиш, като си намериш бъг, е да си напишеш тест и да не го повтаряш. Държавните университети имат много добра стратегия за това - използват учебни програми от преди 30 години, в които повечето бъгове вече са изчистени :).

@Filkolev: Съгласен съм, че ако КПК е паралелен курс, времето не стига. И аз съм карал курса по същия начин, много колеги също... - известно ми е как при тази натоварена програма (ООП + КПК, Advanced JS + КПК...) времето просто не стига (и може би не е поради несериозност). Не ходиш на лекция, за да направиш екипната работа по ООП (или да работиш); претупваш екипната работа в последния момент; не спиш, за да гледаш лекции и да прочетеш нещо повече по тях (SOLID, design patterns, QA - това са лекции, които искат да се прочетат повече неща). Екипът, естествено, си взема поука от цялата работа и от следващия випуск КПК ще бъде отделен курс. Надявам се това да промени много неща.

Judge (@Pe6o601, Pavel_R, mar0der): На всички, които ме повикаха днес, помогнах да submit-нат решения в judge докато кодът се компилира успешно. Не чух някой да казва, че има проблем с размера на файла. Не е част от изпита да се борим със системата за предаване и затова има асистенти и лектори, които помагат с това. В този ред на мисли, моето решение (с тестовете, zip-нато) е 37.9 KB.

Относно повечето на брой малки нулеви тестове, идеята ми харесва и си вземам бележка. Вариант е и всяка команда и резултатът от нея да се дава в различен цвят. Не съм го направил само защото не съм се сетил, а не защото искам да е гадно. Колкото до прекалено украсения изход, това най-често е ситуацията, когато сте на работа. Има един тон глупости, в които някъде има бъг.

За това да виждаме output-a на всеки тест - не знам дали може да се направи това в момента. Решение за това е в нулевите тестове да има всичко. Това беше и целта на нулевите тестове на този изпит. По идея няма случай, в който условието е спазено, нулевите тестове минават, а judge гърми за коректност.

Подготовка (@Pe6o601, ibakyrdjiev): Не решението беше това, което ми отне пет дни, а оправянето с judge системата, която на вярно решение не даваше максимален брой точки. Отново повтарям, проблемите в judge системата са отговорност на екипа (хората, които я пишат и хората, които дават тестовете). Това, че не успях да реша задачата докрай във времето за подготовката е моя вина. Има два основни фактора: 1) обяснявам повече (и пиша по-малко код), с надеждата да покрия повече случаи, които може да се случат на изпита; 2) на подготовка не решавам изпита предварително. Идеята тук е да бъде максимално реално, т. е. да се начукам на някакви проблеми и да ги реша на момента, а не да показвам заучено решение. Факт е обаче, че и двете неща бавят много. Като добавим това, че искам да решавам задачата заедно с хората в залата, забавянето става още по-голямо. Ще опитам да не се бавя толкова в бъдеще, като се надявам това да не е с цената на безинтересна подготовка.

Изпит: Две предварителни бележки: 1) по никакъв начин целта на изпита не беше "да покажем, че знаем повече от вас", никога не е била. Най-трудната част от изпита по идея е дългата документация и дебъгването; 2) изпитът беше доста подобен на подготовката и всичко беше написано (като изключим бъговете, разбира се).

NullReferenceException: в engine-a (Mecanismo.cs в условието) има if(string.IsNullOrEmpty(...)). Трябва да се замени с обратното: if(!string...). Имаше също if (commandLine == null) break;, който е възможно да сте махнали (в подготовката имаше същия проблем, всъщност недоглеждането на това ми докара 0 точки в края на редовната лекция). Този бъг го нямаше в условието, по-вероятно сте го въвели при рефакторирането.

Рефакториране, StyleCop: Няма да говоря за неща като именуване, exception-и с безумни имена и namespaces.

Много полезно нещо в това да си програмист е, че можеш да си напишеш абсолютно всичко. Аз използвам това умение и в живота и мисля, че помага. Ето един Node.js скрипт, който маха новите редове и интервалите в началото. След това отваряте файловете във VS, Ctrl + K, D и повечето простотии вече ги няма (остава да се оправят нещата, които са наблъскани на един ред, но това е доста по-трудно за едно такова просто скриптче). Далеч е от перфектно, но мисля, че спестява доста ръчен труд. Освен това, не ползвам ReSharper, но мисля, че има опция да оправи всичките тези неща. Отне ми 25 минути да го напиша, като се надявам, че би ми спестило повече време на изпита.

ООП: Имаше повтаряне на код в превозните средства. Решението е да се изнесат в базов (абстрактен клас) и да има константи за отделните цени. Конструкторът за команда също може да се напише по-качествено (и целият клас да се махне от command executor-a).

Повторение на код, SOLID: Имаше редове код, които трябваше да се изнесат в методи и / или в променливи (например в ExitVehicle(), цените може да се пресметнат предварително, парсването и четенето на дати в командите също). Имаше вложени класове и безсмислени namespace-и - трябваше да се изнесат.

Insert...() - три метода вместо един.Първоначалната идея беше да не се пипа този интерфейс (защото понякога ви попада кофти интерфейс, който нямате право да променяте, колкото и да е сбъркан). Напълно приемливи са и двете решения - с трите метода и с единия метод. Да се използва друг интерфейс, а другият да стои за украса... не съм сигурен, за мен не е добра практика.

Бъгове:

Park командата е с българско Ръ вместо английско Пи в началото. Това е причината switch-а да не я уцелва. Това беше единственият зачукан бъг :D, но като знаем как работи switch, можем да разберем, че просто case-ът нещо не е в ред. Аз бих заменил всичките cases с оригиналните за по-сигурно.

Объркан регулярен израз за номерата: ^[A-Z]{1}\d{3}[A-Z]{2,}$ трябва да стане ^[A-Z]{1,2}\d{4}[A-Z]{2}$ (няма запетая след 2 накрая).

Объркани параметри във форматиращите низове: ToString() на превозните средства, GetStatus() командата, параметърът на командите на едно място е money вместо price.

SetupPark() командата трябваше да се разкоментира.

При InsertCar() имаше count[s - 1]--;, трябваше да е ++ (в другите методи е направено правилно).

Документация: няма да коментирам, мисля, че нещата там са ясни.

Тестове: Нормалните unit test-ове не изискваха mocking и идеята им беше да са почти същите като в подготовката.

Insert...(): правилни параметри, невалиден сектор (30-ти при 2 налични), невалидно място, заето място, две превозни средства с еднакви номера. Аз имам и допълнителен тест, който гарантира, че ако паркът се напълни докрай, няма да има проблем с добавянето на последната кола.

Това е аналогично на add-ването, което правихме на подготовката. И там тествахме за правилни данни и за всяка възможна грешка, която е дадена в описанието на командата. Между другото, командите бяха толкова подробно разписани в условието, за да се улесни тестването.

ExitVehicle(): правилни параметри (проверка със статуса, както на подготовката проверявахме, че като сме махнали билет, count-a става 0), по-малко от заявеното време (трябва да плати, за колкото е резервирано), повече от заявеното време (трябва да плати и допълнително), невалиден номер, излизане на нещо, което вече е излязло (аналогично на проверката за delete, която правихме на подготовката)

GetStatus(): напълно празен парк, напълно пълен парк, частично пълен парк. Аз имам и допълнителни тестове, които е добре да ги има по принцип, но по никакъв начин не са задължителни: например какво казва статуса на парк с 1 сектор и 1 място, което е пълно / празно. Това е аналогично на tickets count от подготовката.

FindVehiclesByOwner(): една кола, която отговаря на търсенето, две коли, от които само една отговаря, нищо, което да отговаря на търсенето (аз имам два теста за това: 1) пълен парк и грешен собственик, 2) празен парк; един е достатъчен); проверка на сортирането. Тестовете са аналогични на find командата от подготовката.

Performance and data structures: при търсенето по собственик: 1) един излишен foreach цикъл: foreach (var f in found) и един ToList(); 2) търсене по собственик в грешния речник: res.Where(v => v.Owner == owner). Един bottleneck, който е очевиден и един, който изисква малко по-специални познания по структури от данни и алгоритми. Намирането и премахването се оценяват отделно (може да сте намерили нещо и да не сте го махнали). Аз съм в състояние да приема, че в кода има и други bottlenecks, ако видя обосновка.

Всички речници правеха по нещо. Идеята е, че е нормално да има код, който не знаете какво прави и не е нужно да го пипате, докато не се уверите, че е грешен. Нямаше излишни, нямаше и объркани, работеха нормално. С други думи, DATA класът беше коректен откъм структури от данни. Не отричам, че някой може да е махнал някой речник и да е оптимизирал решението повече, но от това няма нужда и тестовете минават и така. Относно това какво прави всеки речник, може да се разбере като се дебъгне. Например ow[carro.Owner].Add(carro); - ключът е owner, стойността е колата. Значи вероятно това са всичките коли на един собственик. Можем да проверим това, като видим на кои места се използва ow. За това Visual Studio има един надпис на всеки речник, който позволява да видим къде се използва. По същия начин можем да видим, че números[carro.LicensePlate] = carro; пази колите по номер.

Извън изпита: имаше два странни "обърнати" речника. Защо речник вместо списък? - Заради оптимизацията на паметта. Ако имаме паркинг с 30 сектора по 30 места, списъкът ще е с 900 елемента, които ще са празни в по-голямата част от времето. Това хаби много памет. Ако обаче имаме речник, той ще има толкова записи, колкото са колите във всеки момент (полезно при предположението, че паркингът в повечето време ще е почти празен). Защо два речника с разменени ключове и стойности (кола -> място и място -> кола)? Най-ценното нещо при речниците е, че търсят много бързо по ключ. Това ми позволява да търся по кола и ведната да ѝ знам мястото от една страна, и веднага да разбера дали на дадено място има вече кола (ако във втория речник има запис), от друга страна.

Dependency injection: Трябвада се направи междинен клас, който имплементира IUserInterface интерфейса. Tрябва да се подаде инстанция от този клас в конструктора на engine-a (само той пише по конзолата): public Engine(IUserInterface userInterface). Engine-ът трябва да има и още един конструктор : this(new ConsoleUserInterface). Трябва всичките (две) извиквания на Console класът да се подадат на this.userInterface (може да е private поле в engine-a, може и да е public, и двете се приемат).

Judge: вече коментирах. Първите тестове са прости, има един тест с всяка възможна грешка, предпоследният прави много операции, последният прави много операции, които препълват парка (в някакъв момент не остава свободно място).

Mocking: 1) DI: Трябва да се направи нещо като dependency injection-a с конзолата, само че с data-та: трябва engine-ът да приема IVehicleParkData примерно като интерфейс. 2) Custom data: имплементация на речниците, която може да се следи "отвън" - извън engine класа. 3) Тестове с custom data-та (1 е достатъчен за доказателство на концепцията).

За финал: Мисля, че няма нужда да обяснявам, че екипът на СофтУни работи в интерес на студентите. Колкото до резултатите, в judge системата има пет изпита, в които никой няма максимален резултат. Има и няколко изпита, в които максималните (и близките до максималните) резултати са малко на брой. Досега тези проблеми са се решавали със скалиране на резултатите. Класирането е относително - очаква се винаги да има хора с отлични оценки.

5
18/05/2015 09:17:43
Filkolev avatar Filkolev 4482 Точки

Всичко е хубаво и прекрасно и съм видял 99% от бъговете и 100% от местата, които трябва да се рефакторират. До момента, в който 6 часа не ми стигат за самото рефакториране. Излиза, че всичко, което е трябвало да знам, съм го знаел. Значи в такъв случай трябва да мога и да го приложа, без в последните 10 минути да ми избива пот на челото от бързане и мислене кое от недооправените неща е по-важно да се оправи и как да го оправя без да разваля нещо друго. Времето никак не беше достатъчно и аз не видях в поста си да засягаш този основен проблем с изпита.

Недей да приемаш критиката, че задачата не беше преценена, като лична. Авторът на задачата не може да е обективен в преценката си, освен ако не е писал поне 10 задачи в подобен стил и не е видял в реална обстановка как студентите се справят с тях. Нека предположа, че не си писал преди задача по КПК; няма как на теб да падне отговорността всичко да е изпипано. Липсва междинната връзка - някой да тества задачата, да се види на какво ниво е и адекватна ли е за 6 часа, тества ли каквото трябва, да се коригира ако има проблеми, да се улесни ако е твърде украсена. Или да го кажа по друг начин (и аз в ролята ми на студент): отговорността не е у тоя, който пише задачата, а у тоя, който я дава на изпит.

14
mihayloff14 avatar mihayloff14 824 Точки

Между другото, нека спомена относно всички възможни случаи в нулевите тестове:

Един от случаите го нямаше - тогава когато FindVehicleByOwner се очаква да изпринтира данните в различен от обичайния вид (сортирани). Това беше и нещото което ме спря от това да имам 16 точки, след изпита като се върнах забелязах това в условието и като го направих стана номера.

Разбира се, всичко това го имаше в условието и все пак трябваше да съм по-внимателен, а от друга страна при наличието на толкова много бъгове наистина е трудно да се покрият всички различни случаи в 2 нулеви теста.

Затова смятам, че наистина имаше повече бъгове отколкото необходимо, но напълно достатъчно, които да се оправят ако не трябваше да се отдели толкова много време на рефакториране/реформатиране на кода.

Като цяло, смятам че изпитът не беше толкова тежък като структура и логика, отколкото обемен като неща за оправяне. И на мен ми отне 4 часа само да реформатирам и преименувам нещата коректно във всички класове, а едва след това започнах да мисля и за unit test-ове и оправяне на бъговете.

3
iordan_93 avatar iordan_93 Trainer 407 Точки

@Filkolev, mihayloff14: Засегнах времето в частта със скрипта. Ако можеш да си направиш нещо такова, много от нещата ще бъдат оправени. Ако сложиш още една проверка (примерно, за всеки ред код, ако е над 30-50 символа дълъг, да ти го split-не по ";" и да го раздели на нови редове), ще оправиш още някои простотии.

Не знам каква ще бъде скалата за оценяване, но като автор на изпита ще предложа такава. Ще я публикувам и в тази тема. Мисля, че оценяващите ще се съобразят с нея. Решението ми в този случай би било да се дават точки за оправени неща: ако примерно повечето неща са оправени, да се дават максимален брой точки за първата задача.

Към всички: Такъв тип оценяване устройва ли ви по принцип?

P. S.: Искам да обърна внимание, че judge дава само 16 от 110 (общо) точки. На мен ми изглежда нормално да се даде висока оценка на човек, който е рефакторирал кода много добре, дори да има малък проблем с коректността. Все пак това е само част от цялата картинка.

Колкото до тестовете, то е и част от задачата. Това със сортирането примерно: 1) го пишеше в условието и 2) все трябва да остане нещо, за което да се сети човек. Така е и на работа - пишеш програма за лелката в банката, която не знае какво е NullReferenceException и ти обяснява как като си запазва отчета за деня, програмата ѝ се затваря. Там има и други подробности, де (трябва да напишеш системата така, че като крашне, да може да се възстанови) :).

-9
19/05/2015 01:23:18
vladimirov avatar vladimirov -6 Точки

Не мисля, че има голяма вина авторът на задачите. Хора без никаква педагогическа подготовак преподават. Колеги студенти им се поверява да изготвят домашни след което изготвяне на изпита се поверява на друг човек да го прави резултатът е тотално разминаване. Възлагат се задачи на хора без нужния опит.

8
zerefel avatar zerefel 70 Точки

Според моето скромно мнение, изпитът беше с твърде голям обем. Не става аз да решавам изпити за подготовка, при които за 2-3 часа взимам 90% от точките в Judge, а на самия изпит времето да не ми стигне дори да прочета задачата в word. През повечето време се чудех какво да оправям по-напред, за да ми стигне времето по някакъв начин (явно е било невъзможно). Дотолкова, че дори забравих да направя документацията на интерфейса и да махна грешките на Style Cop.

След 4 часа реформатиране успях да взема 10 точки. И дотам.


Надявам се да съм го минал, защото ако и поправката е с такъв обем ще има обърнати маси. (JK) laugh

ПП: Все пак благодаря на Данчо за цялата помощ, която ми предостави. Тичаше нагоре-надолу постоянно, като не подминаваше никого.yes

3
18/05/2015 21:58:18
StrahilRuychev avatar StrahilRuychev 117 Точки

Абсолютно същите мисли ми се въртят в главата и на мене от вчера...

2
snipersniperson avatar snipersniperson -21 Точки

Същото беше и на входящия изпит. Питах какъв точно вход очаква judge системата - никакъв отговор, макар че числа изписани така 1,234 (със запетайка за хилядните) или така 1234,00 (запетайка да разделя стотинките от левовете) си е напълно валидно.

 

Да ти кажа ли също така, че вчера разбрах как на момчетата от отбора ни за TPS не са им обяснени основни неща.

-5
thepowerof4 avatar thepowerof4 98 Точки

Лично аз този курс реших просто да го игнорирам за сега, за да мога да се съсредоточа върхо главната програма както трябва, и така и направих. Дори ме е яд, че не го игнорирах в началото още. Не е адекватно да има сериозен, паралелен курс. Когато го взема, тогава - първо основното. Важен е курсът, много, но като мине всичко, тогава. Четейки мненията за изпита, се радвам че съм си спестил подкопаващо мотивацията обезсърчаване. Преподаването след първо ниво е толкова неадекватно все още, че изобщо няма и да си кривя душата за решението.

Промените в новата програма изглеждат подходящи с оглед подредбата на курсовете. Опитните свинчета го сърбаме :). Такъв е животът - драпане :)

8
18/05/2015 16:41:42
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.