Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. Best Practice Question - How do you prefer to pass a bunch of options to a function?

Best Practice Question - How do you prefer to pass a bunch of options to a function?

Scheduled Pinned Locked Moved The Lounge
questiondiscussioncsharprubyhtml
39 Posts 21 Posters 9 Views 1 Watching
  • 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.
  • Kornfeld Eliyahu PeterK Kornfeld Eliyahu Peter

    In most cases I consider a large number of parameters (let say over 8) as design flaw, however it is possible that you end with such a list, in which case I would use struct/class...

    I'm not questioning your powers of observation; I'm merely remarking upon the paradox of asking a masked man who he is. (V)

    K Offline
    K Offline
    kalberts
    wrote on last edited by
    #17

    In the old days, I was working with a Fortran compilers where we had to push the release due to one (important) customer who had run into a limitation of the previous one: It could take only 99 (ninety-nine) parameters. The new version could handle 128 parameters, which was sufficient for the immediate needs of the customer, but the design allowed expansion to 256 parameters. If there ever was a case for Fortran COMMON blocks, I would call this a candidate. (Don't take me wrong - I am not suggesting using COMMON blocks as good programming practice. Nor is 100+ function parameters.)

    D G 2 Replies Last reply
    0
    • P Pete OHanlon

      I would have to go with wrapping the parameters in a struct/class. That way, I can put all sorts of validation in there that gives the object some context.

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #18

      Some more advantages; it's more readable when there are lots of arguments, one can easily modify the parameter-set without having to touch each method, and one can even inherit a new set of parameters. EventArgs - wonderfull example.

      Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

      1 Reply Last reply
      0
      • M Marc Clifton

        Key-Value Options: Let's say you have a function that can take a bunch of options for how to build something, say some auto-generated HTML, when passing them as parameters is just too cumbersome? Personally, I would just put all the options into a struct and pass an instance of the struct into the function. The nice thing about that is, the struct (or class, if you wish) documents all the possible options. Now, in the land of Ruby, I see everybody everywhere using key-value pairs associated with symbols, like this: {option1: true, option2: "foobar", option3: 42} Now of course the symbols usually have some intelligent meaning, but you have absolutely no clue what these optional parameters are unless you look up the online documentation (if it exists) and then can be sprawled across numerous pages on the website. And worse, in the Ruby code, these options are of course usually tested using the symbol: if opts[:option1] ... end such that, if you mistype the "key" (symbol), nothing is going to complain to you, unless the programmer checks the option list for unknown options, which I have NEVER seen done. Now, there's lots of alternatives in the, say, C# world. Your function can take a variable number of parameters. You can require that the caller provides a callback for resolving options. You can just put everything into the function's parameter list, and so forth. Or, like Rubyists, you can pass in a dictionary or some such thing of options. Valueless Options (aka flags): So far, the above discussion deals with options that have associated values. There is also the issue of "valueless" options -- if the "key" is present, then the option is "selected." One of the most common ways of passing in valueless options to a function in most languages is of course with an enum, especially when you can use the "or" operator to combine multiple valueless options. Now, mind you, in Ruby, there is no concept of an enum, which is a serious drawback in my opinion. But I'm curious what people consider to be their own best practice. Marc

        K Offline
        K Offline
        kalberts
        wrote on last edited by
        #19

        We have been using the struct practice for years, and I am personally strongly in favor of it. I would like to add a few comments/modifications, though: First, a set of options is not a function declaration issue, but a system data design issue. Two or more functions referring to, say, page layout properties should not declare "their own" parameter structs (possibly overlooking some essential parameter). The set of options affecting page layout, say, is one well defined set for the entirre application (or even more). Second, you should never slump together completely unrelated options in one struct, even if one function (or even several) inspects them all. One option struct defines page layout parameters, another one typographical characteristics, a third one the current user. So you might end up with "several" (i.e. a few) option parameters, but not a hundred of them. (For all practical purposes, this second point is also a requirement for my first point.) Third, as software develops, new options will be added. For an exported library function, it must be prepared to handle calls from applications both newer (supplying a larger struct with added and unknown fields) and older (supplying structs with missing fields) applications, and be able to handle them both. So the struct must identify the version. So one of the fields in the option struct is "This is format 3". An alternative is "This struct contains 44 valid bytes of parameters. The very best is to include both: This struct contains 44 bytes of parameters of format 3" - then you can add parameters in format 3 as long as the extensions are fully compatible, and bump the format code only when an incompatible extension is introduced. So the caller must fill in two extra fields, but then again, the same declaration can be used twenty years later. (Don't expect anyone below thirty to see the value of that...) Another alternativ is of course the Win32 API way: Start with MyFunction. Then, when one option is added, call it MyFunctionEx. After the second extension, make it MyFunctionEx. After extension eight, it is MyFunctionExExExExExExExEx, and so it continues :)

        1 Reply Last reply
        0
        • M Marc Clifton

          Key-Value Options: Let's say you have a function that can take a bunch of options for how to build something, say some auto-generated HTML, when passing them as parameters is just too cumbersome? Personally, I would just put all the options into a struct and pass an instance of the struct into the function. The nice thing about that is, the struct (or class, if you wish) documents all the possible options. Now, in the land of Ruby, I see everybody everywhere using key-value pairs associated with symbols, like this: {option1: true, option2: "foobar", option3: 42} Now of course the symbols usually have some intelligent meaning, but you have absolutely no clue what these optional parameters are unless you look up the online documentation (if it exists) and then can be sprawled across numerous pages on the website. And worse, in the Ruby code, these options are of course usually tested using the symbol: if opts[:option1] ... end such that, if you mistype the "key" (symbol), nothing is going to complain to you, unless the programmer checks the option list for unknown options, which I have NEVER seen done. Now, there's lots of alternatives in the, say, C# world. Your function can take a variable number of parameters. You can require that the caller provides a callback for resolving options. You can just put everything into the function's parameter list, and so forth. Or, like Rubyists, you can pass in a dictionary or some such thing of options. Valueless Options (aka flags): So far, the above discussion deals with options that have associated values. There is also the issue of "valueless" options -- if the "key" is present, then the option is "selected." One of the most common ways of passing in valueless options to a function in most languages is of course with an enum, especially when you can use the "or" operator to combine multiple valueless options. Now, mind you, in Ruby, there is no concept of an enum, which is a serious drawback in my opinion. But I'm curious what people consider to be their own best practice. Marc

          B Offline
          B Offline
          BobJanova
          wrote on last edited by
          #20

          I think it's important that there's an easy way to find which options are defined. I've had issues with Javascript libraries that take an object as a parameter, and expect you to put the right properties in there (the XMLHttpRequest AJAX handler does this iirc). In a statically typed language like C# or Java (or even C, Delphi, C++ etc), it makes sense to use a struct or class (using those words in their C# meaning) for groups of parameters with values, and a flagwise enum for those without. If you don't have enums then the old school approach of constants set to the appropriate bit values and using | to combine them is fine too. The grouping is important, it shouldn't just be public struct StuffUsedByThisFunction, it should have some semantic meaning even outwith the context of the function call. In dynamic languages the convention seems to be dictionaries with lax validation. I agree that this is often unhelpful, but it's encouraged by the object model in those languages which doesn't really do static declaration of valid members. I've not really worked in those languages enough to have developed a good solution, though.

          T 1 Reply Last reply
          0
          • B BobJanova

            I think it's important that there's an easy way to find which options are defined. I've had issues with Javascript libraries that take an object as a parameter, and expect you to put the right properties in there (the XMLHttpRequest AJAX handler does this iirc). In a statically typed language like C# or Java (or even C, Delphi, C++ etc), it makes sense to use a struct or class (using those words in their C# meaning) for groups of parameters with values, and a flagwise enum for those without. If you don't have enums then the old school approach of constants set to the appropriate bit values and using | to combine them is fine too. The grouping is important, it shouldn't just be public struct StuffUsedByThisFunction, it should have some semantic meaning even outwith the context of the function call. In dynamic languages the convention seems to be dictionaries with lax validation. I agree that this is often unhelpful, but it's encouraged by the object model in those languages which doesn't really do static declaration of valid members. I've not really worked in those languages enough to have developed a good solution, though.

            T Offline
            T Offline
            Tony Moffatt
            wrote on last edited by
            #21

            Dependancy Injection!!

            B 1 Reply Last reply
            0
            • K kalberts

              In the old days, I was working with a Fortran compilers where we had to push the release due to one (important) customer who had run into a limitation of the previous one: It could take only 99 (ninety-nine) parameters. The new version could handle 128 parameters, which was sufficient for the immediate needs of the customer, but the design allowed expansion to 256 parameters. If there ever was a case for Fortran COMMON blocks, I would call this a candidate. (Don't take me wrong - I am not suggesting using COMMON blocks as good programming practice. Nor is 100+ function parameters.)

              D Offline
              D Offline
              Dan Neely
              wrote on last edited by
              #22

              :omg: :wtf: Just thinking about that is probably enough that you need some medication. Have a :beer: on me.

              Did you ever see history portrayed as an old man with a wise brow and pulseless heart, waging all things in the balance of reason? Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful? --Zachris Topelius Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies. -- Sarah Hoyt

              1 Reply Last reply
              0
              • M Marc Clifton

                Key-Value Options: Let's say you have a function that can take a bunch of options for how to build something, say some auto-generated HTML, when passing them as parameters is just too cumbersome? Personally, I would just put all the options into a struct and pass an instance of the struct into the function. The nice thing about that is, the struct (or class, if you wish) documents all the possible options. Now, in the land of Ruby, I see everybody everywhere using key-value pairs associated with symbols, like this: {option1: true, option2: "foobar", option3: 42} Now of course the symbols usually have some intelligent meaning, but you have absolutely no clue what these optional parameters are unless you look up the online documentation (if it exists) and then can be sprawled across numerous pages on the website. And worse, in the Ruby code, these options are of course usually tested using the symbol: if opts[:option1] ... end such that, if you mistype the "key" (symbol), nothing is going to complain to you, unless the programmer checks the option list for unknown options, which I have NEVER seen done. Now, there's lots of alternatives in the, say, C# world. Your function can take a variable number of parameters. You can require that the caller provides a callback for resolving options. You can just put everything into the function's parameter list, and so forth. Or, like Rubyists, you can pass in a dictionary or some such thing of options. Valueless Options (aka flags): So far, the above discussion deals with options that have associated values. There is also the issue of "valueless" options -- if the "key" is present, then the option is "selected." One of the most common ways of passing in valueless options to a function in most languages is of course with an enum, especially when you can use the "or" operator to combine multiple valueless options. Now, mind you, in Ruby, there is no concept of an enum, which is a serious drawback in my opinion. But I'm curious what people consider to be their own best practice. Marc

                K Offline
                K Offline
                Kirk 10389821
                wrote on last edited by
                #23

                Parameters? Why not just use Global Variables??? Wait for it... ROTFLMAO... I did flag this as a JOKE! That is a HORRIBLE IDEA, for the record... And for the record, we used a structure, and it worked beautifully. The tricky part is when you call a function that needs 1 of those parameters... Do you pass the structure, or struct.val3 ? (we based it on the completeness of the function. If we felt it wasn't changing, then we sent as little data as possible, but more than one field meant the structure).

                1 Reply Last reply
                0
                • K kalberts

                  In the old days, I was working with a Fortran compilers where we had to push the release due to one (important) customer who had run into a limitation of the previous one: It could take only 99 (ninety-nine) parameters. The new version could handle 128 parameters, which was sufficient for the immediate needs of the customer, but the design allowed expansion to 256 parameters. If there ever was a case for Fortran COMMON blocks, I would call this a candidate. (Don't take me wrong - I am not suggesting using COMMON blocks as good programming practice. Nor is 100+ function parameters.)

                  G Offline
                  G Offline
                  gggustafson
                  wrote on last edited by
                  #24

                  COMMON is certainly good "programming practice" as long as each COMMON is named and contains a single value. Otherwise I submit that COMMON should be found non-complying in coding standards.

                  Gus Gustafson

                  1 Reply Last reply
                  0
                  • M Marc Clifton

                    Key-Value Options: Let's say you have a function that can take a bunch of options for how to build something, say some auto-generated HTML, when passing them as parameters is just too cumbersome? Personally, I would just put all the options into a struct and pass an instance of the struct into the function. The nice thing about that is, the struct (or class, if you wish) documents all the possible options. Now, in the land of Ruby, I see everybody everywhere using key-value pairs associated with symbols, like this: {option1: true, option2: "foobar", option3: 42} Now of course the symbols usually have some intelligent meaning, but you have absolutely no clue what these optional parameters are unless you look up the online documentation (if it exists) and then can be sprawled across numerous pages on the website. And worse, in the Ruby code, these options are of course usually tested using the symbol: if opts[:option1] ... end such that, if you mistype the "key" (symbol), nothing is going to complain to you, unless the programmer checks the option list for unknown options, which I have NEVER seen done. Now, there's lots of alternatives in the, say, C# world. Your function can take a variable number of parameters. You can require that the caller provides a callback for resolving options. You can just put everything into the function's parameter list, and so forth. Or, like Rubyists, you can pass in a dictionary or some such thing of options. Valueless Options (aka flags): So far, the above discussion deals with options that have associated values. There is also the issue of "valueless" options -- if the "key" is present, then the option is "selected." One of the most common ways of passing in valueless options to a function in most languages is of course with an enum, especially when you can use the "or" operator to combine multiple valueless options. Now, mind you, in Ruby, there is no concept of an enum, which is a serious drawback in my opinion. But I'm curious what people consider to be their own best practice. Marc

                    P Offline
                    P Offline
                    patbob
                    wrote on last edited by
                    #25

                    If the function has "too many" arguments, accept that it's ugly and live with it. Putting them in a struct is just hiding the ugliness and moving the complexity elsewhere, possibly remote from the function call itself. In my mind, it just makes for extra work to understand and maintain. The optional argument example is a perfect time to use an overload. That way you have a place to document the unique behavior of that variation of the function, and have documented for the next developer which arguments need to be specified as a set. The struct solution isn't a bad way to hide the problem, although a polymorphic class might be better depending on the needs.

                    We can program with only 1's, but if all you've got are zeros, you've got nothing.

                    1 Reply Last reply
                    0
                    • P Pete OHanlon

                      I would have to go with wrapping the parameters in a struct/class. That way, I can put all sorts of validation in there that gives the object some context.

                      D Offline
                      D Offline
                      Daniel R Przybylski
                      wrote on last edited by
                      #26

                      I like that approach. It comes in handy with REST wrappers. You can create a struct that can validate and concatenate either the parameter list that you GET URL will need or the XML that your POST will need in a ToString() like method.

                      1 Reply Last reply
                      0
                      • T Tony Moffatt

                        Dependancy Injection!!

                        B Offline
                        B Offline
                        BobJanova
                        wrote on last edited by
                        #27

                        Into a function? I don't even see how that makes sense. Generally though I hate dependency injection. It makes it really really hard to find out what type of object you're actually dealing with when you're looking at the code.

                        1 Reply Last reply
                        0
                        • P Pete OHanlon

                          Except that you have created event arguments for use with none events. The sender is probably going to be completely useless.

                          C Offline
                          C Offline
                          Colborne_Greg
                          wrote on last edited by
                          #28

                          You do understand that we are working with event driven programming right? The entire inner working of the object programming model has a point of origin and the event that triggered it. You should always be making your code generic as it can be understood by everything, and your procedure should be tread safe - which means everything you need should be passed as a parameter.

                          P 1 Reply Last reply
                          0
                          • C Colborne_Greg

                            You do understand that we are working with event driven programming right? The entire inner working of the object programming model has a point of origin and the event that triggered it. You should always be making your code generic as it can be understood by everything, and your procedure should be tread safe - which means everything you need should be passed as a parameter.

                            P Offline
                            P Offline
                            Pete OHanlon
                            wrote on last edited by
                            #29

                            Colborne_Greg wrote:

                            You do understand that we are working with event driven programming right?

                            That's a very narrow point of view, focused on one technology set. At no stage did Marc state he was asking about an event. And while there is a point of origin, there's no guarantee that he is responding to an event - you may have noticed that Marc was talking in a generic sense, hence the reason he mentioned ROR. So, in the case of doing something like processing a batch input on a file, forcing the programming model to use an event signature doesn't really make sense.

                            Colborne_Greg wrote:

                            You should always be making your code generic as it can be understood by everything, and your procedure should be tread safe - which means everything you need should be passed as a parameter.

                            And that is why my response, at the top of this thread, stated that I would normally wrap things up into an object.

                            C 2 Replies Last reply
                            0
                            • P Pete OHanlon

                              Colborne_Greg wrote:

                              You do understand that we are working with event driven programming right?

                              That's a very narrow point of view, focused on one technology set. At no stage did Marc state he was asking about an event. And while there is a point of origin, there's no guarantee that he is responding to an event - you may have noticed that Marc was talking in a generic sense, hence the reason he mentioned ROR. So, in the case of doing something like processing a batch input on a file, forcing the programming model to use an event signature doesn't really make sense.

                              Colborne_Greg wrote:

                              You should always be making your code generic as it can be understood by everything, and your procedure should be tread safe - which means everything you need should be passed as a parameter.

                              And that is why my response, at the top of this thread, stated that I would normally wrap things up into an object.

                              C Offline
                              C Offline
                              Colborne_Greg
                              wrote on last edited by
                              #30

                              When the procedure was called is an event when the processing a batch input on a file BOF reached and EOF reached are events. Everything is an event, and inheriting from eventargs allows your code to be repurposed everywhere, and when all your delegates have the same signature you wont get held back when you want to dive deeper into generics.

                              P 1 Reply Last reply
                              0
                              • P Pete OHanlon

                                Colborne_Greg wrote:

                                You do understand that we are working with event driven programming right?

                                That's a very narrow point of view, focused on one technology set. At no stage did Marc state he was asking about an event. And while there is a point of origin, there's no guarantee that he is responding to an event - you may have noticed that Marc was talking in a generic sense, hence the reason he mentioned ROR. So, in the case of doing something like processing a batch input on a file, forcing the programming model to use an event signature doesn't really make sense.

                                Colborne_Greg wrote:

                                You should always be making your code generic as it can be understood by everything, and your procedure should be tread safe - which means everything you need should be passed as a parameter.

                                And that is why my response, at the top of this thread, stated that I would normally wrap things up into an object.

                                C Offline
                                C Offline
                                Colborne_Greg
                                wrote on last edited by
                                #31

                                Also you can send a class object as the sender for the processing to interact with. In your example of the processing of the batch input, the result can be given in the same procedure to the sender to be displayed.

                                1 Reply Last reply
                                0
                                • C Colborne_Greg

                                  When the procedure was called is an event when the processing a batch input on a file BOF reached and EOF reached are events. Everything is an event, and inheriting from eventargs allows your code to be repurposed everywhere, and when all your delegates have the same signature you wont get held back when you want to dive deeper into generics.

                                  P Offline
                                  P Offline
                                  Pete OHanlon
                                  wrote on last edited by
                                  #32

                                  Seriously, everything isn't an event. Not all environments are event based, and for those that are, creating events for things that don't need to be events is an unnecessary overhead. We might as well stop now because I'm not going to convince you and you aren't going to convince me.

                                  C 1 Reply Last reply
                                  0
                                  • P Pete OHanlon

                                    Seriously, everything isn't an event. Not all environments are event based, and for those that are, creating events for things that don't need to be events is an unnecessary overhead. We might as well stop now because I'm not going to convince you and you aren't going to convince me.

                                    C Offline
                                    C Offline
                                    Colborne_Greg
                                    wrote on last edited by
                                    #33

                                    You are thinking to hard. Kiss - keep it simple stupid. Everything is an event whether you are programming with events, responding to events, or looking for events in code via a conditional statement, an event is a English word that gives abstract context to meaning. Its like arguing that a date/time, or decimal is not a string - well yes those are strings and are processed differently, which is the opposite to generics - inherit from eventargs whether or not you are responding to an actual event so that all your delegates have the same signature, then when you get into the thinking of what an actual event is your code will become cleaner.

                                    P 1 Reply Last reply
                                    0
                                    • C Colborne_Greg

                                      You are thinking to hard. Kiss - keep it simple stupid. Everything is an event whether you are programming with events, responding to events, or looking for events in code via a conditional statement, an event is a English word that gives abstract context to meaning. Its like arguing that a date/time, or decimal is not a string - well yes those are strings and are processed differently, which is the opposite to generics - inherit from eventargs whether or not you are responding to an actual event so that all your delegates have the same signature, then when you get into the thinking of what an actual event is your code will become cleaner.

                                      P Offline
                                      P Offline
                                      Pete OHanlon
                                      wrote on last edited by
                                      #34

                                      I suppose the difference between you and me is that I have experience in none event driven systems, as well as in none .NET platforms so my first instinct is not to always make things an event. They aren't suitable for every platform. So perhaps you need to think a little harder and get out of the .NET bubble. It'll open your mind.

                                      C 1 Reply Last reply
                                      0
                                      • M Marc Clifton

                                        Key-Value Options: Let's say you have a function that can take a bunch of options for how to build something, say some auto-generated HTML, when passing them as parameters is just too cumbersome? Personally, I would just put all the options into a struct and pass an instance of the struct into the function. The nice thing about that is, the struct (or class, if you wish) documents all the possible options. Now, in the land of Ruby, I see everybody everywhere using key-value pairs associated with symbols, like this: {option1: true, option2: "foobar", option3: 42} Now of course the symbols usually have some intelligent meaning, but you have absolutely no clue what these optional parameters are unless you look up the online documentation (if it exists) and then can be sprawled across numerous pages on the website. And worse, in the Ruby code, these options are of course usually tested using the symbol: if opts[:option1] ... end such that, if you mistype the "key" (symbol), nothing is going to complain to you, unless the programmer checks the option list for unknown options, which I have NEVER seen done. Now, there's lots of alternatives in the, say, C# world. Your function can take a variable number of parameters. You can require that the caller provides a callback for resolving options. You can just put everything into the function's parameter list, and so forth. Or, like Rubyists, you can pass in a dictionary or some such thing of options. Valueless Options (aka flags): So far, the above discussion deals with options that have associated values. There is also the issue of "valueless" options -- if the "key" is present, then the option is "selected." One of the most common ways of passing in valueless options to a function in most languages is of course with an enum, especially when you can use the "or" operator to combine multiple valueless options. Now, mind you, in Ruby, there is no concept of an enum, which is a serious drawback in my opinion. But I'm curious what people consider to be their own best practice. Marc

                                        R Offline
                                        R Offline
                                        RafagaX
                                        wrote on last edited by
                                        #35

                                        If the function requires less than 10 arguments, then I let them be as parameters, otherwise, I may start making classes of the one that have something in common and pass that instead.

                                        CEO at: - Rafaga Systems - Para Facturas - Modern Components for the moment...

                                        1 Reply Last reply
                                        0
                                        • P Pete OHanlon

                                          I suppose the difference between you and me is that I have experience in none event driven systems, as well as in none .NET platforms so my first instinct is not to always make things an event. They aren't suitable for every platform. So perhaps you need to think a little harder and get out of the .NET bubble. It'll open your mind.

                                          C Offline
                                          C Offline
                                          Colborne_Greg
                                          wrote on last edited by
                                          #36

                                          -_- I am a cobol programmer, I also started my statement with... when dealing with Microsoft related products which is the dot net bubble...

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups