Effective Java Item 13 and TDD - java

I just googled "Joshua Bloch TDD"... not much came up, which is a huge shame because I'd really like to know what he's got to say on the matter.
Item 13 (I'm looking at the 2nd edition) is entitled "Minimize the accessibility of classes and members". After a couple of pages he says:
To facilitate testing, you may be tempted to make a class, interface
or member* more accessible. ... It is acceptable to make a private
member of a public class package-private in order to test it, but it
is not acceptable to raise the accessibility any higher than that...
Luckily, it isn't necessary either, as tests can be made to run as
part of the package being tested, thus gaining access to its
package-private elements.
* by "members" he means "fields, methods, nested classes and nested interfaces".
As a TDD newb, but gradually finding my feet, I am aware that the current consensus seems to be not to include testing classes with the app code packages, nor even to have a matching structure under src\test and src\main: mostly TDD experts readily seem to structure their testing directories in other ways (e.g. you have one directory called "unittests" another called "functionaltests" and another called "e2etests").
Specifically, I have followed the TDD development of the auction app in "Growing Object Oriented Software Guided by Tests". The author there has no qualms about adding hundreds of public methods. Furthermore, after one chapter I looked at the downloaded "structure so far" and he had completely changed the testing directory structure to divide things into categories of test...
Is there any seasoned TDD hand out there who has, at least in the past, found this to be a source of dilemma? If so, how have you resolved it?
As a practical example, I'm cutting my teeth on TDD techniques by developing a Lucene index app: it indexes documents and then lets you query them. At the current time all the app classes are in the same package. The only method which actually needs to be public is main in one class. And yet, of course, I have many, many public methods: they could all be package-private were it not for the fact that I am using TDD.
PS no tag for "method-visibility" so I chose "class-visibility"
later
It appears that I may have been led down a rather unfortunate path by the approach taken in "Growing Object-Oriented...", where the over-use of public methods was presumably used just because it's a demonstration of the technique. Ha.
If you want to split your categories of tests, does anyone ever use this sort of approach:
\src\unit_tests\java\core\MainTest.java
but also, for example:
\src\func_tests\java\core\MainTest.javaand
\src\e2e_tests\java\core\MainTest.java?

as tests can be made to run as part of the package being tested
This does not mean that you have to put your tests in the same directory as main classes, they just have to be in the same package which can very well be separate directory.
Assume you have a package com.acme.foo. So your directory structure may be:
src
main
java
com
acme
foo
MainClass
test
java
com
acme
foo
MainClassTest
MainClassTest is in the same package as MainClass so it has access to package-private stuff. But these are separate directories, so your resulting JAR will not contain MainClassTest.

I am not sure how this works in Gradle, as I am using Maven, but I imagine the concepts there are similar. Therefore I will explain it with Maven in mind.
The typical setup in a Maven project looks like this:
On the root level of the projects there is src and target. Into the target folder everything goes that is created during the build process. This means that src contains the sources of our actual project. Under src there are two other directories: main and test. Simply put into main goes everything that will end up in the productive code, that will be delivered. The test directory contains the test code for the main tree.
Therefore it is usual that the same package hierarchy from the src/main/java directory is also present in src/test/java and therefore for a test class with the same package definition will have access to all members of the producive class which resides in the main branch.

Related

Class visibility versus test cases

I'm working on a project that provides a library of related functionality to other groups within the company...
It recently became apparent that the library is being used by other groups in ways that makes it unstable - so my task is to limit scope of classes within the project so that only one singleton class is used as the entry point to the project.
What I've done
1) removed the "public" class modifier from "internal" classes
2) set methods to "protected"
Result
this update has been great because classes that are not meant to be exposed are now inaccessible outside of the project.
HOWEVER, the test cases are now not building due to the limited scope.
The person who wrote the test cases wrote the code in such a way that classes are instantiated individually and manipulated. This is no longer possible due to the limited scope (the test cases are in another package).
Question
To rectify this, should the test cases access the inner (private) classes through the singleton, or is there another way ?
Put your tests in the same package! If you want to keep them apart, just put them in another directory:
.
└── src
├── main
│ └── com.my.package
└── test
└── com.my.package
Your code should be written in a way that facilitates your unit tests. Internal implementation specifics not accessible via a public api are normally tested via your public apis.
Also, assuming we're talking about JUnits here, by convention your tests should be in the same package, not a different package. If there were, then even if your methods are default/package visibility, the tests in the same package can still access that code.
You should write your code in a way that makes it easy to test - if you find yourself doing things that seem far too hard, then you've most likely making it hard for yourself. Go back and look at the code again and see if you can refactor it to make it easy to test.
There is a way, but out of due diligence I must echo what others have said and say that test classes should be in the same package. Any approach that differs from this will be painful. Either you will take longer to write the extra bit of code to access the inner class data or you will write code which is not testable. There is no benifit to not doing this that I am aware of or that you have stated.
What you have said about your library that users are easily writting code which is 'unstable' means that you have made some design errors in your API, nothing to be ashamed of we have all done that.
In addition it also concernes me the way you are talking about single point of entry and singletons. The most obvious use-case for singleton is for performing operations on a file. If you had multiple instances which had this prevallige you could have allot of locking going on and writting at the same time. I don't think the pattern is good for controlling how people use your library.
As hard as it is to say to me it sounds like you have some design flaws and that you have some particular problems you are trying to solve which are really just symtoms of these flaws, and cannot really be fixed any simple way.

