Java Deep

Pure Java, what else

The Magic Setter Antipattern

Setters and getter are evil. When the JavaBean definition was created it seemed to be a good idea. But they do a lot of harm to the Java community. Not as many as the null pointer generally, but enough.

The very first thing is that many juniors believe that implementing setters and getter (hey, it is just a few click in Eclispe!) does encapsulation properly. Should I detail why it does not?

The other things is that using setters and getters are against YAGNI. YAGNI stands for You aren’t gonna need it. It means that you should not develop a code that the project does not need now. The emphasis is on the word now. Many programmers tend to develop code that extends the actual functionality and does something more general than actually needed. Even though in principle it could be valuable: in most of the practical cases it is not. The code becomes more complex and on the other hand project never develops to the stage where the generalization the programmer created is needed.

Setters and getter are a clean, simple and very broadly used example of YAGNI. If the setter does nothing else but sets the value of a field and if the getter does nothing else than returns the value of the field then why do we need them at all? Why do not alter the access modifier of the field to the value that the setter and the getter has (probably public)?

The answer usually is that you may need to implement some more complex functionality either in the getter or in the setter and then you need not change the “interface” the bean provides. The words “you may need to implement” suggests that this is YAGNI. What is more: it is dangerous. Implementing the setters and the getters you implicitly expose the implementation of the class. What does a setter do? Sets the value of a field. For example setBirthDate() by definition sets the field birthDate. And this is the way your users, who write the code calling the setter will think about it. You may document in your JavaDoc that setBirthDate() actually “specifies” a birth date but that is too late. You named the method to be a setter and that is it. Nobody reads JavaDoc. API rulez.

Later, when you change your code and setBirthDate() does not only sets birth date or does not even do that the users will not be notified. The change is silent and you just changed the interface you implicitely provided for your users. There will be bugs, debug session, new releases and this is good, because this creates workplace (feel the irony, please). If the users were provided direct access to the fields moving the fields from public to behind the barricades of private access modifier would cause compile time errors. Perhaps it is only a weird personal taste, but I prefer compile time errors more than bugs. They are easier (read: cheaper) to fix.

Do not worry: you still can modify your API. You can still remove your setters and getters from the set of methods and force fellow programmers to fix their code that implicitly assumed that setters really set and getters get. Please do.

What the actual story was making me write this?

Once upon a time there was an object that could do something. To perform its task you could set either field aaa or the field bbb, but never both. The application was developed this way and all was good for more than six years. Some day a young programmer princess came riding on white horse wanting to make the world to be a better place. He wanted to make the before mentioned class safer and modified the setter setAaa() to null the field bbb and the other way around. Unit tests shined. Coverage was 100%. (I should learn not to lie.) He submitted a new release of the library and a few weeks later he finished his internship and went back to school. That time the applications started to use the new version of the library. And they failed miserably because of this small change and rolled back to the old version. We all had hard time and summing up, well, the corporate spent approximately one person year of work caused by the simple change not to mention the amount of hair that programmers tore off from their head.

Why did the programs failed? There was some code that cloned an object containing the fields aaa and bbb in a way like this:

    BadBean newBadBean = new BadBean();
    newBadBean.setAaa(oldBadBean.getAaa());
    newBadBean.setBbb(oldBadBean.getBbb());

You see the point. In the new bean the field aaa was always null.

Now that you have read this article you will never try to create a clever setter. I know you won’t! You know the saying: Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live. Behold!

Quick, Cheap, Quality: choose two

Quick Cheap Fast

You can select two

It is old and common wisdom. Even printed on billboard of the mechanics shop where my car is usually repaired. And as with many well known facts: they are ignored many times.

Although his is a wider issue, and many statements I am going to make in this article is valid for other industries, I will focus on IT and more specifically on software development. I do that, because this is where I have experience and my interest. The software industry is new as compared to building constructions or car repair and the customers many times have unreal expectations. To make the situation worse bad developers and companies harvest the obliviousness of customers cheating them. This leads to misery and many times customers learn that software vendors are unreliable and they just tend not to believe what we say even when they face an honest vendor.

There will be no liberation of the world in this article. There is no such article that could do that, not even such a minor aspect of our lives as customer vendor relationship in software development.

As a vendor choose two you can control

