덴바의 노트

내일배움캠프 14일차 WIL 본문

프로그래밍 노트/TIL

내일배움캠프 14일차 WIL

덴바 2024. 5. 3. 20:51

 

 

오늘의 키워드

 

  • TroubleShooting
  • Func 대리자
  • KPT 회고

 

 

TroubleShooting

 


높아진 결합도


 

현재 팀 프로젝트를 함께 진행중입니다만,

 

가장 힘든 부분이 바로 Dungeon, Enemy 등

 

각자가 만든 클래스를 자연스럽게 이어서

 

Dungeon 내에 턴제 기능을 만드는 것이 어려웠습니다.

 

 

기본적으로, Data, UI, Scene 등을 관리하는

 

Manager들을 GameManager에서 싱글톤으로 연결했으며,

 

Player 스크립트 또한 쉽게 참조하기 위해서 GameManager에 연결했습니다.

 

문제는 싱글톤의 편리함에 취해서 어디서든 Player를 싱글톤에 직접적으로 참조해버렸습니다.

 

이로 인해 현재 프로젝트의 결합도는 내용 결합도로 결합력이 너무 높아져버렸습니다.

 

 

이를 해소하기 위해서 직접 해당 스크립트에 정보를 변경, 기능 사용을 최소화할 방법을 고려했습니다.

 

그게 바로 event Action, event Func 이었습니다.

 

 

        public event Action? onEnemyAttack;

        public void EnemyAttack()
        {
            onEnemyAttack?.Invoke();
        }

        public event Func<bool>? onEnemyAllDie;

        public bool EnemyAllDie()
        {
            return onEnemyAllDie?.Invoke() ?? false;
        }

 

 

위와 같이 EventManager에서 해당 코드들을 관리했습니다.

        public Dungeon()
        {
            GameManager.Instance.Event.onRespawnEnemy += SpawnEnemy;

            GameManager.Instance.Event.onEnterDungeon += ShowEnemies;
            GameManager.Instance.Event.onSelectEnemy += ShowSelectEnemies;
            GameManager.Instance.Event.onPlayerAttack += AttackToEnemy;
            GameManager.Instance.Event.onPlayerSkillAttack += SkillAttackEnemy;
            GameManager.Instance.Event.onPlayerRangeSkillAttack += SkillAttackEnemy;
            GameManager.Instance.Event.onCheckAttackCount += CheckCount;
            GameManager.Instance.Event.onEnemyAttack += AttacktoPlayer;

            GameManager.Instance.Event.onEnemyAllDie += IsAllDie;
            GameManager.Instance.Event.onReward += Reward;
        }

 

 

그 후 각 생성자에서 위와 같이 메서드를 연결하는 방식을 사용했습니다.

 

이렇게 해서 싱글톤에 Dungeon, Store 등의 스크립트들을 모두 이어붙여서

 

최강의 결합도를 자랑하는 프로그램이 되는 것을 약간은 회피했습니다.

 

하지만 위와 같이 미친 듯이 생성자에 메서드를 대리자에 연결하는 방법도

 

크게 좋은 방법이 아닌 것을 알고 있습니다.

 

하지만 이미 되돌리기에는 시간이 너무 부족했기에 위와 같이 진행했습니다.

 

다음부터는 프로그램을 개발할 때 결합도가 최소한이 되도록  설계 후 하는게 좋을 것 같다고 생각합니다.

 



Func 대리자


 

Func 대리자는  Action 대리자와는 다른 특징이 하나 있습니다.

 

바로 반환 타입의 메서드를 사용할 수 있다는 것입니다.

 

예로 들어서 

 

        public event Func<bool>? onEnemyAllDie;

        public bool EnemyAllDie()
        {
            return onEnemyAllDie?.Invoke() ?? false;
        }
        
        
        public bool IsAllDie()
        {
            int count = 0;
            for(int i = 0; i < dungeonData.respawnList.Count; i++)
            {
                if(dungeonData.respawnList[i].isDead)
                {
                    count++;
                }
            }
            return dungeonData.respawnList.Count == count ? true : false;
        }

 

위 코드와 같이 return 타입을 가진 함수를 대리자를 통해서 다른 곳에서 실행할 수 있습니다.

 

만약, 모든 Enemy가 사망 상태인지를 체크하여,

 

전원이 죽었다고 판단되면 True를 반환하는 함수가 필요하다면,

 

Func<bool>을 통해서 연결해서 사용할 수 있습니다.

 

 

 


 


KEEP


 

1. 하루에 한 번씩 코드를 검토하고 진행 상황을 확인.

 

그 후 Git에서 Main으로 합친 후 다시 Branch를 재성성하는 방법은 나쁘지 않은 것 같습니다.

 

2. 싱글톤으로 구현된 하나의 스크립트에 모든 클래스를 때려박지 않는 판단은 좋은 판단 같습니다.

 


PROBLEM


 

1. 팀프로젝트를 시작하기 전에 어느 정도 충분한 설계를 못했던 점이

 

모듈간의 결합도를 최상으로 높이는 결과를 만들어 냈습니다.

 

 


TRY


 

1. 다음부터는 Unity를 사용하겠지만, State패턴 등을 적극적으로 반영

 

스크립트 간의 결합도르 최소한 낮추는 연습올 집중적으로 할 생각입니다.