Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
278 lines (160 sloc) 42.4 KB

Увод

Проектът е необходим, за да завършите курса. Носи до 60 т. Ако не изберете тема в посочените срокове, или не защитите проект, ще трябва да се явите на поправителна сесия.

Темите за проект се избират от студентите. От преподавателския екип се дават няколко примерни теми.

За избора на тема има срок, който обикновено е преди коледно-новогодишните празници на зимния семестър. Обяснява се по време на лекции и като новина на сайта.

Проектите се предават до предварително определена дата един или два дни преди защитата, като се изпращат по имейл. Изпращането на проекта и явяването на защитата са задължителни. Малки промени и поправка на бъгове могат да се правят и след изпращането на проекта (преди защитата). Не трябва да има големи разлики между предадения код и този, който ще покажете на защитата.

Използването на version control система е задължително, както е описано в последната секция на този документ.

Персонални теми

Силно препоръчително е да си изберете тема, която ще ви е интересна и ще сте мотивирани да завършите.

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

Предварителният избор на тема на проекта има няколко функции:

  • Постига се съгласие с екипа на курса, че сложността на проекта ще е достатъчно голяма, без да е непостижимо сложен за рамките на курсов проект и за времето, с което разполагате.
  • Стимулираме ви да започнете да мислите по това отрано и да започнете работа по проекта навреме, защото добрият проект и реалните ползи, които целим от него, изискват влагането на значително количество време и усилия.

За работилите по персонална тема - кодът на проекта е публичен. Вижте секцията за version control в този документ.

Примерни теми

Студентите, които се затрудняват с избора на тема, могат да изберат някоя от примерните. Всяка примерна тема може да бъде избрана от до 5 човека.

Заявяването на работа по примерна тема става в специално създадена за това тема във форума. Темата се създава от преподавателския екип заедно с обявяването на проектите. При избор на примерна тема, студентът е длъжен да провери дали тя има свободен слот от петте възможни, като прегледа предните отговори на темата във форума.

Кодът на проекта не се прави публичен преди защитата. Всяко споделяне на код по примерен проект се счита за преписване. При споделяне на код студентите се явяват на поправителната сесия и трябва да си изберат и направят нови проекти. Това се отнася както за преписалите, така и за тези, които са си споделили кода.

Забележка: Това, че кодът не е публичен, не означава, че не може да се използва version control система. Вижте секцията за version control в този документ.

Приемат се леки модификации на функционалностите, стига целта да не е намаляване на необходимата работа по проекта. Пишете ни, ако искате да направите по-големи промени по темата или замяна на функционалност с друга.

Основна цел на проекта

Темата, която ще си изберете, не е толкова важна за нас. Ние държим да прекарате време с Ruby и екосистемата около него и да напишете нещо по-голямо, което да ви принуди да направите следните неща:

  • Да отделите време да се преборите с практическите проблеми, до които неминуемо води всеки един по-голям и по-практически насочен софтуер.
  • Да намерите най-оптималния и ефективен начин за решение на определен проблем, тъй като това е нещо, което всеки програмист прави ежедневно.
  • Да се преборите с построяването и поддържането на инфраструктура за разработване, ако все още нямате добра такава.
  • Да пробвате нещо ново – например, test-driven development, или изобщо писане на тестове. Много е важно да проучите как се прави в съответния език и екосистема (в случая, Ruby) – с какви инструменти, как да си настроите редактор и помощни програми, така че тестовете да се пускат максимално лесно и да минават максимално бързо. Има какво да се експериментира тук.

Тоест, да научите нови неща - както технологично, така и методологично.

Скала за оценяване

Максималният брой точки за проекта са 60 и са разделени по следния начин:

  • 1/3 за функционалност. Пълен брой точки за тази секция ще получите, ако сте покрили функционалността, за която е постигнато съгласие при избора на тема.
  • 1/3 за стил. Под стил се има предвид стил на кода, а не визуален дизайн. Има се предвид спазване на конвенциите в езика, на добрите практики, стремежът кодът да е прост, изчистен и ясен, добре подреден и модулен, без прекалени зависимости между отделните компоненти.
  • 1/3 за тестове. Unit тестове, интеграционни тестове.

Например, ако проектът ви няма тестове и е написан ужасно, но функционално покрива спецификацията, за която е постигнато съгласие при избора на тема, ще получите 20 т.

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

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

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

Размер и сложност на проекта

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

