Technical challenge for a Software Engineer position in Nubank.
This project implements a command-line application that calculates the capital gains tax for stock trading operations, based on defined business rules like weighted average pricing, tax exemption thresholds, and loss compensation.
- Java 24 or higher is required to run this project.
If you don't have Java 24 installed, download it from:
➡️ https://jdk.java.net/24/
Check your Java version:
java -versionExpected output:
openjdk version "24"
✅ The application runs on Windows, macOS, and Linux, as long as Java 24 is installed.
The application reads a list of operations from stdin, one per line in JSON format. Each line is processed to calculate the tax for each operation, and the result is returned to stdout.
"buy": increases the number of shares and updates the average price."sell": calculates gain/loss, applies exemption (≤ R$20,000), and applies 20% tax if applicable.
./gradlew clean buildjava -jar build/libs/capital-gains-0.0.1-SNAPSHOT.jarThe program will start and wait for input in the terminal (stdin).
You can type or paste a JSON line directly into the terminal and press Enter.
✅ Example input:
[{"operation":"buy", "unit-cost":10.00, "quantity":10000}, {"operation":"sell", "unit-cost":20.00, "quantity":5000}]✅ Example output:
[{"tax":0.00},{"tax":10000.00}]- On macOS/Linux:
Ctrl + D - On Windows:
Enter
- Create an
input.txtfile with:
[{"operation":"buy", "unit-cost":10.00, "quantity":10000}, {"operation":"sell", "unit-cost":20.00, "quantity":5000}]- Run (do not use Windows PowerShell):
java -jar build/libs/capital-gains-0.0.1-SNAPSHOT.jar < input.txtOutput:
[{"tax":0.00},{"tax":10000.00}]Run unit and integration tests with:
./gradlew testAll test cases from the code challenge document are included in these tests.
src/
├── main/
│ ├── java/com/nubank/capitalgains/
│ │ ├── CapitalGainsApplication.java
│ │ ├── cli/CommandLineInterface.java
│ │ ├── calculator/CapitalGainCalculator.java
│ │ ├── model/
│ │ │ ├── OperationInput.java
│ │ │ └── TaxOutput.java
│ │ └── service/OperationProcessor.java
│
└── test/
└── java/com/nubank/capitalgains/
├── calculator/
│ ├── CapitalGainCalculatorTest.java
│ └── CapitalGainCalculatorTestCases.java
└── integration/
└── CommandLineInterfaceIntegrationTest.java
- Java 24
- Spring Boot 3.2+
- Gradle Kotlin DSL
- Jackson for JSON parsing
- JUnit 5 for testing
-
Immutability
Models are defined as Javarecordtypes to ensure immutability, improving code clarity, thread-safety, and preventing accidental state mutations. -
Precision in Financial Calculations
All monetary computations useBigDecimalwith explicit scale and rounding mode to avoid floating-point inaccuracies, which is critical in financial applications. -
Separation of Concerns & Scalability
Business logic is fully encapsulated within theCapitalGainCalculatorclass.
Input/output handling is decoupled from the core logic.
This design allows the calculator to be easily reused in different contexts, such as APIs, batch processes, or UIs, without modification. -
Testability & Robustness
The test suite mirrors exactly the test cases described in the original challenge document (spec-ptbr.pdf), from case #1 to case #9, with both unit tests and a full integration test simulating the real CLI execution.
Implemented using JUnit 5's@ParameterizedTestwithArguments.ofto improve test readability, eliminate duplication, and enable systematic validation of all business scenarios.Test coverage includes:
- Price average calculation (weighted average)
- Tax exemption rules
- Loss accumulation and compensation
- Boundary conditions and edge cases
- Full integration test covering the execution from the command-line interface (CLI) to the core calculation logic
-
Code Quality & Readability
The implementation adheres to SOLID principles, Clean Code, and Clean Architecture practices.Responsibilities are well-defined:
- Models → pure data
- Calculator → business logic
- Processor/Service → orchestration
- CLI → user input/output management
-
Simplicity and Maintainability
The project intentionally avoids unnecessary frameworks or dependencies, keeping the code lean, maintainable, and easy to understand during code review processes or handoffs.