Code is read far more often than it is written. At Verpex Solutions Pty Ltd, we do not favour clever code that sacrifices readability. We write predictable, testable, and highly maintainable software built for enterprise longevity.
1. DRY and YAGNI Principles
Technical debt accrues rapidly when logic is duplicated or when engineers build features anticipating future requirements that never materialize.
public String formatUser(User user) {
return user.getFirstName().trim().toUpperCase() + " " + user.getLastName().trim().toUpperCase();
}
public static String formatName(String firstName, String lastName) {
return firstName.trim().toUpperCase() + " " + lastName.trim().toUpperCase();
}
The Verpex Standard
- DRY (Don't Repeat Yourself): Every piece of knowledge or business logic must have a single, unambiguous representation within the system. If you find yourself copying and pasting code, it must be abstracted into a shared service or utility.
- YAGNI (You Aren't Gonna Need It): Do not over-engineer solutions for theoretical future edge cases. Build the simplest, most robust architecture that solves the immediate business requirement. Code can always be refactored later when the requirements actually change.
2. The SOLID Foundation
We rely heavily on object-oriented design principles to keep our codebases decoupled and resilient to change. The Single Responsibility Principle (SRP) is our primary focus during code reviews.
public class OrderService {
public void process() {
MySqlDatabase db = new MySqlDatabase();
db.save();
}
}
public class OrderService {
private final OrderRepository repository;
public OrderService(OrderRepository repository) {
this.repository = repository;
}
}
The Verpex Standard
- Single Responsibility: A class should have one, and only one, reason to change. Controllers must only handle HTTP routing, services must handle business logic, and repositories must only handle data access. Bleeding concerns across these layers is strictly prohibited.
- Dependency Inversion: High-level modules should not depend on low-level modules. Both should depend on abstractions (interfaces). This ensures that swapping out a specific database implementation or external API provider does not require rewriting core business logic.
3. Constructor Injection in Spring Boot
When developing in Java and Spring Boot, managing component dependencies correctly is critical for application startup and testing.
@Autowired
private UserService userService;
private final UserService userService;
@Autowired
public SystemController(UserService userService) {
this.userService = userService;
}
The Verpex Standard
We mandate constructor-based dependency injection over field injection. This guarantees that application components are strictly immutable, easily mocked in unit tests, and will fail fast during compilation or startup if a required dependency is missing.
4. Immutability by Default
Mutable state is the root cause of the most complex bugs in concurrent and multi-threaded enterprise applications.
public class ServerConfig {
private List<String> allowedIps;
public void setAllowedIps(List<String> allowedIps) { this.allowedIps = allowedIps; }
public List<String> getAllowedIps() { return this.allowedIps; }
}
public class ServerConfig {
private final List<String> allowedIps;
public ServerConfig(List<String> allowedIps) {
this.allowedIps = List.copyOf(allowedIps);
}
}
The Verpex Standard
- Variables, collections, and class fields should be declared as
final whenever possible.
- Avoid creating setter methods on domain objects unless absolutely necessary for an ORM framework. Use constructor initialization or builder patterns to establish an object's state at the moment of creation.
- When returning collections from a service, always wrap them in unmodifiable lists to prevent upstream modifications.
5. Error Handling and Logging
Errors will happen in production. How the code responds determines whether a system degrades gracefully or crashes entirely.
try {
processTransaction(txId);
} catch (Exception e) {
log.error("Error occurred");
}
try {
processTransaction(txId);
} catch (TransactionException e) {
log.error("Payment processing failed for Transaction ID: {}", txId, e);
throw new EnterprisePaymentException("Failed to process transaction", e);
}
The Verpex Standard
- Fail Fast: Validate all input parameters at the very edges of the application. Throw descriptive, custom exceptions immediately if the input is invalid.
- Never swallow exceptions: An empty catch block is one of the most dangerous anti-patterns in enterprise software. If an exception is caught, it must either be handled to safely restore normal operation or logged with full context before being re-thrown.
- Contextual Logging: A log message saying "Error saving user" is useless. Logs must include the relevant identifiers (e.g., "Failed to save User ID: 405 due to DataIntegrityViolationException") to allow for rapid debugging.
6. Version Control and Branch Management
A clean repository history is just as important as clean code. We use a structured Git workflow to ensure every change is traceable, reviewable, and reversible.
$ git checkout main
$ git commit -am "fixed stuff"
$ git push origin main
$ git checkout -b feature/TICKET-102-oauth-integration
$ git commit -m "feat(auth): implement OAuth2 token validation"
$ git push origin feature/TICKET-102-oauth-integration
$ git tag -a v1.4.0 -m "Release v1.4.0: OAuth and Bugfixes"
$ git push origin v1.4.0
The Verpex Standard
- Branching Strategy: We follow a structured feature-branch workflow. All active development occurs on isolated feature or bugfix branches derived from the
develop branch.
- Branch Naming & Commits: Branches must be descriptive and include the relevant tracking ticket reference (e.g.,
feature/TICKET-123-short-desc). Commit messages should follow conventional commit formats to maintain a readable history.
- Protected Branches: The
main and develop branches are strictly protected. Merging code requires an approved Pull Request and a successfully passing CI/CD pipeline. Direct commits to these branches are prohibited.
- Semantic Tagging: Every production deployment must be tied to a specific, immutable Git tag (e.g.,
v1.4.0) to guarantee environment parity and enable immediate rollback capabilities if required.