Aspettative su input / output di dimensioni di array e approcci per implementare il supporto per array di input di dimensioni variabili

1

Preambolo

Poiché stiamo vettorializzando la nostra API di colore, stiamo modificando i tipi di input accettati per la maggior parte delle nostre funzioni. Ci teniamo a mantenere la compatibilità con il codice esistente.

Definiamo le seguenti variabili di input:

numerico

R

shape: ()

Ad esempio, un valore R di pixel di una tripletta RGB.

1d

[R, G, B]

shape: (3)

Ad esempio una tripletta di valori RGB pixel

2d

[[R, G, B],
 [R, G, B],
 [R, G, B],
 [R, G, B],
 [R, G, B],
 [R, G, B]]

shape: (6, 3)

Una linea di valori tripletti RGB, per esempio.

3D

[[[R, G, B],
  [R, G, B],
  [R, G, B]],

 [[R, G, B],
  [R, G, B],
  [R, G, B]]]

shape: (2, 3, 3)

Un'immagine della terzina dei valori RGB, per esempio.

Aspettative

Una funzione che in precedenza accettava un numerico come input ora può accettare una matrice numerica o 1d . Una funzione che in precedenza accetta una matrice 1d come input può ora accettare una matrice 1d , 2d o 3d .

La maggior parte della vettorizzazione del codebase è ora prototipata. In particolare, per supportare gli array 1d , 2d o 3d con funzioni che inizialmente utilizzano un array 1d come input, convertiamo la matrice di input in una 2d . Gli algoritmi interni ora funzionano con gli array 2d , quindi la loro implementazione è semplice e prevedibile.

Per una data funzione, quando modifichiamo le dimensioni dell'array di input per il suo scopo algoritmo, le dimensioni dell'array output risultanti vengono alterate (se non facciamo nulla al riguardo).

Vorremmo sapere quanto segue:

Sta cercando di mantenere le dimensioni dell'array un comportamento comunemente previsto?

Un percorso che sembra logico è quello di mantenere le dimensioni dell'array di input: ad esempio, supponiamo che qualcuno inserisca un'immagine (con una forma 3d ) alla nostra% la funzione diRGB_to_XYZ probabilmente si aspetterebbe di ottenere un'immagine con una forma 3d , se qualcuno immettesse un pixel RGB 1d con quella stessa funzione probabilmente si aspetterebbe di ottenere 1d XYZ pixel in risposta e non una 2d array.

Un percorso alternativo sarebbe quello di far rispettare le dimensioni di array di input / output previsti per ciascuna funzione (che interromperà la compatibilità con le versioni precedenti).

Implementazioni

Il percorso alternativo non presenta alcuna difficoltà nella sua implementazione.

Il percorso logico è comunque più complicato: dato che abbiamo prototipato il codice a tale riguardo, abbiamo un sacco di codice ridondante della piastra della caldaia all'inizio e alla fine di ogni funzione al fine di recuperare le dimensioni della matrice di input, cambiare le sue dimensioni e rimodellare la matrice di output. Questo non è molto elegante e confuso per qualcuno che legge il codice mentre contribuisce a una manutenibilità più difficile.

Esiste un modo elegante per implementare il comportamento del percorso "logico"?

Stiamo pensando a una funzione wrapper (decoratore mentre stiamo usando Python) che potrebbe essere responsabile della gestione di tutte le dimensioni / risagoma delle magie, le funzioni stesse potrebbero quindi avere aspettative fisse sull'input / output come in percorso alternativo.

    
posta Kel Solaar 01.03.2015 - 21:49
fonte

1 risposta

2

Is trying to maintain the array dimensions a commonly expected behaviour?

Per me questo sembra un po 'come "La gente si aspetterebbe che la mia API eseguisse tutte queste conversioni di questo tipo?" a cui la risposta è "Probabilmente sì, ma a loro non dovrebbe importare in alcun modo, dal momento che non dovrebbero preoccuparsi della tua implementazione". Forse hai un modo iper-ottimizzato di colori frobnicating che hanno solo un componente R, e quel "vecchio" sovraccarico dovrebbe chiamarlo.

Se stai cercando di chiedere "La gente si aspetterebbe che mantenessimo la retrocompatibilità sostenendo tutti i vecchi tipi?" quindi la risposta dipende interamente dalla tua base di utenti e non ne sappiamo nulla. Ad esempio, storicamente Microsoft Windows non può nemmeno correggere i bug in modo sicuro , tanto meno cambiare i tipi di argomento. D'altra parte, Python 3 "ha rotto" uno dei suoi elementi di base / O primitivi , e sembra aver funzionato bene. Forse i tuoi utenti apprezzerebbero persino di avere una "pausa pulita" dalla vecchia API. Tutto dipende.

Is there an elegant way to implement the "logical" path behaviour?

La mia soluzione in C ++ sarebbe probabilmente simile a questa:

class ColorFrobnicator {
  public:
    int frobnicate(const int R) {
        std::vector<int> colors = { R, 0, 0 };
        return actuallyFrobnicate(colors);
    }
    int frobnicate(const std::vector<int>& colors) {
        return actuallyFrobnicate(colors);
    }

  private:
    int actuallyFrobnicate(const std::vector<int>& colors) {
        /* the code that actually matters goes here */
        return finalValueAfterExtensiveFrobnication;
    }
}

Penso che questo sia tanto "elegante" quanto la compatibilità all'indietro possa mai ottenere: Metti tutte le conversioni e i wrapper nell'interfaccia e sposta tutto il "codice reale" nell'implementazione. In questo modo, nessuno del tuo codice reale deve mai passare a if(oldAPI) { convertToArray(R); } e puoi facilmente apportare modifiche alle interfacce vecchie o nuove senza toccare il codice reale.

Non ho molta esperienza in Python, ma sono sicuro che c'è un modo altrettanto piacevole di gestirlo in quella lingua.

    
risposta data 01.03.2015 - 22:30
fonte

Leggi altre domande sui tag