102

Most of the blogs or tutorials or books have private methods at the bottom of any class/module. Is this the best practice?

I find having private methods as and when necessary more convenient. For example:

public
def my_method
  # do something
  minion_method
end

private
def minion_method
  # do something
end

public
def next_method
end

This way I find the code more readable instead of scrolling up and down continuously which is very irritating.

Is there something terribly wrong in this approach? Is having private methods at the bottom not just a best practice and something else?

Dennis
  • 56,821
  • 26
  • 143
  • 139
ZX12R
  • 4,760
  • 8
  • 38
  • 53
  • actually your way is not bad either. I also follow the same in few case, it feels more convenient `private def my_method...end` – r3bo0t Oct 13 '16 at 15:55

10 Answers10

132

The best practice in my point of view is to go sequentially and declare your methods without keeping private in point of view.

At the end, you can make make any method private by just adding: private :xmethod

Example:

class Example
 def xmethod
 end

 def ymethod
 end

 def zmethod 
 end

 private :xmethod, :zmethod

end

Does this justify your question?

kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • 23
    I don't think this is a great idea from readability point of view as the class grows longer and longer. – Alexander Suraphel Nov 10 '16 at 12:35
  • 4
    I really think you should sort methods by order of importance and by what calls what when all other things seem equal. Private methods are an implementation details and should be the last thing the reader sees so belong lower in the file. I agree with the above comment that this won't work well with larger files. This should not be the accepted answer, there's so much better advice on this page. – Luke Cowell May 19 '17 at 00:28
  • 2
    Downvoting. This makes the public interface harder to see and is well out of the mainstream for Ruby code (I’ve literally never seen *any* code in this style in 14 years of working with Ruby). – Marnen Laibow-Koser Jun 10 '21 at 01:52
64

There's also the option to prepend private to the method definition since Ruby 2.1.

class Example
 def xmethod
 end

 private def ymethod
 end

 private_class_method def self.zmethod 
 end
end

You can instantly see if a method is private, no matter where in the (large) file it is. And it's consistent with many other languages. But it's a bit more typing and doesn't nicely align.

