Comment marquer une classe comme en cours de développement en Java

12

Je travaille sur un projet de stage, mais je dois partir avant de pouvoir tout finir.

J'ai 1 classe qui n'est pas assez stable pour une utilisation en production. Je veux marquer / marquer cette classe afin que d'autres personnes ne l'utilisent pas accidentellement en production. J'ai déjà mis l'avis dans Javadoc, mais cela ne semble pas suffisant. Une erreur ou un avertissement du compilateur serait préférable.

Le code est organisé comme ceci:

[Package] | company.foo.bar.myproject
          |-- Class1.java
          |-- Class2.java
          |-- Class3.java <--(not stable)

S'il y avait une seule classe d'usine qui appelle ces classes dans les méthodes publiques, j'aurais pu définir la méthode sur class3as private. Cependant, l'API n'est PAS exposée de cette façon. Les utilisateurs utiliseront directement ces classes, par exemple new Class1();, mais je ne peux pas rendre privée une classe de niveau supérieur. Quelle est la meilleure pratique pour faire face à cette situation?

Wei Shi
la source
1
Que voulez-vous dire par "L'API n'est pas exposée par des méthodes?" Cette classe est-elle destinée à être utilisée via l'API Reflection?
Tom G
5
Une erreur de compilation? Pourquoi ne pas simplement lancer une exception dans le constructeur?
Mchl
Désolé pour la confusion. J'ai modifié mon message.
Wei Shi
1
Vous ne pouvez pas rendre la classe privée, mais vous pouvez rendre son constructeur privé.
Peter Taylor

Réponses:

15

Pourquoi ne pas simplement archiver toutes les classes instables dans une branche différente de votre système de contrôle de version?

