Lab 05
In this lab session you will practice basic IDE features, notably launcher configuration, basic refactoring and using the debugger. Parts of this lab session can be realized using your TP project code, in addition you will work with a sample project available on GitHub, including documentation.
Launcher configuration
In class you've seen that the green triangle is somewhat misleading. By default, the green triangles next to your code
listing execute main methods as standard java applications. This can lead to completely chaotic events if you attempt
to run a maven project without further configuration, because effectively your IDE disregards whatever pom.xml
configuration you might have established.
Standard java launcher
- The green triangle in the top bar ("
▶ ") however, can be fully configured to meet your needs. - By default you'll have no run configuration, i.e. the launcher menu will be greyed out.
- You have two options to create a standard java run configuration (without maven)
- Click one of the green triangles next to your code listing. (Which will implicitly add a run configuration to the greyed out top bar menu)
- Manually create a launch configuration: Click the drop-down next to the top bar green triangle, then
select
Edit Configurations
, then+
, thenApplication
Use the green triangle first
You can start with creating an implicit launch configuration using the green triangle next to your code listing. Afterwards, click the dropdown to inspoct which launch configuration has been effectively created.
Your turn
- Create a new maven project and attempt to run it as standard java project.
- Use the maven archetype command to initialize a new maven hello world project
- Open it up in IntelliJ
- Click the green tringle displayed left of the main class code listing.
- Verify you see
Hello, World!
on the console.
It's working is not the same as it's correct.
Inexperienced users often diagnose in dichotomous categories "It's working" and "It's not working", without any nuance for whether a program that can be executes is actually doing what it should. Running a maven project with the default green triange is the perfect example. It seems to work, the code is correctly executed. But non of the maven advantages (dependency management, strict quality controls for code habits) are enforced. The migration to maven has absolutely no effect.
Maven launcher(s)
- Now you want to forever forget about the green triangles left of your code listing !
- Instead, create a Maven launcher configuration using to top bar's run configuration dropdown.
Your turn
- Create a Maven launcher configuration, as presented in the last course unit.
- You will also need to add the
exec
plugin to the project'spom.xml
, because otherwise the launch configuration will only compile your code, never run it.- Revisit the course unit on maven and search for how to add the
exec
plugin to the previously create HelloWorld project'spom.xml
.
- Revisit the course unit on maven and search for how to add the
Use the shortcut to run your program
Once your launcher configuration is working, look up the hotkey to re-execute the last launcher. Search the hotkey cheatsheet and identify the re-execute shortcut, to run your code with jsut a single keystroke.
Basic refactoring
IntelliJ's refactoring menu allows you to restructure your code, without actually needing to rewrite it.
- Refactoring is notably useful for larger software projects, to ensure code changes are realized consistently throughout a project.
- Starting point is always a rightclick on a code element, followed by Refactor (or simply the
Shift
+F6
)
Renaming
Renaming can be applied to any variable, method, class, or parameter. A convenient side feat is that variable renaming is also applied to JavaDoc, that is, you do not have to manually adjust javadoc consistency when you rename a method parameter with the refactoring menu.
Your turn
- Clone the Zoo sample project using:
git clone https://github.com/m5c/Zoo.git
- Open class
Animal.java
and use the refactoring menu to rename variabelfavouriteFood
intofavouriteToy
. - Get familiar with how the rename menu works (you should see a rectangle around the variable to rename, hit enter when done with renaming).
- Verify all occurrences have been renamed, e.g. also
JavaDoc
information and the correspondinggetter
and thetoString
method. - Setup a Maven launcher configuration in IntelliJ and verify the code can still be executed.
- The zoo's
pom.xml
defines anexec
plugin, so the maven command to use is:mvn clean package exec:java
- The zoo's
Info
The zoo project is also a perfect example on what goes wrong when a maven project is executed with the default java green triangles. Unless a maven launcher is configured, the IntelliJ will completely ignore the pom.xml
, i.e. the existing javadoc and checkstyle configurations will be ignored and this project has no longer a coherent javadoc and the code is not tested for formatting flaws (even if it is seemingly "working").
Method extraction
- Method extraction allows you to refactor a sequence of lines of code into a dedicated method.
- This strategy has two main purposes:
- Wrapping up lines of code so it can be reused by a function call rather than duplicating the lines.
- Breaking up overly long methods, so they are easier to understand.
Your turn
- Open the class
Zoo.java
and inspect the constructor. - It should look like this:
/**
* Private constructor, populates the zoo.
*/
private Zoo() {
openingHours = new OpeningHours();
animals = new LinkedHashMap<>();
addAnimal("Charly", new Animal("Chimpanzee", 10, "Bananas"));
addAnimal("Nemo", new Animal("Clownfish", 4, "Plankton"));
addAnimal("Dumbo", new Animal("Elephant", 13, "Peanuts"));
}
- Now let's imagine the zoo is filled with triplets, i.e. every animal exists three times, so there are three Charlys,
three Nemos and three Dumbos.
- It would be easiy to copy paste the existing
addAnimal...
lines three times - ... but that would be code duplication, and we try to avoid that!
- It would be easiy to copy paste the existing
- Instead of manually creating a new method, mark the three
addAnimal...
lines and use the refactoring method to extract a new method. You can use either:- Right click -> Refactor... -> Extract method
Option (⌥)
+Command (⌘)
+M
- You should now have the three lines in a dedicated method.
- Call it three times, and power up the zoo. Verify the program output.
Using the debugger
- In the last course unit you've seen you faulty programs can be analyzed using the debugger.
- The debugger lets you inquiry (and modify!) program state at any point in program execution.
- Never place
System.out.print
commands in your code to diagnose a problem, using the debugger is much faster, requires no code modification and provides a a lot more information.
- Tu run the debugger, you need one_ valid launcher configuration. Best practice is the use the appropriate launcher configuration, i.e. a maven launcher for a maven project etc...
- Click the
bug
symbol, next to the green triangle on the top bar, right next to the launcher dropdown menu.- Avoid right-clicking on the triangle left of the code listing, this is a standard java launcher and not necessarily running the program as you'd expect.
- Unfortunately, when you click the debugger button absolutely nothing different happens. Because your we have not told the debugger yet where we want to inspect program execution (i.e. where we want to program to freeze). We need at least one breakpoint!
Breakpoints
- Breakpoints advise the debugger to freeze program execution.
- Think of it like a movie that's paused, where you have all the time to inspect all details of a still image, as long as you want.
- Chances are high you'll notice some new detail.
Your turn
- To create a breakpoint: just click a bit right of the line number where you want execution to pause.
- You'll see a red circle appear. Congratulations you have created a first breakpoint !
- If the circle is actually diamond shaped, you've selected a line that cannot be executed, e.g. method definition.
- If absolutely nothing happens you've selected a line without code, e.g. an empty line or a comment.
Basic inspection
- Whenever you program is stalled on a breakpoint, you can (amongst others) inspect variable state.
- There are three ways to inspect variable state:
- For primitives, the value is juste printed in italic, at the end of the line. However, for objects this only tells you the object address, which usually is not very helpful.
- For objects, you can just hover the cursor of a variable, a popup will expand and provide you the values of object internal fields.
- Finally, the variables window lets you take deep dive into all variables and there state at a given time.
Your turn
- Set a breakpoint on the last line of your
Zoo
constructor. - Run the debugger and verify your program freezes on the marked line.
- Inspect the program state, use the various ways to inspect all variables.
- Use the variable pane to modify one of the
Nemos
toCaptain Nemo
, then proceed program execution using theResume
button in the debugger window.- Alternatively, you can also use
Option (⌥)
+Command (⌘)
+R
to resume.
- Alternatively, you can also use
Basic navigation
- Often times you do not know where exactly a bug occurs and you need to find it first.
- Luckily the debugger also allows you to go step by step forward in program execution.
- Going back to the movie analogy, think of it like advancing through a movie frame by frame (or if you're very old-school, proceeding in the camera roll, one picture at a time.)
- Revisit the class material and familiarize yourself with the debugger step-by-step advancing menu.
Your turn
- Set a new breakpoint on the first line of the
Zoo
constructor:openingHours = new OpeningHours();
- Start your program again in debug mode, verify it stalls on the first constructor line.
- Carefully inspect which variables are presented in the variables view and what value they have.
- Use the
step-over
button to proceed to the second line.- Check the variables pane again. What has changed ? Can you correlate the changes to the single line that has just been executed by the debugger ?
- On the second line, use the
step-into
button, to access a method call.- What happened, where are you now in program execution. Find a way to get back to the execution in the
previous
Zoo
constructor.
- What happened, where are you now in program execution. Find a way to get back to the execution in the
previous
Conditional breakpoints
- Often times you are not interested in any time a breakpoint is hit, but in specific situations.
- Conditional breakpoints allow you to do just that.
- Conditional breakpoints add contextual information to a breakpoint, and the debugger then only pauses execution when the provided condition is met.
Your turn
- Open the
Animal.java
class and set a breakpoint on the return statement of thetoString
method. - Debug your program. The breakpoint will be hit twice.
- Right-click on the breakpoint and add a condition, so it only triggers for animals of species
Honey Bee
, but not for any other species. - Debug your program again and verify the breakpoint is only hit once.
Bonus: Dependency matrix
- In the last course unit on IDEs, you've briefly seen how to extract a class dependency matrix from a codebase.
- Dependency matrices show for each class, how many dependencies exist to any other class.
Matrix interpretation
- Dependency matrices provides a quick overview and the ability to spot certain design flaws, notably:
- Circular dependencies
- Architectural pattern breaches, e.g. the model depending on view or controller (in MVC only the model must not contain any logic or have any knowledge about controller or view).
- Example: In the below dependency matrix,
Owner
andPet
showcase circular dependencies:
Your turn
- Load your Halma project and create a dependency matrix.
- Inspect the matrix and spot how the MVC pattern is represented in the dependency matrix.
- Test your understanding:
- What does it mean when a class is further down in the matrix representation ?
- Why are all cells in the top right triangle empty ?