Като цяло, проектът не трябва да е нещо, което да може да се напише за едно или две денонощия. Може да се наложи да си измислите и да вкарате още функционалност, за да покриете това изискване за сложност. Преценката за това какво е "достатъчна сложност" засега остава във вашето поле. Изисквания за функционалност могат да се измислят винаги, така че може да се приеме, че сложността на дадена идея никога не е ограничена отгоре. Тоест, каквато и да е идеята ви, може да добавяте и да добавяте функционалност, докато не се получи нещо с "достатъчна сложност".

В крайна сметка, ако не се опитвате просто да напишете нещо, което да ви "прекара" през курса, а пишете проекта с цел да пробвате и научите нови неща и подходите сериозно, няма да имате проблем.

Започнете навреме.

Самостоятелни проекти

Проектите в курса са индивидуални. Не се допуска групова работа.

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

Възможно изключение би било ако всеки прави различен, но самостоятелен модул от проекта и двете неща си комуникират по някакъв начин. Желателно е този вариант да се избягва или да се съгласува много добре с екипа на курса.

Какво да има в предложението за персонална тема

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

Едно-две изречения са твърде малко. Страници текст - твръде много. Напишете описанието на темата си по модела на описанията на примерните теми.

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

Когато пишете описанието, поставете се в следната ситуация:

При вас идва клиент със задание и ви пита "Колко ще струва това?"

Какво бихте искали да има в неговото задание? Какво бихте го попитали? Каква информация ще ви трябва още?

Обикновено ни е необходимо да се опишат точно остновните use cases и от птичи поглед технологиите, които мислите да ползвате и да си "стиснем ръцете" за тези две неща, за да се уверим, че проектът ще е достатъчно, но не и прекалено сложен. Без описанието на тези use cases, няма как да сме сигурни. Понякога питаме и за конкретни технологични подробности, ако преценим, че има нужда и че от това сложността зависи значително.

Лоши примери за описание

"Идеята ми за проект е система за управление на магазин"

Примерът е лош, защото не дава отговор на следните въпроси:

  • Какви технологии?
  • Уеб, command-line, GUI?
  • Бази данни ще има ли?
  • Какви интерфейси?
  • Роли? Автентикация, авторизация?
  • Груби спецификации за това какви данни ще се пазят и какви операции ще могат да се извършват?

"Избрах си тема за проект - играта Battleships"

Този пример също е твърде кратък и оставя много въпроси без отговор:

  • Двама играча ще се редуват на един компютър, или ще се играе срещу компютъра?
  • Ще се играе ли по мрежа, или само локално, на една машина?
  • Кои ще са двата интерфейса? Command-line? Gosu? Друго?
  • Горното е твърде просто - има нужда от "усложнения"; например - save/restore на текущата игра.

Няма един конкретен "одобрен" формат. Просто пратете описание в рамките на до половин-една страница текст.

Как да си изберем тема

Помислете какво ви е интересно. Помислете дали нямате реален, практически проблем, който бихте искали да решите за себе си, или за някой друг. В краен случай, харесайте си съществуващ софтуер и опитайте да реализирате някакво парче от неговата функционалност, като го използвате за спецификация.

Какво става, ако не можете да се справите с нещо, за което сме се разбрали да има в проекта ви?

В реалността често се налага да се променят предварителните изисквания. Допустими са малки вариации в предварително уговорената тема. За по-големи промени, ни пишете. Например, ако ударите на камък в имплементацията на някаква част от вече уговорената функционалност, пишете ни. Или ще ви помогнем, или ще се разберем да отпадне/да се замени с нещо друго. Разбира се, това трябва да стане достатъчно време преди защитата на проектите.

(Не)подходящи теми

Ruby е general-purpose език, но не е удачно решение за някои проблеми, като:

  • Тежки, алгоритмични и изчислителни проблеми, които са CPU-bound, изискват CPU-паралелизация и/или garbage collection-ът ще им пречи.
  • Неща, чието основно ядро е изкуствен интелект (AI).
  • Десктоп приложения с бутончета, менюта и прочее.
  • Тежки и големи игри.
  • Мобилни приложения (но пък има RubyMotion).
  • Embedded системи (но за това пък има mruby).
  • Приложения, чиято основна работа е да имплементират дадено API - окей е за Ruby, но е неподходящо като тема.

Има и някои изключения:

  • Може да пишете десктоп GUI приложения, като ползвате Shoes (новата версия) или Tkinter (Tk) - не е особено практично, но е окей за курсов проект.
  • В случая на десктоп приложение, ще искаме да имате и някакъв алтернативен интерфейс към функционалността (например, command-line).
  • По-прости, 2D-игри, с помощта на Gosu - пак искаме втори интерфейс (например, command-line).

Технически и архитектурни напътствия

Игри и друг GUI intensive софтуер

Тъй като за добро или лошо това е една от най-предпочитаните теми, трябва да обърнем внимание, че Ruby и екосистемата около него не са най-подходящите инструменти за разработване на игри. Това личи най-малко по факта, че няма изобилие от графични и 3D-библиотеки, които да са активно разработвани. Може би най-близо до целта попада gosu. Писането на игра, която е GUI-intensive не е добра идея. Писането на по-простички игри, които могат да имат и command-line интерфейс е приемливо. Причината за тази препоръка, освен споменатата по-рано, е и че не искаме проектът ви да се върти около интерфейса, а по-скоро обратното – интерфейсът да е дребна притурка към логиката на играта.

Когато сте избрали да пишете неща, наподобяващи игри — или каквито и да е други проекти, изискващи сериозно GUI — е много важно да "откачите" основния си код максимално много от рисуването/графиката/GUI-то. Целта ви е да имате много ясно разделение и абстракция между "ядрото" на вашия проект и графичния му интерфейс. Добре би било основната логика на проекта ви да се намира изцяло в "ядрото", под формата на класове, модули и прочее, като това ядро предоставя на своите позлватели някакво API. Тоест, стремете се да пишете въпросното ядро все едно пишете библиотека, която ще се преизползва в друг(и) софтуер(и). От там нататък, GUI-то се прави като wrapper на тази библиотека, ползва публичното й API и е един вид pluggable компонент към нея.

Поради гореизброените причини, за всички игри е задължително да имплементирате повече от един UI – например един конзолен и един графичен. Единствено тогава ще разберете истинската стойност на необходимостта от разделение между логика и интерфейс и единствено тогава ще може да проверите дали сте се справили с тази задача. Допускат се само индивидуални изключения, ако изрично сме се разбрали с вас за това предварително.

В някои случаи, можете да минете и само с кода от основното ядро, който имплементира функционалност без GUI, ако сте писали обилно тестове. Този проект е подходящ шанс за вас да пробвате подхода TDD. Допълнително, това ще ви помогне да покриете едно от изискванията, а именно да имате пълно покритие с unit тестове.

Разбира се, ако държите да дълбаете в посока графичен интерфейс, било то двуизмерно или триизмерно чертане, няма да ви спрем – все пак е важно и да се забавлява човек от време на време :) Просто имайте предивд, че това няма да придаде тежест на проекта ви.

Rails проекти – забранени

Базирайки се на трагичния опит с ваши Rails проекти от минали години, сме принудени за ваше добро да ви забраним да правите такива проекти.

Причината за това е, че Rails сам по себе си е много сложен и за правилната му, канонична употреба, се изисква да положите усилия, които се равняват на още един едносеместриален курс. Ако не сте се занимавали с уеб програмиране преди това, нещата се усложняват допълнително. Rails е още една голяма и сложна абстракция, която трябва да научите прилично, за да става проектът ви за нещо, а това усложнява нещата неимоверно много.

Разбира се, имали сме няколко случая на сносни Rails проекти. Студентите, които са ги направили, са:

  • имали предварителен опит с и силен интерес в областта на уеб програмирането
  • се справяли добре с курса по Ruby и са овладели предварително достатъчно добре самия език
  • прекарали в продължение на месеци множество часове – безсънни нощи и уикенди – в борба с Rails

Всичко останало е обречено на провал.

Ето ви един конкретен пример за възможна грешка (каквито изобилстваха в почти всички Rails проекти), произтичаща от сложността на Rails – ако сте ползвали <form>-тагове, за да направите форма, която не е пряко свързана с Rails модел, вместо да ползвате form_tag view helper-а (понеже вероятно не сте знаели, че има такова нещо). В Rails има много неща (както и в Ruby, между другото), така че се налага да проверявате за почти всичко, преди да тръгнете да си го пишете сами, какви готови решения се предлагат вече от фреймуърка и да прецените дали това решение е окей или не ви върши работа. Да, не е проблем да ползвате таг <form>, ако сте видели, че има form_tag, но, поради някаква причина, той не ви върши работа.

Изключение

Ако не сте студент във ФМИ, или оценката и точките не ви интересуват, е напълно окей да пробвате Rails-проект. На защитата ще ви дадем обратна връзка за проекта ви и ще споделим опит. Въпреки това, на защитата имаме твърде малко време (не повече от 15-20 минути) и няма да можем да отговорим на всичките ви въпроси.

Ако изберете Rails, ви препоръчваме да прочетете поне една книга по темата, преди да дойдете с проекта си на защитата. Може да започнете от The Ruby on Rails Tutorial, който е добър и безплатен.

Уеб приложения на Sinatra – окей

За тези от вас, които са фенове на уеб програмирането и искат да направят такъв проект за курса си по Ruby, ви даваме алтернатива – може да ползвате нещо като Sinatra, или друг минималистичен уеб фреймуърк. Пак ще се налага да опознаете из основи това, на което стъпвате (например, Rack и Sinatra), но това е задача, която е в пъти по-малка и обозрима, от това да научите добре Rails.

Повече информация, както и добри практики, може да намерите в ръководството ни за Sinatra проекти.

Създаване на Ruby библиотеки

Да си направите собствена Руби библиотека е безплатно и не особено трудно. Като начало, запознайте се с няколко кратки ръководства, намиращи се на guides.rubygems.org:

  1. What is a gem?
  2. Make your own gem
  3. Patterns

Описанието на gemspec-формата може също да ви е полезно, докато правите gem. Ще ви трябва безплатен акаунт на rubygems.org.

Архитектура на вашето приложение и мислени ограничения

Ограниченията са причина хората да проявяват изобретателност.

Поставете си следното ограничение - представете си, че правите проекта си в Ruby gem. Представете си, че го правите така, че клиентът му ще бъде друг Ruby код и че не трябва да мислите за потребителски интерфейс, графичен интерфейс, уеб интерфейс... Помислете как може да моделирате вашата бизнес логика и да разделите кода си на модули и файлове по начин, подходящ за вашата предметна област, без да се съобразявате със структура, наложена от Rails, Sinatra, Ruby Tk или каквото и да е друго. Не се притеснявайте да правите повечко файлове и папки, стига това да се вписва добре в модела ви.

Накрая може да ползвате вашия gem в Rails, или Sinatra, или Ruby Tk, или нещо друго, написвайки малко код и малко интеграционни тестове, за да проверите, че интеграцията ви със съответния GUI фреймуърк работи. И трябва въпросното GUI да е тънък слой върху вашата библиотека, а не вашата библиотека да е тънък слой върху Rails, да кажем.

Ако дойдете при нас само с Ruby gem и добри unit тестове, може да получите пълен брой точки. Ценим unit тестовете най-много за тези проекти и може да минете и без интеграционни такива, ако нямате интеграция с външи компоненти.

Гледайте това видео от презентация на "чичо Боб Мартин" по повод архитектурата на приложения и Rails. То се отнася и до проекти, които не са уеб или Rails. По-конкретен пример за това как бихте могли да реализирате на практика идеите, за които Боб Мартин говори в презентацията си, може да намерите в статията на Виктор Савкин "Building Rich Domain Models In Rails. Separating Persistance." Архитектурата, предложена и реализирана по-горе, е до известна степен крайна и доколко е подходяща за даден проект е обект на дискусия. От друга страна, тя е много изчистена и за целите на курсовия проект е много добро упражнение.

Не е необходимо да имате дълбока ОО-йерархия, за да бъде кодът ви добър.

Тъкмо обратното. Когато си мислим за добър дизайн, пред нас стои изкушението да градим архитектурни небостъргачи. Това рядко е добра идея. Търсим практично, изчистено решение, с минимални усложнения. Възможно е дори да нямате никакво наследяване в кода ви. В Ruby често се използва миксиране на модули за споделяне на обща функционалност. Това понякога води до по-добър (по-прост, ясен и изчистен) код.

Целта ви е да постигнете най-простото решение, което ще свърши работа за избраната от вас проблемна област.

Припомнете си следните принципи на Кент Бек за изчистения дизайн:

My guiding light is Kent Beck's rules of Simple Design:

  1. The code must first be correct (as defined by tests);
  2. then it should be a clear statement of the design (what J.B.Rainsberger calls "no bad names");
  3. then it should contain no duplication (of text, of ideas, or of responsibility);
  4. and finally it must be the smallest code that meets all of the above.

