Stiamo costruendo alcuni moduli aziendali che devono essere intuitivi per gli sviluppatori, quindi il codice stesso spiega e obbliga gli sviluppatori a utilizzarlo in un determinato modo. Questo vale sia per migliorare le funzionalità esistenti (dai nostri sviluppatori) sia per riutilizzarle (da sviluppatori di terze parti). Tutti i moduli fanno parte di una grande infrastruttura, quindi condividono le stesse entità (come Utente), ma operano sulle proprie entità. È Java 7 (meh).
Ecco alcuni principi che popolano.
- non incapsulare business in un unico metodo, quindi possiamo avere più flessibilità nel riutilizzarlo in modo diverso (pensate che sia funzionale qui)
- nascondi completamente i modelli agli sviluppatori, perché indipendentemente da come li abbiamo provati, i modelli rappresentano sempre rappresentazioni diverse a seconda del caso d'uso; in più ci sono alcune informazioni tecniche in modelli che non vogliamo condividere con gli sviluppatori. Questo è un passo in avanti dal renderli immutabili.
- non generalizzare; prova a forzare l'utilizzo per gli utenti.
È difficile spiegarlo, quindi lascia che provi a darti una panoramica su come utilizzare questo livello aziendale:
- prima specifica il contesto con cui stai lavorando. Il contesto è un insieme di modelli, che simula l'aggregato.
- nel contesto è possibile specificare action del modello (non avere un nome migliore al momento): questo è un DSL per cambiare il modello. l'utente può modificare solo ciò che questo dsl consente.
- sul contesto, quindi è possibile eseguire uno o più comandi (concatenabili). Questa volta, questo è DSL per il business.
- infine puoi invocare il renderer che ha lo scopo di rendere il contesto nella classe di visualizzazione necessaria per l'interfaccia utente.
Ecco come appare (non essere duro con i nomi delle classi, non sono ancora i migliori):
PollsService polls = new PollsService();
PollsView pollsView = polls.newPoll(new ModelAction<PollsQuestionModelBuilder>() {
@Override
public void execute(PollsQuestionModelBuilder question) {
question.title(title);
question.choices(choices);
if (!expiration) {
question.doesNotExpire();
}
}
}).update(new Command<UpdateService>() {
@Override
public void execute(UpdateService updater) {
updater.savePollQuestion();
updater.savePollChoices();
}
}).render(new ModelView<PollsView, PollsQuerier, PollsQuestionAndChoiceView>() {
@Override
public PollsView render(PollsQuerier pollsQuerier, PollsQuestionAndChoiceView data) {
return new PollsView(data.getPollsQuestion(), data.getPollsChoices());
}
});
A un certo punto questo può essere scritto come:
PollsView pollsView = polls
.newPoll(fromRequest(request))
.update(pollsUpdate())
.render(defaultView());
Ecco un altro esempio sull'aggiornamento:
PollsService polls = new PollsService();
polls.on(questionTicket, new ModelAction<PollsQuestionModelUpdater>() {
@Override
public void execute(PollsQuestionModelUpdater pollsQuestionModelUpdater) {
pollsQuestionModelUpdater.changeTitle("Why do you do this?");
}
}).update(new Command<UpdateService>() {
@Override
public void execute(UpdateService pollsQuestionUpdater) {
pollsQuestionUpdater.savePollQuestion();
}
});
Quindi tutto sopra i passaggi, in modo funzionale (come consentito da java7). Come sviluppatore, devi essere consapevole del tuo contesto e di tutte le modifiche che fai, devono riflettere il contesto. Se hai bisogno di più - crea un nuovo contesto, cioè un nuovo aggregato. Quindi come sviluppatore devi pensare:
- con cosa stai lavorando
- quale operazione eseguire su di essa
- e come dovrebbero apparire i dati.
Ovviamente, i passaggi 2 e 3 non sono obbligatori, cioè puoi avere una vista senza operazioni e viceversa.
Qualcuno ha usato un approccio simile? e perché?