코드 냄새 125 - 'IS-A' 관계
TL:DR; Think about protocol and behavior, forget inheritance
문제
솔루션
문맥
IS-A relation은 데이터 세계에서 나옵니다.
우리는 구조화된 디자인과 데이터 모델링으로 ERDs 배웠습니다.
이제 우리는 행동의 관점에서 생각해야 합니다.
행동은 필수적이며 데이터는 .
샘플 코드
잘못된
// If you made Square derive from Rectangle, then a Square should be usable anywhere you expect a rectangle
#include <iostream>
Rectangle::Rectangle(const unsigned width, const unsigned height):
m_width(width),
m_height(height)
{
}
unsigned Rectangle::getWidth() const
{
return m_width;
}
void Rectangle::setWidth(const unsigned width)
{
/*Width and Height are independant*/
m_width = width;
}
unsigned Rectangle::getHeight() const
{
return m_height;
}
void Rectangle::setHeight(const unsigned height)
{
m_height = height;
}
unsigned Rectangle::area() const
{
/*Valid for both Rectangles and Squares*/
return m_height * m_width;
}
Square::Square(const unsigned size)
: Rectangle(size, size)
{
}
// OK for squares, bad for rectangles
// Protocol is bad, width and height are not relevant on squares
void Square::setWidth(const unsigned size)
{
m_height = size;
m_width = size;
}
// OK for squares, bad for rectangles
// Protocol is bad, width and height are not relevant on squares
void Square::setHeight(const unsigned size)
{
m_height = size;
m_width = size;
}
void process(Rectangle& r)
{
unsigned h = 10;
auto w = r.getWidth();
r.setHeight(h);
std::cout << "Expected area: " << (w*h) << ", got " << r.area() << "\n";
//area is not well defined in squares
//every square IS-A rectangle, but does not behave-like a rectangle
}
int main()
{
Rectangle rectangle{3,4};
Square square{5};
process(rectangle);
process(square);
}
오른쪽
// If you made Square derive from Rectangle,
//then a Square should be usable anywhere you expect a rectangle
#include <iostream>
Rectangle::Rectangle(const unsigned width, const unsigned height):
m_width(width),
m_height(height)
{
}
void Rectangle:changeWidth(const unsigned width)
{
/*Width and Height are independant*/
m_width = width;
// We should discuss if it is good to mutate
// and not create a new Figure
}
void Rectangle::changeHeight(const unsigned height)
{
m_height = height;
}
unsigned Rectangle::area() const
{
return m_height * m_width;
}
//No inheritance
Square::Square(const unsigned size):
m_size(size)
{
}
unsigned Square::area() const
{
return m_size * m_size;
}
void Square::changeSize(const unsigned size)
{
m_size = size;
}
void testRectangleChange(Rectangle& r)
{
unsigned h = 10;
auto w = r.getWidth();
r.setHeight(h);
std::cout << "Expected area: " << (w*h) << ", got " << r.area() << "\n";
//area is not well defined in squares
//every square IS-A rectangle, but does not behave-like a rectangle
}
int main()
{
Rectangle rectangle{3,4};
Square square{5};
testRectangleChange(rectangle);
testRectangleChange(square);
}
발각
[X] 수동
이것은 시맨틱 냄새입니다.
태그
잘못된
// If you made Square derive from Rectangle, then a Square should be usable anywhere you expect a rectangle
#include <iostream>
Rectangle::Rectangle(const unsigned width, const unsigned height):
m_width(width),
m_height(height)
{
}
unsigned Rectangle::getWidth() const
{
return m_width;
}
void Rectangle::setWidth(const unsigned width)
{
/*Width and Height are independant*/
m_width = width;
}
unsigned Rectangle::getHeight() const
{
return m_height;
}
void Rectangle::setHeight(const unsigned height)
{
m_height = height;
}
unsigned Rectangle::area() const
{
/*Valid for both Rectangles and Squares*/
return m_height * m_width;
}
Square::Square(const unsigned size)
: Rectangle(size, size)
{
}
// OK for squares, bad for rectangles
// Protocol is bad, width and height are not relevant on squares
void Square::setWidth(const unsigned size)
{
m_height = size;
m_width = size;
}
// OK for squares, bad for rectangles
// Protocol is bad, width and height are not relevant on squares
void Square::setHeight(const unsigned size)
{
m_height = size;
m_width = size;
}
void process(Rectangle& r)
{
unsigned h = 10;
auto w = r.getWidth();
r.setHeight(h);
std::cout << "Expected area: " << (w*h) << ", got " << r.area() << "\n";
//area is not well defined in squares
//every square IS-A rectangle, but does not behave-like a rectangle
}
int main()
{
Rectangle rectangle{3,4};
Square square{5};
process(rectangle);
process(square);
}
오른쪽
// If you made Square derive from Rectangle,
//then a Square should be usable anywhere you expect a rectangle
#include <iostream>
Rectangle::Rectangle(const unsigned width, const unsigned height):
m_width(width),
m_height(height)
{
}
void Rectangle:changeWidth(const unsigned width)
{
/*Width and Height are independant*/
m_width = width;
// We should discuss if it is good to mutate
// and not create a new Figure
}
void Rectangle::changeHeight(const unsigned height)
{
m_height = height;
}
unsigned Rectangle::area() const
{
return m_height * m_width;
}
//No inheritance
Square::Square(const unsigned size):
m_size(size)
{
}
unsigned Square::area() const
{
return m_size * m_size;
}
void Square::changeSize(const unsigned size)
{
m_size = size;
}
void testRectangleChange(Rectangle& r)
{
unsigned h = 10;
auto w = r.getWidth();
r.setHeight(h);
std::cout << "Expected area: " << (w*h) << ", got " << r.area() << "\n";
//area is not well defined in squares
//every square IS-A rectangle, but does not behave-like a rectangle
}
int main()
{
Rectangle rectangle{3,4};
Square square{5};
testRectangleChange(rectangle);
testRectangleChange(square);
}
발각
[X] 수동
이것은 시맨틱 냄새입니다.
태그
결론
실수 IS-A 복소수(수학에 따름).
정수 IS-A 실수(수학에 따름).
실수는 복소수처럼 행동하지 않습니다.
우리는 real.setImaginaryPart()를 수행할 수 없으므로 우리에 따르면 Complex가 아닙니다.
처지
코드 냄새 92 - 격리된 하위 클래스 이름
Maxi Contieri ・ 2021년 10월 11일 ・ 2분 읽기
#poo
#webdev
#python
#javascript
코드 냄새 11 - 코드 재사용을 위한 하위 분류
Maxi Contieri ・ 2020년 10월 30일 ・ 2분 읽기
#oop
#codenewbie
#tutorial
코드 냄새 37 - 보호된 속성
Maxi Contieri ・ 2020년 11월 29일 ・ 2분 읽기
#oop
#webdev
#tutorial
#codenewbie
더 많은 정보
코드 냄새 92 - 격리된 하위 클래스 이름
Maxi Contieri ・ 2021년 10월 11일 ・ 2분 읽기
#poo
#webdev
#python
#javascript
코드 냄새 11 - 코드 재사용을 위한 하위 분류
Maxi Contieri ・ 2020년 10월 30일 ・ 2분 읽기
#oop
#codenewbie
#tutorial
코드 냄새 37 - 보호된 속성
Maxi Contieri ・ 2020년 11월 29일 ・ 2분 읽기
#oop
#webdev
#tutorial
#codenewbie
더 많은 정보
학점
사진 제공: Joshua Rondeau on Unsplash
DRY - Don't Repeat Yourself - Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
앤디 헌트
소프트웨어 엔지니어링 좋은 인용구
Maxi Contieri ・ 12월 28일 '20 ・ 13분 읽기
#codenewbie
#programming
#quotes
#software
이 기사는 CodeSmell 시리즈의 일부입니다.
코드에서 냄새 나는 부분을 찾는 방법
Maxi Contieri ・ 2021년 5월 21일 ・ 4분 읽기
#codenewbie
#tutorial
#codequality
#beginners
Reference
이 문제에 관하여(코드 냄새 125 - 'IS-A' 관계), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/mcsee/code-smell-125-is-a-relationship-46f4
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
DRY - Don't Repeat Yourself - Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
소프트웨어 엔지니어링 좋은 인용구
Maxi Contieri ・ 12월 28일 '20 ・ 13분 읽기
#codenewbie
#programming
#quotes
#software
코드에서 냄새 나는 부분을 찾는 방법
Maxi Contieri ・ 2021년 5월 21일 ・ 4분 읽기
#codenewbie
#tutorial
#codequality
#beginners
Reference
이 문제에 관하여(코드 냄새 125 - 'IS-A' 관계), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mcsee/code-smell-125-is-a-relationship-46f4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)