Each time i make an interesting program with Codea, it becomes more and more complex, and when i try to make classes or function libraries, i have a lot of difficulty to refractor the code. I dont know how to define the ‘good’ interfaces that will keep progress simple, and enable to build blocs from from other blocs, in the KISS style. And, from the ipad, i cannot view my program architecture easily, so i get lost (too much has to be kept in mind, too many inter-relationships).
At this point i am starting to get disappointed and to wonder if the problem is me, or the very structure of Lua, which would not be suited to build complex programs. On the other hand, lua is an extension langage, so i should be able to create the bricks i need, if only i knew what i need…
Can anyone give me some advice from his experience on how to progress there? Or point to me some efficient tutorial?
Thanks in advance.
What would you define as complex?
@Jmv38 depends what you are wanting to do with Codea. Codea is great for getting an idea and rapidly prototyping it. Taking past this point you really should go back to the start and follow a formal software development approach. This will allow you to set out the requirements for your software or game and the design the necessary functions before doing any actual programming. Essentially this means writing it all down and getting everything straight before committing anything to code. Once at this stage you can then select a suitable programming language to implement it in and then actually write and test it - at this stage you’ll know how complex it is and whether codea is up to the task.
thanks for your answers.
@Luatee mmm complex… Like 20-40 tabs, 5000 lines, many objects. At some point i need to duplicate code over and over again to make new objects, so i think i should make a class and build those objects from this class. So what properties should i define in the the class? So i have to think more general, and many choices are possible, and i dont really knwon what rule i should follow to make these choices.
@West good advice. But what i want is to write some open bricks i can build on, to make an open program always evolving, not a well defined and closed program. And i want to be able to make these brick easily evolve, along with my next views. Maybe this is just not possible. Actually i have an example of nice environement i can make huge and easily evolving very complex programs: at work i use mathCad, which is great for defining and verifying small functions, and building bigger functions from them, etc… When i try to follow the same paradigm with Codea, i just fail at some point.
Any other advice is welcome!
@Jmv38 - Nope, its not you, its not Codea/Lua - its just the nature of software development in general when you get over a certain size and complexity. Like @West says, then you need to start being quite rigourous with your development methodology to prevent things getting unwieldy.
From experience, I try and keep things reeeeeally simple:
Overzealously comment everything that does something useful. Most of my refactoring angst comes from code I wrote months ago and I cant remember what a chunk/function did. This is especially true for functions/classes which have defined entry/return values.
I make things super readible and the code easy to follow, even if its not the most Lua-expert efficient way of writing the same thing. (This is a trick I learnt from my Python ‘other life’ - there are lots of super efficient Python shortcuts for doing things in 1 line, that would usually take 5. Great, but I want to follow my code really easily - readibility at the expense of uber-efficiency!)
Classes can really tie your brain in knots! I use them with a lot of restraint (and respect!) as they can quickly make code far more complex than they need to be if not used properly, especially if you have classes that reference other classes and methods which can then be a nightmare to debug and refactor. I tend to keep a hand-drawn chart handy with all my classes/properties/methods, so I can visualise whats going on and what the relationships are.
Further to the last point, there is no substitute for paper and a pen for doing simple graphical flowcharts and structure diagrams to help with this process. I dont think Codeas ‘linear’ tab system helps organising things visually when you get over a certain size - im constantly flipping between tabs and scrolling to find them. Something, a bit more freeform would help.
However, unlike other ‘pro’ software development IDE’s I dont think Codea/Lua make things easy when code gets over a certain size - especially in respect to debugging and monitoring values/classes etc. Whilst Lua supports some useful functionality through commands such as ‘assert’ and the debug library. It would be nice to have some higher level tools in Codea as wrappers to these to make them easier and more intuitive to use.
I have always ran into a wall when my project starts getting large, it becomes harder to refacter older code. This has lead me into duplicating functionality. Not to mention breaking something when I add new features.
I’ve been using python a lot and really like unit test based development. I’ve started writing tests for my code before actually writting code. I create a test that should show the result I want. I write code until it passes. Then I write annother test for the code and code some more untill it passes. I have found that this make it a lot easier for me to manage code. I write cleaner code and refactoring is rather easy becuase I can immediatly check if my tests pass. I also try to document my code the best I can. This has really helped me when working on larger projects.
I’ve started working on an implementation of unittests for codea.
It does get a little unwieldy but I guess it’s just the nature of things. I try to have one control tab and I bring the tabs I am working on closer together while I work on them.
Having code in other languages/platform, I must say Codea is a much simpler platform for me. Slower cut/paste and find/replace on the ipad is the only drawback.
It really is the same problem as any language faces, further compounded by the difficulty of using a lightweight IDE on an iPad.
The key is classes, but don’t get idealistically OO about it, break them up to encapsulate different areas/problems so you can worry about one problem at a time. Eg: class for drawing, class for movement/AI, class for internal repeatable bits. For example, I did a skeletal animation thing which is hard but not huge amounts of code. I had a class for the mesh which included rendering it, and a separate class for the skeleton itself, which after setup you just use simple methods for setting joint rotation, and otherwise don’t touch it. The mesh class doesn’t do anything to the skeleton apart from retrieve the matrices from it. The logical breakdown is key.
And writing it down/drawing a diagram when it gets too big to fit in your head. As to where the lines should fall, there’s no easy answer apart from learning from how you did it badly, and doing it better next time.
@spacemonkey thanks for the advice. Could you point the link to your code so i can study it from this pov? Thanks.
I have a collection of library projects where I store all my “general” code. When I write something to go in one of those then I try to make it as general as possible and anticipate the most likely uses of that code. I also try to make it so that if I need to edit this code then I only add to it.
I use toadkick’s
cmodule class for actually loading these projects, but it would work just fine with the import feature.
The libraries are organised by “type”, so I have
Library Base for stuff that is pretty much included in every project.
Library UI for my user interface stuff (menus, selectors, that sort of thing).
Library Maths for anything mathematical. And so on.
@Jmv38 My paint app, although not complex to make, is over 9000 lines in code with 37 classes. I find it really helps to take a lot of time to think in an object orientated way so if I find that a piece of code that needs to be used more than once can be replicated in a class form as it needs to be initialised and use the touch and draw functions then I will basically move all my variables in to the init function adding the self. before hand (obviously) and then add the draw and touch parts I use accordingly. I will also use it to clean up my main function to as small as possible (around 200-300 lines max) so anything that is used like a grid or a menu can be put in to a class to neaten things up. You probably know most of that already. I find that having three rules for making a class and those are:
Does it neaten things up a lot.
Will you need to use it more than once.
Does it make things easier to handle in general.
I also will make a class for a physics object, say if its a box, put the mesh and the physics body inside it and anything else like a freeze function or an applyForce function whatever comes to mind, although there is a more efficient way of drawing it than creating one mesh for each body (if they have the same texture).
@Andrew_Stacey thanks for the guidelines.
The problem i have is with the then I try to make it as general as possible and anticipate the most likely uses of that code : i do the same, but this tends to make the code very complex to manage every case, and eventually difficult to maintain. After long periods of work on a library trying to be general, it is usually an intense relief just dto make a program without trying to be general: everything seems so much simpler then. This is why i wonder if i am really on the good track there. One of the forum contributor once emphasized he just tried to be KISS, and that shaked me a little bit: my own attemps were anything but KISS…
@luatee i thought about your app as a good example of a successful complex program. So you advice is quite worth listening to!
The problem i have with classes is the init(): when a class derives from another, the init part of the mother class is overwriten, and there is something that is not right there. There are turn arounds, but they dont look ‘nice’. Often i end up with 4 or 5 levels of class inheritance, and maybe this is my mistake. Maybe i should keep with only 1 level classes, and no inheritance from mother classes?
The event mechanism that was described in another thread turned out to be a very useful tool, at least to explicitly declare dynamic relationships in a single location (i tend to put them all at the end of the init()), which helps to get a better view when maintaining (but not for debugging).
@Jmv38, how about using a code documenter? It will help document your project based on comments that you include. The output is XHTML, so should be nicely linked and include a table of contents. A quick Google found http://keplerproject.github.io/luadoc/.
I’m not sure if you can use it directly to help with your issues, but it will help keep track of functions and classes and their dependencies, inputs, outputs, etc in a reference document that covers a whole project.
@Jmv38, your frustration makes total sense. But the situation is not unique to Codea. Pretty much any non-trivial project, on any development platform, is destined to reach the point, where it starts to crumble under its own weight. Developers then start talking about re-factoring, because they no longer are able to keep everything straight in their heads. I don’t think it’s necessarily bad though, because if successful, the end result of refactoring is usually better code, better design.
Also, in my experience, it is necessary to go through a phase like that. In the beginning of the project, you don’t really need the generic one-fit-all tools, complicated class hierarchies and such. They can actually be more harmful than helpful. Instead, you want something simple and working, because progress is what keeps you motivated to continue.
With regard to the solution of the problem - there is already excellent advice in the posts above, so i won’t repeat that. Just wanted to add one more thing:
What i found useful to do, when project reaches certain size, is this: get your code out of the iPad and into a computer. Look at it in your favourite IDE , or in a text editor of choice. Bigger screen lets you see more of the code, and sometimes it’s all you need. Also, it is easy to do sweeping changes, like moving around large blocks of code, etc. Once the refactoring is done, get the project back onto the iPad and continue on there.
@Jmv38 I’m pleased to hear that! I’m where you’re at with levels in classes at the moment, I have one approach I have now is to have a LevelVertices class (if using box2D for a world body and other items such as dynamic bodies etc) that defines where the bodies are and and the vertices for them, I also use a class for dynamic bodies with the same idea, I have a models class that contains the vertices for each named model in a table along with other information about it. Using this LevelVertices class as a class that contains all the levels with the information for all the levels entities and dynamics I can get each individual class using LevelVertices:init(x) use the x to define the number of the level wanted, then get this class to return all the corresponding bodies and other info. Then I draw all the bodies and backgrounds for each level in the Level class using the same method of using a number to index a level, this creates a miniature hierarchy of levels that can be created and changed to by calling a Level:change(x) function which is quite lengthy so it’s not as neat as I’d like, but it does the job.
In my building game I have the levels set up as above along with children classes such as entities, effects, grid (on/off for the level), I put the ropes in there too. As these are all specific to different levels.
@Jmv38 I think you misunderstood what I meant by: “Then I try to make it as general as possible and anticipate the most likely uses of that code”. I definitely don’t try to add all possible uses right then and there. What I try to do is make it so that I can do so later on if I want to. So I try not to set up anything that’s going to annoy me later on, but I don’t necessarily add all the functionality that I can think of.
This generally means simply being abstract and trying never to hard-code any numbers. So, for example, in my complex numbers program then at first I would be sure that the square root of minus one is
i and always write it as such. But future proofing my code would mean that as some write it as
j, I’d define
Complex.symbol = "i" and use
Complex.symbol instead of
i throughout. But I wouldn’t write code that made it easy to redefine
Complex.symbol until I actually decided that I wanted it.
I hope that makes a little bit of sense.
@juce - wise words. I’m also a huge advocate in prototyping things first, get a functional version working as quickly as you can and dont get too precious about it - including coding style. All the problems, dependencies, flow and data structures tend to shake themselves out of this process and can then be used to understand what the core functionality is.
This is actually what Codea is really good at doing.
Then… start again from scratch.
I think much of the problems stem from carrying over functional prototypes into the refactoring phase and getting hung up too much on being to precious about whats been coded already. Much better to take a step back and look at the architecture of a project from scratch with a fresh pair of eyes and learn from what was good and bad about it.
In reality, this is really hard to do - as we tend to get quite attached to our code (me included) - but im slowly getting the hang of this way of thinking and its quite liberating. Im about to refactor my racing game as I learned so much from my functional prototype and now have a much clearer direction when I re-write it, including all the low-level base classes etc…
This might not work for everyone, but is another approach…
@time_trial thanks for the interesting link. An automatic documentation tool should help, indeed. Have your tried to pull a version working with codea? The link you give seems to be quite a big project with dependancies and so on…