Scripting: Do's and Don'ts – Arma Reforger

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Some wiki formatting)
(Add switch scopes info)
Line 1: Line 1:
{| class="wikitable" style="width: 100%"
{| class="wikitable valign-top" style="width: 100%"
|+ {{Feature|important|Do follow {{Link|Arma Reforger:Scripting: Conventions|Scripting Conventions}}.}}
|+ {{Feature|important|Do follow {{Link|Arma Reforger:Scripting: Conventions|Scripting Conventions}}.}}
! style="width: 50%" | Don't
! style="width: 50%" | Don't
! style="width: 50%" | Do
! style="width: 50%" | Do
|- style="vertical-align: top"
|-
|
|
<enforce noGuess>
<enforce noGuess methods="Print">
class ExampleClass {
class ExampleClass {
   int LProcLgh;
   int LProcLgh;
Line 37: Line 37:
|}
|}


{| class="wikitable" style="width: 100%"
{| class="wikitable valign-top" style="width: 100%"
|+ {{Feature|important|Keep variables as close as possible to their usage.}}
|+ {{Feature|important|Keep variables as close as possible to their usage.}}
! style="width: 50%" | Don't
! style="width: 50%" | Don't
! style="width: 50%" | Do
! style="width: 50%" | Do
|- style="vertical-align: top"
|-
|
|
<enforce>
<enforce>
Line 72: Line 72:
|}
|}


{| class="wikitable" style="width: 100%"
{| class="wikitable valign-top" style="width: 100%"
|+ {{Feature|important|Do not scope more than necessary.}}
! style="width: 50%" | Don't
! style="width: 50%" | Do
|-
|
<enforce>
switch (value)
{
case 0:
{
Print("0");
break;
}
 
default:
{
Print("default");
break;
}
}
</enforce>
|
<enforce>
switch (value)
{
case 0:
Print("0");
break;
 
default: // brackets are needed only if variables are declared in the 'case' code
{ // otherwise scoping is superfluous (and very slightly impacts performance)
string message = "default";
Print(message);
break;
}
}
</enforce>
|}
 
{| class="wikitable valign-top" style="width: 100%"
|+ {{Feature|important|Keep a strong reference (<enforce inline>ref</enforce> keyword) to required objects.}}
|+ {{Feature|important|Keep a strong reference (<enforce inline>ref</enforce> keyword) to required objects.}}
! style="width: 50%" | Don't
! style="width: 50%" | Don't
! style="width: 50%" | Do
! style="width: 50%" | Do
|- style="vertical-align: top"
|-
|
|
<enforce>
<enforce>
Line 104: Line 144:
|}
|}


{| class="wikitable" style="width: 100%"
{| class="wikitable valign-top" style="width: 100%"
|+ {{Feature|important|Avoid strong reference cyclic trap.}}
|+ {{Feature|important|Avoid strong reference cyclic trap.}}
! style="width: 50%" | Don't
! style="width: 50%" | Don't
! style="width: 50%" | Do
! style="width: 50%" | Do
|- style="vertical-align: top"
|-
| {{Feature|informative|Here, both ParentClass and ChildClass have a strong reference to each other, keeping the reference count above zero - creating an "island of isolation" (see [[Arma Reforger:Scripting: Automatic Reference Counting]] for more information).}}
| {{Feature|informative|Here, both ParentClass and ChildClass have a strong reference to each other, keeping the reference count above zero - creating an "island of isolation" (see [[Arma Reforger:Scripting: Automatic Reference Counting]] for more information).}}
<enforce>
<enforce>
Line 173: Line 213:


<!--
<!--
{| class="wikitable" style="width: 100%"
{| class="wikitable valign-top" style="width: 100%"
|+ {{Feature|important|Do this instead of that.}}
! style="width: 50%" | Don't
! style="width: 50%" | Don't
! style="width: 50%" | Do
! style="width: 50%" | Do
|- style="vertical-align: top"
|-
|
|
<enforce>
<enforce>

Revision as of 13:25, 16 May 2024

Don't Do

class ExampleClass { int LProcLgh; int stringlength( string Value ){ LProcLgh= Value.Length(); Print ( "String length obtained: "+LProcLgh ); return LProcLgh; } }

class ExampleClass { protected int m_iLastProcessedLength; int GetStringLength(string value) { m_iLastProcessedLength = value.Length(); Print("String length obtained: " + m_iLastProcessedLength); return m_iLastProcessedLength; } int GetLastProcessedLength() { return m_iLastProcessedLength; } }

Keep variables as close as possible to their usage.
Don't Do

class ExampleClass { protected int m_iLength; int GetStringLength(string name) { m_iLength = name.Length(); Print("String length obtained: " + m_iLength); return m_iLength; } }

class ExampleClass { // keeping the variable into method scope and away from the instance int GetStringLength(string name) { int length = name.Length(); Print("String length obtained: " + length); return length; } }

Do not scope more than necessary.
Don't Do

switch (value) { case 0: { Print("0"); break; } default: { Print("default"); break; } }

switch (value) { case 0: Print("0"); break; default: // brackets are needed only if variables are declared in the 'case' code { // otherwise scoping is superfluous (and very slightly impacts performance) string message = "default"; Print(message); break; } }

Keep a strong reference (ref keyword) to required objects.
Don't Do

// this array only lists pointers but does not increase the reference count array<ExampleClass> classArray = new array<ExampleClass>(); for (int i = 0; i < 10; i++) { ExampleClass newInstance = new ExampleClass(); classArray.Insert(newInstance); // newInstance will be deleted at the end of the scope // as there are no references to it }

// this array keeps strong references to its items array<ref ExampleClass> classArray = new array<ref ExampleClass>(); for (int i = 0; i < 10; i++) { ExampleClass newInstance = new ExampleClass(); classArray.Insert(newInstance); // classArray keeps a strong reference to newInstance - it will not be cleared }

Avoid strong reference cyclic trap.
Don't Do
Here, both ParentClass and ChildClass have a strong reference to each other, keeping the reference count above zero - creating an "island of isolation" (see Arma Reforger:Scripting: Automatic Reference Counting for more information).

class MainClass { ref SubClass m_SubClass; void MainClass() { m_SubClass = new SubClass(this); } } class SubClass { ref MainClass m_Parent; void SubClass(MainClass parent) { m_Parent = parent; } void DoSomething() { Print(m_Parent); } }

Here, the MainClass needs the SubClass (it creates it in its constructor meaning it needs it to work) but the subClass does not require MainClass - if the MainClass reference doesn't exist, it will simply not use it.

class MainClass { ref SubClass m_SubClass; void MainClass() { m_SubClass = new SubClass(this); } } class SubClass { MainClass m_Parent; // ref removed void SubClass(MainClass parent) { m_Parent = parent; } void DoSomething() { if (!m_Parent) // null safety check return; Print(m_Parent); } }