Empêcher la compilation de code obsolète après avoir atteint un délai limite [fermé]

68

Dans mon équipe, nous avons nettoyé beaucoup de vieux matériaux dans le cadre d'un grand projet monolithique (cours entiers, méthodes, etc.).

Pendant ces tâches de nettoyage, je me demandais s’il existait une sorte d’annotation ou de bibliothèque plus sophistiquée que la normale @Deprecated. Cela @FancyDeprecateddevrait empêcher la génération du projet de réussir si vous n'avez pas nettoyé l'ancien code inutilisé après une date donnée.

J'ai effectué une recherche sur Internet et je n'ai rien trouvé qui présente les fonctionnalités décrites ci-dessous:

  • devrait être une annotation, ou quelque chose de similaire, à placer dans le code que vous êtes censé supprimer avant une date donnée
  • avant cette date, le code sera compilé et tout fonctionnera normalement
  • après cette date, le code ne sera pas compilé et il vous enverra un message vous avertissant du problème

Je pense que je recherche une licorne ... Existe-t-il une technologie similaire pour toutes les langues de programme?

En tant que plan BI, je pense à la possibilité de faire de la magie avec certains tests unitaires du code destiné à être supprimé qui commencent à échouer à la "date limite". Que pensez-vous de ceci? Une meilleure idée?

Arcones
la source
168
La désapprobation est faite pour une version , pas une date . Si vous souhaitez que les utilisateurs cessent d'utiliser des fonctionnalités obsolètes, publiez une version sans elles. Cela attirera leur attention et ils pourront toujours revenir en arrière s’ils ne le peuvent pas encore. Beaucoup de gens sont bloqués sur les anciennes versions. Briser leur programme n'est pas la solution.
Isanae
4
Le plan B semble solide. Avec les avantages supplémentaires que vous pouvez mettre dans le test unitaire, expliquez pourquoi il est déconseillé. Ajouter le commentaire au code source ne faciliterait pas la lisibilité dans un grand monolithe
dwana
53
Cela ressemble à une licorne vraiment diabolique. Vous avez un peu de logiciel qui compile bien, passe tous les tests et vous l’a envoyé à un client. Puis un jour, vous relisez le logiciel et il ne se développera pas, même sur la même plate-forme de développement. Vous êtes maintenant obligé de modifier le code qui a déjà passé des tests formels ou de faire des piratages malveillants, comme ramener l'horloge de l'ordinateur à l'arrière.
Simon B
6
Make it @ Deprecated_RemoveMe_2018_06_01 puis 2018-06-01, supprimez l'annotation elle-même. Voila, tout votre code utilisant l'annotation ne sera plus compilé! (car l'annotation est introuvable)
user253751
65
Dans les années à venir, un développeur nouvellement embauché se demandera: pourquoi l'heure du serveur de génération est-elle fixée à janvier 2016? Et le gars qui est là depuis 10 ans lui dira que c'est nécessaire ou que la construction casse à des endroits aléatoires. Soupir.
Wilbert

Réponses:

62

Je ne pense pas que ce soit une fonctionnalité utile quand elle interdit vraiment la compilation. Lorsque, au 01/06/2018, une grande partie du code ne compilera pas celle compilée la veille, votre équipe supprimera rapidement cette annotation, que le code soit nettoyé ou non.

Cependant, vous pouvez ajouter des annotations personnalisées au code telles que

@Deprecated_after_2018_07_31

et construisez un petit outil pour rechercher ces annotations. (Un simple support dans grep le fera si vous ne voulez pas utiliser la réflexion). Dans d'autres langages que Java, vous pouvez utiliser un commentaire standardisé adapté à "grepping" ou une définition de pré-processeur.

Exécutez ensuite cet outil peu de temps avant ou après la date donnée et, s'il trouve toujours cette annotation, rappelez à l'équipe de nettoyer ces parties de code de toute urgence.

Doc Brown
la source
9
@ Bergi: hé, ce n'est qu'un exemple, OP peut utiliser des versions ou des balises de date, quelle que soit leur préférence.
Doc Brown
4
Je ne vois aucun avantage à utiliser cela uniquement en utilisant les fonctions normales de dépréciation et en examinant la sortie du compilateur à la date spécifique. Cela semble être une mauvaise utilisation du temps des développeurs pour ré-implémenter quelque chose qui existe déjà à peu près. Même si vous avez déjà une tonne d’avertissements (qu’il vaudrait la peine de nettoyer), vous pouvez sûrement demander au compilateur de cracher tous les avertissements dans un fichier texte, puis de faire une recherche dans grep.
jpmc26
4
@jpaugh Je recommande de ne pas perdre d'heures (note, temps = argent) dans la création de nouveaux outils pour effectuer des tâches que vous pouvez déjà effectuer efficacement avec les outils existants, quels qu'ils soient.
jpmc26
3
@ jpmc26: Je vois deux (petits) avantages: ne pas recevoir des tonnes d'avertissements de dépréciation (ce qui introduirait un risque d'oubli des plus importants) et une possibilité d'introduire différents critères de dépréciation (dates, versions, peu importe) pour différentes sections de code. De plus, le PO a explicitement demandé à ce que la dépréciation soit associée à une date.
Doc Brown
7
Je voudrais +1 si vous utilisiez simplement l'ordre AAAA-MM-JJ pour la date indiquée dans votre exemple, car je n'ai jamais vu que l'ordre ambigu ?? - ?? - YYYY était source de douleur et de malentendus.
mtraceur
283

