This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Bubba's profile picture

Eight Good Coding Habits

Started by Bubba, 30 October 2012 - 02:42 AM
Bubba #1
Posted 30 October 2012 - 03:42 AM
Props to Lyqyd for pointing out some errors in my tips
Lua is an incredibly versatile programming language. Many things that one would think to be incorrect will run correctly in Lua, and in some cases that's a good thing: Usually though, it's not. When you begin to write long programs (and by long, I mean multiple files and mind-blisteringly complex interweaving of functions), things that you started writing at the beginning of the program are not going to be as obvious several months later as they were when you first wrote them. Bad coding practices in this regard will kill your program in readability and functionality if you're not careful, so try to make these simple programming practices a habit so that life doesn't suck later.

1) Make comments on you own code. You're probably rolling your eyes right now thinking, "I know what my own code does. Why should I put comments on it?" And that's a valid question. Today I was looking back through some several month old code of mine and I didn't even know what the thing was supposed to do, let alone how I was supposed to utilize it. Figuring out its purpose would be nearly impossible without painfully going over every single function and testing them individually. So unless you want to rewrite your code every few months, or if you enjoy that painful 'decompiling' process, don't forget to comment as much as possible.

2) Indentation. I can't stress this one enough. When you're inside of an if statement inside of a for loop inside of a while true do loop inside of a function, your code gets really messy really quick. If you don't indent everything, you are going to absolutely hate life later on when you find get an eof or 'end expected' error and you have no idea why. So yeah. Indentation is important.

3) Be concise: If you are making a function that moves a turtle forwards 12 spaces, don't name it 'thisisafunction()' because somebody looking at your code will have absolutely no idea what it's supposed to do without parsing it out. And it will suck if that somebody is you twelve months later.

4) Use the right tool for the job and be consistent about it. If you think that an ipair loop would fit a certain situation and that situation comes up later, be consistent and use the ipair loop again. Coding consistently is enormously helpful when you find yourself using the same tools over and over again because you become familiar with how you should go about different situations.

5) Remove unnecessary code. This one seems like a no-brainer, but you'd be amazed at how lazy the average human being is (or maybe you wouldn't). I often find myself just ignoring the fact that I don't use a certain function in an API and adding new things just becomes confusing when you keep looking at the unused code to see what it does. Another reason to remove unnecessary code is that it makes the whole program just 'better' and more satisfying than when the whole thing is a rag-tag mess. Making a complex program using only a few ingenious lines of code is the most enjoyable thing in programming, in my opinion :)/>/>

6) Take breaks. If you're stuck on a problem, don't sit there and stare at it for ages trying to figure it out. Go grab a drink, eat some cereal, or play a game to take your mind off it for a while. Better yet, go and take a nap. When you come back, I can promise you that you'll be able to solve the problem much, much quicker than you would otherwise.

7) Try to make an 'outline' of what you want your program to do and how you might want to go about it. This mostly only applies to long and/or complex programs, but if you're having difficulty writing anything, an outline will help out enormously.

8) Program in a way that fits you: If you program best jumping about from function to function, program like that. If you program best completely finishing each function before moving on, program like that. The unique thing about programming is that there are an infinite number of ways to go about a problem. If you have trouble working in a certain way, don't force yourself to do so.

If you take to heart these eight simple coding habits, I promise you life will be infinitely easier when you're faced with that mega-challenge you've been wanting to solve for a long time.

Thank you for reading,

Bubba
Edited on 18 February 2014 - 07:19 PM
Dlcruz129 #2
Posted 31 October 2012 - 03:05 AM
Another idea: always, always, ALWAYS, use local variables unless the program calls for global variables.
Lyqyd #3
Posted 31 October 2012 - 05:25 AM
1) Make comments on you own code. You're probably rolling your eyes right now thinking, "I know what my own code does. Why should I put comments on it?" And that's a valid question. Today I was looking back through some several month old code of mine and I didn't even know what the thing was supposed to do, let alone how I was supposed to utilize it. Figuring out its purpose would be nearly impossible without painfully going over every single function and testing them individually. So unless you want to rewrite your code every few months, or if you enjoy that painful 'decompiling' process, don't forget to comment as much as possible.

