Le troisième refactoring est l'envie des fonctionnalités.
Une fonction dans un module interagit avec une fonction ou une structure de données dans un module externe plutôt qu'avec un module interne.
Par exemple, un exemple courant est lorsque vous utilisez les méthodes get d'autres modules d'une chaîne.
Par exemple, consultez le code ci-dessous.
A partir de la classe Maison
, nous suivons la classe Person Adress class
et appelons la méthode calcurateDistance
de la ʻAdress class`.
De toute évidence, la classe House en sait trop sur les autres classes et y fait trop référence.
House().getPerson().getAdress().calcurateDistance()
Alors pourquoi une référence aussi excessive à un module externe est-elle mauvaise en premier lieu?
En premier lieu, lors d'une bonne conception, il est bon de bien interagir avec le module interne et de minimiser l'interaction avec le module externe.
En faisant cela,
Il existe deux principales solutions possibles:
Fonction de déplacement
Déplacer la valeur du champ
Regardons en fait un exemple de code.
Dans cet exemple de code, il existe quatre modèles. House Price Address SalesPerson
Supposons que vous ayez un programme qui calcule le prix d'une maison ou la distance d'une maison.
class Main {
def main(args: Array[String]): Unit = {
val address = Address(1L, 1L, 100L)
val price = Price(10000)
val house = House(address, price)
val salesPerson = SalesPerson(1, "kin", house)
salesPerson.calculatePrice
}
case class House(address: Address, price: Price)
case class Price(number: Int)
case class Address(
longitude: Long,
latitude: Long,
price: Long
)
case class SalesPerson(
id: Int,
name: String,
house: House
) {
def calculatePrice: Int = {
(house.price.number * 1.1).toInt
}
def calculateDistance: Long = {
house.address.longitude
}
}
}
Il semble y avoir une odeur dans la classe SalesPerson.
Si vous regardez de plus près, les méthodes CalculatePrice et CalculateDistance font toutes deux référence aux valeurs de champ de la classe maison.
C'est une odeur d'envie caractéristique. Autrement dit, fait plus souvent référence aux valeurs de champ du module externe qu'à vos propres valeurs de champ. </ b>
Nous allons refactoriser cela.
Qu'est-ce qui convient le mieux pour refactoriser dans ce cas, déplacer des valeurs de champ ou déplacer des fonctions?
Déplacer les valeurs de champ,
case class House() {
}
case class SalesPerson(id: Int, name: String, house: House, address: Address, price: Price) {
def calculatePrice: Int = {
(price.number * 1.1).toInt
}
def calculateDistance: Long = {
address.longitude
}
}
L'odeur des deux fonctions a peut-être disparu, mais la cohésion du modèle est rompue.
La classe SlaesPerson se retrouvera avec des données non pertinentes telles que le prix de l'adresse.
Déplaçons la fonction docilement.
def main(args: Array[String]): Unit = {
val address = Address(1L, 1L, 100L)
val price = Price(10000)
val house = House(address, price)
val salesPerson = SalesPerson(1, "kin", house)
// salesPerson.calculatePrice
house.calculatePrice
house.calculateDistance
}
case class House(address: Address, price: Price) {
def calculatePrice: Int = {
(price.number * 1.1).toInt
}
def calculateDistance: Long = {
address.longitude
}
}
case class SalesPerson(
id: Int,
name: String,
house: House
)
En déplaçant les deux fonctions vers la classe Maison, l'odeur d'envie des fonctionnalités a disparu, et le comportement de la classe Maison a augmenté et le degré d'agrégation a augmenté.
Comme mon sentiment Si vous essayez d'accéder aux données du module suivant, vous devriez penser que c'est une fonctionnalité envieuse.
L'emplacement où la fonction est définie est-il différent, comme dans la refactorisation ci-dessus, ou vaut-il mieux déplacer les valeurs de champ de l'objet?
Merci jusqu'à la fin.
La prochaine fois, j'écrirai un article sur la classe paresseuse.