2010-07-01 18 views
42

Ho pensato di implementare badge (proprio come i badge qui su Stack Overflow) e penso che sarebbe difficile senza servizi Windows, ma vorrei evitarlo se possibile.Come implementare i badge?

mi si avvicinò con un piano per implementare alcuni esempi:

  • Audobiographer: Controllare se tutti i campi di profilo è compilati.
  • Commento: quando si effettua un commento, verificare se il numero di commenti è uguale a 10, in caso contrario assegnare il badge.
  • Buona risposta: al momento del controllo, controlla se il punteggio del voto è 25 o superiore.

Come può essere implementato nel database? O un altro modo sarebbe meglio?

+0

Si desidera memorizzare in cache alcuni valori di reputazione sul server Web senza dover chiamare costantemente i servizi di Windows. – Russell

risposta

41

Un'implementazione simile a StackOverflow è in realtà molto più semplice di quella che hai descritto, in base a frammenti di informazioni rilasciati dal team di tanto in tanto.

Nel database, è sufficiente memorizzare una collezione di coppie BadgeID - UserID per individuare chi ha cosa (e un conteggio o un rowID per consentire più riconoscimenti per alcuni badge).

Nell'applicazione, c'è un oggetto di lavoro per ogni tipo di badge. L'oggetto si trova nella cache, e quando la cache scade, il lavoratore gestisce una sua logica per determinare chi dovrebbe ottenere il distintivo e facendo gli aggiornamenti, e poi si ri-inserti nella cache:

public abstract class BadgeJob 
{ 
    protected BadgeJob() 
    { 
     //start cycling on initialization 
     Insert(); 
    } 

    //override to provide specific badge logic 
    protected abstract void AwardBadges(); 

    //how long to wait between iterations 
    protected abstract TimeSpan Interval { get; } 

    private void Callback(string key, object value, CacheItemRemovedReason reason) 
    { 
     if (reason == CacheItemRemovedReason.Expired) 
     { 
      this.AwardBadges(); 
      this.Insert(); 
     } 
    } 

    private void Insert() 
    { 
     HttpRuntime.Cache.Add(this.GetType().ToString(), 
      this, 
      null, 
      Cache.NoAbsoluteExpiration, 
      this.Interval, 
      CacheItemPriority.Normal, 
      this.Callback); 
    } 
} 

E un implementazione concreta:

public class CommenterBadge : BadgeJob 
{ 
    public CommenterBadge() : base() { } 

    protected override void AwardBadges() 
    { 
     //select all users who have more than x comments 
     //and dont have the commenter badge 
     //add badges 
    } 

    //run every 10 minutes 
    protected override TimeSpan Interval 
    { 
     get { return new TimeSpan(0,10,0); } 
    } 
} 
+0

wow. Questa è una buona idea. Come fai a sapere quando scade la cache. C'è una funzione di richiamata che puoi chiamare quando scade la cache? – Luke101

+0

@ Luke101 vedere il codice di esempio –

+1

@ Luke101: è una funzionalità dell'infrastruttura di caching .NET: quando il timeout scade (e l'oggetto sta per essere rimosso dalla cache) il runtime richiama automaticamente la richiamata. –

4

Lavori. Questa è la chiave. Lavori fuori processo che vengono eseguiti a intervalli prestabiliti per verificare i criteri menzionati. Non penso che tu abbia nemmeno bisogno di avere un servizio Windows a meno che non richieda alcune risorse esterne per impostare i livelli. In realtà penso che StackOverflow usi anche i lavori per i loro calcoli.

+2

Dovrei aggiungere anche questo per evitare di controllare manualmente ogni utente ogni volta che vorresti probabilmente tenere un tavolo di attività in modo da poter avere il tuo elenco di persone che vorresti controllare.Ovviamente non vuoi sprecare risorse per elaborare utenti che non hanno avuto attività recenti. – spinon

+0

I lavori vengono eseguiti automaticamente? Dove posso trovare ulteriori informazioni sui lavori? – Luke101

+0

I lavori possono essere programmati per essere eseguiti sul database. Li costruisci e poi stabilisci il loro intervallo per il quale dovrebbero essere eseguiti. Noterai su SO che una volta completata un'azione non ti ricompenserà immediatamente. Quindi immagino che abbiano le cose da eseguire ogni pochi minuti o così. Ma davvero non ne ho idea. Ma un piccolo ritardo non è un grosso problema, ma aspetterei fino alla fine della giornata per l'elaborazione. – spinon

0

È possibile utilizzare i trigger e controllare l'aggiornamento o l'inserimento, quindi se le condizioni sono soddisfatte aggiungere badge. Quello lo manterrebbe piuttosto sembrare meno. Iniziare il bashing del trigger in 3, 2, 1 ...

+6

Questo è esattamente il tipo di trigger di motivo (valido) sono stati eseguiti. –

+0

Sono d'accordo che ci sono molti svantaggi dei trigger, ma IMHO ruotano principalmente intorno non includendo la logica di business in un livello dati/database. Esiste qualche problema di prestazioni o di validità che deriva dai trigger, se sono scritti e implementati correttamente? –

+0

i problemi di prestazioni e validità tendono a derivare da trigger perché sono, relativamente parlando, molto difficili da gestire. Sono orientati all'effetto collaterale, mentre in generale è comunemente accettato che il codice con effetti collaterali sia una ricetta per il disastro. È difficile creare un caso forte per una singola operazione (ad es. Inserire) per avere silenziosamente - dal punto di vista del chiamante - una quantità sconosciuta di effetti collaterali aggiuntivi al sistema. –

0

i commenti devono essere memorizzati all'interno del database giusto? quindi penso che ci siano due modi principali per farlo.

1) quando un utente effettua il login si ottiene un conteggio dei commenti. questo non è l'approccio desiderato poiché il conteggio potrebbe richiedere molto tempo

2) quando un utente invia un commento, è possibile eseguire un conteggio e archiviare il conteggio con i dettagli di utilizzo oppure è possibile eseguire un trigger che viene eseguito quando viene aggiunto un commento. il trigger otterrebbe quindi i dettagli del commento appena creato, cattura l'id utente, ottiene un conteggio e lo memorizza contro l'utente in una tabella di qualche tipo.

Mi piace l'idea di un trigger come il programma può restituire w/out in attesa che il server SQL esegua il proprio lavoro.