After you realized that there is no free lunch and selected two of the above, it is still not the end of the story. You can say, for example, that you want quality software and fast, no matter what it costs. If you can not control the time or the quality you may get only one or none of the three above.

Controlling money

Controlling the money is the easiest these days so long as long there is a healthy society where contracts are obeyed and executed. You have a contract with the software vendor and you pay no more than the contract price. I have seen software projects when the software was not ready by time and the vendor demanded more money to finish. The customer had two choices. Pay the extra and get the software with some delay or start the whole project with another vendor from scratch. Both of them meant extra cost. Extra payment: obvious. Project start over: investment into vendor relationship on technical level and time to market money lost.

Looking at the story you can say the vendor simply blackmailed the customer. Real life is not that simple many times and a story can not be told in a paragraph as complex as the life is. I was lucky not to be involved in the whole story since I could see that there was foul play on both sides. It is kind of culture how we play these games.

Controlling time

Perhaps time is the second in this list. At least it can easily be measured since the invention of the chronograph. Controlling is, however, more than just measure. As you could see in the example above facing the fact that the software is not ready at the end of the project is a disaster.

To control the time you should use mile stones and project deliverables that show the progress of the project. It may be so important that in some project I have experienced delivery of artifacts that were not needed in the long run and from the position of the developers it seemed to be waste of money. We were asked, and paid of course, to develop a version of a software with an extremely simple UI that was not appropriate for use in the production version. Not a single line of code of this UI was used in the final version. Even though this was capable to demonstrate that the back-end of the software was partially developed it was possible for the customer to check some of the features and there was no room for slide ware lies. (We actually did not intend to lie, but even if we wanted there was no room: the demo was working on a partially developed back-end.)

On the other hand the strong control of time may lead to something that hardly can be named “control” in the noble sense of management. Tracking the progress, requiring constant administration and deliverables only for the time tracking may lead to unjustifiable overhead cost. Since the developers are usually not knowledgable about management they do not usually understand the importance of the measurement of their work and this may lead to frustration adversely affect motivation and thus work.

As is always: there has to be a good balance. There is no easy way to find the balance though. As one of my junior coworker once said when there was too much control and checkpoint in the project: “It is controlling without con.” (for those who have brain challenges: trolling)

Controlling quality

This is the hardest. It is not even trivial to measure the quality. There are great practices in software development that can help the measurement of the quality of a developing software product but they are not measuring quality itself in purest form. They measure something that may, if we are lucky, correlate with the quality of the software. We can measure the number of bugs discovered during a test phase. We can use sonar, PMD, findbugs, checkstyle on the code and follow strict coding conventions. These alone however does not assert that you will have good quality.

It is also a misconcept to aim for bug free software. There can be bugs in the code. The aim is to have a software that fits the business needs. If a software is targeted toward prospect customers, general internet audience who get distracted from a menu structure not intuitive enough then the UI has to be designed accordingly tested with trial audience and fine tuned. It incurs cost. If the cost is less than the business gain: go for it.

If you work for a company and the intranet application is used by internal users, who spend 8 hours a day using the application they learn to use a menu system even that is not too intuitive. I have experienced a software development project where we wanted to make the menu structure more intuitive and the users refused the change wanting the old, bad style structure back: they have already learnt where to click, what key combos to press.

Conclusion

All of these subjects deserve more discussion than a short article or just a section in an article. Here they are more as a discussion ice breaker than something to learn from like a tutorial. Just some ideas and fragments that you can add to in comments if you like.

Using junit for something else

junit != unit test

Junit is the Java unit testing framework. We use it for unit testing usually, but many times we use it to execute integration tests as well. The major difference is that unit tests test individual units, while integration tests test how the different classes work together. This way integration tests cover longer execution chain. This means that they may discover more errors than unit tests, but at the same time they usually run longer times and it is harder to locate the bug if a test fails. If you, as a developer are aware of these differences there is nothing wrong to use junit to execute non-unit tests.

I have seen examples in production code when the junit framework was used to execute system tests, where the execution chain of the test included external service call over the network. Junit is just a tool, so still, if you are aware of the drawbacks there is nothing inherently wrong with it. However in the actual case the execution of the junit tests were executed in the normal maven test phase and once the external service went down the code failed to build. That is bad, clearly showing the developer creating the code was not aware of the big picture that includes the external services and the build process.

After having all that said, let me tell you a different story and join the two threads later.

We speak languages… many

