2010-02-15 28 views
10

chicos que tienen una "mejor práctica pregunta" Por ejemplo, tengo estas clases:¿Qué pasar? ¿Objeto de referencia o tipo de valor?

class Person 
{ 
    public int age {get; set;} 
} 

class Computer 
{ 
    public void checkAge(Person p) // Which one is recommended THIS 
    { 
     // Do smthg with the AGE 
    } 

    public void checkAge(int p)  // OR THIS 
    { 
     //Do smthg with the age. 
    } 
} 

Lo que se recomienda para pasar? Justo lo que necesito (tipo de valor int) o el objeto completo (tipo de referencia)

Im preguntando esto porque estoy usando LINQ en una aplicación que estoy haciendo y he creado muchas entidades donde debo pasar los ID (extranjeros teclas), pero estoy pasando objetos.

¿Cuál es el mejor enfoque?

+1

+1 Siempre tuve esta confusión y de alguna manera fui al olvido, ahora está clarificada. Gracias. –

+0

Este es el tipo de preguntas que siempre tengo dudas. Necesitaba preguntar: D – MRFerocius

Respuesta

16

La función checkAge solo debe incluir la cantidad mínima de información necesaria para realizar su trabajo. Agregar cualquier otra cosa solo crea una dependencia artificial. Si solo se necesita int, esa es la solución que debería tomar.

+0

Excelente Jared, así que debería tener en cuenta dar la información mínima necesaria.- A veces necesito pasar 2 ints, entonces debería dar a la función 2 ints y así sucesivamente ¿no? – MRFerocius

+0

@MRFerocious, crearía 2 funciones. La versión que solo necesita 1 'int' y otra que acepta 2' int's y tiene un comportamiento claramente diferente – JaredPar

+1

Este principio se llama la Ley de Demeter: http://en.wikipedia.org/wiki/Law_of_Demeter –

12

Yo diría que en este caso, la respuesta probablemente no sea ninguna de las dos. O bien "Edad" se tendría en cuenta en su propia clase, o si la operación es específica del contexto con Persona, se encontraría dentro de la clase Persona misma.

2

Siga la ley del demeter para funciones. Básicamente, la ley establece que las entidades deben estar estrechamente vinculadas. Hágase la siguiente pregunta, ¿debería un objeto informático conocer un objeto de persona? En este caso, tal vez todo lo que está haciendo dentro de checkAge es verificar un valor int. Si ese es el caso, entonces, ¿qué te hace pensar que se necesita pasar todo el objeto? Simplemente pase la edad de la persona y tómela como int en este caso.

Así prefieren

public void checkAge(int n) 
3

con la información dada, ninguna de las soluciones es buena

la primera solución requiere la clase de computación saber sobre Person.Age, sin razón aparente

la segunda adjunta un método a la clase Computer que no tiene nada que ver con las propiedades del objeto Computer

algún contexto sería h elpful - si esto es una validación, CheckAge pertenece a la clase Person (posiblemente con una propiedad IsAgeAceptable)

¿Por qué la computadora está verificando la edad de una persona? La respuesta a esto determina lo que tiene sentido ...

+0

@Steven A. Lowe - Creo que el OP es solo un ejemplo. Estoy * seguro * o espero que él realmente no tenga una función 'checkAge' dentro de la clase de Computadora. – JonH

+0

jajaja Chicos, por supuesto esto es solo un ejemplo. Estoy preguntando esto porque estoy usando Linq y necesito pasar algunos identificadores, pero en algunos casos tengo 3, así que decidí pasar los objetos. Así que voy a pasar solo los puntos. – MRFerocius

0

Me gustaría señalar que al pasar una referencia, la referencia es un entero de 32 bits mientras se copia un tipo de datos. Entonces, si su tipo de valor es más grande que un int de 32 bits, pase por referencia si el rendimiento o la memoria son algún tipo de problema.

0

Me gustaría señalar que int Age probablemente no sea la mejor manera de almacenar ese valor. (Why is DateTime a Property and not a Method )

class Person : IBorn 
{ 
    public DateTime Birth {get; set;} 
} 

interface IBorn 
{ 
    DateTime Birth {get; set;} 
} 

interface IDateTimeFactory 
{ 
    DateTime Now();  
} 

class DefaultDateTimeFactory : IDateTimeFactory 
{ 
    public DateTime Now() 
    { 
    return DateTime.Now; 
    } 
} 

public static class IBornExtensions 
{ 
    public TimeSpan AgeFromNow(this IBorn birthed, IDateTimeFactory dtf) 
    { 
    return dtf.Now() - birthed.Birth; 
    } 
    public TimeSpan AgeFrom(this IBorn birthed, DateTime from) 
    { 
    return from - birthed.Birth; 
    } 
} 

class Computer 
{ 
    public void checkAge(IBorn birthed)   
    { 
    var age = birthed.Age((new DefaultDateTimeFactory()).Now()); 
    } 
} 

estoy seguro de que alguien por ahí está pensando, "Eso es una gran cantidad de código para esta respuesta, seguro que parece indignante". Al igual que DateTime.Now debería haber sido un método (porque los métodos devuelven valores que podrían cambiar por llamada, y la propiedad normalmente no debería cambiar los valores por llame al, consulte el enlace anterior), la edad cambia por llamada, por lo que probablemente la propiedad sea Nacimiento .A continuación, encapsulé el método para determinar la edad como método de extensión porque cualquier cosa que pueda ser IBorn ciertamente puede tener una edad (ignore la cuestión filosófica de que algo está muerto, tiene una edad: P). Y por último, creó el objeto IDateTimeFactory para que uno pueda probar el método Age para determinar si está calculando correctamente la edad (de lo contrario, hardcoding DateTime.Now significa que no puede decir qué tan viejo es algo comparado con otra cosa, por ejemplo, viejo es mi hermano comparado con mi hermana).

Cuestiones relacionadas