다른 문제에 대한 더 쉬운 해결책을 인정하면 코드 냄새가 나는 것이 괜찮습니까? [닫은]


31

친구 그룹과 나는 과거에 한동안 프로젝트를 진행해 왔으며, 우리는 우리 제품과 관련된 시나리오를 표현하는 멋진 OOP 방식을 발명하고자했습니다. 기본적으로 우리는 동방 스타일의 총알 지옥 게임을 진행 하고 있으며 , 우리가 상상할 수있는 총알의 가능한 행동을 쉽게 표현할 수있는 시스템을 만들고 싶었습니다.

이것이 바로 우리가 한 일입니다. 우리는 유니티의 컴포넌트 시스템 처럼 글 머리 기호 인스턴스에 자유롭게 부착 할 수있는 다른 컴포넌트로 총알의 동작을 구분할 수있는 매우 우아한 아키텍처를 만들었습니다 . 그것은 잘 작동하고 쉽게 확장 가능했으며 유연하고 우리의 모든 기지를 덮었지만 약간의 문제가있었습니다.

우리의 응용 프로그램은 또한 대량의 절차 생성, 즉 절차 적으로 총알의 동작을 생성합니다. 이것이 왜 문제입니까? 글쎄, 총알 행동을 나타내는 우리의 OOP 솔루션은 우아하면서도 인간 없이는 작업하기가 약간 복잡합니다. 인간은 논리적이고 영리한 문제에 대한 해결책을 생각할만큼 영리합니다. 절차 적 생성 알고리즘은 아직 영리하지 않으며 OOP 아키텍처를 최대한 활용하는 AI를 구현하는 것이 어렵다는 것을 알게되었습니다. 분명히 이것은 아키텍처의 결함으로 모든 상황에서 직관적이지 않다는 것입니다.

따라서이 문제를 해결하기 위해 기본적으로 다른 구성 요소가 제공하는 모든 동작을 글 머리표 클래스에 적용하여 상상할 수있는 모든 것이 다른 관련 구성 요소 인스턴스가 아닌 각 글 머리 인스턴스에서 직접 제공됩니다. 이것은 우리의 절차 생성 알고리즘을 다루기가 조금 더 쉬워 지지만 이제 우리의 글 머리표 클래스는 거대한 신 객체 입니다. 다른 프로그램보다 5 배나 많은 코드로 프로그램에서 가장 큰 클래스입니다. 유지하는 것도 약간의 고통입니다.

우리 클래스 중 하나가 다른 문제를 다루기 쉽도록 신의 대상으로 바뀌어도 괜찮습니까? 일반적으로 다른 문제에 대한 더 쉬운 해결책을 인정한다면 코드에 코드 냄새가 나는 것이 괜찮습니까?


1
글쎄 ... 이것은 대답하기가 다소 어렵습니다. 내 의견으로는 NO. 특히 다른 사람들과 함께 일하는 경우. 혼자 일하면 원하는대로 할 수 있습니다. 그러나 일반적으로 작업하는 사람에 따라 다릅니다.
Sarcastic Potato

13
"어리 석고 작동하면 어리석지 않다." 즉, 원하는대로 정확하게 작동하더라도 수정을 결정한 방법으로 인해 신 클래스에서 미래의 코딩을 거의 불가능하게 만들지 여부와 상관없이 고려해야합니다.
Flater

8
냄새를 맡고 악취가 나는 것을 알고 다른 사람들 만 알아 차리는 것이 좋습니다. :)
Reactgular

1
절차 코드에 비 OO 인터페이스를 제공하는 어댑터 클래스가 필요하므로 나머지 코드를 깨끗하게 유지할 수 있습니다.
nikie

1
훌륭한 시스템을 구축하고 하나의 기능에서 예상대로 작동하지 않는 지금은 모두 지옥으로 날려하기로 결정한 것 같습니다. 정말 당신이 원하는 것입니까? 당신의 일을 자랑스러워하십시오!
Mast

답변:


74

실제 프로그램을 구축 할 때 실용주의를 유지하는 것과 다른 편을 100 % 깨끗하게 유지하는 것 사이의 절충이 종종 있습니다. 청결을 유지하면 제 시간에 제품을 배송 할 수 없다면 약간의 덕트 테이프 를 사용하여 문 밖으로 물건을 꺼내는 것이 좋습니다.

