Simple exchange calculator in Java - structure and tests I am trying to learn how to correctly structure my projects and write a good, clean code. I would also like to learn how to write good tests. Can you please review it and give me some tips and tricks how to make that better?

The application is calculating the exchange from the bill for lemonade. Lemonade costs 5$ and client may pay with 5$, 10$ or 20$. At the beginning there is no change available.

Project structure

My project structure is as follows:

LemonadeChange (project) with src package and 4 packages inside:


app (contains Main)
calculatorImp (contains CalculatorLongImp and CalculatorShortImp)
calculatorInterface (contains CalculatorInterface)
test (contains CalculatorTest)


Classes

Main

public class Main {

    public static void main(int[] args) {
        CalculatorInterface calc = new CalculatorLongImp();
        calc.lemonadeChange(args);
    }
}


CalculatorInterface

public interface CalculatorInterface {

    public boolean lemonadeChange(int[] bills);
}


CalculatorLongImp

public class CalculatorLongImp implements CalculatorInterface {
    private int five = 0;
    private int ten = 0;
    int acc = 0;

    public boolean lemonadeChange(int[] bills) {
        for (int bill : bills) {
            if(bill == 5) {
                five++;
            }
            else if(bill == 10) {
                five--;
                ten++;
            }
            else {
                if(ten &gt;= 1 &amp;&amp; five &gt;= 1) {
                    ten--;
                    five--;
                }
                else if (five &gt;= 3) {
                    five -= 3;
                }
                else {
                    acc++;
                }
            }
        }

        if(acc == 0) {
            return true;
        }
        else {
            return false;
        }
    }
}


CalculatorTest

public class CalculatorTest {

    @Test
    public void testAllChangeShouldBePossibleToGive() {
        int[] bills = {5,5,5,10,20};
        CalculatorInterface calc = new CalculatorLongImp();
        assertTrue(calc.lemonadeChange(bills));
        calc = new CalculatorShortImp();
        assertTrue(calc.lemonadeChange(bills));
    }

    @Test
    public void testAllChangeShouldNotBePossibleToGive() {
        int[] bills = {20};
        CalculatorInterface calc = new CalculatorLongImp();
        assertFalse(calc.lemonadeChange(bills));
        calc = new CalculatorShortImp();
        assertFalse(calc.lemonadeChange(bills));
    }

    @Test
    public void testAllChangeShouldNotBePossibleToGiveSecond() {
        int[] bills = {10, 20};
        CalculatorInterface calc = new CalculatorLongImp();
        assertFalse(calc.lemonadeChange(bills));
        calc = new CalculatorShortImp();
        assertFalse(calc.lemonadeChange(bills));
    }

    @Test
    public void testAllChangeShouldBePossibleToGiveSecond() {
        int[] bills = {5, 5, 10, 20};
        CalculatorInterface calc = new CalculatorLongImp();
        assertTrue(calc.lemonadeChange(bills));
        calc = new CalculatorShortImp();
        assertTrue(calc.lemonadeChange(bills));
    }

    @Test
    public void testAllChangeShouldNotBePossibleToGiveThird() {
        int[] bills = {10, 20, 5, 5};
        CalculatorInterface calc = new CalculatorLongImp();
        assertFalse(calc.lemonadeChange(bills));
        calc = new CalculatorShortImp();
        assertFalse(calc.lemonadeChange(bills));
    }

    @Test
    public void testAllChangeShouldBePossibleToGiveThird() {
        int[] bills = {5,5,5,5,20};
        CalculatorInterface calc = new CalculatorLongImp();
        assertTrue(calc.lemonadeChange(bills));
        calc = new CalculatorShortImp();
        assertTrue(calc.lemonadeChange(bills));
    }
}


How would you improve that? Any tips and tricks welcomed!

Please let me know if you want to see the task that it solves - that is one of the tasks on LeetCode, so I can post it if that makes review easier.
First off, the implementation of lemonadeChange is pretty complicated. I get worried whenever I see a bunch of nested if statements - these always lead to bugs. Indeed, try adding another test case where you only pass $10 bills, I think it will erroneously return true. It's generally a good idea to limit the complexity of any individual function, take a look at the concept of Cyclomatic Complexity: https://help.semmle.com/wiki/plugins/servlet/mobile?contentId=29393453#content/view/29393453

Also, if you call lemonadeChange more than once on the same instance of CalculatorLongImp then the values of five/ten/acc will persist between calls, giving you odd results. Generally, you'd say this function has "side effects", and it's often a good idea to avoid these where possible. 

It's good that you've included tests. I would separate these out so each test only covers a single implementation - specific tests covering a single function on a single class make it easier to see exactly what's broken. 

Finally, I find the naming a bit confusing. What does acc do? What's the difference between CalculatorLongImp and CalculatorShortImp? Imagine someone else will be reading your code tomorrow and trying to understand what it does. Naming things clearly will make it much easier for someone else (or yourself in the future!) to read and understand your code.