Our programs have user interface, most of the time. The interface contains texts, usually in different languages. Usually in English and local language where the code is targeted. The text literals are usually externalized stored in “properties” files. Having multiple languages we have separate properties file for each language, each defining a literal text for an id.

For example we have the files

messages-de.properties
messages-fr.properties
messages-en.properties
messages-pl.properties
messages.properties

and in the Java code we were accessing these via the Spring MessageSource calling

String label = messageSource.getMessage("my.label.name",null,"label",locale);

We, programmers are kind of lazy

The problems came when we did not have some of the translations of the texts. The job of specifying the actual text of the labels in different languages does not belong to the programmers. Programmers are good speaking Java, C and other programming languages but are not really shining when it comes to natural languages. Most of us just do not speak all the languages needed. There are people who have the job to translate the text. Different people usually for different languages. Some of them work faster, others slower and the coding just could not wait for the translations to be ready. For the time till the final translation is available we use temporary strings.

All temporary solutions become final.

The temporary strings, which were just the English version got into the release.

Process and discipline: failed

To avoid that we implemented a process. We opened a Jira issue for each translation. When the translation was ready it got attached to the issue. When it got edited into the properties file and committed to git the issue was closed. It was such a burden and overhead that programmers were slowed down by it and less disciplined programmers just did not follow the process. Generally it was a bad idea.

We concluded that not having a translation into the properties files is not the real big issue. The issue is not knowing that it was missing and creating a release. So we needed a process to check the correctness of the properties files before release.

Light-way process and control

Checking would have been cumbersome manually. We created junit tests that compared the different language files and checked that there is no key missing from one present in an other and that the values are not the same as the default English version. The junit test was to be executed each time when the project was to be released. Then we realized that some of the values are really the same as the English version so we started to use the letter ‘X’ at the first position in the language files to signal a label waiting for real translated value replacement. At this point somebody suggested that the junit test could be replaced by a simple ‘grep’. It was almost true, except we still wanted to discover missing keys and test running automatically during the release process.

Summary, and take-away

The Junit framework was designed to execute unit tests, but frameworks can and will be used not only for the purpose they were designed for. (Side note: this is actually true for any tool be it simple as a hammer or complex as default methods in Java interfaces.)

You can use junit to execute tasks that can be executed during the testing phase of build and/or release.

  • The tasks should execute fast, since the execution time adds to the build/release cycle.
  • Should not depend on external sources, especially those that are reachable over the network,
    because these going down may also render the build process fail.
  • When something is not acceptable for the build use the junit api to signal failure. Do not just write warnings. Nobody reads warnings.

Default methods and multiple inheritance

Recently Lukas JOOQ Eder posted and article about nested classes and their use. This is an interesting topic and his article is, as always, interesting and worth reading. There was only one slight statement I could not agree with and we had a brief reply chain leading to default method and why there can not be something like

class Outer {
    <non-static> interface Inner {
        default void x() {
            System.out.println(Outer.this.toString());
        }
    }
 
    Inner2 y() {
        return new Inner2();
    }
}
 
class Inner2 implements Inner {
}
 
// This would now print Outer.toString()
// to the console
new Outer().y().x();

in Java. In the above code the default method of an inner interface would refer to the instance that is enclosing the interface, so to say. I believed that a “reply” was not the best communication form for this, as the original topic was different and here I go.

What are default methods

You probably know. If not google it, or read my articles Java 8 default methods: what can and can not do? and How not to use Java 8 default methods.

If you googled you can see that default methods in Java 8 bring the Canaan, multiple inheritance is available.

There is a very good discussion about it on stackoverflow with real professionals, who do know Java:

Java has always had multiple inheritance of types. Default methods add multiple inheritance of behavior, but not of state. (Multiple inheritance of state in languages like C++ is where most of the trouble comes from.) – Brian Goetz Jun 21 ’14 at 2:05

In this article I will examine a little how to interpret and understand that statement.

Types of inheritance

The quote from Brian Goetz mentions:

  • inheritance of types
  • inheritance of behavior, and
  • inheritance of state.

Inheritance of types is very easy and well known for Java programmers. You define abstract methods in the interface, but you do not specify how they work, only the return value and the signature of the methods. With default methods Java 8 introduced inheritance of behavior without inheritance of state. But can you really have inheritance of behavior without inheritance of state? Not really. At least in Java 8 you can have inheritance of state though this is not recommended, not well performing (I mean: it may be slow) and also cumbersome and error prone to program. But you can, and I will show here how. (In addition to the thread local nonsense I published in the article I referred above.)

