I'm teaching myself coding with kotlin and AS and as a self-assigned project I'm making a little game. I have 6 var integers that are used to get some random numbers and to modify those numbers in certain ways. In order to reduce the amount of code and to simplify passing those integers around to functions I have all 6 stored in a single mutable map. Most of the time when I pass them from one function to the other (or one class to the other) I need all 6, but there is one case where I only need 3 of them.
My question is this: Is it more efficient to pass just the 3 values I need? Or is that actually LESS efficient because I'm passing new copies of already existing values? I'm really not sure how that works internally
example: Would you...
fun main() {
val gameArgs = mutableMapOf("numDice" to 3,
"minNum" to 1,
"maxNum" to 20,
"modNum" to 5,
"targetNum" to 17,
"bonusDice" to -1,)
val rollNumbers = rollDice(gameArgs)
// and then send the rollNumbers and the gameArgs elsewhere to evaluate what
// the numbers mean
}
fun rollDice(args: MutableMap<String, Int>):List<Int>{
val numList = mutableListOf<Int>()
repeat(args["numDice"]!!){
numList.add((args["minNum"]!!..args["maxNum"]!!).random())
}
return numList
}
OR, would you...
fun main() {
val gameArgs = mutableMapOf("numDice" to 3,
"minNum" to 1,
"maxNum" to 20,
"modNum" to 5,
"targetNum" to 17,
"bonusDice" to -1,)
val rollNumbers = rollDice(gameArgs["numDice"]!!, gameArgs["minNum"]!!, gameArgs["maxNum"]!!)
// and then send the number list and the other 3 values from the map elsewhere
}
fun rollDice(numDice: Int, minNum: Int, maxNum: Int):List<Int>{
val numList = mutableListOf<Int>()
repeat(numDice){
numList.add((minNum..maxNum).random())
}
return numList
}
My instincts say the latter is less memory intensive, but my anxiety whispers that the latter might be MORE memory intensive because I'm making copies of 3 values that already exist.
So which is more efficient? And does it make a difference if rollDice() is in another class?
Thanks in advance
[edited to fix one type and one copy/paste error]
CodePudding user response:
You are over-concerned about performance. You could pass ten strings or a hundred copies of short strings like this and it's completely insignificant to performance. Think about when a web page opens on a computer 20 years ago, and thousands of words of text appears on your screen near-instantly. But when you pass a String, it is not copied. Only its memory address is copied, which is even more trivial. Regardless, it is both more efficient and cleaner code to pass the whole thing, not the individual components. Focus primarily on the cleanest-looking code and only try to optimize when you have a performance-critical section of code, like a piece of algorithm that's repeated thousands of times while the user is waiting for the result.
You should not use Maps for this. That's the sort of thing you do in weakly-typed languages like JavaScript. Maps are never used in this way in a strongly-typed language. When you have multiple parameters with different meanings, you use a class to represent them. This makes your code robust. The compiler will complain about and red-underline most of your errors before you even have to install your code to test it. With a map, you won't find your errors until after the program is running and you start having weird bugs that you have to go through the debugging process to find. Replace your map with a class like this:
data class GameSession(
val numDice: Int = 1,
val minNumber: Int = 1,
val modNumber: Int = 1,
val targetNumber: Int = 17,
val bonusDice: Int = -1
)
fun main() {
val game = GameSession()
val rollNumbers = rollDice(game)
// ...
}
fun rollDice(game: GameSession): List<Int>{
val numList = mutableListOf<Int>()
repeat(game.numDice){
numList.add((game.minNumber..game.maxNumber).random())
}
return numList
}
To take it a step further, it would make more design sence for rollDice()
to be a function of the GameSession class. Also, you can skip making a temporary MutableList and just return a List directly using the List()
function. So it could look like this:
data class GameSession(
val numDice: Int = 1,
val minNumber: Int = 1,
val modNumber: Int = 1,
val targetNumber: Int = 17,
val bonusDice: Int = -1
) {
fun rollDice(): List<Int> {
return List<Int>(numDice) { (minNumber..maxNumber).random() }
}
}
fun main() {
val game = GameSession()
val rollNumbers = game.rollDice()
// ...
}