and-se / 1kurs-vesna-2018

0 stars 2 forks source link

Task 3.2 Zolotuhin #6

Open and-se opened 6 years ago

and-se commented 6 years ago

Глобальная проблема

Пожалуйста, читайте задания внимательно. В них даны готовые куски кода или словесные рекомендации не просто так, а для того, чтобы помочь Вам сделать задание правильно и усвоить полезные навыки. Рвение сделать задание на основе общего понимания, руководствуясь внезапно вспыхнувшей идеей, похвально, но пока что нужно ограничивать этот поток рамками рекомендуемого пути, чтобы избежать досадных ошибок, даже если сейчас кажется, что все пути одинаковы. Это не так, и выполнение задания согласно рекомендациям на один шаг приблизит Вас к пониманию, как нужно проектировать ПО. Может, пока Вы так и не поймёте, зачем делать так, ничего страшного, но получите некоторый опыт.

Вот например модуль SlovarDalya.h описан в задании. Но у Вас ничего подобного нет. Конечно, код примерно похож на то, как надо было бы делать этот модуль, но с точки зрения подхода к проектированию то, что хочется видеть, и то, что есть сейчас, очень разные вещи.

Модуль SlovarDalya.h описывает интерфейс работы со словарём Даля безотносительно к тому, что там под капотом (массивы там сортированные или что-нибудь другое). Вот как работать со словарём? Взять его с полки (функция загрузки словаря), ну и найти в нём нужно слово (функция поиска). Так, с загрузкой понятно, а с поиском надо поподробней. Вот как искать? Не факт, что можно найти точь-в-точь такое же слово. Надо просматривать словарь по первым буквам искомого слова, что и позволяет делать описанная функция поиска. А как представить результаты поиска независимо от структуры данных, в которой хранится словарь? Для этого и нужен итератор, который независимым от реализации образом позволяет просматривать подходящие к данному началу слова статьи по одной. Именно по одной - Вы же не охватываете взглядом всю страницу при поиске . Вы так или иначе будете пробегать глазами, т.е. смотреть последовательно. Это проще, да и зачем пытаться охватить всё, если интересующая Вас статья найдётся в начале страницы?

Это очень важный принцип - нужно моделировать предметную область и абстрагироваться от деталей реализации. Вот, мы описали интерфейс взаимодействия со словарём. Другие части программы будут пользоваться этим интерфейсом (SlovarDalya.h) и не будут зависеть от конкретной реализации этого модуля. Мы сможем менять реализацию SlovarDalya.cpp так, что это будет незаметно всем участкам кода, которые пользуются словарём Даля для своей работы. Вместо сортированного массива завтра мы будем использовать деревья поиска, потом обращение к базе данных, а потом вообще обращение к веб-сервису. И все эти манипуляции потребуют только подмены файла SlovarDalya.cpp. Естественно, в дополнении к реализации функций из SlovarDalya.h в этом файле могут быть специфичные для реализации функции, но их не надо выносить в SlovarDalya.h!

Именно по этому пути мы и пойдём - откажемся от сортированных массивов. И очень не хочется, чтобы из-за этого пришлось целиком переписывать программу (даже main.cpp). В общем, наличие SlovarDalya.h (необязательно буквально в том же виде, может быть аналог, но полноценный, обладающий теми же свойствами) необходимо для сдачи задания.

Про dictionary.h

У Вас нет ничего похожего на SlovarDalya.h сейчас. Есть dictionary.h, но это совсем не то. Вы говорите, что это key-value storage. Это не совсем так - уши то лежащего в основе массива торчат - вот что это за параметры startPosition, что за явные-неявные сортировки? И мне пока непонятно, нужна ли все описанные в нём методы для решения поставленной задачи? Надо ли возиться со всеми этими заменами элемента по индексу/ключу, если словарь в нашей задаче статичен? Кроме этого, у меня есть ощущение, что Вы выставили наружу (в .h) файл некоторые функции, которые относятся к деталям реализации и место которых - в dictionary.cpp.

Ну ладно, меня больше интересует вопрос, чем функция

unsigned int searchByQuery (Map map, char query, bool isSorted); отличается от Iterator getIterator (Map map, char query, unsigned int startPosition);

В main.cpp очень интересная конструкция на этот счёт:

iter = getIterator(map, query, searchByQuery(map, query, true));

Нет, ну так может не заставлять пользователя (а main.cpp это пользователь Вашего модуля) хитро конструировать итератор, да ещё попробуй ошибись!

По логике модуля, описанного в тексте задания, должен быть только getIterator(Map map, char* query) без всякой startPosition. Вам нужно взять итератор, а потом при помощи NextResult() последовательно получать нужные записи и выводить их на экран - зачем какой-то startPosition, который прибивает нас гвоздями к массивам?

Итого Большая часть написанного Вам кода нужна для решения задачи, но не хватает-таки модуля работы со словарём. В main.cpp должен быть #include только модуля работы со словарём и никаких деталей реализации наподобие использования модулей dictionary.h, dictionaryWorking.h.

P.S. Текущий код на данный момент у меня не работает, я посмотрю, что не так. Но всё равно, делайте модуль SlovarDalya.h!

MrFang commented 6 years ago

@and-se Изначально два модуля были т.к в задании требовалось разделение модулей. Сейчас в нескольких местах изменил код так, что он стал похож на SlovarDalya. Из проекта исключён (но не удалён совсем) dictWorking, все функции из него перемещены в dicitionary. KV storage я реализовал сознательно на базе динамического массива так как с ним работа проще и не требуется дополнительного изучения структур данных. На данный (25.03.2018 19:05 МСК) момент у меня программа падает при загрузке словаря