Utilizzo di un oggetto permessi pervasivo all'interno di un progetto per imitare un sistema di effetti

1

Esiste un modello di progettazione che ho pensato ma che non ho visto implementato dove ogni funzione / metodo passa attorno ad un oggetto permessi. Mi chiedo se utilizzarlo in un progetto sia una buona idea o meno. Le idee chiave qui sono che 1) le capacità sono sempre e solo portate via, non aggiunte (a meno che tu non sia in una specie di entry point) e 2) non ispezionino il contenuto dell'oggetto permessi eccetto per asserire che hai qualche cosa specifica la capacità è necessaria prima di fare qualcosa.

La maggior parte delle lingue tradizionali oltre a Haskell non ha nulla che assomigli a un sistema di effetti, che è davvero quello che sto cercando di emulare.

L'obiettivo è che i campi specifici nel tipo di autorizzazioni siano significativi per l'applicazione. Sembra probabile che le autorizzazioni significative per la traccia cambino più lentamente rispetto al resto dell'applicazione.

Ad esempio,

struct permission {
    bool can_write_db;
    bool can_create_tempfile;
    bool can_delete_tempfile;
};
typedef struct permission permission;

E quindi all'interno di una funzione che scrive sul database potresti fare il seguente

void commit_transaction(permission p, X x, Y y) 
{
    assert(p.can_write_db);
    ...
    do_something_else(p, 47);
    return;
}

con do_something_else è un'altra funzione che viene consegnata all'oggetto autorizzazioni.

Come per (2), il seguente esempio violerebbe la regola contro l'ispezione del contenuto dell'oggetto permessi.

// BAD
void possibly_commit_transaction(permission p)
{
    if (p.can_write_db) {
        // commit the transaction
    } else {
        // write a description of the transaction to a log file
    }
}

L'oggetto permessi non è destinato ad essere usato come gli altri parametri, dato che la cosa sbagliata indica che il programma ha un bug in esso.

Varrà la pena affrontare il problema di usare qualcosa di simile? È probabile che questa cosa porti il suo stesso peso?

P.S.

L'obiettivo di questo è espressamente non la sicurezza o l'irrigidimento dell'applicazione.

    
posta Gregory Nisbet 23.05.2018 - 08:45
fonte

1 risposta

1

Il problema qui è che le autorizzazioni sono controllate al 100% in fase di esecuzione e devono essere controllate manualmente . È facile dimenticare questi controlli. Se li ometti, il codice funzionerà ancora.

Di solito, il problema con cui il tuo indirizzo di permessi è risolto da objects . Cioè: la funzione non è in grado di eseguire le sue azioni a meno che un oggetto o callback che fornisce tali azioni non sia dato ad esso (come parametro).

struct DbWriter;
void DbWriter_write(DbWriter*, Value);

struct Tempfile;
typedef Tempfile* (CreateTempfile)(const char* name);
typedef void (RemoveTempfile)(Tempfile*);

void commit_transaction(
        DbWriter* writer,
        CreateTempfile* mktemp,
        RemoveTempfile* rmtemp,
        X x,
        Y y)
{
    assert(writer);  // must be non-null
    assert(mktemp);
    assert(rmtemp);
    Tempfile* t = mktemp("foo.txt");
    DbWriter_write(writer, foo(x));
    DbWriter_write(writer, bar(y));
    do_something_else(rmtemp, t, 47);
}

Il problema qui è che otterrete molti parametri per le autorizzazioni necessarie direttamente o indirettamente, quindi può ancora avere senso raggrupparli in un oggetto parametro - ma ora la necessità di affermare che devono essere non nulli è meno ovvia .

Sia chiaro: mentre la domanda è tecnicamente indipendente dal linguaggio, C è un linguaggio molto frustrante per questo tipo di design. Anche se si passa solo a C ++, si ottengono due funzionalità principali che semplificano questo: supporto di prima classe per la sintassi dell'oggetto e riferimenti che devono essere non nulli, quindi afferma diventa inutile.

    
risposta data 23.05.2018 - 11:51
fonte

Leggi altre domande sui tag