Tuesday, September 30, 2014

My Rules for Code Logic Clarity

- All accesses of maps should be in a separate private method describing the outcome. A good example is the isReader() method in the ReadWriteLock class shown here.

Saturday, September 20, 2014

Model Transformations

Building on the last two posts, it occurred to me that much of software development within under OOP is transcribing models between modules. That's why it's crucial to use ModelMapper or Automapper or some form of automation to do the tedious field transcriptions.

But even before the transcription process begins it pays to recognize modeling at the lowest levels for what it is, that it has a source, a destination etc. Understanding the model's context is necessary for building the model effectively, so that it's more descriptive and useful than just a plain old DTO.

Pointers for model (i.e. a class that is a "model") design:
- The insertion of null values (or equivalents such an NA enum value, empty string, etc.) is indicative that either the model was not designed properly or has grown beyond it's original scope due to new requirements. Either way it is a signal the software in question needs re-architecting/refactoring.

Thursday, September 11, 2014

My Simple Rules to Enforce OOP

1. Every new class (whether it's a repository, factory, domain object, or algorithm element) created should be package private by default. The following are exceptions.
  1.1. Classes declared public may be placed in packages named "facade" or "api" so long as they serve as the module's interface.
  1.2. Classes declared public may be placed in packages named 'model.' It's in here where you will put all your interfaces and abstract factories -- implementations of which are in other package private packages and are either injected via DI using Spring (or equivalent) or "exported" via factory methods of corresponding package private source model objects called by and passed on by facade classes.

2. In public methods, never return or accept Java API classes such as Map, Set (generic or not), etc.. Those are too low-level and should be used only within the inner workings of a domain model class. Only return/accept strongly typed domain model objects that you roll yourself.
As for primitives, these should not be passed between objects either. They too should be encapsulated in domain model class instantiations.
  2.1 Exception 1: Interfaces ending in 'Repository' may return collections.
  2.2 Exception 2: Interfaces ending in Value may return primitives But:
    2.2.1 An interfaces ending in Value must be nested within a correspondingly named interface (I.e. same name minus the Value suffix).
  2.3 Exception 3: Getters and Setters of primitives are allowed when required by a framework such as ModelMapper or Drools -- but a JavaDoc comment above each accessor must state the framework and that it is used by that framework exclusively.

3. Rule of thumb for whether 'it' should be a Factory or Repository: Repos (interfaces/classes ending in 'Repo') should return root level model objects (i.e. those not composed of other model objects). Factories should be responsible for constructing and returning model objects that are composed of other model objects.

See also:
on favoring package private classes: http://www.codingthearchitecture.com/2014/06/01/an_architecturally_evident_coding_style.html
'model' packages are like "Stable Abstractions" - see http://www.codemanship.co.uk/parlezuml/metrics/OO%20Design%20Principles%20&%20Metrics.pdf