I would stress that the why of the code is far more important than the what of the code you're commenting. Why do we need to take the third character of the string and convert it to uppercase? Oh, because this other function we're calling needs it that way. So instead of "convert the third character to uppercase", something like "checkCharacter() requires its input to be uppercase" where that code is will be much more meaningful. The code will tell you what it's doing usually, but it can be much trickier to figure out why it needs to do that.

3) ALWAYS return something when you exit a function. I know it oftentimes seems unnecessary, but trust me when I say that debugging is a pain in the ass if you don't return something printable.

As with everything, there are exceptions to this rule. Sometimes nil or a boolean is all a function needs to return. Just know when to use what.

4) Keep your programming consistent. What I mean by that is don't sometimes use ipairs loops and other times use fori loops, unless of course the situation absolutely calls for that inconsistency. Things often become confusing when you mix and match your code.

This falls more under "use the right tool for the job" rather than "be consistent with your tools". You can try to drive a screw with a hammer, but damned if it isn't going to suck. Each of those things has their place.

6) Take breaks. If you're stuck on a problem, don't sit there and stare at it for ages trying to figure it out. Go grab a drink, eat some cereal, or play a game to take your mind off it for a while. When you come back, I can promise you that you'll be able to solve the problem much, much quicker than you would otherwise.

Better yet, go sleep on the problem. It's relatively well-documented that your subconscious will continue working on problems long after your conscious mind has moved on to other thoughts.

7) Program in a linear manner. When you program, do you find yourself jumping about from function to function, leaving some unfinished and others with errors in them? If you do, programming big programs will be extremely difficult. When you start a function, don't stop until you either finish it or you do away with it in favor of something else.

8) Program in chunks. This one is sort-of related to the previous point in that you should focus on certain aspects of a program and complete them before moving on to something else. For example, if you're making a mining program which sorts items based on ID, you might want to focus on the comparison of items first before moving on to navigation.

Neither of these are quite right. For the most part, program how it works best for you. Some people find it easiest to crank out code from the top of the file to the bottom and very infrequently jump around until the initial code is all written. Some people use a more figurative top-down approach where they write out the flow of the program using placeholder functions and then go flesh out what everything actually needs to do a bit at a time, until all the details are there. There are a myriad ways to program. Don't try to force yourself into a certain method of doing so. As long as you're creating good code, I wouldn't worry about changing your process. That said, if you're having trouble with getting lost or being unable to keep track of what you're doing, you might consider changing the way you write code.

All in all, a good post, Challenge.Accepted. Hope you don't mind me adding my thoughts!
ChunLing #4
Posted 31 October 2012 - 08:44 AM
I find that it can be very helpful, when you go back over a code with "fresh eyes", to not have any comments on what the code is supposed to do or even why it is supposed to do it. This isn't to say that comments aren't valuable, but if you are going to substantially revise a code later, you might consider having a version that has no comments so you can really approach it fresh. Of course, you don't want to throw away the version that has all the comments, particularly if the code is very complex.

Also, try to distinguish between your comments on something that the code really does and comments saying what you want it to do.
BigSHinyToys #5
Posted 31 October 2012 - 10:14 AM
Writing code in a IDE or word pad designed for development is also a good idea. trying to write code in Microsoft office is not going to end well where as Notepad ++ will help you with highlighting and showing start / end of blocks. Most of the bugs I have fixed in code posted in the "ask a pro" section have been from placing it in Notepad ++ and adding indentation till i find where a missing end is or problems like using "else if" instead of elseif and putting an end for elseif's is also common.

I have been doing most of the tips already I put a header with intended purpose / other relevant information at the top as quick reference I don't comment or have returned values < I may conceder doing this thought. I work form the start of a program to its finish making and testing every function in turn until I have a working program. I don't jump around inside my code much. My main problem is I don't plan out how I want my code to look / what function / structurer at the start I sort of wing it with a basic idea of intended function. This leads to unintelligent solutions for problems that may have never existed had I coded a different way.

Seeing as I want to move to a more powerful language I think I will incorporate some of these tips into my "coding style" .

Thanks for the tips
KaoS #6
Posted 31 October 2012 - 11:34 AM
I find that writing code strictly in functions helps. I will never write a code for a specific menu, I will always write a generic menu generator and use it later, I also store most data in tables etc. basically I try to categorize my code into a function and table for one thing and another function and table for another thing. it keeps things organised, makes bug testing easy as you just test each function and the actual executing part of the code is about 5 lines long, easy to rearrange and change as needed. you will also find that if you keep all generic functions in a single file you end up coding less and less to make stuff 'cos you already have functions for everything… it is a long term tactic but is great in my opinion