Use of modules within Java programming

Hopefully this is a question that only needs a fairly quick answer, but I haven't had much luck finding something online that is in terms I understand!
Quite simply, I'm working on my first real project in Java, a text adventure, (using IntelliJ IDEA) and I was just wondering if I need to be splitting my code into modules? So, for my monsters, should I keep all of my monster classes within a module called Monsters, or can I just keep it in the same module?
I only ask because; a) I wasn't sure whether it was a done thing in order to keep the project tidy and b) When I tried to create a Monster module, I received a warning telling me that the files in this module wouldn't be accessible from the rest of the program, which seems to defeat the object to me...
Many thanks in advance for any advice!
I believe you are referring to IntelliJ's concept of a module. As stated on their page:
A module is a discrete unit of functionality which you can compile, run, test and debug
independently.
Modules contain everything that is required for their specific tasks:
source code, build scripts, unit tests, deployment descriptors, and
documentation. However, modules exist and are functional only in the
context of a project.
So, modules should not be referencing the source code from other modules. They should essentially be completely different units.
As in thecbuilder's answer, you should look into using Java's packaging system instead.
By modules if you mean packages, then its a good habit to keep related classes in one package and distributing unrelated classes in different packages.
And to the thing, that the classes wouldn't be accessible, you'll have to make them public to access them from different packages.
More on package structuring :
http://www.javapractices.com/topic/TopicAction.do?Id=205
http://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
https://stackoverflow.com/a/3226371/3603806
For access specifiers :
Taken from : http://www.go4expert.com/articles/java-access-specifiers-t28019/

Java package understanding in real life projects

