Domanda

Voglio contrassegnare un metodo come obsoleto, ma Delphi 5 non ha una tale funzione.

A titolo di esempio, ecco un metodo inventato con la sua forma obsoleta e nuova preferita:

procedure TStormPeaksQuest.BlowHodirsHorn; overload; //obsolete
procedure TStormPeaksQuest.BlowHodirsHorn(UseProtection: Boolean); overload;

Nota: per questo ipotetico esempio, supponiamo che l'uso della versione senza parametri sia semplicemente negativo. Esistono problemi con il non " utilizzo della protezione " - che non hanno una buona soluzione. A nessuno piace usare la protezione, ma nessuno vuole non usare la protezione. Quindi facciamo decidere al chiamante se vogliono usare la protezione o meno quando suonando il corno di Hodir . Se impostiamo la versione senza parametri per continuare non usando la protezione:

procedure TStormPeaksQuest.BlowHodirsHorn;
begin
    BlowHodirsHorn(False); //No protection. Bad!
end;

quindi lo sviluppatore è a rischio di tutti i tipi di cose brutte. Se forziamo la versione senza parametri a utilizzare la protezione:

procedure TStormPeaksQuest.BlowHodirsHorn;
begin
    BlowHodirsHorn(True); //Use protection; crash if there isn't any
end;

allora c'è un potenziale problema se lo sviluppatore non ha ottenuto alcuna protezione o non ne possiede.

Ora potrei rinominare il metodo obsoleto:

procedure TStormPeaksQuest.BlowHodirsHorn_Deprecatedd; overload; //obsolete
procedure TStormPeaksQuest.BlowHodirsHorn(UseProtection: Boolean); overload;

Ma questo causerà un errore di compilazione e la gente mi farà una cagna (e davvero non voglio sentire il loro lamento). voglio che ricevano un nag , piuttosto che un errore reale.

ho pensato di aggiungere un'asserzione:

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
begin
   Assert(false, 'TStormPeaksQuest.BlowHodirsHorn is deprecated. Use BlowHodirsHorn(Boolean)');

   ...
end;

Ma non posso garantire che lo sviluppatore non spedirà una versione senza asserzioni, causando un brutto incidente per il cliente .

ho pensato di usare solo un'asserzione se lo sviluppatore sta eseguendo il debug:

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
begin
   if DebugHook > 0 then
      Assert(false, 'TStormPeaksQuest.BlowHodirsHorn is deprecated. Use BlowHodirsHorn(Boolean)');

   ...
end;

Ma non voglio davvero causare alcun incidente.

Ho pensato di mostrare un MessageDlg se sono nel debugger (che è una tecnica che ho fatto in passato):

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
begin
   if DebugHook > 0 then
        MessageDlg('TStormPeaksQuest.BlowHodirsHorn is deprecated. Use BlowHodirsHorn(Boolean)', mtWarning, [mbOk], 0);

   ...
end;

ma è ancora troppo dirompente. E ha causato problemi in cui il codice è bloccato nel mostrare una finestra di dialogo modale, ma la finestra di dialogo non era ovviamente visibile.

Speravo in una sorta di messaggio di avvertimento che rimarrà lì a infastidirli - fino a quando non sbarreranno gli occhi e finalmente cambieranno il loro codice.

forse pensavo che se avessi aggiunto una variabile non utilizzata:

procedure TStormPeaksQuest.BlowHodirsHorn; //obsolete
var
   ThisMethodIsObsolete: Boolean;
begin
   ...
end;

Speravo che questo avrebbe causato un suggerimento solo se qualcuno avesse fatto riferimento al codice. Ma Delphi mostra un suggerimento anche se non si chiama effettivamente utilizzare il metodo obsoleto.

Qualcuno può pensare ad altro?

È stato utile?

Soluzione 2

Quello che ho finito per usare era una combinazione di optare per un sistema in cui accetti di non avere alcun codice deprecato, con stringhe di debug di output e punti di interruzione altrimenti.

Come strict html, ho creato un Strict define.

Tutte le unità comuni hanno il codice obsoleto definito se è definito Strict . In questo modo lo sviluppatore ha concordato che non avrà un codice deprecato nel suo progetto:

{$IFNDEF Strict}
procedure TStormPeaksQuest.BlowHaldirsHorn; overload; //obsolete
{$ENDIF}
procedure TStormPeaksQuest.BlowHaldirsHorn(UseProtection: Boolean); {$IFNDEF Strict}overload;{$ENDIF}


{$IFNDEF Strict}
procedure TStormPeaksQuest.BlowHaldirsHorn; //obsolete
begin
   OutputDebugString(PAnsiChar('TStormPeaksQuest.BlowHaldirsHorn is deprecated. Use BlowHaldirsHorn(Boolean)'));

   //Don't debugbreak without a debugger attached!
   if DebugHook > 0 then
        Windows.DebugBreak;

   ...
end;

Quindi, se lo sviluppatore vuole avere un codice adeguato, soffrendo di dover apportare modifiche al codice quando le cose nuove sono deprecate, possono:

{$DEFINE Strict}

In caso contrario, sarà sempre sempre un OutputDebugString e chiunque disponga di Visualizzazione debug può vedere (anche i clienti). È divertente vedere software commerciali (anche quelli di Microsoft) con stringhe di debug di output rimaste.

E infine, se è collegato un debugger, otterranno un breakpoint dal nulla. Se qualcuno chiede qualcosa, posso cogliere l'occasione per prenderli in giro.

Altri suggerimenti

Che ne dici di qualcosa del genere

