////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
////

[[development]]
= Development
:doctype: book
:sectnums:
:icons: font

[[methodologyOverview]]
== Methodology overview

The diagram below explains the overall structure of the OptaPlanner source code:

image::development/methodologyOverview.png[align="center"]

In the diagram above, it's important to understand the clear separation between the configuration and runtime classes.

The development philosophy includes:

* **Reuse**: The examples are reused as integration tests, stress tests and demos.
* **Consistent terminology**: Each example has a class `App` (executable class) and `Panel` (swing UI).
* **Consistent structure**: Each example has the same packages: ``domain``, ``persistence``, ``app``, `solver` and ``swingui``.
* **Real world usefulness**: Every feature is used in an example. Most examples are real world use cases with real world constraints, often with real world data.
* **Automated testing**: There are unit tests, integration tests, performance regressions tests and stress tests. The test coverage is high.
* **Fail fast with an understandable error message**: Invalid states are checked as early as possible.


[[developmentGuidelines]]
== Development guidelines

=== Fail fast

There are several levels of fail fast, from better to worse:

. **Fail Fast at compile time**. For example: Don't accept an `Object` as a parameter if it needs to be a `String` or an ``Integer``.
. **Fail Fast at startup time**. For example: if the configuration parameter needs to be a positive `int` and it's negative, fail fast
. **Fail Fast at runtime**. For example: if the request needs to contain a double between `0.0` and `1.0` and it's bigger than ``1.0``, fail fast.
. *Fail Fast at runtime in assertion mode* if the detection performance cost is high. For example: If, after every low level iteration, the variable A needs to be equal to the square root of B, check it if and only if an assert flag is set to true (usually controlled by the xref:planner-configuration/planner-configuration.adoc#environmentMode[EnvironmentMode]).

=== Exception messages

. The `Exception` message must include the name and state of each relevant variable. For example:
+
[source,java,options="nowrap"]
----
if (fooSize < 0) {
    throw new IllegalArgumentException("The fooSize (" + fooSize + ") of bar (" + this + ") must be positive.");
}
----
Notice that the output clearly explains what's wrong:
+
[source,java,options="nowrap"]
----
Exception in thread "main" java.lang.IllegalArgumentException: The fooSize (-5) of bar (myBar) must be positive.
    at ...
----

. Whenever possible, the `Exception` message must include context.

. Whenever the fix is not obvious, the `Exception` message should include advice. Advice normally starts with the word _maybe_ on a new line:
+
[source,java,options="nowrap"]
----
Exception in thread "main" java.lang.IllegalStateException: The valueRangeDescriptor (fooRange) is nullable, but not countable (false).
Maybe the member (getFooRange) should return CountableValueRange.
    at ...
----
+
The word _maybe_ is to indicate that the advice is not guaranteed to be right in all cases.

=== Generics

. The `@PlanningSolution` class is often passed as a generic type parameter to subsystems.
. The `@PlanningEntity` class(es) are rarely passed as a generic type parameter because there could be multiple planning entities.

=== Lifecycle

One of the biggest challenges in multi-algorithm implementations (such as OptaPlanner)
is the lifecycle management of internal subsystems.
These guidelines avoid lifecycle complexity:

. The subsystems are called in the same order in `*Started()` and `*Ended` methods.
.. This avoids cyclic subsystem dependencies.

. The `*Scope` class's fields are filled in piecemeal by the subsystems
as the algorithms discover more information about its current scope subject.
.. Therefore, a `*Scope` has mutable fields. It's not an `Event`.
.. A subsystem can only depend on scope information provided by an earlier subsystem.

. Global variables are sorted:
.. First by volatility
.. Then by initialization time