I want to understand the packing methodology in real big projects.
Suppose we have a package com.abc.xyz, and for this, we really have a path like com/abc/xyz.
Is it possible to have multiple same package names in different directory structure like:
Directory path 1:
/home/user1/project/module1/src/java/com/abc/xyz
Directory path 2:
/home/user1/project/module2/src/java/com/abc/xyz
And finally when we create jar for the whole project, do we create jar with respect to com directory?
When some application uses import com.abc.xyz, how does it know which directory path's package it is referring to?
And finally, is there any good book/resource which gives guidelines about packaging, how to divide project into modules, package names etc.
One more thing, does a project have common package base name like in above case:
com.abc.xyz (e.g., org.apache.hadoop ).
Thanks,
Vipin
Packages created in different source directories are the same package, as far as the classloader is concerned. It also doesn't matter if the class files are in the same jar or different jars. The JVM does not discriminate based on where the source code came from.
(Of course if you have two jars loaded by different classloaders those are going to be treated differently.)
One case where you frequently have different source trees with the same package is when you have tests in a different directory (using the usual Maven convention where the code is under src/main/java and the tests are in src/test/java) but with the same package as the code that they exercise. These tests are able to exercise protected and package-private parts of the code under test, because they're in the same package as that code.
The path of directories inside the jar should start at the root of the package. (The topmost directory should be /, then one called com or org or whatever, etc.) Packages do form a tree-like structure, and when you put your code in a filesystem you end up having a hierarchy of packages, but the language itself doesn't recognize a concept of "subpackage" (except that packages that start with java are special and get special treatment by the classloader).
Organizing code into packages is done differently by different people. Some people like to organize their code by layer (putting all controllers in one package, all services in another package, all daos in still another package), some like to organize their code by feature.
Package-by-layer is the conventional way of organizing code, it seems to be the preferred practice in the Java community. One consequence of this is that when code implements a feature as a vertical slice at right angles to the package structure (as it may require a new controller endpoint, maybe a new service method, etc.), so closely-related bits of code for the same feature end up scattered across different directories. The Java Practices website makes an interesting case for package-by-feature:
Package By Feature Package-by-feature uses packages to reflect
the feature set. It tries to place all items related to a single
feature (and only that feature) into a single directory/package. This
results in packages with high cohesion and high modularity, and with
minimal coupling between packages. Items that work closely together
are placed next to each other. They aren't spread out all over the
application. It's also interesting to note that, in some cases,
deleting a feature can reduce to a single operation - deleting a
directory. (Deletion operations might be thought of as a good test for
maximum modularity: an item has maximum modularity only if it can be
deleted in a single operation.)
Here's an SO question asking about package by feature or layer.
Yes, you could make duplicate packages in separate directories, but I can't think of a good reason to do it. If the classes within the package have the same names you can certainly get namespace collisions. I am not sure what "module" means in this context but I'd recommend
com.abc.module1.xyz
com.abc.module2.xyz
instead. Those would be distinct packages to the classloader. You can still keep your /home/user1/project/module1/ directory structure up front, that doesn't matter.
From 2 modules you will have two seperate jar files: module1.jar and module2.jar. Both will be loaded into ClassLoader when application starts.
When some application uses import com.abc.xyz, how does it know which directory path's package it is referring to?
Classloader will handle that. http://www.javaworld.com/article/2077260/learn-java/the-basics-of-java-class-loaders.html
If you trying to develop multi module application i recommend you to check Maven tool:
http://maven.apache.org/‎
Why maven? What are the benefits?
For guidance for package organization you can just google 'java packages' phrase.
http://www.tutorialspoint.com/java/java_packages.htm
https://www.facebook.com/Niranthara-Jaya-JavaSocial-Media-Apps-Software-Project-Management-244119296136021/
This page is for people who wish to know how to work with real world Java projects. Send a message to this page and check out the articles.

Do I have to use "package" term in every class?