Andrew Moss
la source
2
Il me semble que cela «cacherait» le code. Que faire si le code fait presque ce que d'autres ont besoin de le faire avec quelques ajustements mineurs. Si vous le mettez dans une branche, ils ne le verront peut-être jamais et réimplémenteront simplement le tout.
c_maker
3
@c_maker: Faire savoir aux autres que la branche existe et ce qu'elle contient devrait faire partie de ce qui se transmet à son départ.
Blrfl
2
@Birlf S'il craint que d'autres ne voient pas l'explication dans le JavaDoc du code qu'ils utilisent, je doute qu'ils iront à la recherche des autres documents qu'il produit.
KeithB
Ma préoccupation est que la fonctionnalité évolue toujours, mais le Scrum Master a choisi de la mettre de côté pour une raison quelconque (moratoire qui bloque les tests E2E, dans notre cas). Si nous ne le rejoignons pas pour maîtriser, il peut y avoir beaucoup de travail de fusion sur la route. Nous venons de rendre le c`tor privé et d'annoter la classe @Experimental, comme dans Spark
Joey Baruch
11

Si vous avez correctement commenté la classe, vous pouvez marquer les bits de fonctionnalité incomplète comme "obsolètes" et / ou commenter les tripes de la méthode et mettre a throw new UnsupportedOperationException();.

Voir Existe - t-il quelque chose comme NotImplementedException de .NET en Java? pour plus de détails.

Heath Lilley
la source
2
C'est la manière de facto de traiter l'esprit frappé comme je comprends les choses
Martijn Verburg
4

Je ne connais pas un tel avertissement du compilateur.

Dans votre situation, j'utiliserais probablement l' @Deprecatedannotation. Il barrera les appels de méthode, il sera donc évident pour les autres que quelque chose se passe. Quand ils regardent ce qui se passe, ils verront vos commentaires sur «pas prêt pour la production» et passeront à AHA.

c_maker
la source
2
les appels de méthode ne sont barrés que si l'EDI le prend en charge.
FrustratedWithFormsDesigner
5
Certes, mais la plupart des gens utiliseront probablement l'un de ces IDE qui le prend en charge.
c_maker
3

Je ne pense pas qu'il y ait un moyen standard de code de marquage WIP, Incompleteou quelque chose comme ça.

Vous pouvez créer une nouvelle exception nommée ClassUnstableException, puis la déclencher dans le Class3constructeur avec un message qui explique comment ils ne devraient pas l'utiliser. C'est mauvais, car cela ne les avertit qu'au moment de l'exécution.

Vous pouvez également essayer de rendre la classe incompilable d'une certaine manière, puis ajouter une note à la section de code qui déclenche le compilateur afin que si quelqu'un va corriger le code, il verra, espérons -le, une explication de la raison pour laquelle il ne devrait pas utiliser cette classe. . Cela peut ne pas fonctionner s'ils utilisent un outil semi-automatisé "résoudre ce problème" que certains IDE possèdent. C'est également mauvais car cela pourrait casser les versions.

Vous pouvez créer une annotation nommée WIP(car la plus proche à laquelle je peux penser est Deprecatedmais cela ne signifie pas vraiment la même chose) et l'utiliser pour annoter la classe. Ce serait probablement un peu plus de travail, et qu'est-ce qui soutiendrait l'annotation?

Enfin, vous pouvez simplement le mettre dans les commentaires, mais cela ne fonctionnera que si les gens les lisent réellement .

ÉDITER:

Cela peut être pertinent: comment provoquer intentionnellement un message d'avertissement du compilateur Java personnalisé?

FrustratedWithFormsDesigner
la source
l'exception d'exception fait que l'éclipse se plaint du code inaccessible. Une solution?
Wei Shi
@Usavich: Je ne sais pas car je n'ai pas vu le code, mais peut-être que cela pourrait également empêcher les futurs développeurs d' utiliser le code?
FrustratedWithFormsDesigner
@Usavich: Jetez un œil au lien que j'ai ajouté dans l'EDIT dans mon article, c'est une question similaire où l'OP voulait ajouter un avertissement de compilateur personnalisé. Pourrait vous aider à ajouter une annotation "UnstableCode" personnalisée.
FrustratedWithFormsDesigner
3

Pourquoi est-il là en premier lieu?

Vous avez archivé du code instable dans la ligne principale? Pourquoi?

Le code instable ne doit pas être archivé dans trunk / main / master ou quel que soit le nom du tronc principal. Ceci est considéré comme un développement à haut risque et aurait plutôt dû être séquestré dans sa propre branche sur laquelle vous avez travaillé plutôt que consigné dans le principal.

Je vous encourage fortement (et votre chef d'équipe) à lire les stratégies avancées de branchement SCM . En particulier, faites attention au rôle de développement et à ce qu'il dit sur ce qui est considéré comme un développement à haut risque:

En général, envisagez d'utiliser des succursales distinctes pour chaque projet à haut risque. Les projets à haut risque se caractérisent par une grande taille, un grand nombre de personnes, un sujet inconnu, un sujet hautement technique, des délais très serrés, des dates de livraison incertaines, des exigences incomplètes ou volatiles et des équipes de projet réparties géographiquement. De même, envisagez de désigner une seule branche pour le développement à faible risque dans chaque version. Plusieurs sources, dont [WING98], recommandent d'utiliser la ligne principale à cet effet. Tenez compte des facteurs discutés ci-dessus pour la ligne principale avant de vous engager dans cette ligne de conduite. Le développement à faible risque peut avoir une politique différente de la ligne principale même si vous avez plusieurs membres d'une famille de produits coordonnés via la ligne principale.

Laisser les gens archiver du code instable (ou inutilisé) dans la ligne principale signifie que vous confondrez les efforts de développement futurs pour essayer de maintenir ce code. Chaque branche et clone du représentant jusqu'à la fin des temps contiendra ceci jusqu'à ce que quelqu'un dise "son code mort" et le supprime.

Il y en a qui disent "eh bien, si c'est dans une branche, il est oublié" et bien que cela puisse être vrai, avoir oublié du code mort (et instable) dans la ligne principale est plusieurs fois pire car il confond tout développement futur jusqu'à ce qu'il soit supprimé - et alors c'est encore plus oublié. Une branche bien nommée de "/ fooProject / branches / WeisBigIdea" (ou équivalent) est visible et plus facile à utiliser à l'avenir - surtout si cela fonctionne.

@Deprecated

La première chose est l' @Deprecatedannotation. Cela va au-delà du javadoc et crache des avertissements du compilateur. javacfournit un -deprecationindicateur qui est décrit comme:

Afficher une description de chaque utilisation ou remplacement d'un membre ou d'une classe obsolète. Sans -deprecation, javacaffiche un résumé des fichiers source qui utilisent ou remplacent les membres ou les classes obsolètes. -deprecation est un raccourci pour -Xlint:deprecation.

Comme indiqué, cela va au-delà des avertissements du compilateur standard.

Dans de nombreux IDE, les méthodes et valeurs obsolètes sont affichées avec un barré:

foo.bar();

Et produirait une sortie comme:

$ javac -Xlint:all Foo.java Bar.java
Bar.java:2: warning: [deprecation] Foo in unnamed package has been deprecated
interface Bar extends Foo { }
                      ^

Selon la structure de votre build, des avertissements peuvent interrompre la build. Cela ne casserait la construction que si l'une de vos classes était utilisée (pas si elle est simplement simplement compilée).

@CustomAnnotation

Il existe de nombreuses approches à ce sujet. Par exemple, l' annotation Lightweight javac @Warning qui fournit un processeur d'annotations qui déclenche un avertissement au moment de la compilation lorsque quelque chose avec cette annotation est utilisée ( un tutoriel netbeans sur les processeurs d'annotations personnalisés afin que vous puissiez avoir une idée de ce qui se passe derrière le scènes).

Oracle décrit même un exemple d'utilisation d'annotations personnalisées pour une @Unfinishedannotation dans Tirer le meilleur parti des métadonnées Java, Partie 2: Annotations personnalisées .

Avec AnnotationProcessor , vous pouvez exécuter du code arbitraire au moment de la compilation. C'est vraiment à vous de décider ce que vous voulez qu'il fasse. Avertissez, cassez la version lorsque quelque chose est utilisé. Il existe de nombreux didacticiels sur le Web pour savoir comment écrire ce type de code. Que vous souhaitiez générer une erreur lors de sa compilation (ce sera ennuyeux et entraîner sa suppression) ou s'il est utilisé (un peu plus complexe à écrire).

Notez que tout cela implique de changer les builds pour utiliser réellement le processeur d'annotation.


la source
2

Vous pouvez introduire le traitement des annotations de compilation, mais cela obligerait tous les membres de l'équipe à ajuster leur processus de compilation.

Cependant, je trouve l'ensemble du processus un peu déroutant. Une API instable doit être clairement séparée en créant une branche dans votre système de contrôle de version. S'il doit vraiment se trouver dans le reste de la base de code, s'il a été documenté comme instable et néanmoins utilisé, le problème n'est pas vraiment technique mais réside dans l'organisation et la communication. Oui, vous pouvez introduire des vérifications techniques (comme le traitement des annotations) mais cela ne résoudra pas le problème - déplacez-le simplement à un autre niveau.

Donc, ma recommandation est la suivante: si vous ne pouvez pas séparer la base de code en la mettant dans différentes branches, parlez aux gens et expliquez-leur pourquoi ils ne doivent pas utiliser l'API.

perdian
la source
0

Pourriez-vous déplacer toutes les classes incomplètes dans un sous-package nommé quelque chose d'évident comme "NOTCOMPLETE"? C'est un peu un hack mais peut-être assez visible.

(S'ils ne sont pas tous dans le même package, vous pouvez recréer la structure du package en dessous.)

Alex Feinman
la source
0

Je ne sais pas qu'il existe vraiment un bon moyen de le faire dans le code. Prendre du recul:

Créez deux copies de l'ensemble du projet, une avec la classe et une sans. Marquez la version sans la classe comme une base de code stable, prête pour la version de production, et la version avec la classe comme développement pour une future version. Documentez ce qui doit se produire avant que cette classe puisse être considérée comme une qualité de production.

Idéalement, vous devriez le faire en utilisant des branches dans la solution de contrôle de source de votre choix. Vous devrez peut-être un peu tricher, car il semble que vous n'ayez pas utilisé une telle stratégie de ramification. Supprimez soigneusement la nouvelle classe, archivez une version sans celle-ci et effectuez des tests de régression. Lorsque vous êtes satisfait qu'elle est stable, vous pouvez baliser cette révision, créer une branche de développement à partir de la balise, puis rajouter la classe dans la branche de développement.

Adam Jaskiewicz
la source
0

J'opterais pour faire le résumé de la classe et commenter de manière appropriée - de cette façon, le code est toujours là pour référence, mais bonne chance à tous ceux qui essaient de l'instancier :)

Phil Lello
la source
-1

Qu'en est-il de créer une dépendance que le compilateur ne peut pas résoudre? Ajoutez simplement:

importer ceci.n'est.pas.done.yet.do.not.use.it;

jusqu'au sommet. Les utilisateurs ne pourront pas compiler avec.

Si vous voulez tester la classe, créez simplement un package / classe avec ce nom (ou utilisez un plus simple comme "experimental.danger") et vous pouvez tester le nouveau code.

Neal Tibrewala
la source
1
La compilation échouera même si je ne l'utilise pas ... mauvaise idée ...
Silviu Burcea