3

If the end_user cannot access the source code of the app, why we still need to make some methods private?

I'm reading the Pragmatic Agile Web Development with Rails and I couldn't understand why we need to make the following method private (even after reading the explanation):

private
  def current_cart Cart.find(session[:cart_id])
   rescue ActiveRecord::RecordNotFound 
   cart = Cart.create 
   session[:cart_id] = cart.id
   cart
   end 
end

It says that it will never allow Rails to make it available as an action, but as a coder, why would I ever do that myself?

Thanks for all the fish
  • 1,671
  • 3
  • 17
  • 31
  • This might be helpful: http://stackoverflow.com/questions/4495078/protected-and-private-methods-in-rails – someoneinomaha Jan 12 '12 at 03:42
  • Thanks for the link. It clarifies the helper methods as they can be accessed directly (which is dangerous). But I would expect more examples for how to use private more efficiently if that's the case. – Thanks for all the fish Jan 12 '12 at 16:52

5 Answers5

6

As you say there may be no external reason to make it private. However, it also prevents you — or somebody else using your code — from accidentally making use of the method where you're not supposed to.

See it as a sanity check on your own future behaviour if you will.

Janne
  • 979
  • 4
  • 13
  • "sanity check on your own future behaviour" - nicely put. – Gaurav Gupta Jan 12 '12 at 04:33
  • I thought that making private is something really essential like "hey, you should do that method private or someone is going to hack your app ." But apparently, that's not that easy to do it anyway. At least on Rails. – Thanks for all the fish Jan 12 '12 at 16:45
  • well if methods are public that shouldn't be then they certainly can hack the app and make calls. It will also depend on your authorization / authentication approach but as with most security it's best to have a few layers and not rely on one thing! – Michael Durrant Jan 13 '12 at 00:56
  • In general, if somebody can access your code at the API level, especially with a dynamic language like Ruby, then they will have plenty of opportunity to do things they should not anyway. This can be important for security in a wider context though, by preventing you from misusing a method and inadvertently introducing a security-related bug. – Janne Jan 13 '12 at 01:28
2

It aims to encourage good practices and good code.

The idea is that you have two separate parts to your code:

"Above the line" (Public). This is the interface to the rest of the world. This is the API, where calls are made when using instances of the object. Once created, you know that THIS is the area where changes can affect current usages of the code.

"Below the line (Private). This is where detailed logic resides. This code can be changed and refactored freely without any affect to the public interface.

It may help guide your test writing

  • Private methods may or may not be (unit) tested.
  • Public methods are more encouraging of both unit and integrated tests as the fact that is is public means that it is serving as the public face for that code and as it is public it might be called from any other point in the future, so having good tests to make sure it continues to work as advertised is essential.

It may help with security as you have greater control who calls private methods (i.e. only public methods in the same class calling them).

It may help reduce name collisions as you have less names in the public space.

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
0

End user might not be able to access your code but someone else in your team can definitely access it and they might change it.

The other benefit of encapsulation is that it allows one class ("server") to make a contract with another class ("client") to provide some service with only a very few things being required to be known about the "server" class such as method signature and return type. The benefit is only realized if the contract of what is required and what is returned remains the same. So, in your example, there is no benefit since the contract was broken by Class A.

Instead of class A changing int type to float, class A should create another new variable of type float for other classes to use so that class B is not "broken" or that contract is not broken between them. Class C could refer to new float variable and Class B could still refer to old int variable and everyone is happy. Better yet, methods would used to retrieve values such as: "getUsersAddress" and "getUSersPhoneNumber" depending on what was wanted.

The real benefit of good encapsulation is that Class A can be completely re-written from top to bottom and as long as the contract is honored as to what Class A is expected to do(have methods "getUsersAddress" and "getUSersPhoneNumber"), then everything in Class B and C works the same. Think carefully about what is exposed and how it is exposed. Things that will change often and break other classes need to be considered carefully before exposing. Good encapsulation means hiding things that are expected to change often so to avoid breaking other classes.

VivekVarade123
  • 3,564
  • 4
  • 24
  • 31
0

It says that it will never allow Rails to make it available as an action,

Hmm, is this in a Rails Conroller class? And is the book you are working through written for Rails 2.x?

In Rails 2.x, by default any public method in a Controller can be triggered by someone accessing the url /name_of_controller/name_of_method .

But there are some methods in your controller that you don't want anyone on the web to trigger, they weren't intended as 'action methods'. So in Rails 2.x, you mark those as protected or private, something not public. "action method" means a method you intend to be directly triggered via a URL.

In Rails 3.x, routing has generally changed such that only certain methods you explicitly route to are available to be triggered via a URL. However, it might still make sense to mark non-action-methods in a Controller as protected or private so:

  • It's more clear from skimming the source which methods are action methods and which aren't
  • As a precaution in case someone changes the routing in such a way that would allow a URL to trigger those methods not intended as action methods

Or for general reasons of code organization that other answers mention, that are not specific to Rails controller classes.

jrochkind
  • 22,799
  • 12
  • 59
  • 74
  • It's from the Pragmatic Agile Web Development with Rails 4th ed for Rails 3.x. The author wasn't very convincing about the usage of private or public. That's why I asked the question here. But it seems to me that there are good reasons, but not essential like "hey if you don't do that private, you app is insecure." – Thanks for all the fish Jan 12 '12 at 16:42
0

There are several reasons as mentioned above. The interesting thing about this encapsulation in ruby is that it can be violated.

See the "send" method and its brother "public_send".

And for a very common metaprogramming technique that uses this method see:

dynamic finders

josephrider
  • 933
  • 5
  • 9