Александър обнови решението на 02.11.2014 22:15 (преди около 11 години)
https://gist.github.com/AleksandarAleksandrov/49a7abaf7a6ef28259c2 Това е линка към по-доброто според мен решение за което стана дума в форума.
Здравей :)
Ето малко коментари по решението ти от gist-a:
- Някои методи плачат да използваш
case. Напомням, че чрезcaseможеш да сравняваш класове на обекти, без да използвашis_a?и подобни методи. - Когато имаш едноредов
ifго пиши по следния начин -<код> if <условие>, неif <условие> then <код> end. - Защо имаш инстанционна променлива
@contentи get и set методи заdata? Просто направи единattr_accessor :dataи ползвай@data. - Вместо да конкатенираш низове използвай интерполация.
"test" + variable=>"test#{variable}". - Защо си използвал
partition, къдетоsplitби ти свършил по-добра работа? Виждам, че си ползвал иsplitнадолу. - По-удобно е да "разпакетираш" масива, който ти връща
partition(или онзи по-подходящият метод), вместо да използвашarr[число]. -
arrе ужасно име за променлива, също катоHelperиHelper2. - Имаш доста стилови проблеми:
- На някои места си слагал скоби, на други - не.
- Условията на if-овете не трябва да са оградени със скоби, а за извикването на методи - избери си един вариант и го следвай.
- Предпочитаме
andиor, вместо&&и||. - След запетаите между аргументите при извикване и дефиниране на метод се слага празно място.
- В
Directoryможеш доста да си улесниш методите, като съхраняваш файловете и директориите по малко по-различен начин - не чрез един хеш@content. Освен това, какво се случва ако имаш директория и файл с едно и също име? Това ще ти реши и проблема с нивата на влагане. Иначе в текущия вариант -filesиdirectoriesможеш да ги напишеш малко по-функционално. Това с трупането на неща в обекта, който ще върнеш, е далеч от руби начина. - И извън
filesиdirectoriesима по-добър начин от натрупването на неща в променлива катоto_return. Сложи си стойностите в променливи и използвай интерполация, за да ги свържеш в общ низ, който ще върнеш. - В
Directory#parseправиш някакви сливания на хешове. Имашattr_accessor- можеш директно да презапишеш съдържанието.
Класа Helper ще го коментирам отделно, тъй като според мен доста неща трябва да се преработят там. Започвайки от името му :)
- Направил си го само, за да заобиколиш ограничението за брой методи, нали?
-
parse_contents:- Можеш да спестиш един ред, като махнеш присвояването
file_count = file_count.to_iи го направиш на по-следващия редfile_count.to_i.times. Същото и заlen. - Имена - имаш
file_count, само дето метода може да чете и директории.lenе лошо име, редом сarrиtmp. Не пишеш на C, опитай да изразяваш по-добре какво прави кода, чрез имената на променливите и методите.
- Можеш да спестиш един ред, като махнеш присвояването
-
countняма да ти трябва, ако промениш начина, по който съхраняваш файловете и поддиректориите (това за@content). И все пак - има методcountв Enumerable. -
add_file_infoиadd_directory_infoсъщо ще се изпарят като следствие от горното.
Това бяха препоръки към текущото ти решение. :)
Понеже ти обещах да ти помогна с преструктурирането - ето някои по-абстрактни неща, над които да помислиш:
Добра идея е, когато имаш клас, да се стремиш максимално да го отделиш от другите. Тоест - да знае колкото се може по-малко за другите класове, особено за тяхната имплементация. Като тайните агенти - трябва да знаят само това, което им трябва, за да си свършат работата - не повече. На тази тема - parse_file_contents знае прекалено много за нещата, които парсва. Това може да го промениш, като например изкараш тази логика - directories ? RBFS::Directory.parse(data) : RBFS::File.parse(data) извън метода, използвайки yield. Тогава няма да ти се налага и да трупаш неща в entries, тъй като това ще го прави извикващият метода.
Друга добра идея е да пазиш текущото състояние в самия обект от конкретен клас. Тоест, вместо да връщаш rest, може просто в класа (който в момента се казва Helper) да има инстанционна променлива с текущия низ, която да променяш. Съответно методите вече няма да са класови.
Третата добра идея е един клас да не се занимава с прекалено много неща. Например Helper прави едновременно и парсване, и сериализация.
Ех, че голям ферман изписах. Надявам се да съм ти помогнал поне с част от препоръките ( и да не съм те демотивирал с количеството им :) ). Освен това, както сме казвали и на лекции, хубав код не се пише от веднъж. Винаги пишем нещо работещо, след това го променяме и променяме - докато сме доволни от резултата. В тази връзка очаквам нова ревизия, имаш още цяла седмица. :)
Мерси за изчерпателният отговор и препоръките. Със сигурност, ще ми помогнат да пооправя кода. Версията която качих тук и в git-а е първоначална, която гледах да работи, тъй като ми се очертават доста други домашни за седмицата и гледах да предам това домашно колкото се може по-рано. Все пак при първа възможно ще гледам да стегна малко кода :) . Отново мерси за бързия отговор.