I believe that Java 8 inventors wanted the default method to keep backward compatibility while implementing the functional interfaces (e.g.: streams) in the standard run time. I recently watched the series Fargo and I feel the language designers just obliviously answered “yes” to the question “Is that what you really want?”

State inheritance with default methods

Default methods can not access fields (except static fields, that are final anyway in interfaces, so let’s forget them for the while). Just like you can not access private fields of class A from a class B extending A. Or the other way around: you can not access the private fields of B from A. You can however have getters and setters in B and if you declare them as abstract methods in A you gain the access. Open sesame. Getters and setters are the solution.

When you declare abstract methods in an interface for all the state fields you want to access from default methods you can access them. This way you get the very same result as if there was real state inheritance. The difference is the syntax: you use getter and setter methods instead of the field name, and you have to declare these in the interface. That way compile phase checks that the getters and setters are really there.

You can see that things with Java 8 get really complicated. Mix that up with generics and you may not find a living soul who understands it all. Having a construct, like

Outer.this.toString()

from the sample code above would make it even more complex with no real leverage, probably.

I believe I have some knowledge about what default methods are in Java 8 and what you can do with them. Having 10 years of Java and more than 30 years of programming experience, however, is not enough for me to tell how you should use default methods. I feel envy for the developers that still work with Java 1.6 or earlier in production code: they need not worry about default methods. (It was meant to be a joke.)

Even though I try to give some advices.

Recommendation

Never mimic state inheritance in default methods. Hard to tell what it is in practice though. Calling a getter or setter is clearly is. Calling some abstract methods that are implemented in the implementing class may or may not be. If doubt: better do not.

Never ever use the threadlocal trick I wrote in the other article.

Use default methods for what Java language inventors used it: keep backward compatibility in your library interfaces. If you ever released a library and it contains an interface (how could otherwise it be, btw) do not change it… Think about client code using your library that implements the interface. From Java 8 you have the possibility to finish the sentence: do not change it incompatible. If there is a new method: create a default implementation so the code that already implemented the previous version remains compatible and there is no need to extend these classes.

Do not unit test bugs

Before getting to the topic of the title let’s have a simple programming sample. On the programming task I will demonstrate some bad coding style and based on that it will be easier for me to explain why the same style is bad in unit tests. Well, now that I wrote this sentence this seems to be a obvious statement. Why something would be good in unit testing when this is not good in programming. One thing is that it is not always the way like that, and the other is that the same mistake may not be so obvious when we create unit tests.

Demo task

The demo task is very simple. Let’s write a class to decide if an integer number > 1 is prime. The algorithm is simple. Check all the numbers starting with 2 until the square root of the number. If the number is not prime we will find a number that divides the number integer times, if we do not find a divisor then the number is prime.

public class PrimeDecider {
	final int number;

	public PrimeDecider(int number) {
		this.number = number;
	}

	public boolean isPrime() {
		for (int n = 2; n * n &lt; number; n++) {
			if (number % n == 0) {
				return false;
			}
		}
		return true;
	}
}

The unit test is

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class PrimDeciderTest {

	@Test
	public void sample_2_IsPrime() {
		PrimeDecider decider = new PrimeDecider(2);
		boolean itIsPrime = decider.isPrime();
		assertTrue(itIsPrime);
	}

	@Test
	public void sample_17_IsPrime() {
		PrimeDecider decider = new PrimeDecider(17);
		boolean itIsPrime = decider.isPrime();
		assertTrue(itIsPrime);
	}

	@Test
	public void sample_10_IsNotPrime() {
		PrimeDecider decider = new PrimeDecider(10);
		boolean itIsPrime = decider.isPrime();
		assertFalse(itIsPrime);
	}
}

This is a great test, readable, some copy paste and most of all it gives us 100% code coverage. Believe me:

Java_EE_-_JavaBeanTester_src_test_java_PrimeDecider_java_-_Eclipse_-__Users_verhasp_github_javax_blog

It is all green. There can go nothing wrong! We happy.

Bug appears

