Конфигуриране на модула Ruby
Мисля, че сте запознати с метода за конфигуриране, който много скъпоценни камъни предоставят за конфигуриране. Например конфигурация на носеща вълна:
Как да внедрите това във вашия модул?
Да започнем с падащи тестове.
Сега, след като имаме падащите тестове, нека започнем да прилагаме функционалността. Първо, нека декларираме модул, съдържащ метода configure.
Имаме нужда от място, където да съхраняваме нашата конфигурация. Мисля, че модулна променлива ще работи добре за това.
Тук има проблем. Няма да можем да съхраним конфигурацията в хеш. Засега ще заменя хеша с OpenStruct, което съответства на функционалността, която ще получим в крайна сметка. След това вече мога да извикам блока вътре в метода и да му предам хранилището като аргумент.
Желаната функционалност е готова. Тестовете минават.
Рефакторинг
Време е да преработим това решение. Веднага се виждат два проблема:
- Можем да съхраняваме всичко в нашата конфигурация. Наборът от методи, на които можем да предадем стойност, не е ограничен от нищо. Това не е готино за конфигуриране, защото скрива грешките от потребителя.Ако потребителят направи грешкав името на метода за конфигуриране,трябва да го уведомим незабавно, като хвърлим изключение.
- OpenStruct не е добра идея за производствен код. Той е много по-бавен от обикновена структура или клас и използва много повече памет.
Имаме два начина да поправим това. Първият е да използвате Struct с бял списък от налични методи за конфигуриране.
Всичко изглежда страхотно. Тестовете преминават, кодът е прост и четим.Но забравих една важна подробност. Конфигурационни стойности по подразбиране. За тях трябва да се добави още един тест.
За да избегнете презаписване на конфигурационните стойности в различни тестове,трябва да добавите нулиране на предишната конфигурация, преди да стартирате всеки тест. Ще добавя метод за нулиране направо в тестовия клас, защото той е само за тестови цели и не е необходимо да бъде част от публичния API.
Нека се върнем към решаването на проблема със стойностите по подразбиране. Най-простото решение би изглеждало така:
Харесва ми това решение. Все още емного простичетлив. Също така е достагъвкав. Можем да зададем сложни стойности по подразбиране и, ако е необходимо, да ги преместим в отделни методи. Имаме и два начина за получаване на конфигурационни стойности: чрез метод и чрез индекс.
Това е всичко, което исках да споделя днес. Източниците са достъпни тук: goo.gl/feCwCC
Northbear предложи алтернатива, която използва Struct с инициализатор вместо клас.
В този случай няма нужда да използвате public_send за дефиниране на индекса, което прави кода още по-прост. Благодаря Northbear!