Dennis
  • 56,821
  • 26
  • 143
  • 139
  • 5
    You should have added note, that this is available in Ruby 2.1 where methods return key with their own name: https://bugs.ruby-lang.org/issues/3753 – konole Aug 01 '14 at 11:55
  • I believe private can also be used as a block, aka enclosing some private methods in private begin ... end – edx Nov 01 '15 at 00:04
  • see @devpuppy 's answer [here](http://stackoverflow.com/a/36510313/2544629) for a note about doing this with class methods. – manroe Aug 28 '16 at 19:25
  • Adding `private` only once, before the `ymethod`, also works. There is no need to add it multiple times. – Iulian Onofrei Mar 13 '18 at 20:09
  • 1
    @IulianOnofrei If you had another method below `zmethod` without `private`, this method would not be private. So, you need to repeat it (at least with Ruby 2.3). – tsauerwein Apr 04 '18 at 09:43
  • I meant on a separate line, before `ymethod`. – Iulian Onofrei Apr 04 '18 at 09:59
  • @IulianOnofrei that approach has already been covered by other answers. This answer introduces another solution (which at the time wasn't mentioned by the other answers) and covers its tradeoffs. – Dennis Apr 12 '18 at 20:21
  • @Dennis, Oh, sorry, somehow I missed them until now. – Iulian Onofrei Apr 13 '18 at 07:27
  • 1
    seems like the most readable way to do this, and also is similar to other programming languages like Java. – Patrick G. Jan 25 '21 at 01:56
55

As others have already pointed out the convention is to put private methods at the bottom, under one private class. However, you should probably also know that many programers use a double indented (4 spaces instead of 2) method for this. The reason is that often times you won't see "private" in your text editor and assume they could be public. See below for an illustration:

class FooBar

  def some_public_method
  end

  def another_public_method
  end

private

    def some_private_method
    end

    def another_private method
    end

end

This method should prevent you from having to scroll up and down and will make other programmers more comfortable in your code.

Noah Clark
  • 8,101
  • 14
  • 74
  • 116
  • 5
    This was all the rage when I left this comment back in '12. I don't see this very often anymore and it has fallen out of favor. – Noah Clark Jul 06 '16 at 19:11
  • privates can also be formatted inside `begin..end` right after `private`. Then the indentation can be set automatically by the editor since code inside the `begin` is (in the example above) semantically indented with 4 spaces. – Petrus Repo Aug 18 '16 at 06:24
  • I follow the same approach...first `public` and then `private` – Rahul Goyal Dec 28 '16 at 18:53
  • 2
    I’ve never ever seen this and I’ve been working with Ruby since 2007. I would generally not recommend it. – Marnen Laibow-Koser Sep 19 '19 at 23:43
15

I think that public methods is a some kind of interface of the object, and it's logical to place them on the most prominent place i.e. in the top of file.

Flexoid
  • 4,155
  • 21
  • 20
  • 6
    Yes, put the public methods where you're most likely to find them, generally near the top of the file, and things you probably shouldn't be looking at should be buried near the bottom. Like a newspaper article is written, put the most important things first. – tadman May 23 '12 at 17:02
14

You don't need to put public or private above each method. I usually put all of my private methods at the bottom of my class. Also, don't have to explicitly say public as methods are public by default. For example:

class FooBar

  def some_public_method
  end

  def another_public_method
  end

private

  def some_private_method
  end

  def another_private method
  end

end
Kyle Decot
  • 20,715
  • 39
  • 142
  • 263
  • Please read my question again. Have edited it to be more specific – ZX12R May 23 '12 at 16:39
  • 1
    It's more of a convention than anything. What you're doing is valid and if it makes more sense to you then you should stick with it. I find the convention to be more readable but that's probably because that's how I was taught to write it so I'm just used to it. – Kyle Decot May 23 '12 at 16:43
  • what does declaring a method as "public" actually mean/do ? – ZX12R May 23 '12 at 16:47
9

One style is to group methods together so that you only use private and protected once per class at most. Another style is to specify visibility right after the method definition:

class Example
  def my_private_method
  end
  private :my_private_method

  def my_public_method
  end
end

As of Ruby 2.1.0 def returns the method name as a symbol, so a more streamlined style is possible:

class Example
  private def my_private_method
  end

  def my_public_method
  end

  protected def my_protected_method
  end

  private_class_method def self.my_private_class_method
  end
end

(Note that we use private_class_method for class methods -- otherwise we'd get NameError: undefined method since private expects an instance method. Even when using it as a macro like in the original example it only affects the visibility of instance methods.)

I like this inline visibility style best, as it allows you to organize methods as you wish. It decreases the risk of adding a new method in the wrong place and inadvertently making it private.

As for the class method syntax, you can handle it this way instead:

class Example
  private def my_private_method
  end

  class << self
    private def my_private_class_method
    end
  end
end
devpuppy
  • 822
  • 9
  • 8
  • this is the only place I've seen mention of the `private_class_method` call before, and the last part about using the `class << self` block to avoid needing to use it is a good tip. Until now, I didn't know that "nornal" class methods (declared with `def self.foo; end` instead of `class << self; def foo; end` wouldn't be affected by the `private` specifier. – manroe Aug 28 '16 at 19:23
7

I'm coming from java background and I hate to have to scroll to see method type. I think it's insane that one cannot specify method visibility per method without ugliness. So I ended up putting a comment #private before each suck method and then declaring private :....

Update: In recent ruby one can write private def method_name so the above is much less relevant.

Update 2: actually see @devpuppy's answer, it has more explanation.

akostadinov
  • 17,364
  • 6
  • 77
  • 85
  • 1
    and recent ruby can just put `private def method...` to have it nicer – akostadinov Jan 23 '17 at 09:28
  • Surely writing everything twice (once in a comment) is worse ugliness. Keep Java verbosity out of Ruby. – Marnen Laibow-Koser Mar 24 '21 at 15:09
  • @MarnenLaibow-Koser, verbosity and visibility are different things. For me high priority is avoiding to scroll around unnecessarily. Especially when code is not written by me or I wrote it yesterday and have no clue what went it there. I updated answer to account for more recent ruby. – akostadinov Mar 25 '21 at 07:53
  • No one (in my experience during 13 years of Ruby development) writes `private` before each private method in Ruby. So if the code is not written by you, it’s all the more important that you learn to effectively navigate code where that isn’t done. A good editor with a symbol list feature (such as the one found in Atom) can really help here. As for scrolling around, if you’re doing a lot of that, that’s the code telling you that it should be broken up into multiple modules/classes. – Marnen Laibow-Koser Mar 26 '21 at 14:20
  • @MarnenLaibow-Koser, question was which approach makes most sense. But I have to navigate multiple projects that I don't maintain - refactoring them all is impossible. And even refactoring projects that do their job is in most cases highly unreasonable. And then what? Switch navigating within a file with navigating between different files (which mixed together have a higher chance to interfere with each other)? All serious projects I've seen have the large classes. You can't escape complexity and I have a favorite famous project, driven by purists that is IMO unreasonable to hell with that :/ – akostadinov Mar 26 '21 at 17:16
  • Serious projects don’t have to have large classes, and if they are written by people who are committed to code quality, they don’t tend to have large classes. You can’t escape complexity, but it doesn’t have to all be in one file. :) – Marnen Laibow-Koser Mar 27 '21 at 16:06
  • As for code navigation, I find that in Ruby I rarely care whether a method is public or private when I’m just reading code. I only care about that aspect if I’m editing code—and then I *can*, and *do*, refactor stuff. As for refactoring projects that do their job: if it did its job, I wouldn’t need to be changing it in the first place! (Also, refactoring is a key part of sustainable development and should be embraced, not feared.) All these, taken together, mean that there’s little reason to put `private` before every private method. – Marnen Laibow-Koser Mar 27 '21 at 16:10
  • Let me turn the question around: if you’re just reading code, why do you care about whether a method is public? Are you just used to seeing that due to Java syntax, or do you derive some particular benefit from seeing it? If so, what? – Marnen Laibow-Koser Mar 27 '21 at 16:12
  • @MarnenLaibow-Koser, you can insist but this is not the reality. Also number of methods and size of class does not necessarily mean complexity. Just a bunch of unrelated methods is long but not complicated. 10 methods with complicated interaction between them is complicated. And I'm reading code to see how to use it due to terrible documentation usually in ruby projects. Not just for the sake of reading. Good for you you have the time to refactor code you are using, although I doubt you do that for libraries that you use. – akostadinov Mar 28 '21 at 08:16
  • “Good for you you have the time to refactor code you are using, although I doubt you do that for libraries that you use.” I usually use libraries that I don’t need to peek into (because they’re well documented and work as documented), but when that’s not the case, I absolutely do contribute back by refactoring, adding tests, and developing the features I need. “Just a bunch of unrelated methods is long but not complicated.” A bunch of unrelated methods shouldn’t be in the same class or module, and yes, I’d say that having them together increases complication by mixing concerns. – Marnen Laibow-Koser Mar 30 '21 at 07:32
  • “you can insist but this is not the reality” I’m not insisting on anything; I’m just sharing my experience that method visibility is usually the least of my concerns when I’m reading code in Ruby (it is important when *writing* code). “And I'm reading code to see how to use it due to terrible documentation usually in ruby projects.” Ruby gems, at any rate, are usually relatively well documented, though the documentation is generally written in a rather different style from Javadoc. I find that it’s rare that I have to peek into gem internals (though it happens). – Marnen Laibow-Koser Mar 30 '21 at 07:36
  • @MarnenLaibow-Koser, usually simple use cases are well documented. I find myself far too often in need of something undocumented though. I don't know, it might be my personal issue ¯\_(ツ)_/¯ – akostadinov Mar 30 '21 at 15:23
5

I don't like having to specify public or private for each method. Putting all private methods at the bottom lets me have a single instance of "private" per file. I guess it's a matter of taste.

David
  • 1,143
  • 8
  • 12
3

Dennis had the perfect answer, that is, when using ruby >=2.1, just prefix the def with private (or protected,public)

But I believe that it's now also possible to use private as a block as in:

private begin
   def foo
   end
   def bar
   end
end

def zip
end
edx
  • 1,317
  • 1
  • 12
  • 14
1

I generally order my methods as follows:

  1. Constructor
  2. Other public methods, in alphabetical order
  3. private, written only once
  4. Private methods, in alphabetical order

I use “go to definition” features in my editor so that this doesn’t involve much scrolling, and in any case, if the class is big enough that scrolling becomes problematic, it probably should be broken up into several classes.

Marnen Laibow-Koser
  • 5,959
  • 1
  • 28
  • 33
  • I should also mention that I usually put conversion methods (such as `to_s`) near the end of the public section. – Marnen Laibow-Koser Feb 25 '20 at 13:13
  • If not broken up into several classes, then broken up into modules in the way that much of Rails is broken up (e.g. ActiveRecord, which uses both additional classes such as ActiveRecord::Connection and modules such as ActiveRecord::Callbacks). – Jack R-G Feb 25 '21 at 01:58
  • @JackR-G That often works too. I think when I wrote "several classes" I meant "several classes or modules". – Marnen Laibow-Koser Feb 26 '21 at 03:52