Search Unity

define functions and call them vs define public fields to access their functions

Discussion in 'Scripting' started by mahdiii, Oct 21, 2017.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Suppose we have a UI class that contains button,panel,progressbar,text,....
    The other class needs to get them and call some functions (setactive for panel, set text, set fill amount,..)
    which way is better?
    define these variables public accessor and get them inside another class and call functions
    or define special methods like (setActive,SetFillamount,SetText,...) and private accessor for variables and call these functions inside the other class.

    Code (CSharp):
    1. public class Class1:Monobehaviour{
    2.    public Text m_text;
    3.    public Progressbar m_progressbar ;
    4.    public GameObject m_panel;
    5. }
    6. //OR
    7. public class Class11:Monobehaviour{
    8.    private Text m_text;
    9.    private Progressbar m_progressbar ;
    10.    private GameObject m_panel;
    11.    public void SetActivePanel(bool _active){}
    12.    public void SetFillAmount(float _value){}
    13.    public void SetText(string _str){}
    14. }
    15. // Use these variables
    16. public class Class2:Monobehaviour{
    17.    public Class1 m_class1;
    18.    public Class11 m_class11;
    19.    void Func(){
    20.       m_class1.m_text="aa";
    21.       //OR
    22.      m_class11.SetText("aa");
    23.    }
    24. }
    I know the second approach encapsulates(and may be better) but in the future it may generate a lot of functions.
     
  2. hasanbayat

    hasanbayat

    Joined:
    Oct 18, 2016
    Posts:
    630
    The second one is better because the sub-object can implement it's own functionally.
    But when you have a feature that does not exist in the sub-object you can add your own method, for example, if you want to fade a text you can use the first way but when you want to set the content of the text, then you need the second way.

    This is some kind of Object Oriented Programming.
    Read more about it:
    Hope this helps.
    Thanks.
     
  3. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    I know OOP!!
    but I sometimes saw that a class define public getter and private setter property and we can get it and call its functions
    instead of defining a private field and public functions
     
  4. hasanbayat

    hasanbayat

    Joined:
    Oct 18, 2016
    Posts:
    630
    I know you know OOP, everyone knows it, but sometimes we miss some concepts and fundamentals of this, for example, myself missed many features of OOP and fallen into questions similar to your question, but when I read the OOP fully then I was solved my problems easily. anyway excuse me for targetting you :)

    Public Properties with Private Fields are the best choice.
    But sometimes the Public Methods with Private Fields are useful, but very rarely.
    So, I recommend the properties for getting and settings values directly to the object instead of using a broker.

    Hope this helps.
    Thanks.
     
    mahdiii likes this.
  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Both are valid approaches, it actually depends on the situation.
    Speaking about UI, the second is probably better IMO. It helps to decouple and it also limits the actions you can do (atm they're public, that's a little bit misleading).

    The main advantage is, that the actual objects to operate on are hidden, instead you manipulate them using that class which encapsulates them (given they're not public). Pretty similar to the MVC/MVP patterns.

    Well, imagine you've got a data model you want to visualize / render in a view.

    Using the first approach, everytime you want to change the visualization, everyone needs to know about the new way - that is, access the correct members, and do everything you need to do and maybe even KNOW how to do it. So, you might even encounter situations in which you need to rewrite half of your program if it's something that is used throughout your application.

    Using the second approach, you do not only have the benefit to 'group' funtionality and hide it behind a single, more descriptive method - which reduces redundant sequences of calls on the caller's side (that's also error prone or at least can lead to inconsistent usage) - but the implementation itself is the only one who cares about all the detailed steps necessary to render the data properly.

    This being said, it's a valid argument that you may end up mimicing alot of methods. If you mimic your objects interfaces one by one to provide all the functionality and you decide to use getters instead, it'd at least make a lot more sense to get these objects using an interface.

    But seriously, if you start to mimic everything one by one for a complex system, it'll be time to think about whether the approach you're using is a good one after all.
     
    Last edited: Oct 21, 2017
    mahdiii likes this.
  6. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    That's actually not true, it's not very rare, it's quite the opposite.
     
  7. hasanbayat

    hasanbayat

    Joined:
    Oct 18, 2016
    Posts:
    630
    Which one of the below is common?
    Public Properties with Private Fields
    Code (CSharp):
    1. public class MyClass {
    2.     [SerializeField]
    3.     private Text _testText;
    4.     public Text testText {
    5.         get {
    6.             return _testText;
    7.         }
    8.     }
    9. }
    10.  
    11. MyClass myClass = GetComponent<MyClass> ();
    12. myClass.testText.text = "Hello World!";
    Public Methods with Private Fields
    Code (CSharp):
    1. public class MyClass {
    2.     [SerializeField]
    3.     private Text _testText;
    4.     public void SetTestText (string value) {
    5.         _testText.text = value;
    6.     }
    7. }
    8.  
    9. MyClass myClass = GetComponent<MyClass> ();
    10. myClass.SetTestText("Hello World!");
     
  8. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Like I stated earlier - it depends.

    The second favors decoupling, as the caller does not need to get the text and operate on it.
    Instead, it tells someone who knows about 'who/what, where, when and how' the text will be shown - if it all. Unless the thing you get is an interface itself... that would be more acceptable than a concrete implementation, but still ... why not leave it up to the one object you call into?

    It's a very simplistic example, so either of both will do.
     
    Last edited: Oct 21, 2017
  9. hasanbayat

    hasanbayat

    Joined:
    Oct 18, 2016
    Posts:
    630
    The first way is used for complex operations and not simple operations.

    For example, if you want to apply an animation to text you can use second way, but when you want to change the text or adjust something that is implemented by text, you should use text object.

    But you are right, it depends. ;)
    Thanks.
     
  10. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Your first statement somewhat contradicts the the second one, at least in my interpretation.

    Anyway, I still wouldn't second that, because you simply cannot say it like that.
    When I say it depends, i refer to
    - OOP principles
    - SRP
    - code architecture
    - code qualities
    - ...
    - last but not least a tiny bit of personal preference
     
  11. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Thank you dudes
    Yes I agree. if we define methods inside a class (that use functions of object fields) and call from the other class, we can change the methods later without need to change the caller class.
    So if we don't define methods and instead define public fields or properties without any function,the caller needs to get and operate on them(that can cause duplicate codes) but if we want to operate on single member of an object (and we are sure that we don't need any function to manipulate it later) we can get this object and change.
    Thank you
     
    Last edited: Oct 21, 2017
    hasanbayat likes this.
  12. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    IMHO, the way the pros do it:

    o If you've seen this exact problem many times, pick the solution you always use and know works well.

    o Otherwise do it the simplest, quickest way possible. As you find the problems (if any) hopefully case 1 will apply. If not, _then_ think of a new approach. You'll have a much better feel for the problem.

    When you make a lot of plug-in abstract classes, you're really planning for those simple variables to change and grow in unexpected ways, and trying to make it easier for yourself later on. But 9 times out of 10 your Class1 is just an int, and will always be an int, and all you did was make the program slower and harder to read.

    The entire purpose of getters/setters/properties is so you can use a simple int at first, and easily convert it to a class later.