Нужна помощь в улучшении Ruby DSL для управления диспенсером напитков, управляемым Arduino (bar monkey)
-
03-07-2019 - |
Вопрос
Я пишу DSL на Ruby для управления проектом Arduino, над которым я работаю;Бардино.Это барная обезьянка, которая будет программно управляться для подачи напитков.Arduino принимает команды через последовательный порт, чтобы сообщить Arduino, какие насосы включить и на какое время.
В данный момент он считывает рецепт (см. Ниже) и распечатывает его обратно.Код для последовательной связи все еще нуждается в доработке, а также некоторые другие идеи, которые я упомянул ниже.
Это мой первый DSL, и я работаю над предыдущим примером, поэтому он очень грубый по краям.Любая критика, улучшения кода (есть ли какие-нибудь хорошие ссылки на лучшие практики или идиомы Ruby DSL?) или какие-либо общие комментарии.
В настоящее время у меня есть черновой вариант DSL, поэтому рецепт напитка выглядит следующим образом (Ссылка на Github):
desc "Simple glass of water"
recipe "water" do
ingredients(
"Water" => 2.ounces
)
end
Это, в свою очередь, интерпретируется и в настоящее время приводит к следующему (Ссылка на Github):
[mwilliams@Danzig barduino-tender]$ ruby barduino-tender.rb examples/water.rb
Preparing: Simple glass of water
Ingredients:
Water: 2 ounces
Это хорошее начало для DSL, однако я думаю, что его можно было бы реализовать немного лучше.Некоторые идеи, которые у меня были ниже:
- Определение того, какие "ингредиенты" доступны, используя название ингредиента и номер насоса, к которому он подключен.Может быть, используя хэш?ингредиенты = {"вода" => 1, "водка" => 2}.Таким образом, когда ингредиент интерпретируется, он может либо: а) отправить номер насоса через последовательный порт, за которым следует количество унций, которые Arduino должен выдать; б) сообщить пользователю, что ингредиент не существует, и прервать выдачу, чтобы ничего не выдавалось; в) легко иметь возможность изменять или добавлять новые ингредиенты, если они были изменены.
- Чтобы рецепт выглядел менее похожим на код, что является основной целью DSL, может быть, создать конструктор рецептов?Использование доступных ингредиентов для запроса у пользователя названия напитка, используемых ингредиентов и их количества?
Проект Github - это здесь, не стесняйтесь разветвлять и делать запросы на извлечение или размещайте свои предложения по коду и примеры здесь, чтобы их могли увидеть другие пользователи.И если вам вообще интересно, код Arduino, использующий платформу разработки Ruby Arduino, является здесь.
Обновить
Я немного изменила и подчистила все, чтобы отразить предложение Ориона Эдвардса по рецепту.Теперь это выглядит следующим образом.
description 'Screwdriver' do
serve_in 'Highball Glass'
ingredients do
2.ounces :vodka
5.ounces :orange_juice
end
end
Я также добавил хэш (ключ - это ингредиент, а значение - номер насоса, к которому он подключен).Я думаю, что это обеспечило значительный прогресс.Пока я оставлю вопрос открытым для любых дальнейших предложений, но в конечном итоге выберу ответ Ориона.Обновленный DSL-код выглядит следующим образом здесь.
Решение
Не вдаваясь в детали реализации (или ваши ссылки на github), я бы попробовал написать DSL следующим образом:
(красть отсюда: http://supercocktails.com/1310/Long-Island-Iced-Tea-)
describe "Long Island Iced Tea" do
serve_in 'Highball Glass'
ingredients do
half.ounce.of :vodka
half.ounce.of :tequila
half.ounce.of :light_rum
half.ounce.of :gin
1.dash.of :coca_cola
#ignoring lemon peel as how can a robot peel a lemon?
end
steps do
add :vodka, :tequila, :light_rum, :gin
stir :gently
add :coca_cola
end
end
Надеюсь, это поможет!
Другие советы
Если вы хотите, чтобы рецепт выглядел более натурально, почему бы и нет (по тому же рецепту, который использовал Орион Эвардс, спасибо!):
Recipe for Long Island Iced Tea #1
Ingredients:
1/2 oz Vodka
1/2 oz Tequila
1/2 oz Light Rum
1/2 oz Gin
1 Dash Coca-Cola
# ignored Twist of Lemon Peel (or Lime)
Затем добавьте Верхушка дерева к смеси.У вас могли бы быть такие правила, как:
grammar Cocktail
rule cocktail
title ingredients
end
rule title
'Recipe for' S text:(.*) EOF
end
rule ingredients
ingredient+
end
rule ingredient
qty S liquid
end
# ...
end
Который компилятор treetop преобразует в хороший ruby-модуль.Затем:
parser = CocktailParser.new
r = parser.parse(recipe)
DSL от Orion выглядит очень красиво.Единственное изменение, которое я бы, возможно, предложил вам от "обновленного" кода, - это
- Заменить
description
сrecipe
.Это более описательный термин Поскольку набор ингредиентов и действий фиксирован, привяжите ингредиенты к переменным, а не к символам, т.е. у вас есть
vodka = :vodka
определенный где-то.Это легче сказатьсмешайте водку, джин и triple_sec # вместо использования :vodka, :gin и :triple_sec.
в любом случае, это мелкая гнида.