-perfectionist coder out

EDIT: Oh yeah, great thread man. kickass stuff
kazagistar #7
Posted 31 October 2012 - 05:49 PM
While I agree with KaoS that more abstraction is needed by a majority of the newer programmers here, there is a danger of overabstraction. If you create a "menu system" and then only use it to build one menu, you have wasted time. Often, the best approach is to only abstract once you are actually building the second menu, and then refactor the first.

If you copy and paste code within your program, you are probably not abstracting enough.

If you have functions you only use once, you are probably overabstracting.
Bubba #8
Posted 31 October 2012 - 08:46 PM
Good stuff
Yes I agree with pretty much everything you said and have shamelessly stolen some of your points and modified my post concordantly.

I should also mention that not all individuals will find that these tips apply to them - as you said, some people do skip around when they're coding, and they can do just as fine a job as someone who does not. If one of these things doesn't work for you, don't try to force it. Find a workflow you like, and utilize that workflow to your advantage. Some things (indentation for example) are in my opinion indispensable - others however are up to you.
Learning_inpaired #9
Posted 20 December 2012 - 03:07 PM
Bumbed!
Tiin57 #10
Posted 20 December 2012 - 03:58 PM
-.-
Bumbed!
Why do you persist in bumping?
Bumbed!
In http://www.computercraft.info/forums2/index.php?/topic/4222-frequently-asked-questions/page__p__62101#entry62101
Stoppit.
sjkeegs #11
Posted 20 December 2012 - 04:50 PM
Here's another tip:

If you are programming something to do X, write the function that does that by just writing the comments. Once you convince yourself that the comment flow is correct then add the actual code.
Doyle3694 #12
Posted 20 December 2012 - 11:25 PM
Ehrm…. How would that work, @sjkeegs ?
Mikeemoo #13
Posted 21 December 2012 - 12:36 AM
Ehrm…. How would that work, @sjkeegs ?


function gotoMyFurnace()
  -- find current  position
  -- grab the position of the furnace
  -- move x times in x direction

  -- move y times in y direction
  -- move z times in z direction

end

Evolves to..



function getCurrentPosition()
  -- return current position
end


function getFurnacePosition()
  -- return furnace position
end
function getRelativeCoords(from, to)
  -- return relative coords
end
function moveBy(vec)
  -- move the turtle by vec (x, y, z)
end
function gotoMyFurnace()
  local currentPosition = getCurrentPosition()
  local furnacePosition = getFurnacePosition()
  local relativeCoords = getRelativeCoords(currentPosition, furnacePosition)
  moveBy(relativeCoords)
end

Evolves to…




function getWaypoint(key)
  return waypoints[key]
end

function getCurrentPosition()
  -- gps.blah
  return { x=, y=, z=}
end


function getFurnacePosition()
return getWaypoint("furnace")
end

function getRelativeCoords(from, to)
  return {x=from.x-to.x, y=from.y-to.y, z=from.z-to.z}
end

function moveX()
  -- face x
turtle.forward()
end


function moveY()
  -- face y
turtle.forward()
end


function moveZ()
  -- face z
turtle.forward()
end

function moveBy(vec)
  for x=1, vec.x do moveX() end
  for x=1, vec.y do moveY() end
  for x=1, vec.z do moveZ() end
end

function gotoMyFurnace()
  local currentPosition = getCurrentPosition()
  local furnacePosition = getFurnacePosition()
  local relativeCoords = getRelativeCoords(currentPosition, furnacePosition)
  moveBy(relativeCoords)
end

..etc..etc..

(this is obviously badly written code that would never work, but you get the idea)
sjkeegs #14
Posted 21 December 2012 - 03:07 AM
Ehrm…. How would that work, @sjkeegs ?


function gotoMyFurnace()
  -- find current  position
  -- grab the position of the furnace
  -- move x times in x direction

  -- move y times in y direction
  -- move z times in z direction

end

Evolves to.. ..etc..etc..