procedure TStormPeaksQuest.BlowHaldirsHorn; //obsolete
begin
  if DebugHook > 0 then asm int 3 end;  
  // This method is Obsolete!  Use XXXXX instead.
  Abort; // Optional, makes method useless  
  // old code here . . . 
end;

Un tipo di compromesso tra un'asserzione e un messaggio di spettacolo. Lo sviluppatore deve solo premere F9 per continuare. Potresti inserire un'interruzione, quindi il metodo non farebbe nulla e ciò li costringerebbe a cambiare metodo e l'interruzione li rende consapevoli.

Personalmente consiglierei l'aggiornamento a una versione più recente di Delphi. 2007 e 2009 sono ottime versioni e valgono davvero l'aggiornamento.

Questo non risponde esattamente alla tua domanda ma potrebbe fornire una soluzione alternativa. Non è possibile aggiornare la funzione originale con un valore predefinito ...

procedure TStormPeaksQuest.BlowHaldirsHorn(UseProtection: Boolean = False);

... in modo che il codice legacy compili e si comporti allo stesso modo ma la nuova funzionalità è disponibile per i nuovi sviluppatori.

Perché vuoi farlo e perché non vuoi aggiornare la versione di Delphi?

Senza il tag deprecato non hai davvero nessuna opzione pulita per filtrare l'uso di metodi deprecati. Quindi dipende da dove vuoi fare la concessione:

  • la ridenominazione rileva l'errore in compiletime (a meno che non esista un altro metodo / funzione con lo stesso nome nell'ambito).
  • tutti gli altri metodi vengono rilevati solo in fase di esecuzione. E questo ha il rischio di scivolare nel codice di produzione.

Quello che puoi fare è creare un registro deprecato. Questo non farà incazzare nessuno, e non è un disastro completo se inserisce il codice di produzione. Ma se i tuoi test hanno una copertura completa, catturerai tutti i colpevoli. Devi solo controllare il file di registro dopo un'esecuzione (di prova).

E ovviamente il modo migliore è usare grep per trovare tutte le occorrenze del codice e modificarlo.

Concordo con un parametro facoltativo se lo farà. Ma posso pensare a situazioni in cui i parametri opzionali non andrebbero bene. Ad esempio, ho spostato le funzioni in nuove unità ma ho mantenuto quelle vecchie e le ho contrassegnate come deprecate.

Immagino che qualunque soluzione tu scelga dipenderà anche dalla disciplina della tua squadra. Notano e lavorano attivamente per correggere tutti i suggerimenti e gli avvisi delle loro app? Speriamo che lo facciano, ma mi vergogno di ammettere che la squadra con cui lavoro (incluso me stesso) non è in cima a tutti i suggerimenti e le avvertenze. Ogni tanto aggiorno tanti suggerimenti e amp; avvertenze quando il tempo lo consente e dovremmo assolutamente correggere le avvertenze, ma in realtà dobbiamo svolgere il lavoro e concentrarci maggiormente sulle nuove funzionalità e scadenze.

Quindi il mio punto è, anche se potessi contrassegnarli come deprecati o dare un suggerimento / avvertimento simile, ritieni che la tua squadra si prenderà comunque il tempo di cambiare il loro codice?

Non è una soluzione totale poiché non è possibile differenziare se hanno utilizzato il metodo o meno, ma se è disponibile in Delphi 5 ma è possibile utilizzare $ MESSAGE direttiva del compilatore per emettere un avviso al momento della compilazione.

Nulla dice " Fix me! " come una pausa del compilatore.
Detto questo, ho un collega che modifica regolarmente le firme delle routine del "codice comune" ... e sì, è fastidioso!

Il mio approccio preferito (ovvero il nostro team non è ancora del tutto lì: /) è il seguente:

  1. Tutti gli sviluppatori devono essere in grado di eseguire facilmente una build completa di tutti i progetti sui propri computer.
  2. Chiunque decida di modificare il codice comune dovrebbe essere responsabile delle conseguenze. Cioè Correggi tutto il codice interessato.
    • Concesso, a volte detto che lo sviluppatore potrebbe non essere l'ideale per implementare e verificare correttamente tutte le correzioni.
    • Ma, allo stesso modo, gli sviluppatori hanno imposto di "adottare il nuovo contratto" nel proprio codice potrebbe non essere chiaro sulle subtelties del nuovo contratto. Cioè
      • C'è qualcosa di speciale che deve essere fatto per usare la protezione?
      • Come viene implementato l'uso della protezione?
      • Quali sono le preoccupazioni su come potrebbe violare il codice esistente?
    • Questo è uno dei motivi principali per cui è importante una serie completa di casi di test.
  3. Generalmente si desidera l'effetto a catena di tutte le modifiche applicate il prima possibile. Cioè Mentre i dettagli più fini del cambiamento sono freschi nella mente dello sviluppatore originario, prima che l'attenzione si sposta su qualcos'altro!
  4. Dovrebbe essere un caso raro che l'effetto a catena sia così vasto (migliaia di righe) che si desidera applicare la modifica per un lungo periodo di tempo.
    • In questo caso, implementa un semplice strumento di raccolta delle metriche di codice integrato nel tuo processo di generazione per segnalare il numero di istanze in sospeso.

Ritengo che il punto 2 sia di fondamentale importanza, anche perché sottolinea la necessità di cooperazione e comunicazione all'interno della squadra.

Tornando alla mia dichiarazione di apertura, prima si rileva e si risolve un errore, meglio è.
Lascia che il compilatore segnali una pausa! - È la prima opportunità " meccanismo di segnalazione degli errori che abbiamo.

Sono i miei 2 rami! : D

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top