즉, 귀하의 설명은 다른 소리를 말했다 - 당신이 추가하지 않을 소리를 조금 당신이 더 나은 솔루션을 위해 오랫동안 열심히 보지 않았기 때문에 전체 구조를 파괴하려고하는 것처럼 덕트 테이프의 비트 들린다. 그러므로 여기에 당신에게 축복을주는 PSE에있는 누군가를 찾는 대신에, 당신은 당신이 깊이있는 문제들에 대한 세부 사항들을 묘사하고 누군가가 당신에게 신을 피하는 아이디어를 제공하는지 다른 질문을하는 것이 좋습니다 동급 접근법.

총알 클래스는 다른 많은 클래스의 정면으로 설계 될 수 있으므로 총알 클래스는 더 작아집니다. 총알이 다른 행동을 다른 전략 개체에 위임 할 수 있도록 전략 패턴이 도움이 될 수 있습니다. 총알 구성 요소와 절차 생성기 사이에 어댑터 만 있으면됩니다. 그러나 솔직히 시스템에 대한 자세한 내용을 알지 못하면 추측 할 수 있습니다.


6
이 답변을 재확인하기 위해, 나는 매우 동일한 두 가지 권장 사항으로 무언가를 쓰려고했습니다. 마지막 문단과 관련하여 OP가 설명하는 것은 다른 수준의 간접적 인 지시가 필요하다는 코드 냄새 자체 인 것처럼 보입니다. 그것이 더 나은 팩토리 클래스, 파사드 또는 AI가 생성 할 수있는 완전한 DSL인지 여부는 OP에 달려 있습니다.
Daniel B

2
Facade / Strategy에 대한 좋은 제안은 코드를 작은 덩어리로 나눕니다. 자세한 내용을 알지 못하면 제안 할 내용을 알기가 어렵습니다.
user949300

25

흥미로운 질문입니다. 이전의 경험으로 인해 약간 편견이있어서 No로 대답하라는 메시지가 표시됩니다.

짧은 대답 : 우리는 학습을 멈추지 않습니다. 그런 벽에 부딪히면 코드 냄새를 추가하는 변명이 아니라 건축 / 디자인 기술을 향상시킬 수 있습니다.

더 긴 버전은 현재 작업중인 프로젝트에서 비슷한 질문을 많이 받았지만 필연적으로이 문제에 대해 훨씬 더 깊이 논의한 후에 원래의 질문자가 그에 대한 신용을 주었다는 것입니다. 근본 원인 분석과 같은 사고 방식을 포함 시키려고합니다.

5 가지 이유가 특히 도움이 된다는 것을 알았습니다 . 여기에 대한 설명은 첫 번째 이유와 같습니다.

  • "지금이 신 수업이 있습니다" 왜?
  • "절차 생성 알고리즘을 단순화하기 때문에"

정확히 단순화 된 것은 무엇입니까? 왜 그런가요? 계속해서 그 선을 따라 가면 일반적으로 발생하는 일은 더 근본적인 문제를 인식하기 시작하지만 동시에 더 근본적인 솔루션을 허용한다는 것입니다.

짧은 이야기, 짧은 문제, 특히 문제와 그 원인에 대해 더 깊이 생각한 후, 내 경험에 따르면 원래의 질문은 모든 참가자에게 무효이며 전혀 흥미가 없었습니다. 당신이 의심이 있다면, 그들에게 도전하고 그들이 사라지거나, 당신이해야 할 일을 알게 될 것입니다. 코드 / 디자인에 대한 이러한 의구심을 갖는 것은 제 의견으로는 좋은 징조입니다. 다른 사람들은 그것을 직감이라고 부르지 만, 이러한 문제에 도전하기 위해서는 먼저 그것을 인식해야합니다. 첫 걸음을 내린 후 축하합니다! 이제 토끼 구멍으로 내려가 ...


9

이와 같은 신 클래스를 갖는 것은 결코 바람직하지 않습니다. 총알이 이제 모 놀리 식 객체 일뿐 아니라 절차 생성 알고리즘도 마찬가지입니다.

