##// END OF EJS Templates
WIP Variants model
cin -
r39:fdd8b56c7024 default
parent child
Show More
@@ -3,6 +3,7
3 "java.compile.nullAnalysis.mode": "automatic",
3 "java.compile.nullAnalysis.mode": "automatic",
4 "cSpell.words": [
4 "cSpell.words": [
5 "implab",
5 "implab",
6 "materializer",
6 "rawtypes"
7 "rawtypes"
7 ]
8 ]
8 } No newline at end of file
9 }
@@ -10,3 +10,33
10 - `find*` рассматриваСтся ΠΊΠ°ΠΊ синоним legacy `get*` (поиск Π±Π΅Π· `fail-fast`).
10 - `find*` рассматриваСтся ΠΊΠ°ΠΊ синоним legacy `get*` (поиск Π±Π΅Π· `fail-fast`).
11 - `require*` это `find*` + `fail-fast` с понятной ошибкой Π² мСстС Π²Ρ‹Π·ΠΎΠ²Π°.
11 - `require*` это `find*` + `fail-fast` с понятной ошибкой Π² мСстС Π²Ρ‹Π·ΠΎΠ²Π°.
12 - Для Π½ΠΎΠ²ΠΎΠ³ΠΎ API ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ Ρ„ΠΎΡ€ΠΌΡ‹ `find/require`; Π½ΠΎΠ²Ρ‹Π΅ `get*` ΠΏΠΎ возмоТности Π½Π΅ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ.
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 public class LazyValue<T> implements Supplier<T> {
6 public class LazyValue<T> implements Supplier<T> {
7 private volatile T value;
7 private volatile T value;
8 private volatile boolean initialized = false;
8
9
9 private final Supplier<T> innerSupplier;
10 private final Supplier<T> innerSupplier;
10
11
@@ -15,7 +16,7 public class LazyValue<T> implements Sup
15 @Override
16 @Override
16 public T get() {
17 public T get() {
17 var v = value;
18 var v = value;
18 if (v != null) {
19 if (initialized) {
19 return v;
20 return v;
20 }
21 }
21
22
@@ -50,6 +50,11 public class Strings {
50 throw new IllegalArgumentException(String.format("Argument %s can't be null or blank", argumentName));
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 public static String sanitizeName(String value) {
58 public static String sanitizeName(String value) {
54 return INVALID_NAME_CHAR.matcher(value).replaceAll("_");
59 return INVALID_NAME_CHAR.matcher(value).replaceAll("_");
55 }
60 }
@@ -7,11 +7,9 import org.implab.gradle.variants.model.
7 public abstract class VariantsPlugin implements Plugin<Project> {
7 public abstract class VariantsPlugin implements Plugin<Project> {
8 @Override
8 @Override
9 public void apply(Project target) {
9 public void apply(Project target) {
10 var extension = target.getExtensions().create("variants", VariantsExtension.class);
11
10
12 target.afterEvaluate(project -> {
11 target.getExtensions().create("variants", VariantsExtension.class);
13
14 });
15
12
16 }
13 }
14
17 }
15 }
@@ -1,35 +1,8
1 package org.implab.gradle.variants.model;
1 package org.implab.gradle.variants.model;
2
2
3 import org.gradle.api.Named;
3 /** A binding between a role and a layer inside a specific variant.
4 import org.gradle.api.provider.SetProperty;
5
6 /**
7 * Binds a role to a set of layers inside a particular variant.
8 *
4 *
9 * The binding name is the role name, e.g. "production", "test", "tool".
5 * @see {@link VariantDefinition} for the context of this binding.
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.
18 */
6 */
19 SetProperty<String> getLayerNames();
7 public record RoleLayerBinding(String name, String layerName) {
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);
35 } No newline at end of file
8 }
@@ -1,11 +1,6
1 package org.implab.gradle.variants.model;
1 package org.implab.gradle.variants.model;
2
2
3 import org.gradle.api.Action;
4 import org.gradle.api.Named;
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 * A named variant, e.g. "browser", "electron".
6 * A named variant, e.g. "browser", "electron".
@@ -14,31 +9,4 import groovy.lang.Closure;
14 * It owns a set of role bindings.
9 * It owns a set of role bindings.
15 */
10 */
16 public interface Variant extends Named {
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 } No newline at end of file
12 }
@@ -33,27 +33,33 public interface VariantsExtension {
33 NamedDomainObjectContainer<Role> getRoles();
33 NamedDomainObjectContainer<Role> getRoles();
34
34
35 /**
35 /**
36 * Domain of variants.
37 */
38 NamedDomainObjectContainer<Variant> getVariants();
39
40 /**
36 * Declared variants.
41 * Declared variants.
37 */
42 */
38 NamedDomainObjectContainer<Variant> getVariantDefinitions();
43 NamedDomainObjectContainer<VariantDefinition> getVariantDefinitions();
39
44
40 /**
45 /**
41 * Creates or returns an existing variant and configures it.
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 return getVariantDefinitions().maybeCreate(name);
50 return getVariantDefinitions().maybeCreate(name);
45 }
51 }
46
52
47 /**
53 /**
48 * Creates or returns an existing variant and configures it.
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 var variant = variant(name);
57 var variant = variant(name);
52 action.execute(variant);
58 action.execute(variant);
53 return variant;
59 return variant;
54 }
60 }
55
61
56 default Variant variant(String name, Closure<?> closure) {
62 default VariantDefinition variant(String name, Closure<?> closure) {
57 return variant(name, Closures.action(closure));
63 return variant(name, Closures.action(closure));
58 }
64 }
59 } No newline at end of file
65 }
General Comments 0
You need to be logged in to leave comments. Login now