Cela constituerait une caractéristique connue sous le nom de bombe à retardement . NE CRÉEZ PAS DE BOMBES TEMPORELLES.

Le code, quelle que soit votre structure et votre documentation, deviendra une boîte noire quasi mythique mal comprise s'il survit au-delà d'un certain âge. La dernière chose dont tout le monde a besoin dans le futur est encore un autre mode de défaillance étrange qui les surprend complètement, au plus mauvais moment et sans solution évidente. Il n'y a absolument aucune excuse pour produire intentionnellement un tel problème.

Examinez la situation de la manière suivante: si vous êtes suffisamment organisé et que vous connaissez suffisamment votre base de code pour vous préoccuper de votre obsolescence, vous n'avez pas besoin d'un mécanisme dans le code pour vous le rappeler. Sinon, vous risquez également de ne pas être au courant des autres aspects de la base de code et de ne pas être en mesure de réagir correctement et correctement à l'alarme. En d'autres termes, les bombes à retardement ne servent à rien. Dis juste non!

Kilian Foth
la source
74
+1 Cela va te mordre. Des mois plus tard. Un vendredi, au moment où vous essayez de déployer d'urgence. Et comme le week-end est long, toutes les personnes qui en savent quelque chose sont absentes du bureau. Ne le fais pas.
Roger Lipscombe
3
Se mettre d'accord. L'obsolescence est un problème d'organisation, pas un problème de codage. Je pourrais toujours brancher une pomme] [et écrire en BASIC, rien ne m'arrête. Mais, ce que je veux aller?
19
La bonne solution, en suivant votre direction "organisé et averti", consiste à soulever un bogue dans votre système de suivi des bogues en disant "Supprimez <tels et tels>", avec un calendrier suggéré dans les commentaires. Et puis, dans 6 mois, lorsque la révision des bogues sera trouvée pour savoir quels bugs devraient être corrigés dans la prochaine version, si ce délai est imminent, vous dites "il est temps de le faire". C'est la gestion de projet de base.
Courses de légèreté avec Monica
1
En fait, si votre calendrier de publication est suffisamment prévisible, il suffit de le définir dès maintenant.
Courses de légèreté avec Monica
13
Reportez-vous au commentaire d' isanae pour une alternative: " Si vous souhaitez que les utilisateurs arrêtent d'utiliser des fonctionnalités obsolètes, publiez une version sans eux. Cela captera leur attention et ils pourront toujours revenir en arrière s'ils ne le peuvent pas encore. "
Stevoisiak
70