One day, however, somebody gets the strange idea to test if 9 is prime. Believe it or not, our program says that 9 is prime. So the tester (or, if you are not lucky a customer) opens a bug ticket:

BGTCKT17645329-KT The method Prime does not give the
correct answer for the numbers that are multiplications of three. For example it results true for an object that represents 9.

Then comes the tedious work of bug fixing. What a joy it is usually. First of all you overcome your feeling that whispers into your ear that “the customer is stupid”. Obviously the customer is stupid because he wanted to use the class to test the number 9 it was never meant to be… hahh!!! and because the bug description is simply wrong. There is no method Prime! And the code correctly detects for example the number 3 (which is a multiplication of 3 itself) is prime. And it also detect correctly that 6 and 12 are not prime number. So how does a customer dare to craft such a bug report. Thoughts in your brain like that may help you calm down but do not help business, which is the first priority for a professional like you.

After calming down you admit that the code does not really work for the number 9 and you start to debug and fix it. First there comes a unit test that fails. That is the way we have to do TDD:

	@Test
	public void demonstrationOf_BGTCKT17645329() {
		PrimeDecider decider = new PrimeDecider(9);
		boolean itIsPrime = decider.isPrime();
		assertFalse(itIsPrime);
	}

and you deliver the fix:

	public boolean isPrime() {
		if (number == 9)
			return false;
		for (int n = 2; n * n &lt; number; n++) {
			if (number % n == 0) {
				return false;
			}
		}
		return true;
	}

I am just kidding!!!… or not

Actually I have seen fixes like that in real production code. When you are under time pressure and since life is finite you are, you may come up with a fix like that even when you know what the proper solution would be. In this case it is as simple as inserting a = in front of the < sign in the loop condition to test that the number is actually not the square of a prime number. Essentially the code

