shao wenzhi
shao wenzhi

Reputation: 11

Two Python modules require each other's contents, what is better design

Two Python modules requiring each other's contents seems to be a common problem that beginners face. Many people have said: "While this kind of setup may make intuitive sense to you now, cyclic dependencies are considered bad software engineering practice." Yes, it is pretty intuitive. But how can we fix it through better design, rather than using import instead of from ... import?

My example is a demo using python in Unreal Engine:

  1. There are four modules: Character, Gun, Bullet and Monster
  2. Character has a gun, it imports Gun, which imports Bullet
  3. In Bullet, it needs to judge whether what it hit is a Monster (or a Character), so Bullet does: from Monster import Monster (it is a class)
  4. The Monsters fight back of course, it needs to check whether what it hit is a Character, so Monster does: from Character import Character

Character and Monster import each other.

Upvotes: 1

Views: 65

Answers (1)

Generally speaking: Decomposition is what you are looking for.

Instead of monsters hitting characters or monsters hitting monsters or characters hitting characters or characters hitting monsters ... you want to recognize that this can be simplified or extracted:

Given you have this scenario now:

   [module]
   Character{
     Shoot() {
       self.pistol.Attack(x,y,z, ...)
     }
   }

   [module]
   Monster{
     Attack() {
       self.swingArm(a,b,c, ...)
     }
   }

Depending on how you detect hits the following may or may not be relevant:

This is one way to solve your problem or to reorganize your code

   [module]               [module]
   Character{             Attack{
     OnHit()  <---------    event-emitter
     Attack() .........|>  attack logic                   
   }

   [module]
    Monster{
     OnHit() <----------   event-emitter
     SwingArm() .......|>  melee attack logic
                          }
    }

  • <--------- is a message
  • .......|> is code composition (you import something and stick it in a property of your class)

This is a simplification of everything you would have to do, but it hopefully gives you an idea: identify common behavior and move it to a third module.

Upvotes: 2

Related Questions