You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
***NEVER use magic numbers** - always use enum constants
470
+
***NEVER write large if-else-if statements over known types** - will not be exhaustive and creates bugs when new types are added. Use exhaustive switch statements over bounded sets such as enum values or sealed interface permits
471
+
472
+
## Functional Style
473
+
474
+
* Combine Records + static methods for functional programming
475
+
* Emphasize immutability and explicit state transformations
476
+
* Reduce package count to improve testability
477
+
* Implement Algebraic Data Types pattern with Function Modules
478
+
* Modern Stream Programming
479
+
* Use Stream API instead of traditional loops
480
+
* Write declarative rather than imperative code
481
+
* Chain operations without intermediate variables
482
+
* Support immutability throughout processing
483
+
* Example: `IntStream.range(0, 100).filter(i -> i % 2 == 0).sum()` instead of counting loops
484
+
* Always use final variables in functional style.
485
+
* Prefer `final var` with self documenting names over `int i` or `String s` but its not possible to do that on a `final` variable that is not yet initialized so its a weak preference not a strong one.
486
+
* Avoid just adding new functionality to the top of a method to make an early return. It is fine to have a simple guard statement. Yet general you should pattern match over the input to do different things with the same method. Adding special case logic is a code smell that should be avoided.
487
+
488
+
## Documentation using JEP 467 Markdown documentation
489
+
490
+
IMPORTANT: You must not write JavaDoc comments that start with `/**` and end with `*/`
491
+
IMPORTANT: You must "JEP 467: Markdown Documentation Comments" that start all lines with `///`
492
+
493
+
Here is an example of the correct format for documentation comments:
494
+
495
+
```java
496
+
/// Returns a hash code value for the object. This method is
497
+
/// supported for the benefit of hash tables such as those provided by
498
+
/// [java.util.HashMap].
499
+
///
500
+
/// The general contract of `hashCode` is:
501
+
///
502
+
/// - Whenever it is invoked on the same object more than once during
503
+
/// an execution of a Java application, the `hashCode` method
504
+
/// - If two objects are equal according to the
505
+
/// [equals][#equals(Object)] method, then calling the
506
+
/// - It is _not_ required that if two objects are unequal
507
+
/// according to the [equals][#equals(Object)] method, then
-**FINE**: Production-level debugging, default for most debug output
518
+
-**FINER**: Verbose debugging, detailed internal flow, class resolution details
519
+
-**INFO**: Important runtime information
520
+
- LOGGER is a static field: `static final Logger LOGGER = Logger.getLogger(ClassName.class.getName());` where use the primary interface or the package as the logger name with the logger package-private and shared across the classes when the package is small enough.
521
+
- Use lambda logging for performance: `LOGGER.fine(() -> "message " + variable);`
522
+
523
+
# Compile, Test, Debug Loop
524
+
525
+
-**Check Compiles**: Focusing on the correct mvn module run without verbose logging and do not grep the output to see compile errors:
-**No Grep Filtering**: Use logging levels to filter output, do not grep the output for compile errors, just run less test methods with the correct logging to reduce the output to a manageable size. Filtering hides problems and needs more test excution to find the same problems which wastes time.
534
+
535
+
## Modern Java Singleton Pattern: Sealed Interfaces
536
+
537
+
**Singleton Object Anti-Pattern**: Traditional singleton classes with private constructors and static instances are legacy should be avoided. With a functional style we can create a "package-private companion module" of small package-private methods with `sealed interfacee GoodSingletonModule permits Nothing { enum Nothing extends GoodSingletonModule{}; /* static functional methods here */ }`.
538
+
539
+
### Assertions and Input Validation
540
+
541
+
1. On the public API entry points use `Objects.assertNonNull()` to ensure that the inputs are legal.
542
+
2. After that on internal method that should be passed only valid data use `assert` to ensure that the data is valid.
543
+
- e.g. use `assert x==y: "unexpected x="+x+" y="+y;` as `mvn` base should be run with `-ea` to enable assertions.
544
+
3. Often there is an `orElseThrow()` which can be used so the only reason to use `assert` is to add more logging to the error message.
545
+
4. Consider using the validations of `Object` and `Arrays` and the like to ensure that the data is valid.
546
+
- e.g. `Objects.requireNonNull(type, "type must not be null")` or `Arrays.checkIndex(index, array.length)`.
547
+
548
+
## JEP References
549
+
550
+
[JEP 467](https://openjdk.org/jeps/467): Markdown Documentation in JavaDoc
551
+
[JEP 371](https://openjdk.org/jeps/371): Local Classes and Interfaces
0 commit comments