What are private methods for in Ruby? - ruby

Am I missing out something?
class Circus
private
def start
puts 'And now for something completely different..'
end
end
And for my disillusion:
c=Circus.new
c.start #NoMethodError: private method `start' called
c.method(:start).call #no problem at all
c.send :start #neither this fails
Can anybody give me a reason why private methods exist in Ruby?

Put it this way. In Ruby you could just as easily monkey-patch a public method into a class which invoked the private method, so... Why would private prevent your behaviour?
You seem to think that private methods are somehow a security thing, that they have to be inaccessible outside the class. Encapsulation isn't about security, is a tool for producing clean, maintainable code. It's up to you to respect the interface exposed by a class. If you really want to find a way to invoke a private method, you will. Ruby cannot enforce this completely, nor should it have to; it would be counter-productive and a waste of time.
I mean, can anybody give me at least one reason why 'private' even exists in Ruby?
For the exact same reason private exists in any other OOP-based language: Encapsulation. Really, you think that just because you can find a convoluted way to circumvent private, it should just be thrown out?

It declares the intent of the method. If it's private you're not supposed to call it and you should be aware that doing so may cause unpredictable or undesirable behaviour.
For what it's worth, this behaviour is not limited to Ruby - it is possible to access private members and variables in Java as well, via the Reflection API.

Private methods are supposed to be called only from inside the same instance, without explicit receiver. They will fail whenever explicit receiver is supplied, including self.some_private_method called from the same instance. The ability to bypass this via send is a nonstandard coding practice, that should be used mainly for maintenance.

Once you start using reflection, all bets are off. That's not unique to Ruby, by the way, almost every language that has reflection has this problem.
You can mitigate this by using coding standards and code reviews, e.g. always use public_send etc. But if you don't like this, you will need to use a language with a properly stratified reflection system such as Newspeak.

Related

How to unit test a private method using Minitest