Yes, Essentially you write the code in comments. The process of doing that makes you think about how you are implementing it before you start to write the code. You find errors in your structure before you start writing anything. If you get half way through and your discover that your implementation isn't actually going to work, you haven't wasted time building code that you are going to have to throw away. It's also easier to recognize that the implementation is wrong and start over. It curbs the desire to muddle through on a design that doesn't quite work. An added bonus is that when you are already done your code should already be commented - No need to go back and do that. You end up with comments that are a better description of the code flow. (You are less likely to have a comment like // increment counter by one)
ChunLing #15
Posted 21 December 2012 - 06:52 AM
I think that Doyle was asking how the function would do anything just by being full of comments.
–snip–
If you are programming something to do X, write the function that does that by just writing the comments.
–snip–
Clearly, this is not the intended meaning. It just happens to be the literal meaning of the actual wording of the post.

In a situation where the apparently possible intended meaning of a post does not match the literal meaning (particularly when the literal meaning is apparently impossible), it is appropriate to ask about the intended meaning. It may be considered less appropriate to focus on the impossibility (or mere silliness, as the case may be) of the literal meaning. We all mess up our literal meanings sometimes.
Loki #16
Posted 04 January 2013 - 05:41 PM
Well, I'm glad I follow 6 out of 8 of these habits. Time to take a nap, I guess…. Or eat some cereal…^_^/>
PixelToast #17
Posted 04 January 2013 - 08:19 PM
the only ones i dont follow are 6 and 7
i dont take verry many breaks and i dont really have an outline for things im making :s
Leo Verto #18
Posted 05 January 2013 - 03:26 PM
I also don't follow 6 and 7, I sometimes spend hours fixing a problem, then finding another one, and another one, etc until my code works.
I think I should organize my coding better by making an outline and adding comments that explain why a function is coded as it is (as immibis explained above).
I did not know about always making a function return stuff, now that I read about it it seems to make sense but a lot of programs I read don't do it.

I think properly naming your arguments is another important point, unless you don't want anyone to be able to read your code.
ChunLing #19
Posted 05 January 2013 - 05:21 PM
Eh, if we're all talking about which ones we don't follow, I'm not very consistent about following any of them. I only comment for the benefit of others, and I suck at it. My indentation is an atrocity. I only bother to put in returns when I'm definitely using them. I have pet functions and control structures. I almost never entirely remove a function, even if I never use it. I obsess over a code till it works. I have a vague concept rather than an outline. And I'm pretty sure that all of this is not "coding in a way that suits" me.

So I try to do whichever of these I happen to remember when the moment is appropriate. I do them "sometimes". Maybe trending up, maybe not.

They're all good ideas.

But I don't do "good" ;)/>
Luanub #20
Posted 05 January 2013 - 05:30 PM
It all depends on the script I'm working on on which ones I follow. Small simple scripts I pretty much do not follow any of them while the larger projects I follow most of them. I do not do a lot of commenting since I pretty much know whats doing what. The only time I return something is if I am going to use it. I'm absolutely horrible about taking breaks, once I start working on a specific part of a script I don't like to stop until I have it functioning as desired.

For someone that is just getting starting I think these are some good guidelines to put in place until you become a little more comfortable with what you are doing.
shiphorns #21
Posted 30 January 2013 - 07:42 PM
When I got started last week programming the mining turtles, I realized very quickly that one important habit is to ALWAYS handle all possible return values of the API calls. The difference between a robust turtle script and a fragile one is how thoroughly all the contingency cases are handled. I see a lot of new coders just calling the functions like turtle.forward() and just hoping they succeed, rather than checking that they do…
Frederikam #22
Posted 30 January 2013 - 11:51 PM
Code Kiddie (That title fits my coding very well) approves this.
digipenguin #23
Posted 31 January 2013 - 11:42 AM
I also have to strongly reccommend that you use an external editor, such as Notepad++.

It allows for better highlighting and also helps to enforce all of these 8 coding principles.
pooluke41 #24
Posted 01 February 2013 - 10:05 AM
This thread is gonna help me alot. :wub:/>
Grim Reaper #25
Posted 02 February 2013 - 12:24 PM
Something that I didn't see on this list, but I think should definitely be there is how pertinent variable and method names are in a script.

This rule kind of goes without saying, but a lot of people seem to write code which has very simple or just entirely irrelevant variable and function names (like 'x' or 'derp', for example) in their scripts. Using a relevant naming convention improves readability a ton and also helps the programmer to understand their own code better.

Also, a naming convention such as camel-cap for variable/function names is usually a good idea. However, naming conventions/styles are entirely up to the programmer.
Bubba #26
Posted 02 February 2013 - 01:52 PM
Something that I didn't see on this list, but I think should definitely be there is how pertinent variable and method names are in a script.

This rule kind of goes without saying, but a lot of people seem to write code which has very simple or just entirely irrelevant variable and function names (like 'x' or 'derp', for example) in their scripts. Using a relevant naming convention improves readability a ton and also helps the programmer to understand their own code better.

Also, a naming convention such as camel-cap for variable/function names is usually a good idea. However, naming conventions/styles are entirely up to the programmer.

I changed #3 from "Always return a value" to "name your functions/variables something that makes sense". Now that I think about it, returning a value is not really always needed.
PixelToast #27
Posted 02 February 2013 - 01:54 PM
when i cant think of a name i just find an achronym or short name for it
like this:
local Mx,My=term.getSize()
local Cx,Cy=math.floor(Mx/2),math.floor(My/2)
Max X,Max Y
Center X, Center Y
see here (at the beginning of all render functions)
Bubba #28
Posted 02 February 2013 - 01:57 PM
when i cant think of a name i just find an achronym or short name for it
like this:
local Mx,My=term.getSize()
local Cx,Cy=math.floor(Mx/2),math.floor(My/2)
Max X,Max Y
Center X, Center Y

I do that too at times, but when it comes to bigger projects I like my variables/functions to be named pretty clearly. The time it takes to type them out is negligible in comparison to the time it takes to read an entire function again in order to figure out its purpose :)/>
PixelToast #29
Posted 02 February 2013 - 02:13 PM
its universal in that case, for other things i have more descriptive names
local tpe,id,data,dist=os.pullEvent()
local rData=infutil.decompress(data) or {}
see here
its still confusing if you dont know what it does though >_>
KaoS #30
Posted 03 February 2013 - 01:32 AM
personally I just use the shortest pertinent names possible, they often do not make much sense but it makes coding it a lot faster and easier for me as I tend to think faster than I type/speak which confuses things sometimes. afterwards I just replace all instances with correct names
KillaVanilla #31
Posted 03 February 2013 - 03:46 PM
A tip I've had to learn the hard way several times over: Organize your code. Especially your function definitions/bodies. Keep them close together. Seriously, if you're working on one part of your program, you're gonna want to keep those parts close by and organized; if you spend 30 seconds just trying to find a function, you need to fix that. Also, put most of your program-wide variables at the very top (or at least close to it). Control+X/Control+V is all you need for this.

