2010-05-20 10 views
5

Si consideri il codice:Erlang: semplice refactoring

f(command1, UserId) -> 
    case is_registered(UserId) of 
     true -> 
      %% do command1 
      ok; 
     false -> 
      not_registered 
    end; 

f(command2, UserId) -> 
    case is_registered(UserId) of 
     true -> 
      %% do command2 
      ok; 
     false -> 
      not_registered 
    end. 

is_registered(UserId) -> 
    %% some checks 

Ora immaginate che ci sono un sacco di comandi e sono tutti chiamata is_registered in un primo momento. C'è un modo per generalizzare questo comportamento (refactare questo codice)? Intendo dire che non è una buona idea posizionare lo stesso caso in tutti i comandi.

risposta

7

mi piacerebbe andare con

f(Command, UserId) -> 
    case is_registered(UserId) of 
     true -> 
      run_command(Command); 
     false -> 
      not_registered 
    end. 


run_command(command1) -> ok; % do command1 
run_command(command2) -> ok. % do command2 
2
f(Command, UserId) -> 
    Registered = is_registered(UserID), 
    case {Command, Registered} of 
      {_, False} -> 
       not_registered; 
      {command1, True} -> 
       %% do command1 
       ok; 
      {command2, True} -> 
       %% do command2 
       ok 
    end. 

is_registered(UserId) -> 
    %% some checks 

Inoltre Wrangler, uno strumento interattivo refactoring, potrebbe essere tuo amico.

1

mi piace l'uso di eccezioni migliori. Permetterebbe la programmazione per il caso di successo e diminuirà l'uso dei livelli di indentazione.

5

Penso codice ctulahoops' legge meglio riscritta in questo modo:

run_command(Command, UserId) -> 
    case is_registered(UserId) of 
     true -> 
      Command(); 
     false -> 
      not_registered 
    end. 

run_command(some_function_you_define); 
run_command(some_other_function_you_define); 
run_command(fun() -> do_some_ad_hoc_thing_here end). 

Questa sfrutta il fatto che le funzioni sono entità di prima classe in Erlang. È possibile passarli in funzioni, anche definirli in modo anonimo in linea nella chiamata. Ogni funzione può essere denominata in modo diverso. Il metodo di cthulahoops richiede che tutte le tue funzioni di comando siano predefinite e chiamate run_command(), disambiguate dal loro primo argomento.

1

preferisco in questo modo, di maggiore versatilità:

f(Command, UserId) -> 
    f(Command,is_registered(UserId),UserID). 

f(command1,true,_UserID) -> do_command1(); 
% if command2 does not need to be registered but uses UserID, for registration for example 
f(command2,_Reg,UserID) -> do_command2(User_ID); 
f(_,false,_UserID) -> {error, not_registered}.