Un de mes collègues développeurs a un code similaire à celui de l'extrait suivant
p> ici Les propriétés de la classe de données récupèrent les informations de DB Dynamiquement. Lorsqu'il est nécessaire de sauvegarder les données dans un fichier, le développeur crée une instance et remplit la propriété à l'aide de l'affectation automatique. Puis appelle enfin une sauvegarde. J'ai essayé de discuter que l'utilisation de la propriété n'est pas correcte. Mais il n'est pas convaincu. p> Ce sont ses points p> est-ce que cette utilisation est correcte? p> p> code>
8 Réponses :
Les propriétés doivent vraiment être aussi légères que possible. P>
Lorsque d'autres développeurs utilisent des propriétés, ils s'attendent à ce qu'ils soient des parties intrinsèques de l'objet (c'est-à-dire déjà chargées et en mémoire). P>
Le vrai problème ici est celui de la symétrie - la propriété get and Set devrait se refléter mutuellement, et ils ne le font pas. C'est contre ce que la plupart des développeurs s'attendent normalement. P>
Avoir la charge de la propriété à partir de la base de données n'est pas recommandée - Normalement, on remplacerait la classe via une méthode spécifique. P>
Je ne suis pas complètement d'accord: je ne vois aucun problème avec des propriétés de lecture paresseusement (si ce n'est pas encore lu, obtenez des charges toutes les données puis renvoie) en supposant que la Convention générale de votre code et à condition que l'objet ait suffisamment d'état pour le faire et Il y a des cas d'erreur raisonnables. Cependant, je pense que le vrai problème est que la propriété Obtenez et définir n'est pas des actions opposées ici.
D'accord. @ferosekhanj: Dans mon expérience chargée une entité avec 20 champs ne prend pas beaucoup plus de temps que de charger un seul champ de l'entité. Peut-être que vous êtes trop optimisé ici.
Ne fais pas ça. Obtenir les valeurs du constructeur provoque un risque (aucune exception dans les CTORS, c'est dangereux) et peut rapidement devenir un drain de performance (rien de poids léger lorsque vous avez une gamme de données), à moins que vous n'en preniez pas en charge par un singleton. Si vous voulez garder cela aussi simple, créez une récupération et / ou un drapeau que vous pouvez tester dans le gettor.
Pas non plus la meilleure idée de charger des données de DB dans le constructeur.
À mon avis, c'est un design terrible. Utiliser une propriété getter pour faire des choses "magiques" rend le système gênant de gérer. Si je rejoindrais votre équipe, comment devrais-je savoir cette magie derrière ces propriétés? P>
Créer une méthode distincte appelée comme elle se comporte. P>
"correct" est souvent dans l'œil du spectateur. Cela dépend aussi de la distance ou de la brillante que vous voulez que votre conception soit. Je n'irais jamais pour la conception que vous décrivez, cela deviendrai un cauchemar de maintenance pour avoir les actions crudes sur les Pocos.
Votre problème principal est l'absence de séparations de préoccupations em> strong>. I.E., l'objet de données est également responsable de la conservation et de la récupération (actions qui doivent être définies une seule fois dans l'ensemble du système). En conséquence, vous vous retrouvez avec un code dupliqué, ballonné et immobilable qui peut rapidement devenir réel lent (essayez une requête LINQ avec une jointure sur le gettor). P> Un scénario courant avec des bases de données consiste à utiliser de petites classes d'entité qui ne contiennent que les propriétés, rien de plus. Une couche DAO s'occupe de la récupération et de la remplissage de ces POCOS avec des données de la base de données et défini uniquement les actions crudes uniquement (à travers des génériques). Je suggérerais NHibernate pour la cartographie ORM. Le principe de base expliqué ici fonctionne également avec d'autres mappeurs Orm et est aussi expliqué ici . p> Les raisons, esp. NR 1, devrait être un candidat principal pour le refactoriser dans quelque chose de plus maintenu. Le code dupliqué et la logique, lorsqu'ils sont rencontrés, devraient être reconsidéré fortement. Si le gettor ci-dessus obtient réellement les données de la base de données (j'espère que j'ai mal comprendre cela), éliminez-le aussi rapidement que possible. P> Exemple trop simplifié de séparations de préoccupations: P> class Data
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
}
class Dao<T>
{
SaveEntity<T>(T data)
{
// use reflection for saving your properies (this is what any ORM does for you)
}
IList<T> GetAll<T>()
{
// use reflection to retrieve all data of this type (again, ORM does this for you)
}
}
// usage:
Dao<Data> myDao = new Dao<Data>();
List<Data> allData = myDao.GetAll();
// modify, query etc using Dao, lazy evaluation and caching is done by the ORM for performance
// but more importantly, this design keeps your code clean, readable and maintainable.
Je ne pense pas qu'un autre développeur qui fonctionnera avec le même code sera heureux de voir: personnellement, je ne ferais jamais cela. P> aussi Ce n'est pas la meilleure idée d'utiliser la propriété pour charger des données de DB.
J'aurais méthode code> qui chargera des données de DB à une variable locale, puis vous pouvez obtenir ces données à l'aide de la propriété. Aussi
get / Set code> logiquement doit fonctionner avec les mêmes données. Il est étrange d'utiliser
obtenir code> pour obtenir des données à partir de dB mais d'utiliser
définir code> pour fonctionner avec une variable locale. P> p>
Ah, ce n'était pas une faute de frappe? Bien repéré :). Pensait que cela signifiait quelque chose comme String String StringOffirSuSugetingProperty = d.prop1 code>.
C'est assez terrible, imo. p>
d.prop1 = d.prop1 code> a l'air em> comme une auto-affectation sans signification, pas une "données de charge de db" appel. Li>
- Même si vous devez charger vingt autres choses différentes d'une base de données, ce faisant de cette façon forces em> il s'agit de vingt voyages de DB différents; Êtes-vous sûr que plusieurs propriétés ne peuvent pas être récupérées dans un seul appel? Ce serait probablement beaucoup mieux, la performance sage. li>
ol>
Si j'étais vous, j'écrirais une fonction Serialize / désérialisze, puis fournissez des propriétés comme des emballages légers autour des résultats en mémoire. P>
Jetez un coup d'œil à l'interface d'iserialisation: HTTP : //msdn.microsoft.com/en-us/library/system.runtime.Serialization.Serializable.aspx P>
Ce serait très difficile de travailler avec,
si vous définissez le PROP1, puis obtenir ProP1, vous pourriez vous retrouver avec différents résultats
par exemple: p> lire le code sans le commentaire que vous vous attendez à ce que MyString soit égal à "ABC", pas "XYZ", cela pourrait être déroutant. P> Ceci ferait travailler avec les propriétés très difficiles et nécessiterait une sauvegarde à chaque fois que vous modifiez une propriété pour le travail. P> P>
Merci à toutes les personnes de répondre. Je suis d'accord avec @ esde84 que la symétrie sera perdue si une propriété est mise en œuvre comme celle-ci.
Ainsi que pour accepter ce que tout le monde a dit sur cet exemple, que se passe-t-il s'il existe d'autres champs dans la classe de données? I.E. PROP2, ProP3, etc., revenez-ils tous à la base de données, chaque fois qu'ils sont accessibles afin de "renvoyer la valeur stockée dans la base de données via une requête". 10 propriétés correspondaient à 10 hits de base de données. Définition 10 Propriétés, 10 écrit à la base de données. Ça ne va pas à l'échelle. p>
La justification de cette implémentation de propriété est le client qui utilise cette classe n'accumule pas toutes les portes. La propriété fait donc une chargement paresseuse de ces propriétés requises.
Je suppose que c'est une chargement extrêmement paresseux. Je n'ai utilisé que le chargement paresseux pour les propriétés qui doivent charger des "enregistrements" de l'enfant (multiple) d'une table associée (comme la lecture des lignes de détail de la commande lorsque la propriété LineItems d'une commande est lue) - jamais une valeur à la fois du même table que d'autres informations.
"CORRECT" est assez subjectif, mais je ne pense pas que vous trouverez beaucoup de gens qui diront leur chemin.
Pourquoi D.Prop1 est-il mis à lui-même? Est-ce nécessaire pour déclencher une sorte de drapeau «sale» afin qu'il sache quoi sauver lorsque SaveData () est appelé?
Quelle est la complexité des extratures: toutes les 20 valeurs sont-elles des lectures triviales à partir d'une seule table, ou sont calculées dans toutes les tables, etc.?
Ongledge: non, c'est l'abus ici; Le get et set font des choses entièrement différentes. Cela stocke une copie locale d'une valeur lue de la base de données.
@Rup oh ouais, désolé je n'ai pas lu les commentaires là-bas. Je viens de montrer que le code auto-commente est très important! Ce qui n'est qu'une raison pour laquelle je dirais que c'est une mauvaise idée.
Donner peu plus d'informations. J'étais convaincu avec la chargement paresseuse des données de la majorité de la DB Béacuse du temps dont le client a besoin de très peu d'informations. Il y a beaucoup de classes qui modélisent les données dans la DB. La taille de DB est également assez énorme. Donc, il ne sert à rien de charger toutes les données du constructeur et de le garder prêt. Mais la mise en œuvre de la charge paresseuse utilisant une propriété comme ci-dessus était la préoccupation pour moi. Quoi qu'il en soit, merci à tous de prendre le temps et de répondre.
@Grant montre également la lecture des commentaires peut être très important
@Drdro - Bien sûr, la lecture des commentaires est probablement une très bonne idée sur un site de questions / réponses! Mais comme nous le savons tous, les commentaires sont souvent obsolètes ou incorrects, et le code est la seule vraie vérité, alors je pense avoir l'habitude de les ignorer. Je pense en général que ce n'est pas une mauvaise stratégie.
Ongled que j'étais juste drôle. Je comprends votre point de vue sur les commentaires en général, mais j'aurais tendance à dire que c'est le premier endroit où aller quand vous rencontrez quelque chose de bizarre. Et je suis sûr que vous le faites habituellement, naturellement.