For example, instead of having:

local frequency = 0
local function receive()
    ...
    ...
    ...
    ...
    ...
    ...
end

local function escape()
    ...
    ...
    ...
    ...
    ...
    ...
end
local ingredients = {}

local function wheee()
    ...
    ...
    ...
    ...
    ...
    ...
end

-- insert 350 lines of other functions here


local function makeCake()
    ...
    ...
    ...
    ...
    ...
    ...
end

local function send(freq)
    ...
    ...
    ...
    ...
    ...
    ...
end

local function blam()
    ...
    ...
    ...
    ...
    ...
    ...
end
local cakes = {}
have:


local cakes = {}
local ingredients = {}
local frequency = 0
local function makeCake()
    ...
    ...
    ...
    ...
    ...
    ...
end

local function send(freq)
    ...
    ...
    ...
    ...
    ...
    ...
end
local function receive()
    ...
    ...
    ...
    ...
    ...
    ...
end

local function escape()
    ...
    ...
    ...
    ...
    ...
    ...
end

local function wheee()
    ...
    ...
    ...
    ...
    ...
    ...
end
local function blam()
    ...
    ...
    ...
    ...
    ...
    ...
end
-- insert 350 lines of other functions here
Lyqyd #32
Posted 08 February 2013 - 08:56 AM
A text editor with code folding helps tremendously in that regard as well–I can simply fold the functions I am not working with and easily concentrate on the ones I am working with. Especially helpful when there are common functions needed by multiple groups of other functions, making them unable to be very close to all of the functions that need it.
baeshra #33
Posted 26 February 2013 - 03:12 PM
As a beginner in this field I know I have an odd coding style. How do most people organize their longer scripts? I tend to lay my code out under functions which allows me to re-order it easily, is there a better way to go about this?
shiphorns #34
Posted 05 March 2013 - 11:53 AM
As a beginner in this field I know I have an odd coding style. How do most people organize their longer scripts? I tend to lay my code out under functions which allows me to re-order it easily, is there a better way to go about this?

It depends on what scale of organization you're talking about. In a small program, it makes sense to put code in a function to organize it, especially if it's called from more than one place. Lua is a procedural programming language, so it is natural to organize using functions. There are some people experimenting with pseudo-OOP organization, but this is largely an academic challenge for them, and it's a bit of banging a square peg into a round hole if you ask me. That is to say, Lua was not designed for OOP, so the results of that experimentation tend to be ugly and cumbersome manipulation of metatables (reminds me a bit of ActionScript 1.0 OOP attempts with prototypes). You shouldn't go that route IMHO. If you're working on a really large project, then at some point it may be worth your while to identify code than you'll want to reuse in other programs, extract it into code libraries that you include with require, or if they are really generally-useful functions that you can generalize to be not specific to your programs, make them into APIs for you or others to use (if you have the access to install lua files on your server).
theoriginalbit #35
Posted 05 March 2013 - 12:37 PM
That is to say, Lua was not designed for OOP, so the results of that experimentation tend to be ugly and cumbersome manipulation of metatables
It actually WAS designed for OO, that is why we can manipulate metatables.


You shouldn't go that route IMHO.
I'm assuming you're another one of those people that prefers procedural programming over OO any day?

extract it into code libraries that you include with require
Doesn't exist, don't suggest things to newbies that don't exist, just causes headaches for us all later http://puu.sh/2cdch
shiphorns #36
Posted 06 March 2013 - 05:57 AM
That is to say, Lua was not designed for OOP, so the results of that experimentation tend to be ugly and cumbersome manipulation of metatables
It actually WAS designed for OO, that is why we can manipulate metatables.

No, it was not "designed for OO", it was designed to be very flexible. This is why Lua does not have built-in syntax for classes, inheritance, encapsulation and access modifiers, etc. You can implement many aspects of object oriented design, but it's cumbersome and you have to reinvent the wheel a bit to do it, writing the OOP infrastructure yourself. While I think that many people consider Lua capable of supporting OOP concepts, it's a bit misleading to say that it was designed for OOP.

You shouldn't go that route IMHO.
I'm assuming you're another one of those people that prefers procedural programming over OO any day?
No sir, I'm a game UI programmer by trade and I mostly work in C++ and AS 3.0. I'm an OOP guy through and through, and only use Lua when I have to.

extract it into code libraries that you include with require
Doesn't exist, don't suggest things to newbies that don't exist, just causes headaches for us all later http://puu.sh/2cdch
Ugh, that is unfortunate. Hopefully the CC guys are working on this, but it does explain why we have so many programs here that are giant 1-file monoliths.
immibis #37
Posted 06 March 2013 - 09:10 AM
There are dofile and os.loadAPI
Roadhouse699 #38
Posted 08 March 2013 - 12:04 PM
I feel so good about myself, I do almost all this stuff!
Pharap #39
Posted 08 March 2013 - 04:40 PM
I highly agree with points 6 and 8.
Though 8 is mostly because I approve of gotos lol
No sir, I'm a game UI programmer by trade and I mostly work in C++ and AS 3.0. I'm an OOP guy through and through, and only use Lua when I have to.

Ugh, that is unfortunate. Hopefully the CC guys are working on this, but it does explain why we have so many programs here that are giant 1-file monoliths.

What sort of libraries do you use out of interest?
I've used windows forms, but beyond that I've only used the ones I've written for use in XNA games.

There is OS.loadAPI. If that doesn't suit you, you can always write your own API loader/importer. Since code files in lua are run as functions I make pretty much all my APIs return a local table that the user can assign to whatever variable they wish (like you can in C#, sort of).
Btw, you'd hate my monoliths. Thank god lua doesn't have to compile.

I still have to disagree about lua not being used for OO though. Sure it's not true OO without a load of mangling or having access to the backend to implement classes, but if you aren't using and treating tables like objects, you're missing out on a lot of that flexibility and structure (if you look beyond the fact a flexible structure is a bit of an oxymoron).
3ydney #40
Posted 09 March 2013 - 01:11 AM
Great tips Bubba!
Ferdi265 #41
Posted 27 March 2013 - 03:49 AM
I follow most of these habits, especially the one about indenting my code (oCd seems to help with coding)

