Come al refactor il seguente codice parallelo per evitare il controllo ridondante?

0

Nel seguente esempio di codice, i processi sono assegnati a diversi contesti. E ogni oggetto App sarà associato a un solo contesto. Sebbene tutti i processi eseguano lo stesso codice, solo quelli appartenenti al contesto eseguiranno i metodi di App. Per implementare questo obiettivo, come mostrato nel codice, devo aggiungere l'istruzione di controllo if in ogni metodo della classe App da verificare. Quindi la mia domanda: ci sono alcuni modi eleganti per fare lo stesso lavoro come modelli di progettazione o pratiche di codice?

class Context {
    public:
        Context(int num_procs);
        bool ContainsCurrentProcess();
        ...
    private:
        std::vector<int> procs_;
        ...
};

bool Context::ContainsCurrentProcess() {
    if (current_process_id belongs to procs_ )
        return true;
    else 
        return false;
}

class App {
    public:
        App(Context *ctx, ...) {}
        void Method1();
        void Method2();
        void Method3();
        ...
    private:
        Context *ctx_;
        ...
};

void App::Method1() {
    if (ctx_->ContainsCurrentProcess()) {
        ...
    }
}

void App::Method2() {
    if (ctx_->ContainsCurrentProcess()) {
        ...
    }
}

void App::Method3() {
    if (ctx_->ContainsCurrentProcess()) {
        ...
    }
}

 // In the parallel program, all processes will run the following code.
 // However, each processes can have different behaviors based on their process IDs.
int main() {
  // Assume we have 8 processes
  Context ctx1(4); // Assign process 0, 1, 2, 3 to ctx1.
  Context ctx2(4); // Assign process 4, 5, 6, 7 to ctx2.
  App app1(ctx1, ...);
  App app2(ctx2, ...);
  // The app1 and app2 will use different groups of processes concurrently.
  app1.Method1();
  app2.Method2();
}
    
posta Yulong Ao 03.11.2017 - 07:07
fonte

2 risposte

3

Se la tua preoccupazione è la duplicazione dell'espressione condizionale nell'istruzione if , allora un'opzione potrebbe essere quella di cambiare il Context::ContainsCurrentProcess in una funzione che accetta un lambda da eseguire quando la condizione è true invece di restituire la% codice%. Ad esempio:

void Context::Invoke(std::function<void()> func)
{
    if (/* current process id belongs to procs*/)
    {
        func();
    }
}

void App::Method1()
{
    ctx_->Invoke([]()
    {
        // Do Method 1 stuff..
    });
}

void App::Method2()
{
    ctx_->Invoke([]()
    {
        // Do Method 2 stuff..
    });
}

Questo elimina la necessità che altre classi conoscano o si preoccupino dello stato di bool , che si adatta alla Tell Do not not Chiedi principio.

Tuttavia, il livello extra di indirizzamento indiretto creato dal lambda può avere un costo in termini di leggibilità, ovvero non è immediatamente chiaro al lettore che il metodo ContainsCurrentProcess sta controllando lo stato del contesto.

Potresti sostenere che questa potrebbe essere una buona o una cattiva cosa - cioè qualcuno che legge il codice probabilmente non dovrebbe aver bisogno di sapere cosa sta succedendo dentro Invoke per capire Invoke - ma se stanno cercando di eseguire il debug di uno strano comportamento in Method1 relativo allo stato di Method1 , potrebbero interferire.

    
risposta data 03.11.2017 - 07:40
fonte
0

Questo sembra un problema di design. Perché un'istanza di App viene chiamata a gestire la funzionalità per un Context che non contiene il processo corrente? Sembra che Context non debba mai essere passato a quel App . Puoi cambiare il costruttore per App in throw se ctx->ContainsCurrentProcess() restituisce false ? O altrimenti non creare nemmeno un App con quel Context ?

    
risposta data 04.11.2017 - 04:27
fonte