• Login
sketchucation logo sketchucation
  • Login
πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

Ruby "good practice" using constants?

Scheduled Pinned Locked Moved Developers' Forum
23 Posts 3 Posters 2.9k Views 3 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    brewsky
    last edited by 26 Sept 2012, 18:01

    I am wondering of it could be a good idea / good practice to use a constant as a placeholder for my plugin's main library object.
    The object pointer itself will never change(and thus could be called "constant"), only it's contents are dynamic.

    I considered this because a constant can be accessed from anywhere in the module, without having to resort to globals, or having to forward the object in every new class instance(as I do now).

    Cheers!
    Jan

    Sketchup BIM-Tools - http://sketchucation.com/forums/viewtopic.php?p=299107

    1 Reply Last reply Reply Quote 0
    • T Offline
      thomthom
      last edited by 26 Sept 2012, 19:34

      I do that. I follow a pattern where TT is my root namespace. Plugins I developer are under TT::Plugins - so in for example QuadFace Tools I have:

      <span class="syntaxdefault">module&nbsp;TT</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Plugins</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">QuadFaceTools<br /><br />&nbsp;&nbsp;PLUGIN&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">self<br /><br />end</span>
      

      I then use PLUGIN as a shortcut within that namespace.

      Thomas Thomassen β€” SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund

      1 Reply Last reply Reply Quote 0
      • D Offline
        Dan Rathbun
        last edited by 26 Sept 2012, 19:50

        @thomthom said:

        I then use PLUGIN as a shortcut within that namespace.

        But you CAN still use self so I do not the point.

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • T Offline
          thomthom
          last edited by 26 Sept 2012, 19:55

          @dan rathbun said:

          @thomthom said:

          I then use PLUGIN as a shortcut within that namespace.

          But you CAN still use self so I do not the point.

          Because I use PLUGIN within sub-modules when I need to refer back to the root namespace for the current plugin.

          <span class="syntaxdefault"><br />module&nbsp;TT</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Plugins</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Example<br /><br />&nbsp;&nbsp;PLUGIN&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">self<br /><br />&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">hello_world<br />&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span class="syntaxstring">';)'<br />&nbsp;&nbsp;</span><span class="syntaxdefault">end<br /><br />&nbsp;&nbsp;module&nbsp;FooBar<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">magic_button<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PLUGIN</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">hello_world<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;end<br /><br />end<br /></span>
          

          Since I use that pattern in my plugins I can port modules from one plugin to another with less rewrite - another benefit.

          Thomas Thomassen β€” SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund

          1 Reply Last reply Reply Quote 0
          • D Offline
            Dan Rathbun
            last edited by 26 Sept 2012, 20:16

            @brewsky said:

            I am wondering of it could be a good idea / good practice to use a constant as a placeholder for my plugin's main library object.

            But.. a class or module identifier IS a constant (it begins with a capital character.)

            @brewsky said:

            I considered this because a constant can be accessed from anywhere in the module, without having to resort to globals, or having to forward the object in every new class instance(as I do now)

            (1) There is never any reason where you should resort to global references, for proprietary object references. (It's poor practice, clutters the global ObjectSpace and they can clash with other globals. Shared global constants are OK, such as MF_CHECKED, ... these are designed to be used by everyone.)

            (2) Let's say you create a BIM library, that you allow me to use.
            It's qualified constant reference is Brewsky::BIM::Lib

            I can use that or, I can create a local reference that points at it. (After all, a Module instance object is like any other instance object in Ruby, it can have any number of references pointing at it, at any time. Also the number of references pointing at an instance object, at any specific time, can vary. Example singleton instances of a specific member of the Integer class. There is only one integer 0, but many different references to it, from many different classes or modules.)

            So imagine I do not wish to type out the fully qualified name all the time:

            module Dan
              module NiftyPlugin
                LIB = Brewsky;;BIM;;Lib
                model = Sketchup.active_model
                LIB.create_wall(model,[0,0,0],(8.0).inch,(9.0).feet,(24.0).feet)
              end
            end
            
            

            But the reference does NOT have to be a local constant.
            It can can an instance reference:
            @lib = Brewsky::BIM::Lib

            It can be a class/module var reference:
            @@lib = Brewsky::BIM::Lib

            .. or even a local var reference (within a method or block.)
            lib = Brewsky::BIM::Lib

            So the type of reference depends upon how you will use it, what scope you want it to have, and for how long you wish to use it (ie, temporary or persistent.)


            Can you give us a code shell showing the namespace nesting, and how you wish to share the reference to your classes ??

            ❓

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • D Offline
              Dan Rathbun
              last edited by 26 Sept 2012, 20:20

              @thomthom said:

              Because I use PLUGIN within sub-modules when I need to refer back to the root namespace for the current plugin.

              <span class="syntaxdefault"><br />module TT</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Plugins</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Example<br /><br />  PLUGIN </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> self<br /><br />  def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">hello_world<br />    puts </span><span class="syntaxstring">';)'<br /></span><span class="syntaxdefault">  end<br /><br />  module FooBar<br />    def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">magic_button<br />       PLUGIN</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">hello_world<br />    end<br />  end<br /><br />end<br /></span>
              

              Sub-modules do not inherit the local constants of outer modules.

              @thomthom said:

              Since I use that pattern in my plugins I can port modules from one plugin to another with less rewrite - another benefit.

              This is what include and extend are for. Shared library modules are best written as "mixin" modules.

              Didn't we just have this discussion in another topic recently ??

              ❓

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • T Offline
                thomthom
                last edited by 26 Sept 2012, 20:47

                @dan rathbun said:

                Sub-modules do not inherit the local constants of outer modules.

                My snippet works. Try it.
                ModuleRef.png

                @dan rathbun said:

                This is what include and extend are for. Shared library modules are best written as "mixin" modules.

                Does that duplicate the methods? Or do they all refer to the source module?

                Thomas Thomassen β€” SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

                1 Reply Last reply Reply Quote 0
                • T Offline
                  thomthom
                  last edited by 26 Sept 2012, 20:51

                  This on the other hand doesn't work:
                  ModuleRef2.png

                  Thomas Thomassen β€” SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund

                  1 Reply Last reply Reply Quote 0
                  • D Offline
                    Dan Rathbun
                    last edited by 26 Sept 2012, 20:56

                    I did the first all in one line, at the console, and it did not work:

                    ` module Dan; OUTER = self; module Plugin; PLUGIN = self; class Special; CLASS = self; end; end; end

                    $ Dan::Plugin::Special::OUTER
                    %(#008000)[Error: #<NameError: (eval): uninitialized constant Dan::Plugin::Special::OUTER>
                    (eval)]`

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • D Offline
                      Dan Rathbun
                      last edited by 26 Sept 2012, 21:00

                      @thomthom said:

                      @dan rathbun said:

                      This is what include and extend are for. Shared library modules are best written as "mixin" modules.

                      Does that duplicate the methods?

                      NO.

                      @thomthom said:

                      Or do they all refer to the source module?

                      YES... it's like a proxy lookup.

                      So if you define two sub-modules that include a library mixin module of constants, and sub-module two changes a value of a constant, it changes IN the mixin module, and any other sub-module that has included the mixin module, will see the changes.

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • D Offline
                        Dan Rathbun
                        last edited by 26 Sept 2012, 21:16

                        @thomthom said:

                        My snippet works. Try it.

                        Reason, because it's a Ruby interpreter block scope issue (Easter egg like thing.)

                        The interpreter reads the humanized script, and translates this:

                        module TT;;Plugins;;Example
                        
                          PLUGIN = self
                        
                          module FooBar
                            def self.magic_button
                               puts PLUGIN.name
                            end
                          end
                        
                        end
                        

                        .. to (something similar on the C-side):

                        TT;;Plugins;;Example = Module.new {
                        
                          PLUGIN = self
                        
                          FooBar = Module.new {
                            def self.magic_button
                               puts PLUGIN.name
                            end
                          }
                        
                        }
                        

                        So the Foobar definition block has access to the object references in the wrapping scope.

                        IMHO: Although it works.. explaining why is complicated and will likely confuse newbies, and it not really following good organizational form, (which is what we want to teach newbies.)

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • T Offline
                          thomthom
                          last edited by 26 Sept 2012, 21:41

                          @dan rathbun said:

                          So if you define two sub-modules that include a library mixin module of constants, and sub-module two changes a value of a constant, it changes IN the mixin module, and any other sub-module that has included the mixin module, will see the changes.

                          That's interesting. So one can then add all common methods and constants to the mixin... and no extra overhead.

                          Thomas Thomassen β€” SketchUp Monkey & Coding addict
                          List of my plugins and link to the CookieWare fund

                          1 Reply Last reply Reply Quote 0
                          • D Offline
                            Dan Rathbun
                            last edited by 26 Sept 2012, 23:23

                            @thomthom said:

                            That's interesting. So one can then add all common methods and constants to the mixin... and no extra overhead.

                            Yea! That is the whole point ... and it also works with the module vars in the mixin module.

                            However sometimes evaluation may actually occur with in the Mixin module, rather than the "mixee" module. SO .. test.

                            I'm not here much anymore.

                            1 Reply Last reply Reply Quote 0
                            • T Offline
                              thomthom
                              last edited by 27 Sept 2012, 07:13

                              @dan rathbun said:

                              However sometimes evaluation may actually occur with in the Mixin module, rather than the "mixee" module. SO .. test.

                              What evaluation?

                              Thomas Thomassen β€” SketchUp Monkey & Coding addict
                              List of my plugins and link to the CookieWare fund

                              1 Reply Last reply Reply Quote 0
                              • D Offline
                                Dan Rathbun
                                last edited by 27 Sept 2012, 07:26

                                of methods... so example you'd have to pass in references from the mixee modules. (Don't expect the mixin method to have access to objects in the mixee module. ... From what I remember.)

                                However (as always,) mixing into classes is different. If the mixin instance method has a ref to a @var, the object used is the one in the mixee class. Which is what you would expect.

                                It's just that including modules into are a bit more "funky" then mixing modules into a class.

                                I'm not here much anymore.

                                1 Reply Last reply Reply Quote 0
                                • D Offline
                                  Dan Rathbun
                                  last edited by 27 Sept 2012, 07:27

                                  But we are getting off-topic here ... let's get back on constants.

                                  I'm not here much anymore.

                                  1 Reply Last reply Reply Quote 0
                                  • T Offline
                                    thomthom
                                    last edited by 27 Sept 2012, 07:50

                                    @dan rathbun said:

                                    of methods... so example you'd have to pass in references from the mixee modules. (Don't expect the mixin method to have access to objects in the mixee module. ... From what I remember.)

                                    I'm not quite following you here.. πŸ˜•
                                    Got a sample code to illustrate?

                                    Thomas Thomassen β€” SketchUp Monkey & Coding addict
                                    List of my plugins and link to the CookieWare fund

                                    1 Reply Last reply Reply Quote 0
                                    • B Offline
                                      brewsky
                                      last edited by 27 Sept 2012, 08:25

                                      Thanks guys!

                                      I have to do some reading to be able to follow the discussion πŸ˜‰
                                      I kinda lost it somewhere along the way...

                                      TT's first post came close to what I want to do.
                                      This is more what I mean:

                                      module TT;;Plugins
                                      
                                        PLUGIN = QuadFaceTools.new
                                      
                                      end
                                      

                                      @dan rathbun said:

                                      Can you give us a code shell showing the namespace nesting, and how you wish to share the reference to your classes ??

                                      This is an example of what I'm doing now.
                                      I make some sort of "root-plugin" object(class-instance, not a module) that holds all other plugin objects/data.
                                      And pass this on to all nested objects to be able to access the embedded data.

                                      module Brewsky;;BimTools
                                      
                                        class BimTools
                                          attr_accessor ;project_list, ;web_dialog
                                          def initialize
                                            btProject = BtProject.new(self)
                                          end
                                        end
                                        
                                        class BtProject
                                          attr_reader ;model, ;guid, ;name, ;description
                                          def initialize(bt)
                                            @bt = bt
                                          end
                                          def update_dialog(value)
                                            dialog = @bt.web_dialog
                                            
                                            # do something with "dialog" using "value"
                                            
                                          end
                                        end
                                        
                                        BimTools.new
                                      
                                      end
                                      

                                      Sketchup BIM-Tools - http://sketchucation.com/forums/viewtopic.php?p=299107

                                      1 Reply Last reply Reply Quote 0
                                      • D Offline
                                        Dan Rathbun
                                        last edited by 28 Sept 2012, 02:51

                                        Sometimes I pass in the outer namespace via the constructor (as you show in your example,) but usually it is into Observer instances. I normally give the "handle" the name @parent, @outer or similar.

                                        Access to data objects in the parent namespace, (if they are few,) can be done with more clarity, by also passing them in via the constructor call.
                                        See my simple plugin example: [Code] AnimateSelection Example
                                        In this example, the references are passed in as individual arguments.
                                        But if there are many, it may make more sense to collect the objects into a Hash or a Struct, and pass that in.

                                        πŸ’­

                                        I'm not here much anymore.

                                        1 Reply Last reply Reply Quote 0
                                        • B Offline
                                          brewsky
                                          last edited by 28 Sept 2012, 19:09

                                          I guess the way I'm passing the object into every sub-object is "structurally" the best way to go.
                                          But in this way I'm constantly making new pointers to always the same old base-object.
                                          And because there is only one instance, would it not be clearer to use some sort of "almost-global" object, such as a module-constant, and have access to it anywhere in the program?

                                          Like TT does?
                                          And after thinking on this, maybe TT's way of just making a module as a base-object for the plugin is a better approach than my BimTools-class. Because is't only used once, the module-approach seems more fitting...

                                          Something like:

                                          module Brewsky
                                          
                                            class BimTools
                                              attr_accessor ;project_list, ;web_dialog
                                              def initialize
                                                btProject = BtProject.new
                                              end
                                            end
                                            
                                            class BtProject
                                              attr_reader ;model, ;guid, ;name, ;description
                                              def update_dialog(value)
                                                dialog = PLUGIN.web_dialog
                                                
                                                # do something with "dialog" using "value"
                                                
                                              end
                                            end
                                            
                                            PLUGIN = BimTools.new
                                          
                                          end
                                          

                                          Sketchup BIM-Tools - http://sketchucation.com/forums/viewtopic.php?p=299107

                                          1 Reply Last reply Reply Quote 0
                                          • 1
                                          • 2
                                          • 1 / 2
                                          1 / 2
                                          • First post
                                            1/23
                                            Last post
                                          Buy SketchPlus
                                          Buy SUbD
                                          Buy WrapR
                                          Buy eBook
                                          Buy Modelur
                                          Buy Vertex Tools
                                          Buy SketchCuisine
                                          Buy FormFonts

                                          Advertisement