I realized that creating a tool that enables the developer to refactor the code like I dreamed is beyond my abilities – but did not regret anything and maybe on one day I will pick up the idea again.
Niceties in my life: participating in an another superb wedding party, settling down in an almost new apartment in the heart of the preferred area – Grüezi von Opfikon! – and assembling furnitures there. I dedicate this post to my favorite piece of equipment: Nespresso Inissia and its invigorating effects.
The cover image was taken of the Kapellbrücke during our recent small trip to Luzerne.
Now I have a small bunch of tests so I have a continuously growing and living specification. The following scenarios are supported:
- moving dependency to a new/existing module (sibling, parent, child)
- moving all java classes depending – even transitively – on the what if the from does not provide the referenced classes by any other dependency
- resolving properties in maven coordinate (groupId, artifactId, version) tags even if there are inherited properties
- dependencyManagement is taken into consideration
- preliminary check: to might contain what but in this case the version must match otherwise the user is asked to resolve the conflict first
- give insight to the user about the completed operations via Intellij’s Event Log panel
what: trivial, the dependency you want to move
from: trivial, the maven module that includes the what
as/to: as is referring to a new, non-existing module while to is marking an existing one
parentTo: the parent of the as/to module
Small lessons learned
Do not use together two dependencies where both contain a class with the same FQCN
com.google.collections:google-collections:1.0 and com.google.guava:guava:18.0 both contain class com.google.common.collect.Iterables with method: void removeIf(Iterable, Predicate). In google-collections it has no modifier so its package-private while the guava provides this as public. This caused a runtime Error sometimes because the classloader found the stricter one:
java.lang.IllegalAccessError: tried to access method com.google.common.collect.Iterables.removeIf(Ljava/lang/Iterable;Lcom/google/common/base/Predicate;)Z
Spin-off: It should be an easy task to implement a validator by reusing the existing code to cover this scenario but at the moment I do not want to lose the focus.
No automated way to publish to JetBrains IntelliJ IDEA Plugin Repository
Spin-off: Let’s create a Jenkins plugin for this!
Use Idea’s built in diagram drawer
Focus on splitting Java classes:
ClassAB depends on DepA and DepB. Let’s move DepB to an another module: split ClassAB into two: ClassA remains in the same place but ClassB must be moved to the new module. Update the dependencies of other modules, fix imports and references in Java classes. The code must compile after the transformation.
Do not think that even the highlighted scenarios are all well-rounded. I track all popping up idea within a Google spreadsheet and it is growing super fast. The more I work on this project the more idea I have and the more I realize how much I do not know about Java and Maven. Most of the time I have nothing but a dim and uncertain assumption.
After travelling 1.5 hours by public transport from Zürich to Intschi and taking the cable car up to Arnisee the hiking finally started. The top, Sunniggrätli offers not just an amazing view but a small mountain hütte too: I have never had a lunch with such an amazing view. The cover image was taken from the dining table: no filters, no photoshop. At the end of the day we climbed – according to my FitBit Blaze – 296 floors, walked 19.9 Kilometers and burned 5453 calories. We took not just the aching toes home but a lifetime experience too. If you have the opportunity to hike in the Canton of Uri then do not hesitate!
I published what I have so far on GitHub and my mind is really full with TODOs and FIXMEs. At the moment I strongly do not recommend to install it unless you want nothing but play with it.
Some really basic scenarios are already implemented and covered with automated tests. I had two options: building up an object structure representing the Maven modules then executing the transformation steps on them. The other way is to create real Maven projects: folders and source files on the file system and using them as input and writing the results back to the disk. I voted for the second but implemented a few but real unit tests beside these high level ones.
Jenkins helped me to make the build more environment independent. Some issues immediately popped out: ignoring different line endings (CR, LF) and indentation is now solved.
A more aesthetic UI, much more handled scenarios and figure out how to push LSR to JetBrains IntelliJ IDEA Plugin Repository.
I am sending out Anmeldeformular für Wohnen, Betreibungsauszug and Kopies auf der Aufenthaltsbewilligung once or sometimes twice each day mostly via e-mail rarely traditional post. Setting up appointments with landlords and actual tenants is my new favorite daily routine. Getting to know the city is just one benefit of searching for a new apartment, however I am now ready to leave behind this joy. Sooner or later it will happen… keep fingers crossed!
Do you know the single responsibility principle and separation of concerns? Have you ever had a huge and complex module where it – would – took tremendous of time to make the first cut or dependency extraction to simplify it?
Probably after some time you gave up for some reason. Maybe the next super important business feature must be implemented asap… and the code is rotten and more rotten. What if this redesign could be like method renaming? Shift + F6 or Alt + Shift + R!
There is a huge module “core” with many dependencies: logging, persistence, web/servlet, etc…
You want to move all logging related dependencies to a new “core-logging” module. So you select logback-core, logback-classic, slf4j-api, jcl-over-slf4j and with one click they are all moved to a new module as well as all the related classes.
As a next step you will move the hibernate/jpa/db/sql dependencies exactly like this to a new “core-persistence” module.
I know: it is a super easy and trivial example. What about really mean and complex scenarios? Will it work? Is this a good idea at all?
A primitive POC is under development and at first I will create a simple plugin for IntelliJ IDEA around it. It will be publish on GitHub soon!