En C #, vous utiliseriez le ObsoleteAttributecomme suit:

  • Dans la version 1, vous envoyez la fonctionnalité. Une méthode, une classe, peu importe.
  • Dans la version 2, vous proposez une fonctionnalité améliorée destinée à remplacer la fonctionnalité d'origine. Vous mettez un attribut Obsolète sur la fonctionnalité, définissez-le sur "warning" et transmettez-lui un message disant "Cette fonctionnalité est obsolète. Utilisez plutôt la meilleure fonctionnalité. Dans la version 3 de cette bibliothèque, qui sera publiée sur telle ou telle une date, l'utilisation de cette fonctionnalité sera une erreur. " Désormais, les utilisateurs de la fonctionnalité peuvent toujours l'utiliser, mais ont le temps de mettre à jour leur code pour utiliser la nouvelle fonctionnalité.
  • Dans la version 3, vous mettez à jour l’attribut pour qu’il s’agisse d’une erreur plutôt que d’un avertissement et que le message "Cette fonctionnalité est obsolète. Utilisez plutôt la meilleure fonctionnalité. Dans la version 4 de cette bibliothèque, qui sera publiée sur telle ou telle une date, cette fonctionnalité va jeter. " Les utilisateurs qui n'ont pas tenu compte de votre avertissement précédent reçoivent tout de même un message utile leur indiquant comment résoudre le problème. Ils doivent le résoudre, car leur code n'est pas compilé.
  • Dans la version 4, vous modifiez la fonctionnalité afin qu'elle génère une exception irrécupérable, puis vous modifiez le message pour indiquer que la fonctionnalité sera entièrement supprimée dans la version suivante.
  • Dans la version 5, vous supprimez complètement la fonctionnalité et si les utilisateurs se plaignent, eh bien, vous leur avez donné trois cycles de publication d'avertissements corrects, et ils peuvent toujours continuer à utiliser la version 2 s'ils en ressentent le besoin.

L'idée ici est de faire un changement radical aussi indolore que possible pour les utilisateurs concernés et de s'assurer qu'ils peuvent continuer à utiliser la fonctionnalité pour au moins une version de la bibliothèque.

Eric Lippert
la source
2
Je pense que c'est la bonne approche, mais je changerais une chose ... ce serait échanger "si les utilisateurs se plaignent" en "quand les utilisateurs se plaignent"
Liath
10
Retirer le corps en même temps que passer à une erreur semble étrange. L'un des avantages de la version d'erreur de deprecated est qu'elle permet au code construit par rapport aux versions précédentes de continuer à fonctionner tout en empêchant le code nouvellement compilé de l'utiliser. Ainsi, vous restez compatible avec ABI tout en interrompant délibérément la compatibilité avec les API. Bien sûr, monde parfait, vous auriez un versioning de style semver, etc., de sorte que le nouveau code ne soit jamais exécuté avec une application précédemment compilée, mais de nombreux projets n'atteignent jamais cet idéal.
Kevin Cathcart
@ KevinCathcart: C'est un bon point; peut-être une autre étape est-elle garantie! Je mettrai à jour le texte.
Eric Lippert
1
En fait, si vous utilisez SemVer, vous pouvez passer directement d'une version obsolète de la version XY0 (toute version obsolète doit être une version mineure) à une suppression complète dans X + 1.0.0. Je dirais que c'est bien de tenir un peu plus loin (à X + 2.0.0?), Mais ce processus en cinq étapes est probablement en train de dorer le lys. La prochaine étape après "warning" devrait être "fatal error" (car la fonctionnalité déconseillée est remplacée par le code générant l'erreur). Puisque libfoo.so.2et libfoo.so.3peuvent parfaitement coexister les uns avec les autres, votre aval peut continuer à utiliser l'ancienne bibliothèque jusqu'à ce qu'ils soient basculés.
Monty Harder
@MontyHarder: Bien sûr. La séquence exacte des événements peut être déterminée par les besoins du développeur et de leur communauté d'utilisateurs. Le point le plus important est qu’il devrait exister une politique réfléchie pour traiter ce type de problème de contrôle de version, qui soit clairement communiquée aux parties prenantes.
Eric Lippert
24

Vous avez mal compris ce que signifie "déconseillé". Obsolète signifie:

être utilisable mais considérée comme obsolète et à éviter, en général parce qu’elle a été remplacée.

Dictionnaires Oxford

Par définition, une fonctionnalité obsolète sera toujours compilée.

Vous souhaitez supprimer la fonctionnalité à une date spécifique. C'est très bien. Comme vous le faites, vous le supprimez à cette date .

Jusque-là, marquez comme obsolète, obsolète ou quelle que soit l’appel de votre langage de programmation. Dans le message, incluez la date à laquelle il sera supprimé et la chose qui le remplace. Cela générera des avertissements indiquant que les autres développeurs doivent éviter les nouvelles utilisations et remplacer les anciennes utilisations dans la mesure du possible. Ces développeurs vont s'y conformer ou l'ignorer, et quelqu'un devra faire face aux conséquences de cette suppression. (Selon la situation, ce peut être vous ou les développeurs qui l'utilisent.)

