Code review for a WIP

A simple project I’m working on.
When complete it will be a physically accurate (as much as you can get from a phone anyway) Sun, Earth and Moon orbital mechanics simulator.

I’ve taken no classes, I’m brand spanking new to programming in LUA. I’ve dabbled with python but only on my phone through Pythonista.

My question is, just based on what’s available in the project, am I breaking any particular conventions? Am I using the tools available appropriately? Or is this a terribly confusing horrific mess and I should just stick to licking windows??

Just some feedback is all I’m looking for.
Thanks!

3Body.zip (3.4 KB)

Hi!

There’s nothing that I can see that stands out as being ‘wrong’ style-wise so far.

I’ll note though that your surfaceGravity() functions all return strings currently. If you expect to do further calculations on those values, use the tonumber(string_val) function to convert the type.

Hope this helps!
Steppers

1 Like

Exactly what I was looking for. Thank you.

Completely blows my mind there’s no math rounding feature built in…

I’ve rewritten the functions as:

function Star:surfaceGravity()
    -- Returns the surface gravity of the star in m/s^2 rounded to 2 decimal places
    return tonumber(string.format('%.2f',((G*self.mass)/(self.radius^2))/10^6))
end

Nice catch.

1 Like

Given the discussion over on the math library thread perhaps we should add some basic math functions like math.round

2 Likes

I use rounding quite a bit in calculations to avoid precision errors. I can accept being off by a few hounded thousandths due to rounding than significantly off due to precision errors.

everything looks fine to me, you have the basic started now keep building

here is my expert level critique that is given to make you think not to imply you are wrong
(best practices and conventions are best because someone said so)

1 - avoid global definitions, there at least 3 different places globals are set, if you really want globals at least keep them in the same place
2 - DRY (do not repeat yourself) , notice how all three types are basically the same with some possible internal key differences, are these 3 bodies really that different that each needs its own class or could they all be one class with a few if else
3 - rounding and performance - i came across a few times when i had to round to the nearest hundredth because any more precision results in data shifting but not significant screen rendering changes, imagine for example you are rotating your bodies and have to calculate everything every frame, the smallest .0001 value change will cause a recalc but if you round you can avoid a recalc when one isn’t really needed, in sims we never actually calculate physics correctly it’s always a best approx

1 Like

Thank you for the feedback.
If you have a moment can I pick your brain?

  1. Is it generally a better idea to define a global once and use it everywhere it’s needed, or the same value as a local in multiple places?

  2. I built the classes without a firm understanding of how nil values would be handled later in code. According to single responsibility principle I should handle all physics related interactions outside of the class correct? Or would it make more sense to condense it all so that the class is a complete representation of the body and its related interactions?

Apologies for being ignorant here, I have zero real world experience and I’m just trying to learn it as I go.

1 - generally better to have local values but because the scoping in Lua will check that first, the farther away in scope you are from global the more steps to find the reference, however the performance of the cpu also matters, this type of stepping issues would have mattered 10 years ago but with Mx+ chips and A14 bionics+ i don’t think as many performance issues exist so you are a bit more free to work with globals and deep nested functions

2 - this is where you have to look at your project like a pyramid and turn it upside down, you want the least amount of things happening at the point of drawing, the most to happen further away from drawing - this is where i personally deviate from single responsibility, it’s almost impossible to make everything single responsibility so instead i practice Composition where you build an entity based on pieces - so in this sim i would have Body class which has all possible keys for bodies, then i would make a Sun class that has
self.Body = Body(options)
when i need Sun to have something special i define it in Sun and use self.Body to input/output data that is similar for all bodies

do not worry about being a self taught beginner, keep training and trying different things and expect that sometimes you work a lot on a project that doesn’t work but you will learn a lot about why it didn’t work

1 Like

That is exceptionally helpful.

So a Body class could handle any data points that are common among all bodies while another class could handle body specific data points. Would calling this a nested inheritance be accurate? Never thought to even try that.

nested is one way to look at it, but each “nest” is a full init of the other class

there are two techniques to facilitate event/data communication between these -

pass the current self as a parent, and also subscriber/publisher algorithm

so in theory:

self.Body = Body({ parent = self })
and
self.event = SubPub:on('myEvent', function() do stuff end)

elsewhere

SubPub:send('myEvent')

1 Like