6
votes

Se débarrasser des directives précompiler en C #

On m'a demandé de maintenir un code non-as-héritage-i-i-ressembler à un code, et il est criblé de directives du compilateur, ce qui le rendait presque illisible et presque aussi maintenu. Cas au point: xxx pré>

en utilisant les directives code> est même plus jolie: p> xxx pré>

Je pensais donner le conditionnellement conditionnelattribute code> A Go mais Cela ne fonctionnera pas tout à fait dans cette situation p>

Y a-t-il une façon de passer à la sortie de ce cauchemar de la directive compilateur? p>

Le code est compilé contre .NET 3.5 code>. p>

mise à jour: strong>

Oded a répondu suggérant de supprimer les directives du compilateur autour de la méthode code> Beforeadd (code> surcharge ainsi. Malheureusement, cela ne fonctionnera pas car les deux méthodes sont censées remplacer une classe code> abstractbusiness code> qui fournit deux implémentations différentes en fonction desquelles les assemblages finissent par être inclus: P>

protected virtual void BeforeAdd(AbstractBusinessEntity entity) {}


6 commentaires

Je parie quiconque a écrit qui pensait qu'ils étaient extrêmement intelligents ...


Si c'était en vie, je vous dirais de le retirer et de le tirer dessus avant que la maladie ne tue plus d'autre qu'elle touche.


Pourquoi avez-vous les deux méthodes différentes? Dans quels scénarios sont-ils utilisés?


@Lasse - Ils sont dans deux versions différentes d'un ensemble de bibliothèques développées à la Société. Ils sont donc utilisés selon la version des bibliothèques que l'application appelante est compilée. Supprimer soit de casser plusieurs applications fonctionnant ailleurs dans la société.


Vous êtes sûr que vous ne pouviez pas utiliser de ramification dans un DVC ou similaire pour gérer cela? c'est à dire. Créez une branche pour le commun, un pour le type 1 et l'un pour le type 2, ajoutez du code à commun et fusionner dans les deux branches lorsqu'il est courant et se développe dans l'un ou l'autre quand ce n'est pas le cas?


@Lasse - Nice! Savez-vous quelle est la situation maintenant? L'ensemble de bibliothèques a différentes branches, mais c'est l'origine de mon cauchemar (et éventuellement de mon acide estomac), ils ont choisi de ne pas brancher les applications qui utilisent les bibliothèques mais créent simplement une solution différente vs Fichier à la place! On dirait qu'il est temps de déléguer;)


4 Réponses :


7
votes

Dans le premier cas, il semble que vous puissiez simplement avoir plusieurs surcharges de la méthode au lieu de cette construction. La résolution de la surcharge devrait prendre soin des choses à ce stade.