I wanted to test a private method but I came across an answer that states simply YOU DONT!
How can I refactor this code so that I can test it?
In my controller, I have a private method
def move_employees
return unless params[:store_id].present?
store = scope.find(params[:store_id])
store.employments << #store.employments
store.save!
end
This method is called inside the destroy action such that when I want to delete a store that has employees, I can move them over to an existing store picked from an drop down menu
def destroy
#store = scope.find(params[:id])
authorize([:manage, :settings, #store])
if #store.destroy
move_employees
...
I am thinking of moving the method to the model, but I am not sure if that is the best approach, and also, I don't know how I would then test it.
What is the best practice in this case?
Thank you.
Philosophically, you shouldn't, as private methods are expected to be tested in the context of the public code. For example, if move_employees must be called as part of destroy, test the end state, not the mechanism to get there. That is, assert that after deletion the employees are correctly moved.
Practically you can test directly if you're prepared to bust out send. This more direct method of testing can be useful for particularly complex implementations, but in those cases you should probably separate your concerns and have some other tool that facilitates that operation which does have a public interface.

Checking for validity in Java

I have heard that it is good practice to check public method arguments for validity and throw exceptions in the case that they are not valid. I have also heard that you should check the arguments of private methods using assertions.
A couple questions I have are:
Should you ever pass objects with multiple fields into private methods?
If you do, should you check the validity of all fields in the public method before doing so or check at time of use?
Should asserts in private methods be used just to check arguments or also in the case where you have object as null and it tries to call a method as shown below?
A.doSomething()
Should you ever pass objects with multiple fields into private methods?
There's nothing inherently wrong, bad, or special in doing so. You'll find yourself very restricted if you try to avoid passing complex objects to private methods.
If you do, should you check the validity of all fields in the public method before doing so or check at time of use?
This is entirely up to you.
If checking ahead of time will avoid doing a lot of unnecessary work, then it's probably a good idea to check earlier rather than later. (No point doing a lot of CPU work or some long network calls if you know that you've been given invalid input in the first place!)
However, you don't always know that what you've been given is invalid so there are cases where it might be impossible to check right away.
Should asserts in private methods be used just to check arguments or also in the case where you have object as null and it tries to call a method as shown below?
Asserts are typically used to make sure that your logic is right, not that inputs are right. Suppose that you're certain that the logic in some method is such that it will never return a negative number, you could put in an assert that will alert you if it does which indicates either a mistake in the implementation or in your design. You should use Exceptions to catch invalid inputs.

Why do we need 'private' methods in Ruby

Can someone give me a concrete example where a 'private' method would accomplish something that can't be done with a 'protected' method? In other words I am want to know why a language designer would put 'private' methods in Ruby.
It really depends on your development team and how your code is going to be used. In Ruby these tags are often suggestions more than hard and fast rules, there's ways to bypass private and protected methods if necessary, but they can serve as a strong hint to someone using your code that calling them is undesirable.
private is something that should be used sparingly as it can make life very difficult for those trying to subclass something. protected is usually sufficient, and helps steer external code to the methods that should be used.
There are occasions where private is necessary, that is you want to prevent subclasses from knowing too much about how the parent class works. This is more common in libraries where you encourage people to subclass but you also want to wall off some of the internal functions that aren't intended to be used by them. This allows you to refactor these methods later at will without breaking someone else's code.
One of the principles of good object-oriented design is controlling how much method exposure you have. Too much exposure means you're committed to making them behave identically now and in the future unless you're prepared to make breaking changes. Too little exposure means your class might be difficult to use, if not useless. Finding that balance is always tricky.
So private and protected exist for reasons, and it's largely the same reasons that C++, Java, PHP, Python and many others have these. It's to assert control over how and where your methods should be used.

Is it reasonable to use a non-static class if that class does not contain state?

At my workplace there seems to currently be a crusade against static classes. I can understand part of that, they do sort of break the whole unit testing modularity thing. However, I am seeing an influx of code reviews that call for removing static classes.
A common case is a utility class this is spring-injected with a few other objects that are "known" at compile-time. It has no other member variables. If class M is calling this static class, I always see the suggestion to make this utility class non-static and inject it into class M.
This doesn't make sense to me. I don't particularly see anything wrong with it other than that it seems a waste of time and makes utility class less easily usable. As far as I can tell the justification is usually for unit testing, but I don't like the idea that valid code has to be changed to conform to a testing paradigm. Admittedly mocking a simple static utility class would probably be overkill.
Are static classes appropriate in this use case, or best avoided?
I think the differences in the two approaches are small, but as long as the class contain no state it is slightly better to make it static. Let's say I have this code in class A:
StaticClass.utilMethod()
If I want to use this code in class B I can copy and paste. That's it. No adding member variables, injection, etc. cmd-c cmd-v.
Considering your existing code uses static classes and modifying that will take work, it's definitely best to continue using static classes.
I vote for using the static classes... i.e. A class with just static methods for purely Utility purposes. Even java has provided us such classes like java.util.Collections and java.util.Arrays
If you pretend for a moment that your static class did not belong to you, that it was, say, part of the .NET framework, how would your team handle it? Their answer would be my answer. In other words, if their answer to that question is inconsistent with what they're asking you to do, then they should probably either change how they work with .NET static classes or with how they work with yours.
I avoid using static classes (assuming we are actually talking about classes that contain static methods), and I do it for the sake of testability.
If you are using static methods, you will have a difficult time mocking/stubbing the portion of your code that uses said static for your unit tests.
Consider this:
public String myMethod() {
String complicatedStringOutput = MyUtility.createComplicatedStringOutput();
//do some more complicated work on this String
}
To write a unit test for this method, how would you go about making it a 'true unit test' without needing to also test the creation of complicatedStringOutput? In my unit tests, I prefer to test only the method that is the focus of the unit test.
Change it to this:
public String myMethod(MyNonStaticUtility util) {
String complicatedStringOutput = util.createComplicatedStringOutput();
//do some more complicated work on this String
}
Suddenly, this class is much easier to write a 'true unit test' for. You can control the behavior of MyNonStaticUtility by either using a stub or mock.
All that said, it is really up to you (or your Business Unit). If you value unit tests and feel that it is important to have good test coverage of your complicated code, this is the preferred approach. If you do not have time/money to invest in 'fixing' your code, then it just won't happen.
Depends, naturally.
How do you want to test the code that uses the static classes?
Do the static classes encapsulate behavior you'll need to mock often?
Will anybody ever need to modify the behavior of those static classes?
Finally:
Is there a compelling reason not to inject a Spring-managed singleton bean?
Admittedly mocking a simple static utility class would probably be overkill.
You're absolutely right on this. Static classes should only be used for utility classes that are extremely simple, where there is no benefit of mocking such a class. If you're using them for any other purpose, you should rethink your design.
Is it reasonable to use a non-static class if that class does not contain state?
This really has nothing to do with state. For example, strategy objects often contain no state, yet they are not static; they usually implement a common interface and need to be interchangeable / mockable.

Too many public methods forced by test-driven development

A very specific question from a novice to TDD:
I separate my tests and my application into different packages. Thus, most of my application methods have to be public for tests to access them. As I progress, it becomes obvious that some methods could become private, but if I make that change, the tests that access them won't work. Am I missing a step, or doing something wrong, or is this just one downfall of TDD?
This is not a downfall of TDD, but rather an approach to testing that believes you need to test every property and every method. In fact you should not care about private methods when testing because they should only exist to facilitate some public portion of the API.
Never change something from private to public for testing purposes!
You should be trying to verify only publicly visible behavior. The rest are implementation details and you specifically want to avoid testing those. TDD is meant to give you a set of tests that will allow you to easily change the implementation details without breaking the tests (changing behavior).
Let’s say I have a type: MyClass and I want to test the DoStuff method. All I care about is that the DoStuff method does something meaningful and returns the expected results. It may call a hundred private methods to get to that point, but I don't care as the consumer of that method.
You don't specify what language you are using, but certainly in most of them you can put the tests in a way that have more privileged access to the class. In Java, for example, the test can be in the same package, with the actual class file being in a different directory so it is separate from production code.
However, when you are doing real TDD, the tests are driving the class design, so if you have a method that exists just to test some subset of functionality, you are probably (not always) doing something wrong, and you should look at techniques like dependency injection and mocking to better guide your design.
This is where the old saying, "TDD is about design," frequently comes up. A class with too many public methods probably has too many responsibilities - and the fact that you are test-driving it only exposes that; it doesn't cause the problem.
When you find yourself in this situation, the best solution is frequently to find some subset of the public methods that can be extracted into a new class ("sprout class"), then give your original class an instance variable of the sprouted class. The public methods deserve to be public in the new class, but they are now - with respect to the API of the original class - private. And you now have better adherence to SRP, looser coupling, and higher cohesion - better design.
All because TDD exposed features of your class that would otherwise have slid in under the radar. TDD is about design.
At least in Java, it's good practice to have two source trees, one for the code and one for the tests. So you can put your code and your tests in the same package, while they're still in different directories:
src/org/my/xy/X.java
test/org/my/xy/TestX.java
Then you can make your methods package private.

Resources