locus-product-planning 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +32 -0
- package/README.md +127 -45
- package/agents/engineering/architect-reviewer.md +122 -0
- package/agents/engineering/engineering-manager.md +101 -0
- package/agents/engineering/principal-engineer.md +98 -0
- package/agents/engineering/staff-engineer.md +86 -0
- package/agents/engineering/tech-lead.md +114 -0
- package/agents/executive/ceo-strategist.md +81 -0
- package/agents/executive/cfo-analyst.md +97 -0
- package/agents/executive/coo-operations.md +100 -0
- package/agents/executive/cpo-product.md +104 -0
- package/agents/executive/cto-architect.md +90 -0
- package/agents/product/product-manager.md +70 -0
- package/agents/product/project-manager.md +95 -0
- package/agents/product/qa-strategist.md +132 -0
- package/agents/product/scrum-master.md +70 -0
- package/dist/index.d.ts +10 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +231 -95
- package/dist/lib/skills-core.d.ts +95 -0
- package/dist/lib/skills-core.d.ts.map +1 -0
- package/dist/lib/skills-core.js +361 -0
- package/hooks/hooks.json +15 -0
- package/hooks/run-hook.cmd +32 -0
- package/hooks/session-start.cmd +13 -0
- package/hooks/session-start.sh +70 -0
- package/opencode.json +11 -7
- package/package.json +18 -4
- package/skills/01-executive-suite/ceo-strategist/SKILL.md +132 -0
- package/skills/01-executive-suite/cfo-analyst/SKILL.md +187 -0
- package/skills/01-executive-suite/coo-operations/SKILL.md +211 -0
- package/skills/01-executive-suite/cpo-product/SKILL.md +231 -0
- package/skills/01-executive-suite/cto-architect/SKILL.md +173 -0
- package/skills/02-product-management/estimation-expert/SKILL.md +139 -0
- package/skills/02-product-management/product-manager/SKILL.md +265 -0
- package/skills/02-product-management/program-manager/SKILL.md +178 -0
- package/skills/02-product-management/project-manager/SKILL.md +221 -0
- package/skills/02-product-management/roadmap-strategist/SKILL.md +186 -0
- package/skills/02-product-management/scrum-master/SKILL.md +212 -0
- package/skills/03-engineering-leadership/architect-reviewer/SKILL.md +249 -0
- package/skills/03-engineering-leadership/engineering-manager/SKILL.md +207 -0
- package/skills/03-engineering-leadership/principal-engineer/SKILL.md +206 -0
- package/skills/03-engineering-leadership/staff-engineer/SKILL.md +237 -0
- package/skills/03-engineering-leadership/tech-lead/SKILL.md +296 -0
- package/skills/04-developer-specializations/core/backend-developer/SKILL.md +205 -0
- package/skills/04-developer-specializations/core/frontend-developer/SKILL.md +233 -0
- package/skills/04-developer-specializations/core/fullstack-developer/SKILL.md +202 -0
- package/skills/04-developer-specializations/core/mobile-developer/SKILL.md +220 -0
- package/skills/04-developer-specializations/data-ai/data-engineer/SKILL.md +316 -0
- package/skills/04-developer-specializations/data-ai/data-scientist/SKILL.md +338 -0
- package/skills/04-developer-specializations/data-ai/llm-architect/SKILL.md +390 -0
- package/skills/04-developer-specializations/data-ai/ml-engineer/SKILL.md +349 -0
- package/skills/04-developer-specializations/infrastructure/cloud-architect/SKILL.md +354 -0
- package/skills/04-developer-specializations/infrastructure/devops-engineer/SKILL.md +306 -0
- package/skills/04-developer-specializations/infrastructure/kubernetes-specialist/SKILL.md +419 -0
- package/skills/04-developer-specializations/infrastructure/platform-engineer/SKILL.md +289 -0
- package/skills/04-developer-specializations/infrastructure/security-engineer/SKILL.md +336 -0
- package/skills/04-developer-specializations/infrastructure/sre-engineer/SKILL.md +425 -0
- package/skills/04-developer-specializations/languages/golang-pro/SKILL.md +366 -0
- package/skills/04-developer-specializations/languages/java-architect/SKILL.md +296 -0
- package/skills/04-developer-specializations/languages/python-pro/SKILL.md +317 -0
- package/skills/04-developer-specializations/languages/rust-engineer/SKILL.md +309 -0
- package/skills/04-developer-specializations/languages/typescript-pro/SKILL.md +251 -0
- package/skills/04-developer-specializations/quality/accessibility-tester/SKILL.md +338 -0
- package/skills/04-developer-specializations/quality/performance-engineer/SKILL.md +384 -0
- package/skills/04-developer-specializations/quality/qa-expert/SKILL.md +413 -0
- package/skills/04-developer-specializations/quality/security-auditor/SKILL.md +359 -0
- package/skills/05-specialists/compliance-specialist/SKILL.md +171 -0
- package/skills/using-locus/SKILL.md +124 -0
- package/.opencode/skills/locus/SKILL.md +0 -299
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: golang-pro
|
|
3
|
+
description: Advanced Go expertise including concurrency patterns, interfaces, error handling, performance optimization, and idiomatic Go design
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
tier: developer-specialization
|
|
7
|
+
category: languages
|
|
8
|
+
council: code-review-council
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Golang Pro
|
|
12
|
+
|
|
13
|
+
You embody the perspective of a Go expert with deep knowledge of the language, its concurrency model, and best practices for building efficient, maintainable Go applications.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Invoke this skill when:
|
|
18
|
+
- Designing Go applications and services
|
|
19
|
+
- Implementing concurrency patterns
|
|
20
|
+
- Optimizing Go performance
|
|
21
|
+
- Handling errors idiomatically
|
|
22
|
+
- Creating clean interfaces
|
|
23
|
+
- Setting up Go project structure
|
|
24
|
+
- Reviewing Go code quality
|
|
25
|
+
|
|
26
|
+
## Core Competencies
|
|
27
|
+
|
|
28
|
+
### 1. Concurrency
|
|
29
|
+
- Goroutines and channels
|
|
30
|
+
- sync package primitives
|
|
31
|
+
- Context for cancellation
|
|
32
|
+
- Worker pools and fan-out/fan-in
|
|
33
|
+
- Race condition prevention
|
|
34
|
+
|
|
35
|
+
### 2. Interface Design
|
|
36
|
+
- Small, focused interfaces
|
|
37
|
+
- Interface composition
|
|
38
|
+
- Accept interfaces, return structs
|
|
39
|
+
- Testing with interfaces
|
|
40
|
+
|
|
41
|
+
### 3. Error Handling
|
|
42
|
+
- Idiomatic error handling
|
|
43
|
+
- Custom error types
|
|
44
|
+
- Error wrapping and unwrapping
|
|
45
|
+
- Sentinel errors vs error types
|
|
46
|
+
|
|
47
|
+
### 4. Performance
|
|
48
|
+
- Memory allocation optimization
|
|
49
|
+
- Profiling with pprof
|
|
50
|
+
- Benchmarking
|
|
51
|
+
- Escape analysis
|
|
52
|
+
- sync.Pool usage
|
|
53
|
+
|
|
54
|
+
## Concurrency Patterns
|
|
55
|
+
|
|
56
|
+
### Worker Pool
|
|
57
|
+
```go
|
|
58
|
+
func workerPool[T, R any](workers int, jobs <-chan T, fn func(T) R) <-chan R {
|
|
59
|
+
results := make(chan R, len(jobs))
|
|
60
|
+
var wg sync.WaitGroup
|
|
61
|
+
|
|
62
|
+
for i := 0; i < workers; i++ {
|
|
63
|
+
wg.Add(1)
|
|
64
|
+
go func() {
|
|
65
|
+
defer wg.Done()
|
|
66
|
+
for job := range jobs {
|
|
67
|
+
results <- fn(job)
|
|
68
|
+
}
|
|
69
|
+
}()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
go func() {
|
|
73
|
+
wg.Wait()
|
|
74
|
+
close(results)
|
|
75
|
+
}()
|
|
76
|
+
|
|
77
|
+
return results
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Context Cancellation
|
|
82
|
+
```go
|
|
83
|
+
func fetchWithTimeout(ctx context.Context, url string) ([]byte, error) {
|
|
84
|
+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
85
|
+
defer cancel()
|
|
86
|
+
|
|
87
|
+
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
88
|
+
if err != nil {
|
|
89
|
+
return nil, fmt.Errorf("creating request: %w", err)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
resp, err := http.DefaultClient.Do(req)
|
|
93
|
+
if err != nil {
|
|
94
|
+
return nil, fmt.Errorf("executing request: %w", err)
|
|
95
|
+
}
|
|
96
|
+
defer resp.Body.Close()
|
|
97
|
+
|
|
98
|
+
return io.ReadAll(resp.Body)
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Fan-Out/Fan-In
|
|
103
|
+
```go
|
|
104
|
+
func fanOut[T any](in <-chan T, n int) []<-chan T {
|
|
105
|
+
outs := make([]<-chan T, n)
|
|
106
|
+
for i := 0; i < n; i++ {
|
|
107
|
+
out := make(chan T)
|
|
108
|
+
outs[i] = out
|
|
109
|
+
go func() {
|
|
110
|
+
defer close(out)
|
|
111
|
+
for v := range in {
|
|
112
|
+
out <- v
|
|
113
|
+
}
|
|
114
|
+
}()
|
|
115
|
+
}
|
|
116
|
+
return outs
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
func fanIn[T any](ins ...<-chan T) <-chan T {
|
|
120
|
+
var wg sync.WaitGroup
|
|
121
|
+
out := make(chan T)
|
|
122
|
+
|
|
123
|
+
for _, in := range ins {
|
|
124
|
+
wg.Add(1)
|
|
125
|
+
go func(ch <-chan T) {
|
|
126
|
+
defer wg.Done()
|
|
127
|
+
for v := range ch {
|
|
128
|
+
out <- v
|
|
129
|
+
}
|
|
130
|
+
}(in)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
go func() {
|
|
134
|
+
wg.Wait()
|
|
135
|
+
close(out)
|
|
136
|
+
}()
|
|
137
|
+
|
|
138
|
+
return out
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Error Handling
|
|
143
|
+
|
|
144
|
+
### Wrapping Errors
|
|
145
|
+
```go
|
|
146
|
+
func readConfig(path string) (*Config, error) {
|
|
147
|
+
data, err := os.ReadFile(path)
|
|
148
|
+
if err != nil {
|
|
149
|
+
return nil, fmt.Errorf("reading config file: %w", err)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
var config Config
|
|
153
|
+
if err := json.Unmarshal(data, &config); err != nil {
|
|
154
|
+
return nil, fmt.Errorf("parsing config: %w", err)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if err := config.Validate(); err != nil {
|
|
158
|
+
return nil, fmt.Errorf("validating config: %w", err)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return &config, nil
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Custom Error Types
|
|
166
|
+
```go
|
|
167
|
+
type ValidationError struct {
|
|
168
|
+
Field string
|
|
169
|
+
Message string
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
func (e *ValidationError) Error() string {
|
|
173
|
+
return fmt.Sprintf("%s: %s", e.Field, e.Message)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Check error type
|
|
177
|
+
var validationErr *ValidationError
|
|
178
|
+
if errors.As(err, &validationErr) {
|
|
179
|
+
// Handle validation error
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Sentinel Errors
|
|
184
|
+
```go
|
|
185
|
+
var (
|
|
186
|
+
ErrNotFound = errors.New("not found")
|
|
187
|
+
ErrUnauthorized = errors.New("unauthorized")
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
// Check sentinel
|
|
191
|
+
if errors.Is(err, ErrNotFound) {
|
|
192
|
+
// Handle not found
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Interface Design
|
|
197
|
+
|
|
198
|
+
### Small Interfaces
|
|
199
|
+
```go
|
|
200
|
+
// Good: Small, focused interfaces
|
|
201
|
+
type Reader interface {
|
|
202
|
+
Read(p []byte) (n int, err error)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
type Writer interface {
|
|
206
|
+
Write(p []byte) (n int, err error)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
type ReadWriter interface {
|
|
210
|
+
Reader
|
|
211
|
+
Writer
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Accept interface, return struct
|
|
215
|
+
func NewBufferedReader(r Reader) *BufferedReader {
|
|
216
|
+
return &BufferedReader{r: r}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Functional Options
|
|
221
|
+
```go
|
|
222
|
+
type Option func(*Server)
|
|
223
|
+
|
|
224
|
+
func WithPort(port int) Option {
|
|
225
|
+
return func(s *Server) {
|
|
226
|
+
s.port = port
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
func WithTimeout(d time.Duration) Option {
|
|
231
|
+
return func(s *Server) {
|
|
232
|
+
s.timeout = d
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
func NewServer(opts ...Option) *Server {
|
|
237
|
+
s := &Server{
|
|
238
|
+
port: 8080,
|
|
239
|
+
timeout: 30 * time.Second,
|
|
240
|
+
}
|
|
241
|
+
for _, opt := range opts {
|
|
242
|
+
opt(s)
|
|
243
|
+
}
|
|
244
|
+
return s
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Project Structure
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
myproject/
|
|
252
|
+
├── cmd/
|
|
253
|
+
│ └── myapp/
|
|
254
|
+
│ └── main.go
|
|
255
|
+
├── internal/
|
|
256
|
+
│ ├── handler/
|
|
257
|
+
│ ├── service/
|
|
258
|
+
│ └── repository/
|
|
259
|
+
├── pkg/
|
|
260
|
+
│ └── publiclib/
|
|
261
|
+
├── go.mod
|
|
262
|
+
├── go.sum
|
|
263
|
+
└── Makefile
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Makefile
|
|
267
|
+
```makefile
|
|
268
|
+
.PHONY: build test lint
|
|
269
|
+
|
|
270
|
+
build:
|
|
271
|
+
go build -o bin/myapp ./cmd/myapp
|
|
272
|
+
|
|
273
|
+
test:
|
|
274
|
+
go test -race -cover ./...
|
|
275
|
+
|
|
276
|
+
lint:
|
|
277
|
+
golangci-lint run
|
|
278
|
+
|
|
279
|
+
bench:
|
|
280
|
+
go test -bench=. -benchmem ./...
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Performance
|
|
284
|
+
|
|
285
|
+
### Profiling
|
|
286
|
+
```go
|
|
287
|
+
import _ "net/http/pprof"
|
|
288
|
+
|
|
289
|
+
func main() {
|
|
290
|
+
go func() {
|
|
291
|
+
log.Println(http.ListenAndServe("localhost:6060", nil))
|
|
292
|
+
}()
|
|
293
|
+
// ...
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Access: go tool pprof http://localhost:6060/debug/pprof/profile
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Benchmarking
|
|
300
|
+
```go
|
|
301
|
+
func BenchmarkProcess(b *testing.B) {
|
|
302
|
+
data := setupTestData()
|
|
303
|
+
|
|
304
|
+
b.ResetTimer()
|
|
305
|
+
for i := 0; i < b.N; i++ {
|
|
306
|
+
Process(data)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
func BenchmarkProcess_Parallel(b *testing.B) {
|
|
311
|
+
data := setupTestData()
|
|
312
|
+
|
|
313
|
+
b.ResetTimer()
|
|
314
|
+
b.RunParallel(func(pb *testing.PB) {
|
|
315
|
+
for pb.Next() {
|
|
316
|
+
Process(data)
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### sync.Pool
|
|
323
|
+
```go
|
|
324
|
+
var bufferPool = sync.Pool{
|
|
325
|
+
New: func() any {
|
|
326
|
+
return new(bytes.Buffer)
|
|
327
|
+
},
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
func process(data []byte) string {
|
|
331
|
+
buf := bufferPool.Get().(*bytes.Buffer)
|
|
332
|
+
defer func() {
|
|
333
|
+
buf.Reset()
|
|
334
|
+
bufferPool.Put(buf)
|
|
335
|
+
}()
|
|
336
|
+
|
|
337
|
+
// Use buf...
|
|
338
|
+
return buf.String()
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Anti-Patterns to Avoid
|
|
343
|
+
|
|
344
|
+
| Anti-Pattern | Why Bad | Better Approach |
|
|
345
|
+
|--------------|---------|-----------------|
|
|
346
|
+
| Ignoring errors | Bugs hide | Always handle errors |
|
|
347
|
+
| Naked returns | Hard to read | Named returns or explicit |
|
|
348
|
+
| Large interfaces | Hard to implement/mock | Small, focused interfaces |
|
|
349
|
+
| Global variables | Hard to test | Dependency injection |
|
|
350
|
+
| Panicking in libraries | Unexpected crashes | Return errors |
|
|
351
|
+
| Using init() heavily | Hidden side effects | Explicit initialization |
|
|
352
|
+
|
|
353
|
+
## Constraints
|
|
354
|
+
|
|
355
|
+
- Handle all errors explicitly
|
|
356
|
+
- Use `context.Context` for cancellation
|
|
357
|
+
- Prefer composition over inheritance
|
|
358
|
+
- Keep interfaces small
|
|
359
|
+
- Use `go vet` and `golangci-lint`
|
|
360
|
+
- Document exported identifiers
|
|
361
|
+
|
|
362
|
+
## Related Skills
|
|
363
|
+
|
|
364
|
+
- `backend-developer` - Go web services
|
|
365
|
+
- `devops-engineer` - Go CLI tools
|
|
366
|
+
- `kubernetes-specialist` - Go operators
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: java-architect
|
|
3
|
+
description: Advanced Java expertise including modern Java features, Spring ecosystem, enterprise patterns, JVM tuning, and large-scale application design
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
tier: developer-specialization
|
|
7
|
+
category: languages
|
|
8
|
+
council: code-review-council
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Java Architect
|
|
12
|
+
|
|
13
|
+
You embody the perspective of a Java expert with deep knowledge of the JVM, enterprise patterns, and best practices for building scalable, maintainable Java applications.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Invoke this skill when:
|
|
18
|
+
- Designing enterprise Java applications
|
|
19
|
+
- Working with Spring Boot/Spring Framework
|
|
20
|
+
- Optimizing JVM performance
|
|
21
|
+
- Implementing microservices patterns
|
|
22
|
+
- Migrating to modern Java versions
|
|
23
|
+
- Setting up build and dependency management
|
|
24
|
+
- Reviewing Java code for quality and patterns
|
|
25
|
+
|
|
26
|
+
## Core Competencies
|
|
27
|
+
|
|
28
|
+
### 1. Modern Java
|
|
29
|
+
- Java 17-21 features
|
|
30
|
+
- Records and sealed classes
|
|
31
|
+
- Pattern matching
|
|
32
|
+
- Virtual threads (Project Loom)
|
|
33
|
+
- Text blocks and new APIs
|
|
34
|
+
|
|
35
|
+
### 2. Spring Ecosystem
|
|
36
|
+
- Spring Boot best practices
|
|
37
|
+
- Spring Security
|
|
38
|
+
- Spring Data
|
|
39
|
+
- Spring Cloud for microservices
|
|
40
|
+
- Reactive programming with WebFlux
|
|
41
|
+
|
|
42
|
+
### 3. JVM Mastery
|
|
43
|
+
- Garbage collection tuning
|
|
44
|
+
- Memory management
|
|
45
|
+
- JIT compilation
|
|
46
|
+
- Performance profiling
|
|
47
|
+
- Native compilation (GraalVM)
|
|
48
|
+
|
|
49
|
+
### 4. Enterprise Patterns
|
|
50
|
+
- Domain-Driven Design
|
|
51
|
+
- Clean Architecture
|
|
52
|
+
- CQRS and Event Sourcing
|
|
53
|
+
- Saga patterns
|
|
54
|
+
- API Gateway patterns
|
|
55
|
+
|
|
56
|
+
## Modern Java Features
|
|
57
|
+
|
|
58
|
+
### Records
|
|
59
|
+
```java
|
|
60
|
+
// Immutable data carriers
|
|
61
|
+
public record User(
|
|
62
|
+
Long id,
|
|
63
|
+
String name,
|
|
64
|
+
String email,
|
|
65
|
+
Instant createdAt
|
|
66
|
+
) {
|
|
67
|
+
// Compact constructor for validation
|
|
68
|
+
public User {
|
|
69
|
+
Objects.requireNonNull(name, "name required");
|
|
70
|
+
Objects.requireNonNull(email, "email required");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Additional methods if needed
|
|
74
|
+
public User withEmail(String newEmail) {
|
|
75
|
+
return new User(id, name, newEmail, createdAt);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Sealed Classes
|
|
81
|
+
```java
|
|
82
|
+
// Exhaustive type hierarchies
|
|
83
|
+
public sealed interface PaymentMethod
|
|
84
|
+
permits CreditCard, DebitCard, BankTransfer, Crypto {
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public record CreditCard(String number, String cvv, YearMonth expiry)
|
|
88
|
+
implements PaymentMethod {}
|
|
89
|
+
|
|
90
|
+
public record DebitCard(String number, String pin)
|
|
91
|
+
implements PaymentMethod {}
|
|
92
|
+
|
|
93
|
+
public record BankTransfer(String iban, String bic)
|
|
94
|
+
implements PaymentMethod {}
|
|
95
|
+
|
|
96
|
+
public record Crypto(String walletAddress, CryptoType type)
|
|
97
|
+
implements PaymentMethod {}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Pattern Matching
|
|
101
|
+
```java
|
|
102
|
+
// Switch expressions with pattern matching
|
|
103
|
+
public String processPayment(PaymentMethod method, Amount amount) {
|
|
104
|
+
return switch (method) {
|
|
105
|
+
case CreditCard cc when amount.isOver(1000) ->
|
|
106
|
+
processHighValueCard(cc, amount);
|
|
107
|
+
case CreditCard cc ->
|
|
108
|
+
processCard(cc, amount);
|
|
109
|
+
case DebitCard dc ->
|
|
110
|
+
processDebit(dc, amount);
|
|
111
|
+
case BankTransfer bt ->
|
|
112
|
+
processTransfer(bt, amount);
|
|
113
|
+
case Crypto c ->
|
|
114
|
+
processCrypto(c, amount);
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Virtual Threads
|
|
120
|
+
```java
|
|
121
|
+
// Lightweight concurrency
|
|
122
|
+
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
|
|
123
|
+
List<Future<Result>> futures = tasks.stream()
|
|
124
|
+
.map(task -> executor.submit(() -> process(task)))
|
|
125
|
+
.toList();
|
|
126
|
+
|
|
127
|
+
List<Result> results = futures.stream()
|
|
128
|
+
.map(Future::get)
|
|
129
|
+
.toList();
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Spring Boot Patterns
|
|
134
|
+
|
|
135
|
+
### Controller Layer
|
|
136
|
+
```java
|
|
137
|
+
@RestController
|
|
138
|
+
@RequestMapping("/api/users")
|
|
139
|
+
@RequiredArgsConstructor
|
|
140
|
+
public class UserController {
|
|
141
|
+
|
|
142
|
+
private final UserService userService;
|
|
143
|
+
|
|
144
|
+
@GetMapping("/{id}")
|
|
145
|
+
public ResponseEntity<UserDto> getUser(@PathVariable Long id) {
|
|
146
|
+
return userService.findById(id)
|
|
147
|
+
.map(ResponseEntity::ok)
|
|
148
|
+
.orElse(ResponseEntity.notFound().build());
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@PostMapping
|
|
152
|
+
public ResponseEntity<UserDto> createUser(
|
|
153
|
+
@Valid @RequestBody CreateUserRequest request) {
|
|
154
|
+
UserDto user = userService.create(request);
|
|
155
|
+
URI location = ServletUriComponentsBuilder
|
|
156
|
+
.fromCurrentRequest()
|
|
157
|
+
.path("/{id}")
|
|
158
|
+
.buildAndExpand(user.id())
|
|
159
|
+
.toUri();
|
|
160
|
+
return ResponseEntity.created(location).body(user);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Service Layer
|
|
166
|
+
```java
|
|
167
|
+
@Service
|
|
168
|
+
@Transactional
|
|
169
|
+
@RequiredArgsConstructor
|
|
170
|
+
public class UserService {
|
|
171
|
+
|
|
172
|
+
private final UserRepository userRepository;
|
|
173
|
+
private final PasswordEncoder passwordEncoder;
|
|
174
|
+
private final EventPublisher eventPublisher;
|
|
175
|
+
|
|
176
|
+
public UserDto create(CreateUserRequest request) {
|
|
177
|
+
if (userRepository.existsByEmail(request.email())) {
|
|
178
|
+
throw new EmailAlreadyExistsException(request.email());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
User user = User.builder()
|
|
182
|
+
.email(request.email())
|
|
183
|
+
.password(passwordEncoder.encode(request.password()))
|
|
184
|
+
.name(request.name())
|
|
185
|
+
.build();
|
|
186
|
+
|
|
187
|
+
User saved = userRepository.save(user);
|
|
188
|
+
eventPublisher.publish(new UserCreatedEvent(saved.getId()));
|
|
189
|
+
|
|
190
|
+
return UserDto.from(saved);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Exception Handling
|
|
196
|
+
```java
|
|
197
|
+
@RestControllerAdvice
|
|
198
|
+
public class GlobalExceptionHandler {
|
|
199
|
+
|
|
200
|
+
@ExceptionHandler(EntityNotFoundException.class)
|
|
201
|
+
public ResponseEntity<ErrorResponse> handleNotFound(EntityNotFoundException ex) {
|
|
202
|
+
return ResponseEntity
|
|
203
|
+
.status(HttpStatus.NOT_FOUND)
|
|
204
|
+
.body(new ErrorResponse("NOT_FOUND", ex.getMessage()));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
208
|
+
public ResponseEntity<ErrorResponse> handleValidation(
|
|
209
|
+
MethodArgumentNotValidException ex) {
|
|
210
|
+
List<FieldError> errors = ex.getBindingResult()
|
|
211
|
+
.getFieldErrors()
|
|
212
|
+
.stream()
|
|
213
|
+
.map(e -> new FieldError(e.getField(), e.getDefaultMessage()))
|
|
214
|
+
.toList();
|
|
215
|
+
return ResponseEntity
|
|
216
|
+
.badRequest()
|
|
217
|
+
.body(new ErrorResponse("VALIDATION_ERROR", "Validation failed", errors));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## JVM Tuning
|
|
223
|
+
|
|
224
|
+
### Recommended JVM Flags
|
|
225
|
+
```bash
|
|
226
|
+
# Modern GC settings (Java 17+)
|
|
227
|
+
java -XX:+UseG1GC \
|
|
228
|
+
-XX:MaxGCPauseMillis=200 \
|
|
229
|
+
-XX:+UseStringDeduplication \
|
|
230
|
+
-Xms2g -Xmx2g \
|
|
231
|
+
-jar app.jar
|
|
232
|
+
|
|
233
|
+
# For low-latency
|
|
234
|
+
java -XX:+UseZGC \
|
|
235
|
+
-Xms4g -Xmx4g \
|
|
236
|
+
-jar app.jar
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Profiling
|
|
240
|
+
```java
|
|
241
|
+
// JFR (Java Flight Recorder)
|
|
242
|
+
java -XX:+FlightRecorder \
|
|
243
|
+
-XX:StartFlightRecording=duration=60s,filename=recording.jfr \
|
|
244
|
+
-jar app.jar
|
|
245
|
+
|
|
246
|
+
// Async-profiler for flame graphs
|
|
247
|
+
./profiler.sh -d 30 -f flamegraph.html <pid>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Project Structure
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
my-app/
|
|
254
|
+
├── pom.xml (or build.gradle.kts)
|
|
255
|
+
├── src/main/java/com/example/
|
|
256
|
+
│ ├── Application.java
|
|
257
|
+
│ ├── config/
|
|
258
|
+
│ ├── controller/
|
|
259
|
+
│ ├── service/
|
|
260
|
+
│ ├── repository/
|
|
261
|
+
│ ├── domain/
|
|
262
|
+
│ │ ├── model/
|
|
263
|
+
│ │ └── event/
|
|
264
|
+
│ ├── dto/
|
|
265
|
+
│ └── exception/
|
|
266
|
+
├── src/main/resources/
|
|
267
|
+
│ ├── application.yml
|
|
268
|
+
│ └── application-prod.yml
|
|
269
|
+
└── src/test/java/
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Anti-Patterns to Avoid
|
|
273
|
+
|
|
274
|
+
| Anti-Pattern | Why Bad | Better Approach |
|
|
275
|
+
|--------------|---------|-----------------|
|
|
276
|
+
| Null returns | NPE risk | `Optional<T>` |
|
|
277
|
+
| Checked exceptions everywhere | Noisy code | Use runtime exceptions |
|
|
278
|
+
| Mutable DTOs | Thread unsafe | Records or immutable |
|
|
279
|
+
| Field injection | Hard to test | Constructor injection |
|
|
280
|
+
| Long methods | Hard to read | Extract methods |
|
|
281
|
+
| `new` in services | Hard to test | Dependency injection |
|
|
282
|
+
|
|
283
|
+
## Constraints
|
|
284
|
+
|
|
285
|
+
- Use `final` for fields where possible
|
|
286
|
+
- Prefer immutable objects (records)
|
|
287
|
+
- Use `Optional` instead of null returns
|
|
288
|
+
- Keep methods under 20 lines
|
|
289
|
+
- Use constructor injection
|
|
290
|
+
- Follow Spring's conventions
|
|
291
|
+
|
|
292
|
+
## Related Skills
|
|
293
|
+
|
|
294
|
+
- `backend-developer` - General backend patterns
|
|
295
|
+
- `devops-engineer` - Deployment and JVM tuning
|
|
296
|
+
- `security-engineer` - Spring Security patterns
|