As you probably already know, last month, Apiumhub sponsored this year’s edition of the JBCNConf, and our development team had the pleasure attending the event and sharing knowledge with the Java community in Barcelona.
JBCNConf 2019 Highlights
During JBCNConf 2019, the Apiumhub team was able to attend various talks on very different topics and the general feeling was that the conference revolved around the main sponsor, Red Hat, since they had several speakers who gave talks and workshops. This inspired me to do some proof of concept with the tool they presented, Quarkus. They define it as “a Kubernetes Native Java framework”. But today I won’t talk about Quarkus, today I would like to talk about one of the talks that caught my attention the most. I speak about the talk given by Victor Rentea – Senior Java Engineer, Technical Team Lead and Java Coach at IBM. The talk was about “Evolving a Pragmatic, Clean Architecture – A Craftsman’s Guide“.
Evolving a Pragmatic, Clean Architecture – A Craftsman’s Guide
Probably you think about Clean Code or Clean Architecture, and in part you are right, but what caught my attention the most, was Victor’s approach, relying mainly on the bases of Clean Code and Extreme Programming, putting the developer in the spotlight, as well as the well-being of the technical team and its comfort to be able to perform quality work in the best possible conditions.
Rentea exposes that a project or repository of code is not a code construction, but he defends the idea that it has much in common with the garden, that is, something organic, in constant growth, that requires continuous care, referring to the refactoring. But we’ll talk more about this later.
The techniques on which he bases his talk are very well known:
- Single Responsability Principle ( SRP ),
- Do not Repeat Yourself ( DRY ),
- Keep it Short and Simple ( KISS ),
- You Are not Gonna Need It ( YAGNI ), among others.
Caring for the technical team
One of the key points that he defends is based on the fact that a good architect must protect the technical team with tools of automation, that guarantee to minimize the risks of the project, thus it affirms: “Fear kills creativity”. Minimizing the risks in the project, the technical team feels more secure and this provokes proportionally an improvement of the productive code.
To minimize these risks, he proposes testing techniques that ensure the code and its functionality.
Another factor that I found very interesting, was the proposition to always make the team think, in order to maintain the motivation. He proposes several solutions:
- Regulate brainstorming: The technical team must think jointly how to improve the code. In my opinion, this technique not only improve the quality of the code, but it also causes an alignment between the different members of the team.
- Continuous Refactoring: Provoked by the previous point, apply the decisions made during the brainstorming session.
- There are no boring tasks: automate boring and repetitive tasks as a method to maintain the motivation of the technical team. Removing this factor from the equation is fundamental to motivation.
As a declared follower of “Clean Code” and “Clean Architecture”, Rentea proposes the application of a hexagonal architecture, also known as layered architecture or “Ports and adapters”. Victor went over the fundamentals of this architecture, but I do not want to talk about it again, as we have written several articles on this topic, like Applying Hexagonal Architecture to a symfony project.
One of the most interesting points is when the need arises to refactor a class or service that has grown too much. Once the decision to divide it has been made, a new responsibility appears for the new class or emergent service ( SRP ), this part is, in my opinion, one of the most complex ones to apply in code refactoring. To know how to define the new responsibility and also to decide the hierarchy that exists between the original class and the new emerging one, let’s look at these techniques:
- Vertical ( DRY ): Defining a new extraction layer, and this implies that one class depends on the other.
- Horizontal ( SRP ): The responsibilities of both classes are totally separate and have no dependencies on each other.
It also classifies the types of duplication that can appear in a project, sensitive to refactoring in many cases:
- Rush/Lazy: Duplicate code or business rules using “Copy & Paste”.
- Imposed: These are duplications that can hardly be suppressed. For example, validations that are carried out in frontend and backend in a project.
- Inadvertent: A bad organization of the repository, can sometimes make us forget functionalities already implemented some time ago and may cause us to repeat functions that already exist in our repository.
- Inter-developer: A developer does not know a functionality already developed by another team member and implements it again.
To try to minimize duplication, improve the quality of the code and the interaction of the technical team with it, Rentea lists down some techniques that favor the quality of the code. As a cornerstone and fundamental basis, he proposes Pair Programming Sessions – best technique to share knowledge within the team, improve the code produced, minimize bugs production or errors and also increases the speed of development in the medium-long term.
All this, also backed by sessions of “Coding Katas”, “Refactoring Hackatons”, “Coding dojos” or “Offensive Refactoring”.
One of the key points to have a comfortable environment in which the technical team can develop in optimal conditions and can develop organic quality code – is a code that has been tested. Affirms that a well tested code is a good code, since it implies a simple code, decoupled and dynamically documented: the tests are indicating us the functionality of our production code and its business rules.
Rentea enumerates various types of tests, ordered from lowest to highest difficulty, based on their maintainability:
- Pure functions: corresponds to the most internal and independent code within our domain. Pure functions lack status, so the same input will always return the same output. These functions perform a very specific action, which facilitates their testing. This code has no dependencies or side effects.
- Mock-based: It is more complex to perform and maintain, since in spite of having those dependencies replaced by mock objects, If those dependencies change, the test may need to be refactored or rewritten.
- In-memory Emulation: Justify it as “fragile data fixtures”. Relying on a concrete data structure implies that if in a determined point of the constant evolution of our organic code, said data structure changes, implies having to change all the data structures that we are using as “fixtures” in our tests.
- On Real System: Integration tests, End-to-End, in which tests are carried out on real systems, involve dependencies on third parties (such as a database or a cache system in Redis). These dependencies can produce false negatives by problems outside our code or force us to refactor them for version changes or updates.
In conclusion, Victor encourages us to keep all the logic of our business within our “Core Domain”, as uncoupled as possible, to favor the unit testing of our code, favoring its maintainability and thus increasing the speed of development.
As conclusions, Victor lists the following key points:
- The importance of avoiding the “overengineering”, thus defending the principle “KISS”.
- Protect the technical team in a comfortable environment that generates the necessary confidence to face any challenge and not fear refactoring legacy code for fear of breaking existing functionalities.
- To abstract from our domain all external dependencies.
- Refactor and extract only when strictly necessary. (Through “DRY” or “SRP”)
- Apply the architecture by layers to abstract the responsibilities in each layer and extract dependencies from our domain. Emphasizes in maintaining our agnostic domain of external dependencies.
- Tests: The importance of testing the limits of your code and your design.
Finally, I would like to draw my own conclusions on the paper by Victor Rentea. Personally, I agree with everything he said during this talk. You have to be pragmatic on a day-to-day basis, keep simplicity in our code, opt for a well-structured design that favors the growth and refactoring of our code.
As Victor comments at the beginning of his presentation, the techniques that are exposed are based on basic principles and are favored by applying the following techniques reflected in the book “Extreme Programming” ( XP ):
- Continuous Integration
- Pair Programming
- Continuous Refactoring
- Test Driven Design
These techniques, in conjunction with those already mentioned during the article, will encourage our code to grow organically and improve its quality, increasing the happiness and motivation of our technical team.
In addition, he encourages us to improve our skills with the following quote: “The fastest way to learn is to teach the others. Way to grow into a senior is to help the others grow”.
It is one of the quotes that made me think a lot and that I can not agree more with everything I learned in the JBCNConf.