Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Coding standard question

Discussion in 'Scripting' started by HjorthBjorn, Aug 18, 2020.

  1. HjorthBjorn

    HjorthBjorn

    Joined:
    Aug 12, 2013
    Posts:
    21
    I am new to Unity and C# but not coding in general and I thinking about what seems to be the coding standard in Unity ( or maybe C# in general?)

    Consider these two simple piece of code snippets:

    Standard tutorial way:
    Code (CSharp):
    1.  
    2. using UnityEngine
    3. public class MoveForward :MonoBehaviour
    4. {
    5.     public float speed = 40.0f;
    6.     public GameObject projectilePrefab;
    7.  
    8.     void Update()
    9.     {
    10.         transform.Translate(Vector3.forward * Time.deltaTime * speed);
    11.  
    12.  
    13.         if (Input.GetKeyDown(KeyCode.Space))
    14.         {
    15.             Instantiate(projectilePrefab, transform.position, projectilePrefab.transform.rotation);
    16.         }
    17.     }
    18. }
    How I would write it
    Code (CSharp):
    1. public class MoveForward : UnityEngine.MonoBehaviour
    2. {
    3.     public float speed = 40.0f;
    4.     public UnityEngine.GameObject projectilePrefab;
    5.  
    6.     void Update()
    7.     {
    8.         this.transform.Translate(UnityEngine.Vector3.forward * UnityEngine.Time.deltaTime * this.speed);
    9.  
    10.  
    11.         if (UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.Space))
    12.         {
    13.             MoveForward.Instantiate(
    14.                 original: this.projectilePrefab,
    15.                 position: this.transform.position,
    16.                 rotation: this.projectilePrefab.transform.rotation
    17.             );
    18.         }
    19.     }
    20. }
    I am not a big fan of using "using" as I like to type out where I get things to avoid mistakes.
    I am also a fan of the C# way of using named parameters but I have not seen anyone using it in the guides I have read or watched.
    Also for static methods I like to type out the base class.

    So here is the question are these 3 things considered the "bad practice" in the Unity/C# community as it is to verbose? I am well aware of people having there own coding standards, I am just curios.
     
  2. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,009
    Are you also using System. namespace explicitly ?
     
    HjorthBjorn likes this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,725
    This is really a C# question and while obviously it's an opinion thing, I think including the full namespace constantly just makes the code really difficult to read. The noise-to-signal ratio of the code goes way up. I don't think it improves clarity at all. The namespaces are simply not relevant information most of the time.

    Occasional inclusion of named parameter lists can certainly be helpful however.
     
    Last edited: Aug 18, 2020
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    It's not wrong, but a bit unusual and feels like a huge waste of time to write, or even read, thus reducing maintainability. If i was working on a team with you i'd at least ask you about why you'd do it. You said you are not new to coding, regardless this feels like something someone new would do when he or she is still a bit unsecure about what they are doing, or where things come from. This is of course not meant offensively, but if you hadnt written that you are not new to coding, my reply would have been just that. It just makes stuff longer, not clearer imho.
     
    HjorthBjorn and Yanne065 like this.
  5. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    One of the design goals with C# was the speed at which you can use it to write your own code. You're basically throwing that advantage away, as I can't see the 2nd example being written as quickly as the 1st. Memorizing built in namespaces is pretty much a waste of time IMO, but you'll be doing that for the 2nd example. Writing "this" is just redundant in most cases, wasting more time and filling your code with unnecessary clutter.

    This seems like if when you talked to your best friend and always middle named him.

    "Hey Christopher Bartholomew von Neumann, you free for a beer after work?"
    "Uhhh, just call me Chris.... For the 100th time, why do you keep doing that? We've been friends for a decade."
    "I'm just trying to be clear who I'm talking to, Christopher Bartholomew von Neumann. What's the big deal?"
    "But I'm the only Chris here.... I'm the only Chris in the entire office, and the only one you know.... Just stop..."
    "But Christopher Bartholomew von Neumann, I just..."
    "STOP DOING THAT!"

    :p
     
    Yanne065, HjorthBjorn, Vryken and 2 others like this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    Ah Uncle Joe, I love you man...
     
    HjorthBjorn and Joe-Censored like this.
  7. HjorthBjorn

    HjorthBjorn

    Joined:
    Aug 12, 2013
    Posts:
    21
    What do people think of named parameters in general? I loved that feature in Swift for example. It not only make the parameters more easily to understand and it changes the names off method in a likable way(opinion)
    No as I assumed one could not name things to Class or static for example. Maybe this is incorrect I didn't try.


    No offence taken of course :)
    Unsecure might not be such a bad word in this case, the explicit use of the namespace is for sure that when one uses maybe 6 libraries and one have not used them as much it is hard by just looking at the code to know where things come from.

    It is also to avoid collisions and mindfarts, example if "I" or my "team" would develop our own unique Vector3 method, this would then be hard to distinguish which is what.


    Agree, could be that I am a little stuck thinking it should look more like C++ as it is Language from Microsoft.
    The explicit use of the keyword "this" is to avoid shadowing of class variables and parameters in methods. I would argue that using "this" gets more useful as all use the "using" keyword.


    Thank you all for taking the time to answer this post, I really like to talk about styles and when trying many different styles and languages there are so many opinions what is the "best practice". I find it valuable to learn from the programmers using it to learn more about a certain language.
     
    Last edited: Aug 19, 2020
    Joe-Censored likes this.
  8. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Which is exactly what namespaces exist for. You'd then of course differentiate between the two Vector3s by specifying which you meant by writing out its full identifier, including the namespace. Only if you have to import both namespaces tho. But no need to do this while only one option exists :)
     
    HjorthBjorn likes this.
  9. HjorthBjorn

    HjorthBjorn

    Joined:
    Aug 12, 2013
    Posts:
    21
    Indeed a valid point but then if you see Vector3 in the code to identify which one it is you need to either look in the top of the file or hover it with the mouse cursor to get a type hint from the IDE.

    I will of course change the way I program to be more inline with the standards of C# and the Unity community when I am using Unity, more important to be understood then having a opinion :D
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    They have their place. I try to force myself to use them whenever I have a function that accepts two or more of the same type of argument, or an argument that can be inadvertently coerced into another type (int -> float for example).

    But generally if you use them everywhere, your code starts to look like ObjectionableC code which is an absolute abomination to the programming world. Never have I squinted so hard at multiple auto-wrapped lines of miserable bracketed punctuation crud with entire paragraphs of the War and Peace novel embedded in the argument list. Good lord what a bad idea that language was! I mean, I get what they were trying to do, but whoo boy, not useful. I'd say it is even worse than Java! :)

    Finally, for certain crazily-overloaded Unity API functions I have gotten into the habit of naming the args, such as this one:

    https://docs.unity3d.com/ScriptReference/Physics.Raycast.html

    Unity should put an addendum on that function's docs:

    "When this function doesn't work for you, go back and label all your arguments first. Then troubleshoot."

    Come to think of it that would be an interesting decorator to make: ForceNamedArgumentsAttribute... that way you could signal that this part of your API benefits from such a thing. But it would have to be a warning because if I encountered an API that enforced this across its breadth with no good reason, I think I'd delete it before using it.
     
    Last edited: Aug 19, 2020
  11. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    Eh, there really isn't a "standard" with regards to these things. Technically, there isn't even a "best practice" with syntactic sugar because, in the end, whatever works best for you is what you should use.

    That said, this seems a bit overboard.
    using
    statements are critical, especially in complicated code. Since most IDEs allow you to hover over a class during assignment and see it's namespace, it's pretty easy. I'd think an easier mistake would be to use the WRONG namespace manually typing them all out all of the time.

    Of course, I have my own peculiarities with these sorts of things. I refuse to use the
    var
    keyword. In fact, sometimes I'll use it to see what class/struct it maps to (say, in a Linq query), then replace it with the actual class or struct. I also use the
    this
    keyword anytime I'm manually writing a property or any method that updates class fields. It's sensible to me for the names to be the same, so I'll often do:

    class Foo
    {
    float f = 0.0f;

    void UpdateFloat(float f)
    {
    this.f = f;
    }
    }


    But it makes sense to me just because of how I visualize scope.

    In your initial post, can you even do
    MoveForward.Instantiate()
    given that MoveForward isn't a static class?
     
    HjorthBjorn likes this.
  12. HjorthBjorn

    HjorthBjorn

    Joined:
    Aug 12, 2013
    Posts:
    21
    That reads like a bait to me to start some flaming haha I think I'll pass ;)

    Not a bad idea :)

    I do understand your point but I do think it depends, as then I could write Unity games with a Javascript developer standard or a C++ developer standard. I am sure it would all work but I do think I would miss out on strong features a language have.

    I was assuming that an entire class do not have to be static to call a static method I inherited from the Object class.

    Deep in the inherited voids of `UnityEngine.MonoBehavior`
    Code (CSharp):
    1. namespace UnityEngine
    2. {
    3.  
    4.     public class Object
    5.     {
    6.         public Object();
    7.  
    8.         ...
    9.  
    10.         public static T Instantiate<T>(T original) where T : Object;
    And to be very explixit and if someone wants to get extra hearts from me you could write it like this ( and to be fair it reads a lot better ;) )
    Code (CSharp):
    1. UnityEngine.Object.Instantiate
     
    Last edited: Aug 19, 2020
  13. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    Not really - that's why it's syntactic sugar. For the vast majority of cases, at least, the things you note have zero bearing on code functionality or features.

    using System.Drawing;

    class Foo
    {
    Graphics gr;
    }


    vs

    class Foo
    {
    System.Drawing.Graphics gr;
    }


    There's no difference in features, and in that tiny snippet, there really isn't a difference in readability. But many classes are not that small. And it doesn't matter if you're writing code in C# or C++ or Javascript - any higher level inherently doesn't care what form you write the code in, so long as it's the right code. It comes down to a matter of readability and working with others. The argument is a bit pedantic. It's like "which is standard, class name bracket newline code bracket, or class name newline bracket code bracket?" - neither are standard. Neither have any bearing on features of the language. They're just two ways to do something identical. Which is standard: camelcase, pascalcase, Hungarian notation? It's good to standardize within a given project for readability, and when working with a team it's best to have a team standard so code looks uniform, but it doesn't really matter which you use. You could standardize on using variable names in all caps that are totally random string of characters. It wouldn't be wise, but it wouldn't miss out on any features.

    Actually, I believe you've made my point for me - this is why there isn't a "standard" for such things. Frankly, I find it far, far less readable. Personally, I also find the use of var to be far less readable, but it's incredibly common practice. Neither are right or wrong - it's entirely preference. If I was using someone else's code in an app and they explicitly called out namespaces like that, I would go through and "fix" every instance of it. It would drive me nuts. In fact, in many cases I already do that with var, especially if I'm making heavy modifications to the code. For instance, Dungeon Architect is a great package. For my use, it had a lot of stuff I didn't need that I ended up removing, and there was a lot I added for specific things I wanted it to do. In the end, my version of the Dungeon Architect package looks pretty much just like all the code I write myself. It didn't when I downloaded it from the Asset Store, but it sure does now. ;)
     
    HjorthBjorn likes this.
  14. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    But then, I will also do this:

    using System;
    using UnityEngine;
    using Random = System.Random;

    public class Foo
    {
    Random rnd = new Random();
    }


    if I know I'm only going to use
    System.Random()
    .

    If I'm going to use both, I'd specify it on initialization of the variable, like:

    using System;
    using UnityEngine;

    public class Foo
    {
    System.Random sysRnd = new System.Random();
    UnityEngine.Random unityRnd = new UnityEngine.Random();
    }
     
    HjorthBjorn likes this.
  15. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,725
    Disambiguating between two classes with the same name in different namespaces like this is really the only reason to use the fully qualified name. Even then, you can do a type alias to make things easier to read. For example:
    Code (CSharp):
    1. using UnityRandom = UnityEngine.Random;
    2. using SystemRandom = System.Random;
     
    Xepherys and HjorthBjorn like this.
  16. HjorthBjorn

    HjorthBjorn

    Joined:
    Aug 12, 2013
    Posts:
    21
    Thanks for the long response :)

    I do agree that the style have no bearing on the functionality of the code and in the end the software will run just the same, sorry If I didn't explain that well enough.

    But I disagree about the namespace, it is a feature of the language and using it changes the way the code is written. Using namespaces changes the way people will name there methods and variables.

    But not only that as I am new to C# I do not know things about the language, maybe using "using" demands a different compiler down the line to Tree shake some content, maybe named parameters brings an overhead to something.
    I really do think when learning and checking a new language just embrace how the community write things and then in the future change if one wants.

    When I look at this code snippet another questions pops up in my head if it's ok I side-track a moment, Is there a way to only use the methods or classes one need to decrease bundle size, or is it everything in UnityEngine or nothing at all?
     
    Xepherys likes this.
  17. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    That's fair. For the record, it doesn't impact the compiler. Really, you're using the namespace either way. With
    using
    , you're specifying it once. Inline, you're specifying it every time. But after thinking about this, I have two examples of why
    using
    makes for more readable code.

    Let's say I have code in the ns
    Xepherys.Labyrintheer
    . In one file I define a class Foo. In another file I define a class Bar that calls a static method in Foo. Would you find it more readable to write
    Xepherys.Labyrintheer.Foo.Method()
    rather than
    Foo.Method()
    given that they're in the same ns? Without an explicit ns, it's presumed that it's in the same ns, and either would work the same (even without
    using
    ).

    Next, assume I have namespaces
    Xepherys.Labyrintheer.Utils
    ,
    Xepherys.Labyrintheer.Managers
    , and
    Xepherys.Labyrintheer.PrimaryShapes
    .

    Now I have this code:

    Code (csharp):
    1.  
    2. namespace Xepherys.Labyrintheer
    3. {
    4.     class Foo
    5.     {
    6.         private Xepherys.Labyrintheer.Managers.ObjectManager _objMgr;
    7.  
    8.         public void BuildFoo()
    9.         {
    10.             _objMgr.shapes = new Xepherys.Labyrintheer.PrimaryShapes.Shape[3];
    11.             _objMgr.shapes[0] = new Xepherys.Labyrintheer.PrimaryShapes.ShapeSphere();
    12.             _objMgr.shapes[1] = new Xepherys.Labyrintheer.PrimaryShapes.ShapeCube();
    13.             _objMgr.shapes[2] = new Xepherys.Labyrintheer.PrimaryShapes.ShapeCylinder();
    14.         }
    15.  
    16.         public void ModifyFoo()
    17.         {
    18.             foreach (Xepherys.Labyrintheer.PrimaryShapes.Shape shape in _objMgr.shapes)
    19.             {
    20.                 Xepherys.Labyrintheer.Utils.ModifyShapeMesh.Modify(shape);
    21.             }
    22.         }
    23.     }
    24. }
    25.  
    or:

    Code (csharp):
    1.  
    2. using Xepherys.Labyrintheer.Managers;
    3. using Xepherys.Labyrintheer.PrimaryShapes;
    4. using Xepherys.Labyrintheer.Utils;
    5.  
    6. namespace Xepherys.Labyrintheer
    7. {
    8.     class Foo
    9.     {
    10.         private ObjectManager _objMgr;
    11.  
    12.         public void BuildFoo()
    13.         {
    14.             _objMgr.shapes = new Shape[3];
    15.             _objMgr.shapes[0] = new ShapeSphere();
    16.             _objMgr.shapes[1] = new ShapeCube();
    17.             _objMgr.shapes[2] = new ShapeCylinder();
    18.         }
    19.  
    20.         public void ModifyFoo()
    21.         {
    22.             foreach (Shape shape in _objMgr.shapes)
    23.             {
    24.                 ModifyShapeMesh.Modify(shape);
    25.             }
    26.         }
    27.     }
    28. }
    29.  
    I suspect most people would prefer to read the latter. The first is so verbose and text-dense. Which is why most people write it the second way.
     
    HjorthBjorn likes this.
  18. HjorthBjorn

    HjorthBjorn

    Joined:
    Aug 12, 2013
    Posts:
    21
    I suspect most would prefer the latter, but we could have a talk about the abyssal naming conventions and naming it different would make it easier to understand.
    taking this
    Xepherys.Labyrintheer.Utils.ModifyShapeMesh.Modify(shape);

    to this
    Xepherys.Utils.ShapeMesh.Modify(shape);


    Or
    _objMgr.shapes[0] = new Xepherys.Labyrintheer.PrimaryShapes.ShapeSphere();

    to
    _objMgr.shapes[0] = new Xepherys.PrimaryShapes.Sphere();


    And then I would argue the verbose nature of the code is worth it for readability.

    But with that said I think we both understand each other and our reasoning here :)
     
    Xepherys likes this.