Dans le second cas (à l'aide de directives) - Vous pouvez alias certaines des directives et les inclure tous, en utilisant l'alias si nécessaire. Que se passe-t-il lorsque tous les espaces de noms sont inclus? Toutes les collisions de noms?


7 commentaires

@ODED - Merci pour les conseils. Malheureusement, oui, beaucoup d'espace de noms et de collisions de noms de classe.


@Sergi - donc, des noms de classe identiques définis dans différents espaces de noms?


Pire encore: voir que les deux méthodes sont remplacées? Cela rend impossible d'utiliser des surcharges, car la méthode Takin A logentity n'a pas de remplacement valide si conditon_1 n'est pas satisfait


@Oded - Dans plusieurs cas Oui.


@Sergi - Tout ce que je peux suggérer, c'est de commencer à nettoyer ce que vous pouvez. Vous devriez être capable de supprimer lentement les directives de pré-processeur et que les choses devraient être plus faciles à suivre. Renommez des fonctions si nécessaire, créez des surcharges d'emballage ... tout ce qui est vraiment.


Si cela utilise des surcharges telles que celle-ci, la classe de base peut peut-être prendre un paramètre générique que dans les sous-classes peut être explicitement définie sur la logentitilité / abstractbusinessentité:


@ODED - Je souhaite que cela "simple". Ce code obtient ses dépendances d'un ensemble de bibliothèques de société créé un peu de temps dans le passé et ont "la mise à niveau" depuis. Ils ont maintenant 4 versions différentes de cet ensemble de bibliothèques avec des espaces de noms collants et des implémentations différentes. Tous au nom de la "compatibilité à l'envers" avec des applications utilisant les versions (très) anciennes. En arrière, certainement. Compatibilité? Pas assez.



1
votes

Sur la base de ce que je vois, il semble que le développeur original n'avait aucun sentiment d'héritage et de polymorphisme. Il est un peu difficile de dire du code, mais il semble que la logentitilité et l'abstractbusinité partagent des propriétés communes. Existe-t-il un modèle d'héritage ou sont-ils deux classes totalement non liées? S'ils ne sont pas liés, pourriez-vous créer un modèle d'héritage ou une interface qu'ils peuvent à la fois mettre en œuvre? Cela pourrait aider si vous avez collé les classes.

Longue histoire courte, je ne perdrais pas mon temps à essayer de travailler avec ce code dans sa forme actuelle. Je trouverais un moyen d'éliminer les directives du compilateur, à tout prix. Cela ne semble pas être complètement désagréable, mais cela pourrait prendre des efforts.


0 commentaires

0
votes

Je ne sais pas si c'est pratique, mais ce que je ferais serait de créer des succursales dans mes DVC, Mercurial, de gérer cela.

J'aurais 2 branches en jeu et un 3ème temporairement pendant que je Correction des bugs / Ajouter un code commun.

Voici comment je créerais les versions initiales: xxx

pour fixer des bugs dans une seule d'entre elles: < / p> xxx

pour corriger les bugs qui sont communs: xxx

note : cela suppose que vous êtes Ne pas faire de refactoriser les mains lourdes dans des branches de type ou communes, si vous faites cela, vous êtes probablement mieux à votre disposition avec votre situation actuelle, au moins comparée à une manière ramifiée comme celle-ci. Tout refactoring de ce type ferait de futurer des fonts vraiment douloureux.


5 commentaires

3 mots: serveur de fondation de l'équipe. ;)


Pour être honnête, je n'aime pas particulièrement tfs. Il est régulièrement confus à propos de ses propres fonte. C'est à dire. Demandez-lui quels changements dans la branche X ne sont pas dans la branche Y, et il énumère beaucoup. Ensuite, vous fusionnez quelques-uns de ceux-ci dans la branche Y. Ensuite, vous le demandez l'inverse, et cela listera heureusement la modification de la fusion que vous venez de vous engager comme non présente dans X. Je prendrai du mercuriat n'importe quel jour de la semaine. tant que j'ai un choix :)


Garçon, je suis d'accord. Je dis simplement que ce n'est pas une option dans ce cas. La société utilise TFS et c'est la fin de celui-ci ...


Aha, je pensais que tu voulais dire que tu avais recommandé que :)


Bonjour Downvoter, notez que cela ne vous dérange pas que vous descendiez mes questions et / ou mes réponses. Je comprends bien et j'apprécie que les gens ont des opinions différentes et des points de vue, mais ce serait le bienvenu si vous pouviez poster un bref commentaire sur la raison pour laquelle vous m'avez révélé. Ai-je tapé quelque chose d'inexact? Quelque chose qui est tout simplement faux? Êtes-vous simplement en désaccord? Quoi qu'il en soit, je l'accueillerais même si vous venez de courber un compte SockPuppet pour laisser un commentaire anonyme. Je veux améliorer mes messages et ma carrière professionnelle, et je veux toujours apprendre de nouvelles choses, alors donnez-moi une chance, s'il vous plaît?



2
votes

Je prétendrais que le problème n'est pas dans cette classe. Cette classe n'est qu'un symptôme. Le problème est dans la classe de base qui appelle beforeaddd. Si vous pouvez le refacteur là-bas, vous n'aurez pas besoin de compiler des compiles conditionnels.

Si vous avez des noms de noms et des espaces de noms en conflit, vous pouvez contourner cela avec l'utilisation de mots-clés (non celle des assemblages). P>

Vous pouvez donc faire quelque chose comme p> xxx pré>

Je pense aussi que le problème est dans la classe de base, pas dans cette classe, en soi. P>

in Cet événement vous pouvez vous contourner ce non-sens en utilisant l'adaptation ou l'interface. p>

Je ne sais pas ce que l'autre classe est appelée, mais disons que cela s'appelle un entityaggregator. P>

#if CONDITION_1
using MyAbstractBusinessEntity = LogEntity;
#else
using MyAbstractBusinessEntity = AbstractBusinessEntity;
#endif

// ...

protected override void BeforeAdd(MyAbstractBusinessEntity entity)
{
    // in CONDITION_1, the case is a no-op
    ((LogEntity)entity).DateTimeInsert = DateTime.Now;
    base.BeforeAdd(entity);
}


1 commentaires

Il est difficile de dire avec les informations que j'ai devant moi, mais je dois deviner, cela se complique toujours la situation. Bien que j'aime l'idée de l'interface (j'ai suggéré une approche similaire ci-dessous), cela ressemble à la situation parfaite pour une usine. Je discuterais dans StructureMap (ou un autre conteneur de COI) bien avant d'écrire une seule directive compilateur.