jpmc26
la source
Intéressé par ce que le votant inférieur n'est pas d'accord.
jpmc26
2
+1 Si vous utilisez JIRA pour le développement agile, créez une tâche et placez-la dans un futur sprint. Adaptez-vous aux autres outils et méthodes de gestion de projet que vous suivez. Ceci est mieux résolu avec des méthodes non techniques.
Matthew lu
1
Et assurez-vous également que la classe / la bibliothèque reste dans la documentation telle qu’amortie et / ou supprimée dans la version Xx
Phil M
12

N'oubliez pas que vous devez conserver la possibilité de créer et de déboguer des versions antérieures du code afin de prendre en charge les versions du logiciel déjà publiées. Saboter une construction après une certaine date signifie que vous risquez également de vous empêcher d'effectuer des travaux de maintenance et de support légitimes à l'avenir.

En outre, il semble être une solution de contournement triviale de remettre l’horloge de ma machine un an ou deux avant la compilation.

Rappelez-vous, "obsolète" est un avertissement que quelque chose va disparaître dans le futur. Lorsque vous souhaitez empêcher de manière forcée les personnes d'utiliser cette API, supprimez simplement le code associé . Il ne sert à rien de laisser du code dans la base de code si un mécanisme le rend inutilisable. La suppression du code vous donne les vérifications à la compilation que vous recherchez, sans solution de rechange simple.

Edit: Je vois que vous faites référence à "l'ancien code inutilisé" dans votre question. Si le code est vraiment inutilisé , il est inutile de le déconseiller. Supprimez-le simplement.

bta
la source
La meilleure réponse, de loin, peut-être souligner que la suppression du code est le meilleur moyen de résoudre le problème plus tôt dans votre réponse. Il peut être facile de faire défiler les réponses textuelles au-delà du mur
Clint
6

Je n'avais jamais vu une telle caractéristique auparavant - une annotation qui prend effet après une date donnée.

Le @Deprecatedpeut être suffisant, cependant. Attrapez les avertissements dans CI et faites-le refuser d'accepter la construction s'il en existe. Cela déplace la responsabilité du compilateur vers votre pipeline de construction, mais présente l'avantage de pouvoir modifier (semi) facilement le pipeline de construction en ajoutant des étapes supplémentaires.

