Search Unity

One question about naming convention

Discussion in 'Scripting' started by mahdiii, Jul 6, 2018.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Hi all.
    Suppose I want to name a variable about a weapon is in hand and active.
    What do you suggest?

    Code (CSharp):
    1. private bool _weaponIsInHand
    2. private bool _weaponIsActive
    3. private bool _weaponHasSelected
    4. private bool _weaponHasBeenSelected
    5. private bool _weaponHasBeenChosen
    6. private bool _weaponHasChosen
    7. private bool _weaponIsReady
    8. private bool _weaponIsReadyToUse
    9. private bool _weaponIsUsing
    10.  
     
  2. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,206
    None of them. I'd implement it completely differently. Below is a quick example and not necessarily how it would end up.

    Code (csharp):
    1. public class Equipment : MonoBehaviour {
    2.     public WeaponSlot leftHand;
    3.     public WeaponSlot rightHand;
    4. }
    5.  
    6. public class WeaponSlot : ItemSlot {
    7.     public bool isReady = false;
    8. }
    9.  
    10. public class ItemSlot {
    11.     public Item item;
    12. }
    13.  
    14. public class Item {
    15.     // foo
    16. }
    Getting back to your question. Choosing a name isn't important. All of those names would be fine. What is important is maintaining the same naming style across all your scripts. Consistency makes it easier to understand and debug code.
     
    Last edited: Jul 6, 2018
  3. ozymandiax

    ozymandiax

    Joined:
    Nov 25, 2017
    Posts:
    12
    Ryiah gave you a good design pattern, there are other ways but if you absolutely want to stick to your bools their names should start with "is..." or "has...", you don't have to but it's good form and improves readability when you use them in if statements.

    Code (CSharp):
    1.  
    2. bool isWeaponInHand
    3. bool isActiveWeapon
    4. // and so forth
    5.  
    6.  
    7. if (isWeaponInHand)
    8. {
    9.   // Do something...
    10. }
    11.  
     
    Last edited: Jul 8, 2018
    Socrates likes this.
  4. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,579
    I wouldn't start a field name with an underscore.

    This is a C++ habit, as variables that start with underscored are technically reserved by the language.

    Similar to @Ryiah , I most likely turn the weapon into an object or monobehavior.
     
    X3doll likes this.
  5. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,622
    It's pretty much standard in the .NET Framework source code. It seems they use _ and m_ prefixes for non-public instance fields across the .NET Framework code.

    _ prefix examples:
    https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
    https://referencesource.microsoft.com/#mscorlib/system/io/filestream.cs

    m_ prefix examples:
    https://referencesource.microsoft.com/#mscorlib/system/int32.cs
    https://referencesource.microsoft.com/#mscorlib/system/text/stringbuilder.cs

    I guess there exists a guideline in the .NET Framework naming guidelines somewhere, that reads "prefix non-public instance fields with _ or m_", because that's done excessively across the entire code and I find it hard to believe that everybody working on that code did prefix non-public fields with an underscore or m_ by accident.

    I only found a guideline regarding g_, s_ prefixes though, which should not be used and the .NET framework code reflects that guideline:
    https://msdn.microsoft.com/en-us/library/ms229012(v=vs.100).aspx
     
    mahdiii likes this.
  6. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,206
    There are no guidelines at all for internal or private fields.

    https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-type-members
     
    TextusGames and Peter77 like this.
  7. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,622
     
  8. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Thank you.
    I have a WeaponManager that manage weapons. It has a weapon list (weapon object list) and current index shown current weapon in the list. I have used the boolean variable to detect that the player has a weapon in hand and selected.
    Yes I can keep the current weapon (left and right or one based on design) instead of keeping weapon index and boolean to check that it is in hand.

    Code (CSharp):
    1.  
    2. public class WeaponManager:MonoBehaviour{
    3.    private Weapon _leftWeapon;
    4.    private Weapon _rightWeapon;
    5. // or private Weapon _currentWeapon
    6.    private List<Weapon> _weapons;
    7.    private int _currentWeaponIndex;
    8.  
    9.    private void UnSelectLeftWeapon(){
    10.       _leftWeapon=null;
    11.    }
    12.    private void UnSelectRightWeapon(){
    13.       _rightWeapon=null;
    14.    }
    15. }
    16.  
     
  9. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    I hate to write "this" for inner variables. Underscore (_) is standard and common for private and internal variables in C++ and java and C#.

    Code (CSharp):
    1. public void SetFunc(int a){
    2.    this.a=a;
    3. }
     
  10. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,206
    It's definitely common, I'll give you that, but it's definitely not standard. For C# and Java it isn't a problem but you should never do it with C++ as the C++ Standard dictates that any names starting with an underscore are reserved and should never be used.

    https://stackoverflow.com/questions...-in-c-and-c-sharp-variables/20496955#20496955
    https://stackoverflow.com/questions...an-underscore-in-a-c-identifier/228797#228797
     
    Last edited: Jul 7, 2018
  11. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,579
    Hungarian notation, again. This thing should probably be axed at this point.

    The reason why prefixes pop up in .NET is because it is really fond of properties, and properties often redirect data to internal fields.

    I actually do
    Code (CSharp):
    1.  
    2. public void Constructor(int storedValue_){
    3.     storedValue = storedValue_;
    4. }
    5.  
    a lot.

    Argument name is less important that member name, since it can get a "_" suffix.

    And I bet you'd hate working with python
    Code (Python):
    1.  
    2. class Test:
    3.     def __init__(self, arg):
    4.         self.arg = arg;
    5.  
    Because "self" is required in it. For ANY attempt to access a member.
     
  12. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,579
    Speaking of which, I think GLSL shaders have similar limitation.

    Hence the TRAILING underscore in situation with name clashes, but almost never for class members.
     
  13. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    So you do not actually apply the standard way to name!!
    If you use .net functions, please show me only and only one function that uses "name_" argument!!
    I absolutely prefer to name parameters without any prefix and postfix, because others who call it, can see it clearly.
    Private members are internal and have not been seen from outside.
    Finally every team has a special convention.


    I do not hate any languages. I only try to match and respect common conventions in the language.
    In python, I name them differently. In c++ and javascript, I use camelCase functions, etc.
    In CG, I use _PascalCase for variables. Just, I do not invent conventions.
     
    Last edited: Jul 7, 2018
  14. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I only use a starting underscore for the unusual case where a variable should never be accessed, even inside the class. So basically backing variables for complex properties.

    But its rare. Normally such a variable can be properly encapsulated inside its own class or struct, which eliminates the need to protect the backing variable via convention.
     
    mahdiii likes this.
  15. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,579
    I try to find whatever works best to me instead.

    Standard "convention" used in microsoft has a fairly bad idea of starting funciton names with capital letter.
    Microsoft is also responsible for overuse of hungarion notation with with lpszName and such in older C/C++ code. Neither of them are good.

    Just because convention exists, it does not mean it is good. You need to look through it and see if it works for your code or not.

    Parameter name is something you will almost never have to type out, while variable names is something you will interact with one way or another. Therefore trailing _ is more suitable for functions
     
  16. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,206
    Why is it a bad idea?
     
    Last edited: Jul 8, 2018
  17. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Because he does not like LoL
     
  18. ozymandiax

    ozymandiax

    Joined:
    Nov 25, 2017
    Posts:
    12
    I only speak for myself and I do follow the uppercase standard in c# but i prefer my verbs to be lowercase.

    Code (CSharp):
    1. SoundManager.playSound(Alarm)
    vs.

    Code (CSharp):
    1. SoundManager.PlaySound(Alarm)
    As far as the bigger picture goes, it's a non-issue as far as I am concerned though.
     
  19. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I'm curious too.

    I get that the convention for giving properties a capital letter is a bad idea. But I've never seen the problem for methods. Its always nice to have something minor to remind me I need to invoke a method.
     
    mahdiii likes this.
  20. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Java style: mySelectedAndActiveWeaponInLeftHandWhichIsReadyNow

    Unix style: wpn_rdy_lft

    early 90's microsoft style: boomStick

    Realistic style: right now your game has 2 types of guns. You think you're going to add melee weapons, but you won't, so don't try to be all fancy calling it a weapon. The obvious name is: gun

    Design Pattern style: gunProxyLocator. It is used like: gunProxyLocator.locate(Hand.handID("left")).get(). You will cache it in a variable named G.
     
  21. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Use this this keyword instead
    Code (CSharp):
    1.  
    2. public void Constructor(int storedValue){
    3.     this.storedValue = storedValue;
    4. }
    5.  
     
  22. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    In that case you could still turn that member into a property. You wouldn't use a boolean backing field though, but instead do some internal checks that evaluate the current state, i.e. whether there is something in your left/right hand, if it's still "alive" (in regards of behaviours) and whether it's a weapon or not.

    That property would be way more descriptive and it's got a clear intent, and it's up to the declaring type what's considered 'weapon in hand' and 'no weapon in hand'.

    Querying a weapon field (or weapon property instead) may leave the caller alone with some guess work... If it's null, there's certainly no weapon. If you use interfaces and the weapon behaviour has been destroyed for some reason (bug, improper reset to null or whatever may lead to this), it would not be null and additional checks may be required.

    And If you decide to have shields and other stuff in that hand at some point, the property can handle all of that in that one single place - noone has to do some guess-work and do extra-checks, it won't cause alot of inconsist checks on the caller's side.
     
    mahdiii likes this.
  23. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    You are an English man?
    Because I think weapon word is more general than gun!! At least dictionary says that.
     
  24. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    I actually use "this" a lot when referencing internal variables, regardless if they have prefixes/suffixes. This sprang up when i had the headache of bringing my perfectly working code into another project and then suddenly my code would get confused and try to use some class some code monkey wrote (which was left in global namespace btw) that was named exactly like one of the fields in my classes. For me it helps to be explicit and by now it just became habit.

    I disagree, I think properties using PascalCase, just like methods makes perfect sense. Because Properties ARE methods, despite the fact that the code sugar makes them seem like fields, under the hood you are still calling methods. and the power of today's IDE makes figuring out if a class Member is a property, field, or method trivial.

    As for neginfinity saying the convention itself is bad, I can't agree with that. The fact that they chose PascalCase over camelCase is superficial. to me it doesn't matter which they chose, just as long as its well documented and consistent, which it is more so than most other conventions out there.
     
  25. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    My problem with this approach is that properties are consumed as if they are fields. The consuming code normally doesn't know the difference. So I like to keep properties and fields consistent with each other. That way when I refactor a property into a field or vice versa, I don't need to change any of the consuming code.
     
  26. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    I'm curious, do you remember specifically what happened? Normally that should be impossible, right? Can some special "using" move globals above fields in the order names are checked? I was thinking maybe an extension method, but no, they only use var.myFieldWithSameNameAsGlobal. Or was this not in C#?

    When this happens to me, it's almost always I _thought_ it was a problem with thing A, spend an hour looking, then finally find it was something else. But I remember the problem was with thing A.
     
  27. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    But the consuming code does know the difference. What if the property was a getter-only (with a setter either not implemented or private), the consuming code would know that attempting to set the member would be an access violation, and it would know this at compile time. despite the lack of a parenthesis, the consuming code does have context as to how the target member is allowed to be interfaced with (as in interacted with, not necessarily using interfaces).

    I get what you mean in terms human readability, but more often than not code is read in an IDE which with intellisense gives a human enough context for an effective use of a member.

    I can't recall exactly which class it was (very likely the current code is completely different then how it was back then just because of this) but I do remember looking at the code back when I used monodevelop and it kept highlighting my field as if it was a class and then show a compile error saying something like my field was a System.Type and that it wasn't valid in how i was using it. when I clicked to goto definition it jumped me to this random class someone wrote for something else, instead of upto the top of my class where I defined my field. And it wasn't a freak occurrence it actually happened consistently.

    You're right, local scope should supersede global scope. It should have been impossible, but it was happening anyway. The compiler felt that I was being too ambiguous. Thats why it was such a headache; I couldn't figure out why it was happening.
     
  28. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Ah...a wonky IDE. I remember early versions of Visual Studio, purely working within it, often wrongly displayed errors, but compiled just fine.

    Right now in Unity, VisualStudioCode is wrongly telling me a class has been declared twice -- once in the Unity assembly, and once in some odd local cache which is somehow an echo (it's resolved just fine, but it's still got that wavy green warning line under it.) But at least I don't have to switch to another tab and back to display code folds, like in MonoD.
     
    JoshuaMcKenzie and Ryiah like this.
  29. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    An example may help illustrate. Lets say I have this code:

    Code (CSharp):
    1. public string myString;
    Now at a later date I decide I need a property and refactor this to:

    Code (CSharp):
    1. public string myString {
    2.     get {
    3.         return someOtherString;
    4.     }
    5.     set {
    6.         someOtherString = value;
    7.     }
    8. }
    If properties and fields use the same naming convention, then I can switch between them without any adverse consequences anywhere else.

    On the other hand if I change my code to this:

    Code (CSharp):
    1. public string MyString {
    2.     get {
    3.         return someOtherString;
    4.     }
    5.     set {
    6.         someOtherString = value;
    7.     }
    8. }
    Then every piece of code that references the field also has to change. That's if I even have control over the consuming code.

    Edit: You can also get around this by insisting everything public be a property and never exposing fields directly. That's another great example of a 'best practice' that adds in performance overhead for little to no gain.
     
    Ryiah likes this.
  30. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    That's why I started to follow a convention that says: If fields are public, no matter why, it's PascalCase. For classes, if state is important for being in a valid state, i.e. it's not used as a substitute for over-sized structs, then there shall be no publics at all except readonly & const.

    But that discussion will never end.

    I'm wondering about how much overhead I could avoid. :D Plus all the interfaces that I use. :rolleyes:

    Nah seriously, I'm a huge supporter of exactly that, except for the cases listed above.