##// END OF EJS Templates
WIP Variants model
cin -
r39:fdd8b56c7024 default
parent child
Show More
@@ -3,6 +3,7
3 3 "java.compile.nullAnalysis.mode": "automatic",
4 4 "cSpell.words": [
5 5 "implab",
6 "materializer",
6 7 "rawtypes"
7 8 ]
8 9 } No newline at end of file
@@ -10,3 +10,33
10 10 - `find*` рассматривается как синоним legacy `get*` (поиск без `fail-fast`).
11 11 - `require*` это `find*` + `fail-fast` с понятной ошибкой в месте вызова.
12 12 - Для нового API предпочтительны формы `find/require`; новые `get*` по возможности не добавлять.
13
14 ## Identity-first modeling
15
16 Prefer an **identity-first** split between:
17
18 - **identity objects** used for discovery and selection
19 - **stateful/materialized objects** obtained through separate API calls
20
21 ### Rules
22
23 - Objects intended for replayable observation (`all(...)`, similar collection APIs) should be **identity objects**.
24 - Identity objects must be:
25 - cheap to create
26 - effectively immutable
27 - limited to identity and cheap selection metadata
28 - Heavy, computed, provider-based, or runtime-bound state must be resolved separately.
29 - Aggregate content should be accessed through dedicated lookup/materialization APIs.
30 - Eager observation of identity is acceptable.
31 - Eager observation of computed state is not.
32
33 ### Do not
34
35 - Do not store heavy computed state inside identity objects.
36 - Do not store runtime references to foreign domains inside identity objects.
37 - Do not use custom events when replayable identity registries plus on-demand lookup are sufficient.
38
39 ### Rule of thumb
40
41 **Identity objects contain selection metadata.
42 Aggregate content is obtained separately, on demand.**
@@ -5,6 +5,7 import java.util.function.Supplier;
5 5
6 6 public class LazyValue<T> implements Supplier<T> {
7 7 private volatile T value;
8 private volatile boolean initialized = false;
8 9
9 10 private final Supplier<T> innerSupplier;
10 11
@@ -15,7 +16,7 public class LazyValue<T> implements Sup
15 16 @Override
16 17 public T get() {
17 18 var v = value;
18 if (v != null) {
19 if (initialized) {
19 20 return v;
20 21 }
21 22
@@ -50,6 +50,11 public class Strings {
50 50 throw new IllegalArgumentException(String.format("Argument %s can't be null or blank", argumentName));
51 51 }
52 52
53 public static String requireNonBlank(String value) {
54 argumentNotNullOrBlank(value, "value");
55 return value;
56 }
57
53 58 public static String sanitizeName(String value) {
54 59 return INVALID_NAME_CHAR.matcher(value).replaceAll("_");
55 60 }
@@ -7,11 +7,9 import org.implab.gradle.variants.model.
7 7 public abstract class VariantsPlugin implements Plugin<Project> {
8 8 @Override
9 9 public void apply(Project target) {
10 var extension = target.getExtensions().create("variants", VariantsExtension.class);
11 10
12 target.afterEvaluate(project -> {
13
14 });
11 target.getExtensions().create("variants", VariantsExtension.class);
15 12
16 13 }
14
17 15 }
@@ -1,35 +1,8
1 1 package org.implab.gradle.variants.model;
2 2
3 import org.gradle.api.Named;
4 import org.gradle.api.provider.SetProperty;
5
6 /**
7 * Binds a role to a set of layers inside a particular variant.
3 /** A binding between a role and a layer inside a specific variant.
8 4 *
9 * The binding name is the role name, e.g. "production", "test", "tool".
10 */
11 public interface RoleBinding extends Named {
12
13 /**
14 * Layer names participating in this (variant, role) selection.
15 *
16 * Core model keeps names here deliberately:
17 * source/materialization semantics live elsewhere.
5 * @see {@link VariantDefinition} for the context of this binding.
18 6 */
19 SetProperty<String> getLayerNames();
20
21 /**
22 * Adds one layer to this binding.
23 */
24 void layer(String name);
25
26 /**
27 * Adds several layers to this binding.
28 */
29 void layers(String... names);
30
31 /**
32 * Adds several layers to this binding.
33 */
34 void layers(Iterable<String> names);
7 public record RoleLayerBinding(String name, String layerName) {
35 8 } No newline at end of file
@@ -1,11 +1,6
1 1 package org.implab.gradle.variants.model;
2 2
3 import org.gradle.api.Action;
4 3 import org.gradle.api.Named;
5 import org.gradle.api.NamedDomainObjectContainer;
6 import org.implab.gradle.common.core.lang.Closures;
7
8 import groovy.lang.Closure;
9 4
10 5 /**
11 6 * A named variant, e.g. "browser", "electron".
@@ -14,31 +9,4 import groovy.lang.Closure;
14 9 * It owns a set of role bindings.
15 10 */
16 11 public interface Variant extends Named {
17
18 /**
19 * Role bindings declared inside this variant.
20 *
21 * The binding name is the role name.
22 */
23 NamedDomainObjectContainer<RoleBinding> getRoleBindings();
24
25 /**
26 * Creates or returns an existing role binding and configures it.
27 */
28 default RoleBinding role(String name) {
29 return getRoleBindings().maybeCreate(name);
30 }
31
32 /**
33 * Creates or returns an existing role binding and configures it.
34 */
35 default RoleBinding role(String name, Action<? super RoleBinding> action) {
36 var role = role(name);
37 action.execute(role);
38 return role;
39 }
40
41 default RoleBinding role(String name, Closure<?> closure) {
42 return role(name, Closures.action(closure));
43 }
44 12 } No newline at end of file
@@ -33,27 +33,33 public interface VariantsExtension {
33 33 NamedDomainObjectContainer<Role> getRoles();
34 34
35 35 /**
36 * Domain of variants.
37 */
38 NamedDomainObjectContainer<Variant> getVariants();
39
40 /**
36 41 * Declared variants.
37 42 */
38 NamedDomainObjectContainer<Variant> getVariantDefinitions();
43 NamedDomainObjectContainer<VariantDefinition> getVariantDefinitions();
39 44
40 45 /**
41 46 * Creates or returns an existing variant and configures it.
42 47 */
43 default Variant variant(String name) {
48 default VariantDefinition variant(String name) {
49
44 50 return getVariantDefinitions().maybeCreate(name);
45 51 }
46 52
47 53 /**
48 54 * Creates or returns an existing variant and configures it.
49 55 */
50 default Variant variant(String name, Action<? super Variant> action) {
56 default VariantDefinition variant(String name, Action<? super VariantDefinition> action) {
51 57 var variant = variant(name);
52 58 action.execute(variant);
53 59 return variant;
54 60 }
55 61
56 default Variant variant(String name, Closure<?> closure) {
62 default VariantDefinition variant(String name, Closure<?> closure) {
57 63 return variant(name, Closures.action(closure));
58 64 }
59 65 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now