Also, a very important thing is to stay with your style. And when I adopt a function from somewhere else, it really bugs me when the coder uses a style different from mine. I then just HAVE to change his sometable[ Myvariable ]+5 statements to the (in my opinion) more visually pleasing someTable[myVariable] + 5
airtonix #42
Posted 28 March 2013 - 08:56 PM
I wonder if Lua has the equivilant of Pythons PEP8.

My contribution to this would be to say that any code that does not have unit tests is broken by design.
theoriginalbit #43
Posted 28 March 2013 - 09:00 PM
I wonder if Lua has the equivilant of Pythons PEP8.

My contribution to this would be to say that any code that does not have unit tests is broken by design.
http://lua-users.org/wiki/UnitTesting
Dlcruz129 #44
Posted 11 April 2013 - 01:53 PM
One thing I see people doing a lot is:


gui = {
"/-------\",
"|		  |",
"\-------/",
}

And then iterating through the table and printing each index. While this isn't a bad habit, I find it much simpler to do:


print [[
/------------\
|				 |
\-------------/
]]

It's a lot shorter and really saves time.

EDIT: Meh, the code highlighting screwed up my boxes, but I think you get the point ;)/>
SuicidalSTDz #45
Posted 11 April 2013 - 04:42 PM
One thing I see people doing a lot is:


gui = {
"/-------\",
"|		  |",
"\-------/",
}

And then iterating through the table and printing each index. While this isn't a bad habit, I find it much simpler to do:


print [[
/------------\
|				 |
\-------------/
]]

It's a lot shorter and really saves time.

EDIT: Meh, the code highlighting screwed up my boxes, but I think you get the point ;)/>
I would agree except in this case:


local w,h = term.getSize()
local foo = {
 {text = "+", col = colours.red, pos = math.random(1,w)},
 {text = "*", col = colours.blue, pos = math.random(1,w)},
 {text = "+", col = colours.orange, pos = math.random(1,w)}
}

for _,v in pairs(foo) do
 term.setTextColour(v.col)
 term.setCursorPos(v.pos,math.random(1,h))
 term.write(v.text)
end

Just saying :P/>
Dlcruz129 #46
Posted 11 April 2013 - 05:10 PM
One thing I see people doing a lot is:


gui = {
"/-------\",
"|		  |",
"\-------/",
}

And then iterating through the table and printing each index. While this isn't a bad habit, I find it much simpler to do:


print [[
/------------\
|				 |
\-------------/
]]

It's a lot shorter and really saves time.

EDIT: Meh, the code highlighting screwed up my boxes, but I think you get the point ;)/>
I would agree except in this case:


local w,h = term.getSize()
local foo = {
{text = "+", col = colours.red, pos = math.random(1,w)},
{text = "*", col = colours.blue, pos = math.random(1,w)},
{text = "+", col = colours.orange, pos = math.random(1,w)}
}

for _,v in pairs(foo) do
term.setTextColour(v.col)
term.setCursorPos(v.pos,math.random(1,h))
term.write(v.text)
end

Just saying :P/>

Yeah, but for simple single-color textboxes and whatnot, multi-line strings are the best way to go.
airtonix #47
Posted 14 July 2013 - 07:52 PM
I sometimes wish there was a unittest framework for computercraft, but considering how the testable outputs would involve an object moving around in 3d gamespace, I can imagine how large a task it would be to create such a framework.
Bubba #48
Posted 14 July 2013 - 10:06 PM
I sometimes wish there was a unittest framework for computercraft, but considering how the testable outputs would involve an object moving around in 3d gamespace, I can imagine how large a task it would be to create such a framework.

pcall should suit your needs for unittesting. Not exactly a unittest, but it would protect you from errors and would, at the same time, allow you to identify any bit of code that does not run.
strayzer #49
Posted 20 July 2013 - 03:38 PM
considered myself a proficient coder until i read this and realized i am guilty of every single habit. Another good practice that I would recommend is ALWAYS use functions and name them correctly.I often find that even with simple code i confuse myself trying to figure out which function does what as i have the terrible habit of naming them the letter that my finger is hovering over at the time. :wacko:/>
Engineer #50
Posted 20 July 2013 - 07:20 PM
ALWAYS use functions

