Dividing code into modules

Monkey Forums/Monkey Programming/Dividing code into modules

mteo77(Posted 2013) [#1]
Hello all.
I am trying to tidy up my code and divide it into different modules, so i don't have to scroll thousands of lines (i am using jungle and over a certain amount of lines it slows down my pc quite a bit).
What i am trying to do is having my classes into a class file, functions into a function file and so on.
The problem i am having is that inside classes i access external variables (mostly lists) that are actually created into the main function.
Example:
Class enemy
   field x:int,y:int,speed:int
   field image:Image
   field target:player
   Method Init()
      x=100
      y=200
      speed=4
      image="bla bla bla"
      target="such and such"
      addLast(enemyLayer)
   end method
end class

As you can see i have a command that add the enemy to a list.
Problem with that is that the list get initialised in the main function of the main program.
That list is also used by other objects.
How can i resolve the issue?
Is it wrong to import the main program into the enemy module?
Or should every module be self sufficent if possible?(to avoid multiple includes of modules already included somewhere else?).
Hope what i said make sense.


Midimaster(Posted 2013) [#2]
a good style woul be never to access anything outside a class from inside.

For me a class is a closed code piece, which should only be accessed over a few interface-points:


Class Enemy
   Global Layer:List<Enemy> =New List<Enemy>
   Field x:int,y:int,speed:int
   Field image:Image
   Field target:player
   Method Init()
      x=100
      y=200
      speed=4
      image="bla bla bla"
      target="such and such"
      Layer.AddLast Self
   end method
end class



you can still access the list form outside:

 For loc:Enemy =EachIn Emeny.Layer
     loc.x=....
Next


...but you can also move all functions related to the list into the class.

also possible t ocall a function inside the class to add new members:

Class Enemy
   Global Layer:List<Enemy> =New List<Enemy>
   Field x:int,y:int,speed:int
   Field image:Image
   Field target:player

   Function AddOne()
        loc:Enemy=New Enemy
        loc.Init
   End 

   Method Init()
      x=100
      y=200
      speed=4
      image="bla bla bla"
      target="such and such"
      Layer.AddLast Self
   end method
end class


end method
end class[/code]


[code][/code]


Gerry Quinn(Posted 2013) [#3]
I would think a sort of 'hierarchy' is usually best, in which top-level classes know about lower-level classes, but the lower-level ones are fairly self-contained and should not import too many important modules.

So, for example, the code to add an Enemy to the higher-level EnemyLayer would be contained in EnemyLayer or the class containing it.

Enemy is probably not the best example as it may know some things about the level and may even initiate actions like damaging the player (though I would probably tend to have this sort of thing passed through the main game-controlling class as well).

As far as I know you don't have to worry about circular imports in Monkey like in C++, but it is good to keep the system simple anyway.


mteo77(Posted 2013) [#4]
Thanks all.
At the moment i resolved importing the main into the classes file and vice versa.
At least now i can speed up the typing and scrolling, until i rewrite my classes in a more organised way.
The problem is that most of my classes depends on other classes, like some enemy code depend on where the player is, so i find it difficult to really make my classes stand alone:especially if i am dealing with lists.
Second little game i will create will have everything build from scratch(i plan to finish it by october..optimistic lol).
Thanks for the help.


Gerry Quinn(Posted 2013) [#5]
The less tangled you can make your code the better. Don't tangle it in the interests of efficiency.

There are ways to reduce the entanglement. For example, what if your enemies just remembered the coordinates they are going for? You could periodically say:

For local enemy:Enemy = Eachin enemies
enemy.SetTarget( player.position )
Next

Now Enemy no longer needs to import Player.

And even if the enemies have an elaborate AI to decide which player unit to chase (e.g. in a wargame) they need only know the units' position and type.


Paul - Taiphoz(Posted 2013) [#6]
I keep all class's in a class specific file, along with any additional function, or global that require or interact with the class.

All my alien lists, globals, consts, functions and methods are all within the alien.monkey file.

makes finding things a hell of a lot faster.


Gerry Quinn(Posted 2013) [#7]
What Taiphoz says, too.

One class per file in general is probably a good idea.

There will be cases when you want more than one, either because they are tightly linked (example: Monkey.List), or because one is simply a small data structure or such like that is used only by one class, and doesn't deserve its own file.

But by and large, aim for one file per class.

It helps make your code more re-usable, too. In a perfect world we would write every class as though it were to be a publicly available module.


Why0Why(Posted 2013) [#8]
I would actually be interested in seeing a decent size project from one of the experienced coders on here. As my projects have gotten larger I have had to spend more time on how to organize them. In Mike's book he does touch on it and I have been using his method, which is have all of your imports in a gameclasses file and then just import that file in your separate class files. One of the disadvantages of being self taught and learning from code snippets is you have to figure this stuff out on the fly.


Paul - Taiphoz(Posted 2013) [#9]
WhyOwhy thats not always a bad thing, you tend to learn the stuff and come up with things that work for you, things that work for me might suck to you, but they work for me and they help me be productive.

Its not simply a matter of whats the most efficient system, but rather which system can the individual programmer use fluidly and frequently without problems.

for me its class's per file, I know some one who cant work like that they need everything in a single file which would make me want out pull my very limited amount of hair out.


Why0Why(Posted 2013) [#10]
I know everyone has their own style. I personally feel one class per file is a little too much separation, I tend to group closely related items, which might have more than one class. I just meant I was concerned about doing something in a very inefficient way and might not know the difference.


muddy_shoes(Posted 2013) [#11]
Depends what you mean by efficient and the nature of your project. There's efficiency in the build step, efficiency on a collaborative level and efficiency as an individual.

Project file organisation can have a significant effect on build times for large projects in some languages but that's unlikely to be much of a factor for most Monkey coders.

When working in teams, project file organisation becomes an issue because it affects both the ease with which a codebase can be understood (or broken down so a single section can be understood to work on) and how easily it can be worked on in parallel. A nicely modular codebase simplifies task breakdown and reduces branching and merging problems.

However, if it's just you working on a project then all that's left is your own ability to navigate and work on the code. To that extent the most efficient project layout is going to be a matter of personal taste. From experience most coders' tastes evolve as their projects scale and they find the limitations of their work patterns.

It should be noted that your IDE makes a big difference here. Unfortunately there are no Monkey IDEs that incorporate the templating/refactoring features that make it easier to both create and improve your structure.