첫 번째 단계는 AI가 패턴의 복잡성을 처리하는 데 왜 그렇게 많은 어려움을 겪었는지를 분석하는 것이 었습니까?

우연히, 가능한 모든 단일 속성의 의미를 완전히 인식하면서 AI를 신 클래스 객체로 바꾸려고 했습니까? 그랬다면 문제가 시작된 곳입니다.

솔루션은 모든 전략을 불릿 클래스 자체에 통합하는 것이 아니라 AI 코어에서 AI 구현을 전략 구현 자체로 오프로드하는 것이 었습니다.

레거시 동작으로 인한 부작용에 대한 두려움없이 원하는대로 새로운 전략으로 시스템을 확장 할 수있는 옵션을 포함하여 원래 원하는 유연성을 제공했을 것입니다.

대신 신 객체와 관련된 모든 문제가 생겼습니다. 신 클래스 자체 만 이해하기 어렵고 모놀리스를 디버그하기는 어렵지만 그러한 신 클래스에 액세스하는 다른 모든 구성 요소도 마찬가지입니다. 추상화의 부족으로 인해 AI는 이제 모든 중복 된 개별 속성을 인식해야하기 때문에 유사한 복잡성의 혐오로 바뀌어야합니다.

지금도 유지 관리에 문제가 있습니다. 이러한 문제는 특히 그 클래스가 어떻게 작동해야하는지에 대한인지 적 모델을 갖고있는 팀원을 풀어 놓으면 더욱 악화되고 있습니다.

지금까지 그러한 신 클래스 또는 신 기능을 사용하는 모든 단일 프로젝트는 처음부터 완전히 다시 작성되거나 중단되었습니다. 예외는 없습니다.


크거나 복잡한 클래스의 크기에 대한 토론에서 종종 누락되는 한 가지는 "X 유형의 참조를 보유하는 코드가 얼마나 많은 클래스를 사용해야하는지"와 " 엑스". 클라이언트가 다양한 기능을 지원하는 객체 컬렉션 (예 : "노인")을 갖고 있고 컬렉션의 모든 구성원에게 "가능한 경우 노블, 그렇지 않은 경우"를 요청하려는 경우 인터페이스가있는 경우 이러한 많은 방법을 결합한 인터페이스는 인터페이스를 분할하는 것보다 훨씬 도움이 될 수 있습니다.
supercat

그러한 인터페이스가 주어지면 다른 조합을 개별적으로 처리하지 않고도 코드가 모든 기능 조합으로 객체를 캡슐화 할 수 있습니다. 메소드 X를 지원하는 유형에 대한 프록시는 X가 불가능한 오브젝트를 랩핑하는 데 사용될 수없고 X가 불가능한 오브젝트를 랩핑 할 수있는 프록시는 사용할 수 없으므로 인터페이스를 분리하면 여러 가지 프록시 클래스를 작성해야합니다. X 메소드를 지원할 수있는 오브젝트를 랩핑하더라도 메소드 X를 노출 할 수 없습니다.
supercat

8

여명기 이후 모든 나쁜 코드에는 단계적으로 합리적으로 보이는 진화론에 대한 이야기가 있습니다. 당신도 예외는 아닙니다. 코더는 코딩으로 학습합니다. 지금 당장 예상 할 수 없었던 문제의 측면이 있습니다. 점진적으로 합리적인 결정을 내렸지 만 전반적으로 잘못된 방향으로 아키텍처를 이끌었습니다. 이러한 결정을 식별하고 재검토해야합니다.

사람들이 문제를 해결하는 방법에 대한 아이디어가 있는지 사무실 주위에 문의하십시오. 내가 일한 대부분의 장소, 프로그래머의 약 10-20 %가 그런 종류의 일에 대한 진정한 요령을 가지고 있으며 방금 기회를 기다리고 있습니다. 그 사람들이 누구인지 알아 내십시오. 대체로 가장 쉽게 대안을 볼 수있는 현재 아키텍처에 역사적으로 투자하지 않은 것은 신입 사원입니다. 재향 군인 중 한 명과 짝을 짓면 그들이 함께하는 것에 놀랄 것입니다.


