Il modo più coerente dal punto di vista logico per creare i metodi del modulo a interessa b?

5

Ho uno scenario comune in cui ho un oggetto (a) che influisce logicamente su un altro oggetto (b), come a fa una nota su b, o su un segno b come disabilitato (di solito a è un oggetto utente del sistema e b è una specie di oggetto aziendale come un cliente o un appuntamento).

In passato, il metodo era sull'oggetto interessato come:

customer.Disable(user); // user is marking the customer as disabled

... ma non legge bene (appare a ritroso). Il contrario:

user.Disable(customer);

... legge meglio, ma c'è qualcosa a riguardo che non riesco a capire che non sembra giusto. L'unica altra opzione è avere un intermediario statico:

ThirdPartyClass.DisableCustomer(customer, user);

... ma gli oggetti del dominio finiscono per diventare più simili agli DTO e preferisco l'approccio del modello di dominio perché ha più senso.

Quindi la domanda è: che ha più senso? C'è un'opzione che non ho considerato? Chi possiede effettivamente un'operazione come questa?

Modifica

Con la seconda opzione, gli oggetti utilizzabili nel sistema (di solito gli utenti) diventano enormi perché gli utenti del sistema sono quelli che praticamente fanno e influenzano tutto.

    
posta Steven Evers 05.11.2010 - 18:56
fonte

4 risposte

7

Che ne dici di

customer.SetDisabledBy(user);

o se si utilizza C # 4.0 o una lingua diversa con capacità simili:

customer.SetDisabled(by: user);

oppure se stai utilizzando C # 3.5 o più recente, puoi scrivere quanto segue:

user.DisableCustomer(customer);

mentre il metodo DisableCustomer è un metodo di estensione che si trova in una classe chiamata CustomerActions che si trova insieme alla classe Customer . In questo modo, quando sei using dello spazio dei nomi Customer , User avrà quel metodo di estensione. Quando non sei using , non c'è più. User non è più un oggetto dio ma la classe intermedia non si trova da nessuna parte nel codice. Potresti anche avere una classe OrderActions che fornirà user.CancelOrder(order) , ecc.

Bella domanda, mi ha fatto pensare!

    
risposta data 05.11.2010 - 20:24
fonte
4

user.Disable(customer) sembra quasi che stia dicendo che user è disabilitato, poiché user.Disable() verrebbe letto come se agisse sull'utente, non sul cliente.

user.DisableCustomer(customer) si legge un po 'meglio, penso, poiché chiarisce che il cliente è disabilitato. Significa anche che non hai bisogno di una classe extra solo per il gusto di farlo.

    
risposta data 05.11.2010 - 19:04
fonte
0

Se i tuoi oggetti utente assumono così tante responsabilità che sembra che abbiano troppi metodi "user.DoFooOnBar (bar)", allora potresti guardare un oggetto divino. Potresti sentirti meglio usando le interfacce per suddividere i ruoli dell'utente in pezzi specifici del dominio o usando la composizione per fare lo stesso.

Interfacce

Avresti un'interfaccia ICustomerController implementata dall'Utente, quindi quando hai bisogno che gli utenti disabilitino i clienti, lanci il cliente in un ICustomerControl e puoi usare ICC.DisableCustomer (cliente). Ciò fornisce una lettura naturale della mossa perché il cliente viene manipolato non da un utente, ma da "qualcosa che manipola i clienti".

Inoltre ti lascia più flessibile per consentire alle cose che non sono utenti di aggiornare i clienti, se necessario.

Composizione

Solo un'estensione dall'ultima idea: invece che gli utenti siano ICustomerControllers (IS-A), sarebbero proprietari di un ICustomerController (HAS-A). Così ora la chiamata si legge come user.CustomerController.Disable (cliente). Di nuovo, questo rende chiaro che gli utenti agiscono in una certa capacità (per influenzare i clienti) e solo contro quel dominio di oggetti (clienti).

Non avevi menzionato quel problema, ma un metodo come user.Disable () potrebbe sembrare che possa influenzare qualsiasi cosa, anche l'utente stesso. Uno dei due sopra lo corregge.

    
risposta data 05.11.2010 - 20:10
fonte
0

Come fai notare che avere molti metodi sulla classe User sta introducendo l' anti-pattern di God Object . Sembra che il problema sia di incapsulamento, quindi il flusso di dati

User performs an action on an entity

può essere reinterpretato come

System perform command on entity with reference to User

Ciò significherebbe un design che ha preferito utilizzare un pattern Command con un comando tipico simile a questo:

public class DisableCustomerCommand implements EntityCommand<Customer,User> {

  // This is the single EntityCommand templated method
  public Customer execute(Customer customer, User user) {
    customer.setEnabled(false);

    // TODO Add in audit code for User object

    return customer;
  }
}

Questo segue il principio OOD generale della creazione di oggetti semplici per la ricerca di grani che fanno molto poco, ma lo fanno bene.

Modifica

Devo sottolineare che si tratta di una semplificazione eccessiva. In genere, la disabilitazione di un cliente richiederebbe la modifica di diversi altri campi. Anche questo porta a entità anemiche (il Cliente sarebbe solo un mucchio di getter / setter), ma a volte può essere un design generale più semplice.

    
risposta data 06.11.2010 - 21:37
fonte

Leggi altre domande sui tag