È 'Mantenere l'aspetto simile al codice di esempio' un motivo valido per preferire il principio WET over DRY?

2

Ad esempio, per oauth, potrei aver bisogno di copiare e incollare il codice di callback oauth e oauth come tale (supponiamo che il client sia il framework che uso, non utilizzo la struttura reale come google perché voglio semplificare il codice):

codice di esempio:

public function oauth(){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(SOME_URL);
  //some $client settings
  header('Location: ' . filter_var($client->getURL(), FILTER_SANITIZE_URL));
}

public function oauth_callback(){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(SOME_URL);
  //some $client settings
  if(!$_GET['code']){
        //back to oauth and return;
  }
  $userInfo=$client->getUserInfo();
}

Nel codice reale, vorrei copiare e incollare un codice di esempio come questo:

Login:

public function login_oauth(){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(MY_URL.'login_callback');
  //some $client settings
  header('Location: ' . filter_var($client->getURL(), FILTER_SANITIZE_URL));
}

public function login_callback(){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(MY_URL.'login_callback');
  //some $client settings
  if(!$_GET['code']){
        //back to oauth and exit;
  }
  $userInfo=$client->getUserInfo($_GET['code']);
  //check login valid
}

Registra:

public function register_oauth(){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(MY_URL.'register_callback');
  //some $client settings
  header('Location: ' . filter_var($client->getURL(), FILTER_SANITIZE_URL));
}

public function register_callback(){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(MY_URL.'register_callback');
  //some $client settings
  if(!$_GET['code']){
        //back to oauth and exit;
  }
  $userInfo=$client->getUserInfo($_GET['code']);
  //check is user already registered
}

So che è seriamente a causa del principio SECCO perché copio e incollo il codice, quindi cerco di estrarre parti comuni:

funzioni comuni:

public static function createClient($url){
  $client=new Client([MY_APP_ID,MY_APP_SECRET]);
  $client->setCallbackUrl(URL_PREFIX.$url);
  //some $client settings
  return $client;
}

public static oauth($url){
  $client=MyClass::createClient($url);
  header('Location: ' . filter_var($client->getURL(), FILTER_SANITIZE_URL));
}

public static oauth_callback($url){
  $client=MyClass::createClient($url);
  if(!$_GET['code']){
        //back to oauth and exit;
  }
  $userInfo=$client->getUserInfo($_GET['code']);
  return $userInfo;
}

Login:

public function login_oauth(){
  oauth('login_callback');
}

public function login_callback(){
  $userInfo=oauth_callback('login_callback');
  //check login valid
}

Registra:

public function login_oauth(){
  oauth('login_callback');
}

public function login_callback(){
  $userInfo=oauth_callback('login_callback');
  //check is user already registered
}

Ma ho trovato che il codice refactored è più difficile da mantenere perché:

  1. Sembra molto diverso dal codice di esempio, che è meno comprensibile, specialmente per i principianti che non usano mai questo framework prima

  2. Il più recente ha più funzioni secondarie, che impiegano molto più tempo per collegare la relazione tra queste funzioni secondarie.

  3. Quando si aggiunge una nuova API, l'utilizzo del codice di esempio è semplice perché ho solo bisogno di copiare e incollare direttamente, ma se uso la mia versione refactored, ho bisogno di studiare come ho prima rifattorizzato il codice.

  4. Il refactoring del codice di esempio può introdurre alcuni nuovi probemi, ad esempio: manca qualche riga di codice durante la copia

  5. Il codice può essere completamente sostituito da una versione più recente del codice di esempio o da un altro framework

Quindi la mia domanda è, è "Mantieni simile al codice di esempio" un motivo valido per preferire il principio WET su DRY?

    
posta mmmaaa 11.07.2018 - 04:48
fonte

1 risposta

8

Non ci sono.

In effetti, seguendo il principio DRY a volte è possibile rendere il codice molto semplice un po 'più complesso (il che potrebbe essere il caso, con enfasi su "un po'").

Tuttavia, questo è un piccolo prezzo da pagare quando hai bisogno della stessa logica in più di un punto del tuo sistema. Non centralizzando avrà l'impatto di darti diversi posti da cambiare nel caso in cui tu abbia bisogno di cambiare quella logica. E ha un alto rischio di dimenticare uno di quei posti e introdurre un bug in questo modo.

Il tuo esempio sembra molto chiaro come quello che rientra in quest'ultima categoria. Anche in questo piccolo snippet di codice, sembra importante che oauth_callback e oauth utilizzino sempre la stessa logica per creare un oggetto $client , quindi la logica dovrebbe essere in un unico punto, un metodo createClient è il naturale scelta.

Ciò che hai scritto mi dà l'impressione che il tuo team stia lavorando su un prodotto software, con l'esigenza di utilizzare la stessa logica di autenticazione in tutto il sistema in diversi punti. Quindi immagina cosa succede quando i "principianti" che hai citato iniziano a duplicare la logica createClient intorno a una dozzina di punti nel codice base, e quindi devi estendere la logica di inizializzazione per l'oggetto $client . Vuoi veramente cercare tutti quei posti e testarli tutti, uno per uno? Sicuro di non dimenticartene uno in un'enorme base di codice, specialmente quando il codice di autenticazione è stato modificato in qualche modo ogni volta?

Quindi, è meglio dare ai principianti (e anche a chiunque altro) alcune funzioni testate che possono riutilizzare senza copiare, invece di lasciare che producano un disordine copiando sempre la stessa logica più volte.

Vedi anche:

risposta data 11.07.2018 - 08:15
fonte

Leggi altre domande sui tag