Notez que cette réponse ne résout pas complètement votre problème (par exemple, les constructions locales sur les machines des développeurs continueraient à fonctionner, bien qu'avec des avertissements) et suppose que vous avez un pipeline CI configuré et en cours d'exécution.

Mael
la source
4

Vous recherchez des calendriers ou des listes de tâches .

Une autre alternative consiste à utiliser des avertissements personnalisés du compilateur ou des messages du compilateur, si vous réussissez à avoir très peu d’avertissements dans votre code. Si vous avez trop d'avertissements, vous devrez déployer des efforts supplémentaires (environ 15 minutes?) Et prendre l'avertissement du compilateur dans le rapport de construction fourni par votre intégration continue pour chaque construction.

Les rappels que le code doit être corrigé sont bons et nécessaires. Parfois, ces rappels ont des échéances strictes dans le monde réel. Il peut donc être nécessaire de les programmer.

L’objectif est de rappeler continuellement aux gens que le problème existe et qu’il doit être corrigé avec un laps de temps donné - une fonctionnalité qui rompt simplement la construction à un moment donné non seulement ne le fait pas, mais est également un problème qui doit être résolu. être fixé avec un laps de temps donné.

Peter
la source
1
Se mettre d'accord. Mais si un problème existe et doit être résolu dans un délai donné, il doit devenir la priorité absolue de quelqu'un au bon moment. Je me souviens que lors d'une réunion, mon responsable m'avait donné une "priorité absolue", puis avait ensuite déclaré: " Ceci est votre priorité numéro un" (quelque chose de différent). Mon superviseur a dit: "Il ne peut pas avoir deux priorités numéro un!" Le gestionnaire a été surpris. Je suppose qu'il pensait que ... je pourrais. Planifier quelque chose à réparer "au bon moment", c'est manquer de temps.
3

Une façon de penser à cela est ce que vous entendez par heure / date ? Les ordinateurs ne savent pas ce que sont ces concepts: ils doivent être programmés d'une manière ou d'une autre. Il est assez courant de représenter des durées au format UNIX "secondes depuis l'époque" et d'introduire une valeur particulière dans un programme via des appels de système d'exploitation. Cependant, quelle que soit la fréquence de cet usage, il est important de garder à l'esprit que ce n'est pas le moment "réel": c'est simplement une représentation logique.

Comme d'autres l'ont fait remarquer, si vous définissiez une "échéance" à l'aide de ce mécanisme, il est trivial d'alimenter une heure différente et de dépasser cette "échéance". Il en va de même pour les mécanismes plus élaborés tels que la demande à un serveur NTP (même sur une connexion "sécurisée", puisque nous pouvons substituer nos propres certificats, autorités de certification ou même appliquer des correctifs aux bibliothèques de chiffrement). Au début, il peut sembler que ces personnes sont responsables du travail effectué autour de votre mécanisme, mais il se peut que cela se fasse automatiquement et pour de bonnes raisons . Par exemple, il est judicieux de disposer de versions reproductibles et des outils d'aide à cette fin pourraient réinitialiser / intercepter automatiquement ces appels système non déterministes. libfaketime fait exactement cela,définit l'horodatage de tous les fichiers sur 1970-01-01 00:00:01, la fonction d' enregistrement / lecture de Qemu simule toute interaction matérielle, etc.

Ceci est similaire à la loi de Goodhart : si le comportement d'un programme dépend du temps logique, le temps logique cesse alors d'être une bonne mesure du temps "réel". En d'autres termes, les gens ne vont généralement pas jouer avec l'horloge système, mais ils le feront si vous leur en donnez la raison.

Il existe d'autres représentations logiques du temps: l'une d'entre elles est la version du logiciel (soit votre application, soit une dépendance). C’est une représentation plus souhaitable pour une "échéance" que, par exemple, l’heure UNIX, car elle est plus spécifique à ce qui vous intéresse (modification des ensembles de fonctionnalités / API) et est donc moins susceptible de piétiner des préoccupations orthogonales contourner votre échéance pourrait casser des fichiers journaux, des tâches cron, des caches, etc.).

Comme d’autres l’ont dit, si vous contrôlez la bibliothèque et souhaitez "pousser" cette modification, vous pouvez proposer une nouvelle version qui déprécie les fonctionnalités caractéristiques entièrement. Vous pouvez les publier immédiatement les uns après les autres si vous le souhaitez, car (encore) les versions ne sont que des représentations logiques du temps, elles n'ont pas besoin d'être liées au temps "réel". La gestion sémantique peut aider ici.

Le modèle alternatif consiste à "tirer" le changement. Cela ressemble à votre "plan B": ajoutez un test à l'application consommatrice, qui vérifie que la version de cette dépendance est au moins la nouvelle valeur. Comme d'habitude, red / green / refactor pour propager ce changement dans la base de code. Cela peut être plus approprié si la fonctionnalité n'est pas "mauvaise" ou "mauvaise", mais simplement "un mauvais ajustement pour ce cas d'utilisation".

Une question importante avec l'approche "pull" est de savoir si la version de dépendance compte ou non comme une "unité" ( de fonctionnalité ) et mérite donc d'être testée; ou s'il s'agit simplement d'un détail d'implémentation "privé", qui ne doit être exercé que dans le cadre de tests unitaires ( de fonctionnalité ) réels . Je dirais: si la distinction entre les versions de la dépendance compte vraiment comme une fonctionnalité de votre application, faites le test (par exemple, en vérifiant que la version Python est> = 3.x). Si non, alors ne le faites pasajouter le test (car il sera fragile, peu informatif et trop restrictif); si vous contrôlez la bibliothèque, descendez ensuite la route "push". Si vous ne contrôlez pas la bibliothèque, utilisez simplement la version fournie: si vos tests réussissent, inutile de vous limiter; S'ils ne passent pas, c'est votre "date limite"!

Il existe une autre approche, si vous souhaitez décourager certaines utilisations des fonctionnalités d'une dépendance (par exemple, appeler certaines fonctions qui ne fonctionnent pas bien avec le reste de votre code), en particulier si vous ne contrôlez pas la dépendance: interdisez vos normes de codage. / décourage l'utilisation de ces fonctionnalités et ajoute des contrôles à votre linter.

Chacun de ceux-ci sera applicable dans des circonstances différentes.

Warbo
la source
1

Vous gérez cela au niveau du paquet ou de la bibliothèque. Vous contrôlez un package et sa visibilité. Vous êtes libre de retirer la visibilité. J'ai vu cela en interne dans de grandes entreprises et cela n'a de sens que dans des cultures qui respectent la propriété des packages, même si ces derniers sont open source ou gratuits.

Cela est toujours gênant parce que les équipes de clients ne veulent tout simplement rien changer. Vous avez donc souvent besoin de listes blanches, car vous travaillez avec des clients spécifiques pour convenir d'un délai de migration, leur offrant éventuellement une assistance.

Djechlin
la source
J'aime la partie support. Tous les changements se font de manière plus douce, plus agréable et probablement avec moins de difficultés si les personnes qui les promeuvent offrent leur soutien. C'est en partie un effet psychologique: un bon soutien est coopératif; il prend tout impliqué sérieux. En revanche, les changements imposés d'en haut, sans impliquer les personnes concernées, leur donnent le sentiment d'être ignorés et peu coopératifs. (Bien que la convivialité doive être associée à une volonté implacable de faire passer les changements.)
Peter - Reinstate Monica
1

Une exigence est d'introduire une notion de temps dans la construction. En C, C ++ ou d' autres langages / construire des systèmes qui utilisent un type C préprocesseur 1 , on pourrait introduire un horodatage par définit pour le préprocesseur à moment de la construction: CPPFLAGS=-DTIMESTAMP()=$(date '+%s'). Cela se produirait probablement dans un fichier makefile.

Dans le code, on pourrait comparer ce jeton et provoquer une erreur si le temps est écoulé. Notez que l'utilisation d'une macro de fonction intercepte le cas que quelqu'un n'a pas défini TIMESTAMP.

#if TIMESTAMP() == 0 || TIMESTAMP() > 1520616626
#   error "The time for this feature has run out, sorry"
#endif

Alternativement, on pourrait simplement "définir" le code en question lorsque le moment sera venu. Cela permettrait au programme de compiler, à condition que personne ne l'utilise. Dites, nous avons un en-tête définissant une api, "api.h", et nous ne permettons pas d'appeler old()après un certain temps:

//...
void new1();
void new2();
#if TIMESTAMP() < 1520616626
   void old();
#endif
//...

Une construction similaire éliminerait probablement old()le corps de la fonction d'un fichier source.

Bien sûr, cela n’est pas infaillible; on peut simplement définir une ancienne TIMESTAMPen cas de construction d'urgence du vendredi soir mentionnée ailleurs. Mais c’est, je pense, plutôt avantageux.

Cela ne fonctionne évidemment que lorsque la bibliothèque est recompilée - après quoi le code obsolète n’existe tout simplement plus dans la bibliothèque. Cela n'empêcherait cependant pas le code client de créer un lien vers des fichiers binaires obsolètes.


1 C # ne prend en charge que la simple définition des symboles du préprocesseur, sans valeur numérique, ce qui rend cette stratégie non viable.

Peter - Réintégrer Monica
la source
Il est également intéressant de noter que cette définition de préprocesseur obligera tout le code utilisé TIMESTAMPà être recompilé à chaque génération. Il va également neutraliser des outils comme ccache. Cela signifie que le temps de compilation typique pour les générations incrémentielles augmentera considérablement en fonction de la quantité de base de code affectée par les fonctionnalités obsolètes de cette manière.
mindriot
@ mindriot C'est un aspect intéressant. Je suppose que cela est vrai pour toutes les méthodes introduisant une notion de temps dans le code - le PO dit explicitement "après une date donnée". On pourrait toutefois gérer l'aspect temporel dans le système de construction et laisser le code seul, c'est vrai. Mais le PO a explicitement demandé "quelque chose dans le code". Ma solution présente l'avantage d'être indépendante de toute méthode de construction particulière. Il peut être trompé, mais vous devez y répondre d’une manière ou d’une autre.
Peter - Réintégrer Monica
Vous avez absolument raison. Votre solution est essentiellement ici la seule qui fournit une solution pratique à l'OP réelle question. Néanmoins, j’ai jugé important de souligner les inconvénients. Ce sera au PO de peser le pour et le contre. Je pense qu'un juste milieu pourrait même être obtenu, par exemple, en divisant la TIMESTAMPvaleur par 86400, par exemple, pour obtenir une granularité quotidienne et par conséquent moins de recompilations.
mindriot
0

Dans Visual Studio, vous pouvez configurer un script de pré-génération qui génère une erreur après une certaine date. Cela empêchera la compilation. Voici un script qui génère une erreur à partir du 12 mars 2018 ( pris ici ):

@ECHO OFF

SET CutOffDate=2018-03-12

REM These indexes assume %DATE% is in format:
REM   Abr MM/DD/YYYY - ex. Sun 01/25/2015
SET TodayYear=%DATE:~10,4%
SET TodayMonth=%DATE:~4,2%
SET TodayDay=%DATE:~7,2%

REM Construct today's date to be in the same format as the CutOffDate.
REM Since the format is a comparable string, it will evaluate date orders.
IF %TodayYear%-%TodayMonth%-%TodayDay% GTR %CutOffDate% (
    ECHO Today is after the cut-off date.
    REM throw an error to prevent compilation
    EXIT /B 2
) ELSE (
    ECHO Today is on or before the cut-off date.
)

Assurez-vous de lire les autres réponses sur cette page avant d'utiliser ce script.

utilisateur2023861
la source
-1

Je comprends l'objectif de ce que vous essayez de faire. Mais comme d'autres l'ont mentionné, le système de compilation / compilateur n'est probablement pas le bon endroit pour appliquer cela. Je suggérerais que la couche la plus naturelle pour appliquer cette stratégie soit les variables SCM ou d'environnement.

Si vous effectuez cette dernière opération, ajoutez en gros un indicateur de fonctionnalité qui marque une exécution antérieure à la dépréciation. Vérifiez chaque fois que vous construisez la classe obsolète ou appelez une méthode déconseillée. Définissez simplement une fonction statique unique assertPreDeprecated()et ajoutez-la à chaque chemin de code obsolète. Si cette option est définie, ignorez les appels d’assertion. Si ce n'est pas jeter une exception. Une fois la date passée, désactivez l'indicateur de fonctionnalité dans l'environnement d'exécution. Tous les appels obsolètes en attente au code seront affichés dans les journaux d'exécution.

Pour une solution basée sur SCM, je suppose que vous utilisez git et git-flow. (Si ce n'est pas le cas, la logique est facilement adaptable à d'autres VCS). Créer une nouvelle branche postDeprecated. Dans cette branche, supprimez tout le code obsolète et commencez à supprimer toutes les références jusqu'à la compilation. Toutes les modifications normales continuent à apporter à la masterbranche. Gardez en fusionnant les modifications correspondantes du code non dépréciées à masternouveau dans postDeprecatedde minimiser les problèmes d'intégration.

Une fois la date d'exprécision terminée, créez une nouvelle preDeprecatedbranche à partir de master. Puis fusionnez postDeprecateddans master. En supposant que votre version soit sortie de la masterbranche, vous devriez maintenant utiliser la branche post-déconseillée après la date. En cas d'urgence ou si vous ne pouvez pas fournir les résultats à temps, vous pouvez toujours revenir en arrière preDeprecatedet apporter les modifications nécessaires sur cette branche.

utilisateur79126
la source
7
Cette approche ressemble à un cauchemar logistique. Si vous commencez à maintenir des branches parallèles presque en double, vous perdrez tout votre temps à le faire. Total des déchets.
Courses de légèreté avec Monica
6
Je ne peux pas accepter que le maintien de branches parallèles, l'utilisation d'une seule pour supprimer des fonctions obsolètes de nombreuses versions avant que vous souhaitiez réellement les supprimer du produit, est en aucune manière "la norme de l'industrie". Quel est le but de cela? Oui, un VCS peut automatiquement effectuer certaines fusions, mais une fusion doit être effectuée avec l'œil du développeur afin de résoudre les conflits logiques (et que se passe-t-il lorsqu'un conflit ne peut même pas être résolu de manière lexique?). Avoir un système de compilation qui se fusionne chaque jour de façon arbitraire est simplement… inutile. Supprimez la fonctionnalité lorsqu'il est temps de la supprimer.
Courses de légèreté avec Monica
3
Parce qu'il y a une bonne raison de maintenir les branches de publication (porter en arrière les correctifs importants). Il n'y a aucune bonne raison de maintenir une branche "quelque chose que je pourrais faire dans le futur". C'est des frais généraux, sans bénéfice. Aussi simple que cela.
Courses de légèreté avec Monica
4
Où l'ai-je eu? C'est littéralement la définition de la dépréciation. Vous déconseillez quelque chose que vous pourriez supprimer à l'avenir. Ainsi, il n'y a pas de malhonnêteté, pas de déplacement des poteaux de but, et certainement pas d'inventer des choses juste "pour gagner l'argument". Ce n'est pas "un cas d'utilisation classique de la branche SCM" dans les organisations pour lesquelles je souhaite travailler! Je suppose que nous devrons accepter d'être en désaccord. Bonne soirée!
Courses de légèreté avec Monica
2
@ lightness - Il existe de nombreuses raisons pour lesquelles la dépréciation officielle du code n'est pas simplement une "chose que nous pourrions faire chaque fois que nous y arrivons". Peut-être que le code obsolète utilise une bibliothèque où le support officiel est supprimé. Peut-être que le code obsolète est IP dont la licence expire après une date fixe. Peut-être qu'après la date donnée, il y a de nouveaux règlements, et le code n'est pas conforme. Votre solution est satisfaisante si vous vivez dans une tour d’ivoire. Mais les organisations du monde réel traitent tout le temps de ce type de situation. Les logiciels doivent répondre aux besoins de l'entreprise et non l'inverse.
user79126