I very, very disagree. I see where you are coming from with naming them, but really only use functions when you need a piece of code several times. To name it I would do something like:

-- This is the "function's" name
term.write( "This is " )
local s = "doing"
term.write( "what this code is " .. s )

I suppose then you are sometimes doing things like:

local function p()
   local s = "Hi!"
   term.write( s )
end

local function r( name )
   p() -- The one and only call in the whole script
   term.write( name )
end
Of course using some more (complicated) code.
In my opinion it is bad practise, but thats me. I think this is better:

function pr( name )
    local s = "Hi!"
    term.write( s .. name )
end
Pharap #51
Posted 20 July 2013 - 11:58 PM
ALWAYS use functions

I very, very disagree. I see where you are coming from with naming them, but really only use functions when you need a piece of code several times. To name it I would do something like:

-- This is the "function's" name
term.write( "This is " )
local s = "doing"
term.write( "what this code is " .. s )

I suppose then you are sometimes doing things like:

local function p()
   local s = "Hi!"
   term.write( s )
end

local function r( name )
   p() -- The one and only call in the whole script
   term.write( name )
end
Of course using some more (complicated) code.
In my opinion it is bad practise, but thats me. I think this is better:

function pr( name )
	local s = "Hi!"
	term.write( s .. name )
end

Seeing this makes me think how sometimes good practise and optimisation are at odds.
Dunno why, just does
Fifi #52
Posted 21 July 2013 - 06:50 AM
Well, I think using functions even if not necessary is acceptable only when the code don't have to be 100% optimized and the code simplicity would extremly suffer when everything will be write in a single code block. Although I still prefer vertical separation and comments instead of faking the need for refactorization. It's not a good practice to make a function of everything.
Bubba #53
Posted 21 July 2013 - 11:53 AM
If by optimized, people mean short, I would have to disagree. To me, optimization is a combination of readability, number of operations, and ease of customization later on. In Lua especially, there is no reason to program only in one block of code for non-repetitive tasks simply because you may at one point want to make the task repetitive and functions make that extremely easy. Also, functions have essentially no effect on speed in CC Lua, and I rather doubt that they have much of effect in a regular Lua environment either.
Pharap #54
Posted 21 July 2013 - 01:07 PM
If by optimized, people mean short, I would have to disagree. To me, optimization is a combination of readability, number of operations, and ease of customization later on. In Lua especially, there is no reason to program only in one block of code for non-repetitive tasks simply because you may at one point want to make the task repetitive and functions make that extremely easy. Also, functions have essentially no effect on speed in CC Lua, and I rather doubt that they have much of effect in a regular Lua environment either.
By optimised I mean goes fast.
Short code does not mean optimised code.
Sometimes 4 really long lines of code can generate faster bytecode than 2 short lines.
How fast functions are depends on their setup, for example a vararg function is slower than an explicit params function, but using a vararg function can be faster than passing a table to a function depending on how much indexing is involved.
Generally functions aren't a problem though, they only start to become a problem when you start giving them upvalues (each upvalue adds about 2 instructions to the function.

JLua is a lot different to CLua, and I believe it does some JIT compiling, in which case it's impossible to say anything other than CLua almost always runs faster.
Tjakka5 #55
Posted 21 July 2013 - 04:16 PM
W00T, I got perfect habits!
willdude123 #56
Posted 11 August 2013 - 07:57 AM
Good tips- goes for all coding, not just CC
theoriginalbit #57
Posted 11 August 2013 - 08:14 AM
If by optimized, people mean short, I would have to disagree. To me, optimization is a combination of readability, number of operations, and ease of customization later on.
Agreed. yet at the same time disagreed… There are times where good readability can make a large negative impact on the performance of a program. I definitely agree that programs should be readable to an extent, however sometimes readability must be sacrificed slightly for a more optimal solution… Also I have found that in most cases more optimised code is in fact shorter, and mostly still nice and readable, so I can definitely understand peoples confusion/correlation between optimised and lines of code. Normally things like number of operations is the main aspect of optimised code. One last thing is readability cannot really go into the general criteria of optimised programming as, well, everyone is different. My idea of readable code I can guarantee would be very different to yours, or most other peoples… Most people have their own "flare" and programming style that is guaranteed that others will not find readable… This is the sole purpose behind development companies implementing and forcing their employees to use specific naming conventions, habits and practises…