I have looked at other discussions about this topic (on StackOverflow) however the other questions seem to be language specific whereas this is not language specific and I'm considering no longer using private methods, classes, and modules.
I want to test my private methods, classes, and modules so that I can more easily locate bugs. To allow me to do this I'm considering no longer using private methods, classes, and modules for two reasons, (1) I see no reasonable way of testing a private method, class, or module without injecting test code or using some sort of "magic" and (2) to improve code reuse. Note that I'm not considering no longer using private variables and properties because data needs protecting and does not provide behaviour therefore it does not need to be public during testing.
As a lame example, if you're writing a module called OneOperations that has two public methods addOne and subtractOne, and two private methods add and subtract. If you were not allowing yourself to have private methods you would put the two private methods into another module (basicOperations) where they are public and import those methods inside the OneOperations module. From this you should now be able to write testing code for all the methods in both modules without injecting code. An advantage of this is that the methods add and subtract can now be used in other modules by importing the basicOperations module (2 - improving code reuse).
I have a feeling this a bad idea, but I lack the real world experience to justify not doing this, which is why I've posted this question on StackOverflow.
So, how do you test your private methods, classes, and modules? Is not writing private methods, modules, and classes a potential solution?
1) Like in many other answers on this topic, the main question is why would you want to test your private methods? The purpose of a class is to provide some functionality to its clients. If you have comprehensive unit tests that prove that the public interface of this class behaves correctly, why do you care what it's doing in its private methods?
2) Your idea of not having private methods at all seems like cutting your leg off. For small projects it may be possible to have every tiny behaviour well separated and tested. But for large projects it's an overkill. What matters, is the domain logic behaving correctly.
Consider for example a method:
public double getDistanceSquared(Point other)
{
return getDifferenceSquared(this.x, other.x)
+ getDifferenceSquared(this.y, other.y);
}
private double getDifferenceSquared(double v1, double v2)
{
return (v1 - v2)*(v1 - v2);
}
Ad1) Does it really make sense to unit test getDifferenceSquared method, if getDistanceSquared returns correct results for all test cases?
Ad2) Creating a separate class for calculating squared distance between doubles - in case there is only one place when it'll be used leads to a swarm of tiny classes, with millions of tests. Also, constructors of your domain classes will accept like 10 different interfaces for every tiny thing they're doing internally.
Maintaining all this is a lot of unnecessary work. Imagine that you would like to change the method of calculating the distance (maybe use some precomputed values). The behaviour of getDistanceSquared would not change. But you would have to change all of the tests of getDifferenceSquared even though you shouldn't have to care how is the distance being calculated, as long as it's calculated correctly.
Diving into minor details when it's not necessary makes you forgot what you're really doing - you lose the "big picture view". Value your time, and focus on important problems.
As a side note, also - the main concern of unit tests is not "locating bugs" as you suggest. They impose a clean design, provide an always up-to-date documentation of your code's behaviour and allow convenient refactoring giving you flexibility. Additionally they assure you that the code is working as you expect it to.
http://artofunittesting.com/definition-of-a-unit-test/
http://en.wikipedia.org/wiki/Unit_testing#Benefits
There is another way to look at this, which is how do you generate a private method?
If we are following the TDD process properly, then the first thing we write is the test. At this point the test should contain all of our code, e.g.
public void ShouldAddTwoNumbers()
{
(1 + 1).ShouldEqual(2);
}
Yes, that looks appalling. But consider what happens as we write is some more tests.
public void ShouldAddTwoMoreNumbers()
{
(2 + 2).ShouldEqual(4);
}
Now we have something to reactor, so it can become
public void ShouldAddTwoNumbers()
{
Add(1, 1).ShouldEqual(2);
}
public void ShouldAddTwoMoreNumbers()
{
Add(2, 2).ShouldEqual(4);
}
private int Add(int a, int b)
{
return a+b;
}
So now we have a private method that we can test inside our test class. It's only when you complete further refactoring to move the code out into your application, that the private becomes an issue. Most automated refactoring tools will offer you the option of changing the methods signature at this point, so that the private method is still accessible, because its not private.
(There is a fabulous exercise called TDD as if you mean it by Keith Braithwaite which I've just paraphrased above)
However, this isn't the end of our refactorings and development. One thing that we should be doing as we write and refactor our tests is to delete old tests, for example when functionality is duplicated. Another is to extract new methods so we don't repeat ourselves. Both of these can lead to scenarios where we have private methods back in the non-test code base.
So my advice is to be pragmatic, make the best decision you can for the code that you have in front of you. I wouldn't advise not creating private methods, but I would instead look at the factors that lead you to create them.
Related
Background
I'm in the process of reworking and refactoring a huge codebase which was written with neither testability nor maintainability in mind. There is a lot of global/static state going on. A function needs a database connection, so it just conjures one up using a global static method: $conn = DatabaseManager::getConnection($connName);. Or it wants to load a file, so it does it using $fileContents = file_get_contents($hardCodedFilename);.
Much of this code does not have proper tests and has only ever been tested directly in production. So the first thing I am intending on doing is write unit tests, to ensure the functionality is correct after refactoring. Now sadly code like the examples above is barely unit testable, because none of the external dependencies (database connections, file handles, ...) can be properly mocked.
Abstraction
To work around this I have created very thin wrappers around for example the system functions, that can be used in places where non-mockable function calls were used before. (I'm giving these examples in PHP, but I assume they are applicable for any other OOP language as well. Also this is a highly shortened example, in reality I am dealing with much larger classes.)
interface Time {
/**
* Returns the current time in seconds since the epoch.
* #return int for example: 1380872620
*/
public function current();
}
class SystemTime implements Time {
public function current() {
return time();
}
}
These can be used in the code like so:
class TimeUser {
/**
* #var Time
*/
private $time;
/**
* Prints out the current time.
*/
public function tellsTime() {
// before:
echo time();
// now:
echo $this->time->current();
}
}
Since the application only depends on the interface, I can replace it in a test with a mocked Time instance, which for example allows to predefine the value to return for the next call to current().
Injection
So far so basic. My actual question is how to get the proper instances into the classes that depend upon them. From my Understanding of Dependency injection, services are meant to be passed down by the application into the components that need them. Usually these services would be created in a {{main()}} method or at some other starting point and then strung along until they reach the components where they are needed.
This model likely works well when creating a new application from scratch, but for my situation it's less than ideal, since I want to move gradually to a better design. So I've come up with the following pattern, which automatically provides the old functionality while leaving me with the flexibility of substituting services.
class TimeUser {
/**
* #var Time
*/
private $time;
public function __construct(Time $time = null) {
if ($time === null) {
$time = new SystemTime();
}
$this->time = $time;
}
}
A service can be passed into the constructor, allowing for mocking of the service in a test, yet during "regular" operation, the class knows how to create its own collaborators, providing a default functionality, identical to what was needed before.
Problem
I've been told that this approach is unclean and subverts the idea of dependency injection. I do understand that the true way would be to pass down dependencies, like outlined above, but I don't see anything wrong with this simpler approach. Keep in mind also that this is a huge system, where potentially hundreds of services would need to be created up front (Service locator would be an alternative, but for now I am trying to go this other direction).
Can someone shed some light onto this issue and provide some insight into what would be a better way to achieve a refactoring in my case?
I think You've made first good step.
Last year I was on DutchPHP and there was a lecture about refactoring, lecturer described 3 major steps of extracting responsibilyty froma god class:
Extract code to private method (it should be simple copy paste since
$this is the same)
Extract code to separate class and pull
dependency
Push dependency
I think you are somewhere between 1st and 2nd step. You have a backdoor for unit tests.
Next thing according to above algorithm is to create some static factory (lecturer named it ApplicationFactory) which will be used instead of creation of instance in TimeUser.
ApplicationFactory is some kind of ServiceLocator pattern. This way you will inverse dependency (according to SOLID principle).
If you are happy with that you should remove passing Time instance into constructor and use ServiceLocator only (without backdoor for unit tests, You should stub service locator)
If you are not, then You have to find all places where TimeUser is being instantiated and inject Time implemenation:
new TimeUser(ApplicationFactory::getTime());
After some time yours ApplicationFactory will become very big. Then You have to made a decision:
Split it into smaller factories
Use some dependency injection container (Symfony DI, AurynDI or
something like that)
Currently my team is doing something similar. We are extracting responsibilities to seperate classes and inject them. We have an ApplicationFactory but we use it as service locator at as hight level as possible so classes bellow gets all dependencies injected and don't know anything about ApplicationFactory. Our application factory is big and now we are preparing to replace it with SymfonyDI.
You asked for a good mechanism to do this.
You've described some stages you might force the program to go through to accomplish this, but you are still apparantly planning to do this by hand at apparantly a very high cost.
If you really want to get this done on a huge code base, you might consider automating the steps using a program transformation engine: http://en.wikipedia.org/wiki/Program_transformation
Such a tool can let you write explicit rules for modifying code. Done right, this can make code changes reliably. That doesn't minimize your need for testing, but can let you spend more time writing tests and less time hand-changing the code (erroneously).
I have inherited a project that has no interfaces or abstract classes i.e. concrete classes only and I want to introduce unit testing. The classes contain lots of functions, which contain business logic and data logic; breaking every rule of SOLID (http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29).
I had a thought. I was thinking about creating interfaces for each of the poorly designed classes, exposing all functions. Then at least I can Mock the classes.
I am relatively new to Unit Testing (I have experience with a project, which was very well developed using interfaces in the right places). Is it a good idea to do this i.e. create interfaces for all the concrete classes (exposing all the functions and sub routines), just for unit testing?
I have spent some time researching this but I have not found an answer.
If your project has no tests at all, before adding any unit tests I'd much rather create higher level tests (i.e acceptance, functional and/or integration tests).
When you have those tests in place you know that the system is behaving as it should and also that it has certain level of 'external' quality (meaning by this that the inputs and outputs of your program are the expected ones).
Once your high level tests are working, you could try to add unit tests to the classes that already exist.
I bet that you will find yourself in the need to refactor some of the existing classes if you want to be able to unit test them so you can use your high level tests as a safety net that will tell you if you've broken anything.
This is a tough thing to tackle. I think you are on the right track. You'll end up with some ugly code (such as creating header interfaces for each monolithic class), but that should just be an intermediate step.
I'd suggest investing in a copy of Working Effectively with Legacy Code. First you could start by reading this distillation.
In addition to Karl's options (which let you mock via interception), you could also use Microsoft Fakes & Stubs. But these tools will not encourage you to refactor the code to adhere to SOLID principles.
Yes, that is a good start, however, having interfaces is less of a priority than having dependencies injected. If all of your legacy classes gain interfaces, but hidden internally they are still all interdependent, the classes will still be no easier to test. For instance, let's say you had two classes that looked like this:
Public Class LegacyDataAccess
Public Function GetAllSales() As List(Of SaleDto)
' Do work with takes a long time to run against real DB
End Function
End Class
Public Class LegacyBusiness
Public Function GetTotalSales() As Integer
Dim dataAccess As New LegacyDataAccess()
Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
I know what you're already saying... "I wish the legacy code was at least layered that well", but lets use that as an example of some legacy code which would be hard to test. The reason it's hard to test is because the code reaches out to the database and executes a time-consuming query on the database and then calculates the results from that. So, in order to test it in its current state, you would need to first write out a bunch of test data to the database, then run the code to see if it returns the correct results based on that inserted data. Having to write a test like that is problematic because:
It is a pain to write the code to setup the test
The test will be brittle because it depends on the outside database working properly and on it containing all the correct supporting data
The test will take too long to run
As you correctly observe, interfaces are very important to unit testing. So, as you recommend, lets add interfaces to see if it makes it any easier to test:
Public Interface ILegacyDataAccess
Function GetAllSales() As List(Of SaleDto)
End Interface
Public Interface ILegacyBusiness
Function GetTotalSales() As Integer
End Interface
Public Class LegacyDataAccess
Implements ILegacyDataAccess
Public Function GetAllSales() As List(Of SaleDto) _
Implements ILegacyDataAccess.GetAllSales
' Do work with takes a long time to run against real DB
End Function
End Class
Public Class LegacyBusiness
Implements ILegacyBusiness
Public Function GetTotalSales() As Integer _
Implements ILegacyBusiness.GetTotalSales
Dim dataAccess As New LegacyDataAccess()
Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
So now we have the interfaces, but really, how does that make it any easier to test? Now we can easily create a mock data access object, which implements the same interface, but that's not really the core problem. The problem is, how do we get the business object to use that mock data access object instead of the real one? To do that, you need to take your refactoring to the next level by introducing dependency-injection. The real culprit is the New keyword in the following line of the business class:
Dim dataAccess As New LegacyDataAccess()
The business class clearly depends on the data access class, but currently it is hiding that fact. It's lying about it's dependencies. It's saying, come-on, it's easy, just call this method and I'll return the result--that's all it takes. When really, it takes a lot more than that. Now, let's say we stopped it from lying about it's dependencies and made it so it unabashedly stated them, like this:
Public Class LegacyBusiness
Implements ILegacyBusiness
Public Sub New(dataAccess As ILegacyDataAccess)
_dataAccess = dataAccess
End Sub
Private _dataAccess As ILegacyDataAccess
Public Function GetTotalSales() As Integer _
Implements ILegacyBusiness.GetTotalSales
Dim sales As List(Of SaleDto) = _dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
Now, as you can see, this class is much easier to test. Not only can we easily create a mock data access object, but now we can easily inject the mock data access object into the business object. Now we can create a mock which quickly and easily returns exactly the data we want it to return and then see if the business class returns the correct calculation--no database involved.
Unfortunately, while adding interfaces to existing classes is a breeze, refactoring them to use dependency-injection typically requires a lot more work. You will likely need to plan out which classes make the most sense to tackle first. You may need to create some intermediary old-school wrappers which work the way the code used to, so you don't break existing code while you are in the process of refactoring the code. It's not a quick and easy thing, but if you are patient and in it for the long-haul, it is possible to do it, and you will be glad you did.
I would recommend you go the interface route, but if you want to pay for a solution, then try one of these:
TypeMock
JustMock
Creating interfaces to test the classes is not a bad idea - the goal of unit testing is to exercise if the functions on a class are functioning as expected. Depending on the classes you are working with, this could be easier said than done - if there are a lot of dependencies on global states, etc. you will need to mock accordingly.
Given how valuable unit tests are, putting a bit of work into them (to a limit) will benefit you and developers you work with.
I prefer to create interfaces and classes as you need to test things and not all upfront.
Besides interfaces, you can use some techniques to test legacy code. The one I often use is "Extract And Override", where you extract some piece off "untestable" code inside other method and make it overridable. Them derive the class that you want to test and override the "untestable" method with some sensing code.
Using a mock framework will be as easy as adding keyword Overridable to the method and sets the returning using the mock framework.
You can find many techniques on the book "Working Effectively with Legacy Code".
One thing about existing code, is that sometimes it is better to write integration tests than unit tests. And after you have the behavior under test, you create unit tests.
Another tip is to start with modules/class that have less dependencies, that way, you become familiar with the code with less pain.
Let me know if you need an example about "extract and override" ;)
So as I've been reading/learning about classes and the methods within them I've found very little about the practical differences between declaring a method as public versus private.
I know that the difference is a private class can only be accessed within the class, while a public method can be accessed from code outside the class (other classes, functions). But what I really want to know is:
Why would you want/not want to declare it one way or another when deploying an application?
Are there best practices that can guide whether to declare a method public vs private?
Also, I don't know if it matters, but I am learning primarily VB.Net and C# in a web application environment, so specifics to that would help.
Encapsulation means that you should think of each class as a machine that provides a service. For example, a chair allows you to sit on it, or a lawnmower allows you to cut your lawn.
The private methods pertain to the machine's internal workings. In contrast, the public methods relate to how you (other classes) interact with the machine.
Example one: Chair...
When sitting on a chair, you don't need to know volume of stuffing or the number of staples, you basically need to know whether or not it's occupied and if it's stable.
Public methods: IsStable, IsOccupied, Sit
Private methods: CalculateStuffingVolume, CountNumberOfStaples
Example two: Lawnmower...
For the lawnmower, you need to know if it has enough fuel (or is plugged in), if the blades are sharp, and be able to turn it on.
Public methods: GetFuelLevel, IsBladesSharp, TurnOn, TurnOff
Private methods: Combust, etc, Too many to imagine.
Conclusion:
So when you're developing all you will see is...
Example one: Chair.Sit, Chair.IsStable and Chair.IsOccupied
or
Example two: Lawnmower.GetFuelLevel, Lawnmower.IsBladesSharp, Lawnmower.TurnOn, LawnMower.TurnOff
As a developer, you will not have to think about number of threads in the uphosltry, the colour of the fuel cap, the number of RPM of the blades or whether the chair is glued or stapled together. This distinction makes it much easier to put your application together without being swamped in detail. Additionally, it allows programmers to expose only necessary information which adds a level of security. As John mentioned, this prevents the Person class from calling Lawnmower.Combust(fuel) when they're not supposed to.
If the method is private, then you don't have to think about outside classes calling it incorrectly.
One of the benefits of this is that it allows for a separation between the interface to your class (the public parts of it), and the implementation of it. If nobody knows how you implemented your class (that is, if there is no code that depends on how you implemented it), then you're free to change the way you implemented it without breaking any other code.
It's one of the most importand principles of the object-oriented programming -- encapsulation.
A class usually provides a (public) interface. E.g. (pseudocode):
class Rectangle {
private length;
private width;
public getPerimeter() {
// return calculatePerimeterOld();
return calculatePerimeterNew();
}
private calculatePerimeterOld() {
// old variant
}
private calculatePerimeterNew() {
// Here the perimeter is caltulated.
// so: perimeter = 2 * (length + width)
// or so: perimeter = 2 * (length) + 2 * (width)
// or maybe so: perimeter = length + width + length + width - (0.5 * length) + 2 * 0.25 * length)
return perimeter;
}
}
I can change my private methods however I want. I can rename or replace them with oher methods. But my public interface will stay the same -- and it has to stay the same, because it's a contract I sign, when I'm defining a mehod as public. Everything, what is signed as private is my "blackbox" and I can do there whatever I want.
It's the main reason. Another reason is, that we should not provide the user(-s) of our class with methods/informations, they don't need. To much (information) is not good.
If you're developing a one off website maintained just by you, you may find the concept of public and private functions unnecessary.
However, if you're delivering software to other people, and they're building on top of your software, it is an absolutely critical concept.
Think of it like a physical machine that has a thousand knobs and switches inside it, but is contained inside a pretty case with only a few clearly labelled knobs on the outside.
The public functions and methods are the ones you create for external parties to interact with your software.
The private functions and methods are the ones you create for your software to interact with
itself.
But, again, if it's a one-off website maintained by a single developer, these differences are less important.
In my src, there exist a class which contains a method
public static boolean doExtensionsMatch(String s, String t) {
There is nothing wrong with it, except that there is no need for it to be public. It is used inside the class where it is declared.
It is public however, since some time ago, i felt this method needed to be tested directly and thus, private visibility did not work for me.
At this point:
I'd rather not throw away those tests. If i make the method private however, tests will become unusable.
I would rather for tests to remain in it's current src-test folder, thus maintaining separate locations for source and tests
So, you tell me, what should i do?
Should i change the method to private and delete the tests?
You test interface to prove that class behaves as it should.
So private methods don't need to be tested as long as they aren't accessible. And even more - you shouldn't care of how interface does its work, you should be fine with just the results.
You test the behaviour, not the implementation.
I would suggest using partial classes. If your test classes are partial classes of the class to be tested they will have access to all methods and variables whether or not they are public.
Decomposing a member function
In a class there is a member function that is rather long. Let's say we have
class Customer {
public:
void process();
...
};
The method process is by nature long and consists of a couple of different
steps. You'd like these steps to be functions of their own, to avoid having
multiple levels of abstraction in the process method. I have thought of these
different options (including the noop-alternative):
Create stand-alone functions for the steps outside of the class.
double step_a(vector<Order> orders, double foo);
void step_b(double bar);
void Customer::proccess()
{
double foo;
...
double bar = step_a(this->orders, foo);
...
step_b(bar);
};
Concerns: The class is less self-contained. The stand alone functions are so
specific to the process function that they would never be of interest to any
other code, making it feel unnatural to keep them outside of the class.
Create private methods.
class Customer {
public:
void process();
private:
double step_a(double foo);
void step_b(double bar);
};
Concerns: The private methods for the steps (at least some of them) wouldn't
operate on any class members at all. They have no side effects, they only
compute a value from arguments and return it, so they have no need at all to
be member functions of the class.
Leave Customer::process as is
Concerns: The function becomes long, and could be hard to read, because of all
the details in the steps making it hard to see the big picture of what steps
the process contains.
Question:
What would be the cleanest way to handle this?
(Perhaps none of the above, but someting I hadn't thought of.)
The question isn't really language agnostic. Not all languages have stand alone functions.
In C++ or C# I would probably use private member functions (static if possible).
In C++ you could use stand-alone functions (possibly in an anonymous namespace) so they are not visible to the outside.
I'd point you at the refactoring books - especially Martin Fowler's Refactoring, and Joshua Kerievsky's Refactoring to Patterns. This problem is explored at some depth in those books.
The "stand-alone" option you describe is often called "helper methods"; there's nothing inherently wrong with this, except that they often explode into becoming the core of the method, and this leads to dependency explosion.
Private (static) methods are best if the code is directly related to the duties of the class in question.
Leaving it as is can be okay - but there's a fairly well-understood correlation between the complexity of a method and the likelihood it contains bugs. If this is a living code base, I'd refactor it.