It's time to stop refactoring when the code makes a reasonable stab at meeting those goals, and when any further changes would add no further benefit.

Докато пишете своя код, задавайте си следните въпроси:

  • Какви отговорности носи този обект? Твърде много ли са? Ако са, как да го разделя на по-малки парчета, които имат ясен фокус?
  • Какви външни зависимости има този обект? Твърде много ли са? Как да ги намаля?
  • Има ли начин да напиша кода така, че по-ясно да изразява какво прави? Да е по-лесно да се разбере каква е целта му от незапознат читател?
  • Има ли по-прост начин да напиша този код, като запазя функционалността му и изразителността му?

И прочее.

Добрият дизайн е трудна задача, особено в контекста на неизследвана проблемна област и множество нови и непознати технологии. За целта, обикновено е нужно да се направи повече от една итерация над възможното решение. Една ефективна технология за това е прототипизирането.

Прототип (spike)

Обикновено технологиите, които ще изберете за проектите си, ще са нови и непознати за вас. Проблемната област също ще включва неща, които не сте предвидили. В контекста на тази неизвестност, да постигнете добър дизайн на кода е много тежка задача.

Затова силно препоръчваме първото нещо, което да направите за проекта си, да е прототип.

Важно е да проучите нещата, преди да започнете реалния строеж. Това се прави посредством т.нар. "spike". Spike-ът е експериментален прототип, който има за цел да ви запознае с възможни решения и подходи към избрания проблем, както и да опознаете технологиите, възможните усложнения, които те ще ви сервират, както и възможни решения за тези проблеми. В spike-а не мислите за тестове, дори не мислите за добър дизайн. Вашата основна цел е изцяло изследователска и искате да сглобите нещо работещо с тел и тиксо.

Когато прототипизирате, е важно да си поставите някаква крайна цел за прототипа. Когато достигнете тази крайна цел, протипът е изпълнил своята функция и трябва да бъде изоставен. Задължително е да започнете начисто, като не преизползвате код, а само наученото от изследователската фаза.

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

Да вземем за пример, че пишете двуизмерна игра и използвате Gosu. За крайна цел може да си поставите да имате елементарно рисуване по екрана и елементарна интеракция с потребителя и с обект от екрана. За междинни цели бихте могли да имате:

  1. Инсталация и подкарване на необходимите зависимости. Това може да е проблем и да е времеемко само по себе си.
  2. Изрисуване на нещо дребно на екрана. Първо фон, после някакъв обект.
  3. Анимиране - местене на неща по екрана, без потребителска намеса.
  4. Приемане на потребителски вход, вероятно от клавиатура или мишка. Местене на неща в зависимост от този вход.
  5. Интеракция с други неща по екрана (напр. някакъв прост collision detection механизъм).

С постигане на тези цели, ще сте покрили огромна част от неизвестните за вас въпроси и ще сте натрупали много ценен опит. Също така, ще сте видели продукта на своя труд и няма да работите на "сляпо", с надеждата, че някой ден нещо ще се появи на екрана и ще мърда. Ще сте по-мотивирани.

С наученото, захвърляте прототипа и използвате само наученото от него. Започвате на чисто. Правите си архитектурата както смятате, че трябва да бъде, за да е максимално изчистено, просто и подредено. Не прекалявате с излишните наследявания и йерархии. Пишете тестове.

Version control

Изискването да се ползва система за контрол на версиите е задължително. Силно препоръчваме да ползвате Git и GitHub.

Ако пишете по персонална тема, няма проблем кодът на проекта да ви е публичен. Ако сте си избрали от примерните теми имате три варианта:

  • Използвайте Git локално без да push-вате никъде. Така ще получите всички бонуси на git, с изключение на защитата от това да си изтриете цялата папка.
  • Възползвайте се от GitHub за студенти - имате право на неограничен брой безплатни скрити хранилища.
  • Използвайте алтернатива на GitHub - например BitBucket, който позволява безплатни скрити хранилища.

Ако все пак държите да ползвате друга version control система, пак ще приемем това изискване за покрито. Важното е да има някакъв version control.

Отново, задължително е да използвате version control система и да правите чести commit-и. Запазваме си правото да приспадаме точки от проекта при много неправилно използване - например ако имате само един commit.