2

어떤 경우에는 이것이 확실합니다. 그러나 절차 생성과 멋진 첨부 / 구성 요소 기반 동작 아키텍처를 모두 사용하는 좋은 솔루션이 없다고 생각하기가 어렵습니다. 총알 클래스에 방금 가져온 모든 동작이 god 객체와 깔끔한 아키텍처 버전간에 기능적 차이가 없습니다. 절차 생성 알고리즘을 사용하기 어려운 이유는 무엇입니까?

proc과 함께 아키텍처에 어떤 문제가 있는지 간략히 설명하는 새로운 질문 (여기 또는 gamedev.stackexchange.com?)을 생각합니다. gen., 정말 재미있을 것입니다. 새로운 질문이 있으시면 여기로 알려주십시오!


3
신 클래스를 갖는 것이 수용 가능하고 바람직한 상황 인 반면에이 클래스는 단지 개별 소스의 자동 편집이 아닌 상황에 대한 예를 제공 할 수 있습니까?
Ext3h

"다른 문제에 대한 더 쉬운 해결책을 인정한다면 코드 냄새가 나도 괜찮습니까?" 신 수업은 일반적으로 구성을 사용하여 쉽게 해결할 수 있습니다. 그러나 네, 항상 100 % 제거 할 가치가없는 특정 코드 냄새가 있습니다. 결국 일부 실용주의는 작업을 수행해야합니다 :). (이것은 당신이 변덕에 모범 사례를 버려야한다고 생각하지 않습니다. 나는 대부분의 소프트웨어 하우스가 모범 사례를보다 엄격하게 따르는 것이 낫다고 믿습니다).
Roy T.

0

영감을 얻기 위해 함수형 프로그래밍 또는보다 정확하게 맞춤 된 유형을 살펴볼 수 있습니다. 작동하지 않는 아이디어는 사용 가능한 유형 시스템에서 표현하기가 불가능합니다. 예를 들어 "총알 발사"및 "총알 잡기"구성 요소가있는 총이 있다고 가정합니다. 그것들이 두 개의 분리 된 구성 요소라면, 타당하지 않은 구성이 있습니다-총알을 쏘지 만 보관함에는없는 총 또는 총알을 저장하지만 발사하지 않는 총을 가질 수 있습니다.

이 수준의 복잡성에서 "인간은 이것이 쓸모없고 불가능한 조합을 피할 것"이라고 생각합니다. 더 좋은 방법은 이것을 불가능하게 만드는 것입니다. 예를 들어, "총알 촬영"의 구성 요소에는 "총알 보유"구성 요소에 대한 참조 가 필요할 수 있습니다 (또는 자체 문제가 있음에도 불구하고 구성 요소를 그대로 유지해야 함).

예제가 훨씬 더 복잡 할 수 있지만 핵심은 여전히 ​​가능한 조합을 제한하여 제약 조건을 추가하는 것입니다. 어떤 식 으로든 절차 생성이 제대로 이루어지기가 너무 복잡하다면 어쨌든 너무 복잡 할 수 있습니다. 무기를 설계 할 때 자신을 제한하는 모든 방법을 생각해보십시오. "이 총에는 이미 화염 방사기가 있고 수류탄 발사기를 추가 할 필요가 없습니다"라고 스스로에게 말하고 있습니까? 이것이 휴리스틱에 통합 할 수있는 것입니다. 각 구성 요소를 가질 확률을 고정시키는 것보다 조금 더 복잡한 확률 메커니즘을 사용하려고 할 수 있습니다. 서로 배제하는 구성 요소 나 함께 작동하는 구성 요소가있을 수 있습니다.

마지막으로 실제로 큰 문제인지 고려하십시오. 게임의 재미를 망치고 있습니까? 결과 총이 쓸모 없거나 강력합니까? 얼마나? 10 가지 중 하나가 무의미합니까? 절차 적으로 생성 된 무기 효과가있는 Borderlands와 같은 게임은 종종 무의미한 효과 조합을 무시합니다. 그럼에도 불구하고 보더 랜드에서 자주 발생합니다. 그것은 생성 메커니즘의 실패로 간주되기보다는 웃음을 위해 재생되었습니다 :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.