Intro to Coding - raisercostin/software-wiki GitHub Wiki

Check that every commit respect the following rules:

Use principles as guide in unknown territory.

Styles

  • Offensive programming
  • Functional style
    • top down, focus on input-output parameters (intention) rather than implementation details, TDD
    • non strict, imutable collections
  • Bad Objectual style
    • Getter/setter vomit
    • Prefer aggregation over inheritance

Principle Samples

  • SRP
    • Do not use Singletons
    • Do not use modifiable static fields (log is acceptable)
  • Elegant Objects
    • Use NullObjects (read about nullability in kotlin)
      • Collections (list, map, array, ...) should be empty collections not null
      • Do not use null (use java.util.Optional) - Null Object
        • Do not have references to null objects.
        • If you could return null better to return Optional.empty()
    • Never return null
    • Simple classes
      • Should
        • be immutable: all fields final and imutable themselfs
        • ideally : private final Type field; . If really needed public final Type field;
        • initialized once at construction time
      • Should Not
        • have getters - imutable fields can be public if information needs to be exposed
        • setters - imutable fields don't need setters
    • Spring classes
      • Use @Component, have one @Autowired, use constructor injection (do not use setter injection)
  • DCSS
    • Do not use for(...) . Use functional operations on collections: .map, .foreach, .filter etc.
    • Important collections
      • vavr: Seq, List, Map, Option, Try, Either
      • reactor: Flux, Mono - future
    • Do not use multithreading code. See DCSS. Thread, synchronized, Executor, java.Future, java.concurrent.* are raw (so dumb) structures. Actors, Flux are smarter.
  • DRY
    • Use lombok: @Data @Getter(lombok.AccessLevel.NONE) @Setter(lombok.AccessLevel.NONE)
    • Use short methods
    • Use libraries
  • Defer Execution
    • Prefer smart delayed/lazy/non-strict structures - https://www.scala-lang.org/blog/2017/11/28/view-based-collections.html
      • Supplier, Callable, vavr.Function, Flux, Mono, Iterable
      • vavr: Seq, List, Map - they are immutable data structures that by design are not strict (don't have all the elements computed)
    • Do not use:
      • java.Function - not smart enough - not composable
      • java.Stream - not smart enough, but not strict which is good
    • If is possible do not use:
      • java collections - they are strict structures

Libraries

The absolute needed libraries are:

  • junit5 - testing api
  • slf4j - logging api - Intro to Logging
  • logback - simple logging implementation (robust reporting on bean config and version of the used libraries)
  • guava - google utilities
  • typesafe config - more robust reporting than properties
  • vavr
    • vavr imutable collections over java standard ones
    • vavr Option not standard java Optional
  • reactor-flux
  • java.time

Rules to follow when writing code:

  1. Careful on exception idioms
    • Never swallow an exception. If in doubt rethrow it.
    • principle~Fail Fast
    • A logged exception at info level is always a bug.
    • The exception should give enough details to be able to investigate the problem without debugging. If the investigation lasts more than 30s you have a bug on investigation of the exception.
    • see Checked Exceptions vs Unchecked Exceptions
  2. Beans, Getters and Setters are overhyped
  • Immutable classes (do not confuse with final fields)

Sample refactorings

Huge refactoring. Attention to

  • use slf4j - private final static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DataSupplier.class);
  • never hide exceptions
  • at least log as debug: catch(...){ logger.debug("",ex); }
  • catch(...){ /do nothing/ }
  • never throw CheckedExceptions, catch and throw new RuntimeException(checkedException)
  • logger.info("text",ex) (never do an ex.toString())
  • never use static except for logger
  • never expose internals to others
  • create immutable classes
  • no duplicate code
  • all fields by default private and final
  • no circular dependencies
  • attention to Runnable that can throw exceptions