for (int n = 2; n * n =&lt; number; n++) {

would be nice.

In real production cases this may be a real and huge refactoring and if these special cases appear rarely since the code is usually used for numbers less than 25 then this fix is (may be) commercially OK.

Realistic fix for the bug

Be more realistic and assume that you realize that problem is not limited to the number 9 but to all square numbers and you apply the fix:

public class PrimeDecider {
	final int number;

	public PrimeDecider(int number) {
		this.number = number;
	}

	public boolean isPrime() {
		if (isASquareNumber(number))
			return false;
		for (int n = 2; n * n &lt; number; n++) {
			if (number % n == 0) {
				return false;
			}
		}
		return true;
	}

	private boolean isASquareNumber(int number) {
		double d = Math.sqrt(number);
		return Math.floor(d) == d;
	}
}

This is ugly, but it works. Real word code with god classes containing a few thousand lines do not get any better than this even after refactoring.

Are we finished? Not really. Lets look at the unit tests again. It documents that the code

sample 2 is prime
sample 17 is prime
sample 10 is not prime
demonstration of BGTCKT17645329

Thats is not really meaningful, especially the last line. The bug was reported (in addition to some false statement) that the number 9 is not handled properly. But the actual bug was that the program did not handle properly the numbers that were squares of prime numbers. If you know ITIL the first one is the incident and the second one is the problem. We created a unit test for the incident and it was good we did that. It helped the debugging. But when we identified the problem, before applying the fix we did not create one to test the fix for the problem. This was not real TDD and because there was a unit test for the incident but we did not create it to test the fix.

The proper test would have a name something like

some sample square number is not prime

(with the appropriate camel casing in the method name) and it would have some square numbers, like 9, 25, 36 as test data.

Conclusion

When fixing bug be careful with TDD. You may apply it wrong. TDD says to write the unit test before you code. The unit test you write will define what you want to code. This is not the unit test that demonstrate the bug. You can use that as a tool to debug and find the root cause. But that is not the part of TDD. When you know what to write, no matter how eager you are to fix the code: do write the unit test that will test the functionality that you are going to write.

This is what I wanted to imply (in an attention catching way) in the title: write a unit test for the functionality or functionality change that fixes the bug instead of the bug.

Calling grandparent methods in Java: you can not

In the article Fine points of protection I detailed how “protected” extends the “package private” access. There I wrote:

What you can do is

  • Override the method in the child class or
  • call the parents method using the keyword super.

And generally this is really all you can do with protected methods.

(Note that in this article I talk about methods and method calling, but the very similar statements can be said about fields, constructors.)

If you can call super.method() to access the parent’s method() even if the actual class has overridden it why can not you call super.super.method()?

The absolutely correct and short answer is: because Java language does not allow you to do that. (JVM does though, but you should not.) You can not directly access grandparent methods skipping parent methods. The interesting question is: Why?

The reason lies in object orientation principles. When you extend a class you extend the defined functionality of the class.

The fact that the parent class extends another class (the grandparent class) is part of the implementation that is none of the business of any other code outside of the class. This is the basic principle of encapsulation: advertise the defined functionality of a class to the outside world but keep the implementation private. There are secrets that you keep hidden even from your son. “Nicht vor dem Kind.”

Generally this is the reason. If you could access the grandparent directly you would create a dependency on the implementation of the father, and this would violate encapsulation.

Fine points of protection

In the article Some Sentences about Java I wrote that “Protected methods and fields can be used from
classes in the same package (so far the same as package private) and in addition to that it can be used from other classes that extend the class containing the protected field or method.”

Although the statement above is true it may not reveal the whole truth and I believe it deserves a new article.

When you have a private X (method, field, class, interface, constructor) in a class you can use that X from within the top level class. The use means, as described in the previous article, that X can be accessed in the instance “this” and in other instances so long as long the code accessing is in the same top level class where X is.

If you remove the private keyword in front of X then you extend the visibility to package level. You can use X inside the package the same way as you could use it before from within the class when it was private.

If we still go further one step and insert the keyword protected in front of X it will became visible from classes that extend the class where X is declared but can NOT be accessed the SAME WAY as private X from within the class or package private from within the same package. Since protected is extending the visibility of X from package private, protected X can still be used the same way within the package, but not the same way outside of it.

The difference is that you can only access a protected X in the code that is extending the functionality of X.

The above is not a precise definition. The Java Language Specification that I cite here in this blog many times details that in chapter 6.6.2 What can I say about that? Precise, complete but may not be easy or entertaining to read, which may also be true for this article, but since you are reading it I assume that you find it entertaining, educating or you have some very specific reason to read it.

While you are in the same package as the class declaring X you can access X on other instances. We can have some simple classes to demonstrate this. First of all we can have a root class that we will extend:

package a;
public class A {
	protected void protectedMethod(A a) { }
}

We have the class ‘B’ which extends ‘A’ and is in the same package.

package a;
import a.A;
public class B extends A {
	@Override
	protected void protectedMethod(A a) {
		a.protectedMethod(this);
		super.protectedMethod(this);
	}
}

If we move/copy the class ‘B’ to another package, like here:

package b;
import a.A;
public class B extends A {
	@Override
	protected void protectedMethod(A a) {
		a.protectedMethod(this);
		super.protectedMethod(this);
	}
}

then the line 6 will not compile. When it was in the previous package the compiler allowed it to access the method, because package protection made it possible. No matter what implementation instance the argument ‘a’ is to the method, they are in the same package. In case of ‘b.B’ class package protection does not allow access and because the actual object instance that we store in the method argument ‘a’ may be an instance of a class that ‘b.B’ is not extending it can not access it. It can be an instance for example of the class:

package c;
import a.A;
public class C extends A { }

What you can do is

  • Override the method in the child class or
  • call the parents method using the keyword super.

And generally this is really all you can do with protected methods outside of their package.

Use copy paste programming!

Copy paste is bad

We hate copy paste. Why? Because the result code is unmaintainable. I get a bug reported from QA, I analyze the code, look at logs, debug, drink a lot of coffee and finally I get to the code that is the root cause of the bug. I fix it, test the use case, release new code to learn next day that a very similar bug appears in a similar use case. In that case a different code runs looking very similar to the one I was mending the day before and I just start to wonder how many more copies of the same code will I face and have to change.

There are things worse than copy paste

Now imagine a schnitt, like in movies. Let’s jump to another time. I get a bug reported from QA, I analyze the code. I do not understand. There are a lot of small interfaces, abstract classes, deep hierarchies. Many of the classes have no direct relation to business. I ask for help from the developer who created the code, and he starts to explain. In two days I start to understand his idea of coding structure and how he was implementing the code in a strict object oriented way, avoiding the slightest copy/paste. After three days I find the place where a single line has to be modified. Before doing that I plan to create the unit test to fail first, then fix the code and re-run the unit test to see that the same error never comes again. So I open the unit test class testing the one I am going to modify and I do not understand how it works. It is complex and extends another class that uses another and another. This time it is a bit easier to understand since I already know the mindset of the programmer, who created it but it is still a whole day to create the new test. We are already in day #4 following the bug report customers banging on the door for fix.

To copy or not to copy…

Which is the better approach? Have some copy paste and face that some of the bugs will just appear in other areas or have an extremely strict but deep hierarchy OO design in the code that avoids bug reappearing but has a steep learning curve?

There is no one and only one best ever answer for this question. Neither of them is a good approach. Sometimes some copy paste may be forgivable sin. Deep inheritance structure is difficult to understand. It is usually recommended not to have more than three levels. One may also argue that in the above example the code could have been created with less levels of inheritance without actual copy paste. (Except that the above is not an actual but an imagined example distilled from many years of experience.) The level of repetition may conflict with OO structure. When you have the OO structure you make abstraction. Abstract code is harder to understand. When you copy-paste-modify the modified code will be on the same abstraction level as the one you copied. It may be easier to understand.

Copy unit test code

When it is about unit tests, I tend to forgive copy paste and verbosity to get simpler structures and readability. But that is because unit tests are more documentation than code. They have to be expressive as you look at it immediately. It should not require investigation and understanding of code structures defined somewhere else to get the point what the test is doing. I tend to agree with a unit test that copies one test and then contains slightly modified code. It still has one of the drawbacks on maintenance: if you change the code the change has to be propagated to all other places as well where the code was copied. But in this case if you forget to propagate the change you will get test errors or failures. This way you can see copy paste as an advantage: when you change the code you are forced to look at, refactor and think through all the test cases that are affected.

Do not copy production code

These effects that turn drawbacks to advantages in case unit test code may become a nightmare in production code. If you have doubt then do not copy. Do not be afraid to create too steep hierarchy structure. Programmers fall more often into the copy-paste trap than into steep hierarchies. Unless you are a senior programmer I recommend that you avoid copy-paste in production code at all costs as a rule of thumb. If you are senior you do not need my recommendation: you will avoid copy-paste on your own.

Side note

Just a story: Some time ago I wrote some mail about copy-paste in a code and I created a typo writing copy-pasta. In a few minutes I got a reply: “Pasta? You are referring to spaghetti code?” Nomen est omen.

Some more sentences on Java, private variables

In the article Some Sentences about Java I described that privates variables are visible from inner and nested classes and the other way around also. This is done on Java level, it is a feature of the language. However knowing that the JVM does not know anything about inner and nested classes one may wonder how this is implemented.

No inner classes in JVM

When you compile a Java class source file the compiler generates the binary file with the extension .class from the .java file. This binary file contains the symbolic information needed by the compiler to compile other classes that some way depend on this class and it also contains the JVM byte code, which is needed to execute the program. The same is true for interfaces except that they contain executable code only for default methods and for field initialization code executed when the classloader loads the interface.

When there is a class inside another class or interface then the compiler generates extra .class files for these classes. The name of these classes usually contain the name of the outer class, $ sign and the name of the inner or nested class. Since the $ sign is a legal character in an identifier in Java the JVM can not tell, and does not bother to tell if the class is an inner or top level class in Java language level.

Private is not private then?

Private methods and fields this way are accessed between classes. Because JVM does not know class nesting these are, for the JVM, “top level” classes.

As a sample lets have a Java code:

package com.javax0;
public class Inner {
	private static class InnerInner {
		private static Object b;
	}
	public void m() {
		InnerInner.b = null;
	}
}

If I compile the code with the command line

$ javac  Inner.java
$ ls -1
Inner$InnerInner.class
Inner.class
Inner.java

I get the two class files. Dissassembling the inner class:

$ javap -v Inner\$InnerInner.class 
Classfile /Users/verhasp/github/JavaBeanTester/src/test/java/com/javax0/Inner$InnerInner.class
  Last modified 2014.12.27.; size 413 bytes
  MD5 checksum 79f4ea55abe8211fec751d9a4dec9ae1
  Compiled from "Inner.java"
class com.javax0.Inner$InnerInner
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Fieldref           #3.#15         // com/javax0/Inner$InnerInner.b:Ljava/lang/Object;
   #2 = Methodref          #4.#16         // java/lang/Object."<init>":()V
   #3 = Class              #18            // com/javax0/Inner$InnerInner
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               b
   #6 = Utf8               Ljava/lang/Object;
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               access$002
  #12 = Utf8               (Ljava/lang/Object;)Ljava/lang/Object;
  #13 = Utf8               SourceFile
  #14 = Utf8               Inner.java
  #15 = NameAndType        #5:#6          // b:Ljava/lang/Object;
  #16 = NameAndType        #7:#8          // "<init>":()V
  #17 = Class              #22            // com/javax0/Inner
  #18 = Utf8               com/javax0/Inner$InnerInner
  #19 = Utf8               InnerInner
  #20 = Utf8               InnerClasses
  #21 = Utf8               java/lang/Object
  #22 = Utf8               com/javax0/Inner
{
  static java.lang.Object access$002(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: dup
         2: putstatic     #1                  // Field b:Ljava/lang/Object;
         5: areturn
      LineNumberTable:
        line 4: 0
}
SourceFile: "Inner.java"
$ 

you can notice that an synthetic method was created to set the value of the private field b. This method is needed to access the field from the outer class. The direct access is prohibited by the JVM but the compiler allows you to access the field through the synthetic methods it generates. You can not, however call the synthetic method from any other class, because the Java compiler will refuse to compile the code that tries to access directly a synthetic method. This protection works on the compiler level. If you happen to craft some JVM code directly using some special tool that accesses the synthetic method, the JVM will not stop you.

Eclipse warnings

There is another sign that you may face when creating classes causes the compiler to create synthetic methods. This is when Eclipse warns you about it:

Fullscreen_2014__12__27__19_00

This screen capture shows the line #7 of the previous Java source code where Eclipse tells you that though the code “InnerInner.b = null;” looks like a simple assignment it will be executed as a method call.

Fortunately you can configure Eclipse not to display this warning.

Synthetic methods

If you are interested more in synthetic and bridge methods, read a previous article of Java Deep.

Should we avoid private variables inside inner classes?

The final question after we looked at this detail of the Java language is how seriously we should be worried about the warning that Eclipse gives us. Should we use private nested classes or should we avoid them?

If we use them then the generated JVM code will be littered with synthetic methods and thus the execution will be more complex. If we do not use them then the generated JVM code will be simpler. Should I be worried about the simplicity and the coolness of the generated JVM? I doubt.

What I would focus on is the readability of the code we maintain and not the code javac generates.

Do not work on unimportant projects

I have heard many times from junior developers that they are working on a project that is not important. This is demotivating a lot when you do some work just to be thrown away after some while. It is just like digging a hole and next day bury it. (Unless, of course, you are a sexton, in which case it makes sense. But that is a different story.)

Eugène Ferdinand Victor Delacroix 018

Once I met a person, who was working on algo-trading algorithms. This is when computers perform tradings and compete with each other executing stock and money trading in milliseconds. He was paid well, the mathematical background was interesting and creating the algorithms was a challenge for him. However he claimed not seeing too much of value of his work to the advantage of the human mankind. He said algo-trading was just machines trading with other machines and nothing else.

We were on a long train travel and had time to discuss, and I explained that algo-trading is a form of competition but not between machines rather between the people who create, execute, maintain the trading. This way algo-trading is an essential part of the evolution that our economy is based on, in my view it may also add to the money liquidity that help the money flow where it really is needed to support investment and innovation.

This person was open to embrace my ideas and was happy seeing that there is more result of his work than just getting the salary. After a half year we met again just by accident (both of us traveled frequently between Budapest and Zürich) and explained that since he believes that his work has real value he is not only happier but also sees the algorithms from a different point of view resulting more success.

Although I believe that the statement above is partly fairy tale, partly result of auto suggestion it still has an important point. You will work better if you know what the meaning of your work is. Being agnostic I know that the life is pointless generally, so the above means that it is only the level how deep you have to dig to find meaning. If you are a shallow person getting paid may make the job important. If you think more complex you want to know what good your work does for the company and through that to the shareholders. If you are a humanistic type you have to know what your work advances humanity, human mankind general. (Be aware not to dig deeper than that risking mental illnesses.)

However what you really have to do: understand the meaning of your work, otherwise it will be no benefit for anybody. Seniors know it.

Happy Christmas!

Follow

Get every new post delivered to your Inbox.

Join 1,004 other followers