2008-10-02 6 views
6

Estoy escribiendo un DSL en Ruby para controlar un proyecto Arduino en el que estoy trabajando; Bardino. Es un mono de barra que será controlado por software para servir bebidas. El Arduino toma comandos a través del puerto serie para decirle al Arduino qué bombas encender y durante cuánto tiempo.Necesito ayuda para mejorar un DSL Ruby para controlar un dispensador de bebidas controladas por Arduino (barra mono)

Actualmente lee una receta (ver a continuación) y la imprime de nuevo. El código para las comunicaciones en serie todavía necesita ser trabajado, así como algunas otras ideas que he mencionado a continuación.

Este es mi primer DSL y estoy trabajando en un ejemplo anterior, por lo que es muy difícil en los bordes. Cualquier crítica, mejoras en el código (¿hay alguna buena referencia para las mejores prácticas o expresiones idiomáticas de Ruby DSL?) O cualquier comentario general.

Actualmente tengo un borrador de la DSL por lo que una receta de la bebida tiene el siguiente aspecto (Github link):

desc "Simple glass of water" 
recipe "water" do 
    ingredients(
    "Water" => 2.ounces 
) 
end 

Esto a su vez se interpreta y actualmente se traduce con la siguiente (Github link):

[[email protected] barduino-tender]$ ruby barduino-tender.rb examples/water.rb 
Preparing: Simple glass of water 

Ingredients: 
Water: 2 ounces 

Este es un buen comienzo para el DSL, sin embargo, creo que podría implementarse un poco mejor. Algunas ideas que tuve a continuación:

  1. Definir qué "ingredientes" están disponibles utilizando el nombre del ingrediente y la bomba de número a la que está conectado. ¿Tal vez usando un hash? ingredientes = {"agua" => 1, "vodka" => 2}. De esta manera, cuando se interpreta un ingrediente, puede a) enviar el número de la bomba sobre el puerto serie seguido del número de onzas para que el Arduino lo distribuya b) decirle al usuario que el ingrediente no existe y abortar para que no se administre nada c) tener fácilmente la capacidad de cambiar o agregar nuevos ingredientes si se cambian.
  2. Hacer que la receta tenga un aspecto similar al de un código, que es el objetivo principal de una DSL, ¿tal vez crear un generador de recetas? ¿Usando los ingredientes disponibles para solicitar al usuario el nombre de una bebida, los ingredientes involucrados y cuánto?

El proyecto Github es here, siéntase libre de tenedor y hacer solicitudes de extracción o publicar sus sugerencias de código y ejemplos aquí para que otros usuarios vean. Y si tiene curiosidad, el código de Arduino, que utiliza el marco de Ruby Arduino Development es here.

actualización

he modificado y limpié un poco las cosas para reflejar Orion Edwards sugerencia para una receta. Ahora se ve como el siguiente.

description 'Screwdriver' do 
    serve_in 'Highball Glass' 
    ingredients do 
    2.ounces :vodka 
    5.ounces :orange_juice 
    end 
end 

También he añadido un hash (siendo el ingrediente clave y el valor del número de la bomba está conectada a). Creo que esto proporcionó mucho progreso. Dejaré la pregunta abierta para cualquier otra sugerencia por ahora, pero finalmente seleccionaré la respuesta de Orion. El código DSL actualizado es here.

+0

Para agregar un pseudo código a la mezcla. para ingrediente en ingredientes {if ingredient.exists? serial.send (pump_number) espere 1 segundo serial.send (cantidad) espere OK desde Arduino para continuar al siguiente ingrediente} – mwilliams

Respuesta

5

sin mirar en los detalles de implementación (o sus enlaces de GitHub), que lo intentaría escribir una DSL así:

(robar desde aquí: 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 

Espero que ayude!

+0

puede poner 0.5.ounces.of: vodka si le da la gana, solo encuentro el alias para ' la mitad es más legible –

+0

Gracias por ese consejo, en realidad es mucho más legible y me adaptaré en consecuencia en la próxima revisión. – mwilliams

1

El DSL de Orion se ve muy bien. El único cambio que posiblemente le sugiero a usted código de "actualización" que es

  1. Reemplazar description con recipe. Es un término más descriptivo
  2. Dado que el conjunto de ingredientes y acciones es fijo, una los ingredientes a variables en lugar de símbolos, es decir, si tiene vodka = :vodka definido en algún lugar. Es más fácil decir

    mezclar vodka, gin y triple_seC# en lugar de utilizar: vodka,: gin y: triple_sec.

de todos modos eso es un nit menor.

+1

Personalmente estoy en desacuerdo con los ingredientes vinculantes a las variables, porque bueno, las variables están diseñadas para variar. el enlace a una variable implícitamente "le dice" al desarrollador que. Nunca se debe permitir que el "vodka" vuelva a ser "queso". –

+0

de acuerdo con la sustitución de 'describe' por 'recipe_for' o similar –

3

si desea que la receta para un aspecto más natural, ¿por qué no (de la misma receta Orion Ewards utilizar, gracias!):

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) 

A continuación, agregue a la mezcla Treetop. Podría tener reglas como:

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 

Que el compilador treetop transformará en un buen módulo Ruby. Luego:

parser = CocktailParser.new 
r = parser.parse(recipe) 
Cuestiones relacionadas