Firstly, I'm trying to learn Java with Java, A Beginner's Guide, 4th Edition. I use Ubuntu as my OS and Netbeans as my IDE. I need to create a project to create a class when using Netbeans.
Here is my hello world app.
class First{
public static void main(String args[])
{
System.out.println("Hello!");
}
}
But this returns a lot of errors. When I put package first; line to top line of my Java class it runs. But, the book isn't using package term. Is this a rule of Netbeans, or what I need to know about this?
You never need to put a class in a package. However, it is almost always a good idea. This is something that Netbeans aggressively tries to encourage you to do.
For small projects, using the default package (that is, a file without a package statement) is OK. However, once your project grows and starts adding external libraries, bad things can happen. What if someone else decided to use the default package and happened to have an identically-named class? Now, since you're both in the same package, collisions can occur!
Your file structure should also reflect your package. That is, a file in package com.myurl.helloworld should be located in a folder called com/myurl/helloworld. This is for the same reasons as above.
Also, and you probably haven't gotten here in your studies, you cannot import classes from the default package, or use the package-private visibility modifier in a default package class.
That's because the author of Java, A Beginner's Guide, 4th Edition most likely used the "default package". This way, you don't have to include any package. A package is a namespace declaration.
What the heck is a namespace declaration!?
A namespace declaration is simply a package which is made to organize your classes. For an instance, if you're going to have multiple classes for, let's say your GUI, and multiple classes for algorithms, blending them together is always a bit confusing. Sorting them in different packages, however is a superior solution.
There is also a naming convention which you should follow if other people are going to look at your code. Packages should be named after a top-level domain. I tend to create SourceForge projects and then I end up with something like this:
net.sourceforge.softwarename.security, net.sourceforge.softwarename.gui, etc...
Also note that you should never use upper case when naming your package. More info here.
You're going to encounter lots of situations like these when learning to programming. They're all a part of the game. You'll just have to figure out a bit by yourself.
The best I can do for you is to recommend Eclipse. Also, when learning Java, I would suggest that you do not use an IDE at ALL! That's because you'll learn to code independently. It's up to you, though.
No you don't need to put in a package into your class UNLESS you are going to import it to another class that will be in it's own file. This is where protected type variables come in when you don't want to make them priviate but only want the subclasses (or child classes) access to them. You are also missing your public statement for your class so it should look like
public class First{
public static void main(String[] args){
System.out.println("Hello!");
}
}
Package represents a directory that contains related group of classes and interfaces.
A package is a namespace that organizes a set of related classes and
interfaces. Conceptually you can think of packages as being similar to
different folders on your computer. You might keep HTML pages in one
folder, images in another, and scripts or applications in yet another.
Because software written in the Java programming language can be
composed of hundreds or thousands of individual classes, it makes
sense to keep things organized by placing related classes and
interfaces into packages.
Below you can find some good discussions regarding java packages:
Java packages com and org
Are there best practices for (Java) package organisation?
Java com.* package namespace

How can I avoid a name conflict between a class and a package in Java?

I have two projects, Main and Core. I have a package called com.package.Sample (along with its contents) and a class called Sample in package com.package. If I were to include both in Main, I would run into an error with one being unable to resolve - in my actual case it was the Sample class that could not be resolved. We have ant scripts that builds and that has always worked.
However, carefully examining what was required of each project, I noticed that I could move the package com.package.Sample into Core along with its dependencies that were in Main. The Sample class technically belonged inside of Main so I did not move it. This allowed me to build successfully within Eclipse.
A couple of things I'm wondering about:
Is this common in large projects?
What is the best approach for this kind of situation? Prior to examining the conflict, I thought the best solution was to re-factor the Sample class.
If however, I could not move the package com.package.Sample out of Main. What should I do? Or is this a case of it will never build?
To answer your bullets, respectively:
I don't know if this is common in large projects, I would assume not. Large projects would probably never become large if the codebase was designed to cause name conflicts (especially in Java, which makes solving problems like this easy).
I wouldn't refactor the Sample class if the name is appropriately descriptive. I would however, name my packages (and subpackages) with all lowercase letters. You implied that this is a smallish project, so I'm guessing you have control over naming. I have never seen in my recollection production Java code (commercial or open source) that used any capitals in a package name. Since the convention in Java is to use Pascal case or camel case or whatever you want to call it, if you follow that convention you will never have a class/package name conflict.
Of course it will build. Pretty easy fix. Since you are using Eclipse, you should be able to right-click the package in the explorer, choose "refactor", change the name to lowercase, and be pretty much done.
Good luck!
Package names should be all lowercase, class names should start with a capital. Following this practice makes sure that problems like you describe never occur.

Categories

Resources