{"id":"c90065c2-eb97-4228-8439-98d8220add79","shortId":"zQQe7A","kind":"skill","title":"python-architecture","tagline":"Python application architecture with functional core, effectful shell, DDD, and data modeling. Use when designing application layers, separating pure business logic from IO, defining domain models, implementing validation, or structuring bounded contexts.","description":"# Python Application Architecture\n\nModern Python application architecture following functional core / imperative shell pattern, Domain-Driven Design, and type-safe data modeling.\n\n## Core Principle: Functional Core / Imperative Shell\n\nSeparate pure business logic from side effects:\n\n- **Functional Core**: Pure functions, business logic, no IO\n- **Imperative Shell**: Coordinates external dependencies, handles side effects\n\nSee [references/functional-core.md](references/functional-core.md) for detailed patterns and examples.\n\n## Layered Architecture\n\nFollow bottom-up dependency flow:\n\n```\nRouter/Handler → Service → Repository → Entity → Database\n```\n\nEach layer depends only on layers below.\n\n**Responsibilities:**\n- **Entity**: Domain models, validation, business rules, data transformations (fromRequest, toRecord, toResponse)\n- **Repository**: Abstract storage interface, returns domain entities\n- **Service**: Business workflows, orchestrates entities and repositories\n- **Router/Handler**: HTTP handling, delegates to services\n\n## Domain Models\n\n### Entity Example\n\n```python\nfrom dataclasses import dataclass\nfrom uuid import UUID\nfrom decimal import Decimal\n\n@dataclass\nclass Order:\n    \"\"\"Entity - has identity and encapsulated behavior\"\"\"\n    id: UUID\n    customer_id: UUID\n    total: Decimal\n    status: str\n\n    def apply_discount(self, rate: Decimal) -> None:\n        \"\"\"Business rule - encapsulated in entity\"\"\"\n        if self.status == \"pending\":\n            self.total = self.total * (1 - rate)\n\n    @classmethod\n    def from_request(cls, req, customer_id: UUID) -> \"Order\":\n        \"\"\"Transform API request → entity\"\"\"\n        return cls(id=uuid4(), customer_id=customer_id, total=Decimal(\"0\"), status=\"pending\")\n\n    def to_response(self):\n        \"\"\"Transform entity → API response\"\"\"\n        return {\"id\": self.id, \"total\": self.total, \"status\": self.status}\n```\n\n### Value Object Example\n\n```python\nfrom dataclasses import dataclass\n\n@dataclass(frozen=True)\nclass Money:\n    \"\"\"Value object - immutable, no identity\"\"\"\n    amount: Decimal\n    currency: str\n\n    def add(self, other: \"Money\") -> \"Money\":\n        if self.currency != other.currency:\n            raise ValueError(\"Cannot add different currencies\")\n        return Money(self.amount + other.amount, self.currency)\n```\n\nSee [references/ddd.md](references/ddd.md) for aggregates, bounded contexts, and domain services.\n\n## Repository Pattern\n\nAbstract storage behind interface:\n\n```python\nfrom abc import ABC, abstractmethod\nfrom typing import Optional\n\nclass OrderRepository(ABC):\n    \"\"\"Abstract repository - interface only\"\"\"\n\n    @abstractmethod\n    def get(self, order_id: UUID) -> Optional[Order]:\n        pass\n\n    @abstractmethod\n    def save(self, order: Order) -> None:\n        pass\n\nclass PostgresOrderRepository(OrderRepository):\n    \"\"\"Concrete implementation\"\"\"\n\n    def get(self, order_id: UUID) -> Optional[Order]:\n        record = self.session.get(OrderRecord, order_id)\n        return Order.from_record(record) if record else None\n\n    def save(self, order: Order) -> None:\n        record = order.to_record()\n        self.session.merge(record)\n        self.session.commit()\n```\n\n## Data Modeling\n\n- **dataclasses**: Domain models and internal logic (lightweight, standard library)\n- **Pydantic**: API boundaries (validation, JSON schema, OpenAPI)\n- **Entity transformations**: `from_request()`, `to_response()`, `from_record()`, `to_record()`\n\nSee [references/data-modeling.md](references/data-modeling.md) for validation patterns, Pydantic features, and transformation examples.\n\n## Best Practices\n\n1. **Pure functions first** - Write business logic without IO dependencies\n2. **Entity encapsulation** - Keep business rules inside entities\n3. **Repository abstraction** - Hide storage details, work with domain entities\n4. **Validate at boundaries** - Use Pydantic at API edges, simple validation in entities\n5. **Immutable value objects** - Always use `frozen=True`\n6. **Single Responsibility** - Each layer has one reason to change\n7. **Dependency direction** - Always depend on abstractions, not implementations\n\n## Anti-Patterns\n\n❌ **Anemic Domain Model** - Entities with only getters/setters, all logic in services\n❌ **Transaction Script** - All logic in service layer, entities just data\n❌ **Leaky Abstraction** - Repository exposing database details\n❌ **God Object** - Entity with too many responsibilities\n❌ **Mixed Concerns** - Business logic calling IO directly\n\nFor detailed examples, patterns, and decision trees, see the reference materials:\n- [references/functional-core.md](references/functional-core.md) - Core vs shell separation\n- [references/ddd.md](references/ddd.md) - DDD patterns, aggregates, bounded contexts\n- [references/data-modeling.md](references/data-modeling.md) - dataclasses, Pydantic, transformations","tags":["python","architecture","atelier","martinffx","agent-skills","agentic-coding","anthropic","claude-code","claude-skills","code-review","codex","codex-skill"],"capabilities":["skill","source-martinffx","skill-python-architecture","topic-agent-skills","topic-agentic-coding","topic-anthropic","topic-claude-code","topic-claude-skills","topic-code-review","topic-codex","topic-codex-skill","topic-opencode","topic-prompt-engineering","topic-sdd","topic-spec-driven-development"],"categories":["atelier"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/martinffx/atelier/python-architecture","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add martinffx/atelier","source_repo":"https://github.com/martinffx/atelier","install_from":"skills.sh"}},"qualityScore":"0.461","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 23 github stars · SKILL.md body (4,840 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:05:23.127Z","embedding":null,"createdAt":"2026-05-10T07:03:11.974Z","updatedAt":"2026-05-18T19:05:23.127Z","lastSeenAt":"2026-05-18T19:05:23.127Z","tsv":"'0':226 '1':200,416 '2':426 '3':434 '4':444 '5':457 '6':465 '7':475 'abc':304,306,314 'abstract':129,298,315,436,481,509 'abstractmethod':307,319,329 'add':267,278 'aggreg':290,549 'alway':461,478 'amount':262 'anem':487 'anti':485 'anti-pattern':484 'api':213,235,387,451 'appli':184 'applic':5,19,37,41 'architectur':3,6,38,42,97 'behavior':173 'behind':300 'best':414 'bottom':100 'bottom-up':99 'bound':34,291,550 'boundari':388,447 'busi':23,67,76,121,136,190,421,430,523 'call':525 'cannot':277 'chang':474 'class':166,255,312,337 'classmethod':202 'cls':206,217 'concern':522 'concret':340 'context':35,292,551 'coordin':82 'core':9,45,59,62,73,541 'currenc':264,280 'custom':176,208,220,222 'data':14,57,123,375,507 'databas':108,512 'dataclass':154,156,165,249,251,252,377,554 'ddd':12,547 'decim':162,164,180,188,225,263 'decis':533 'def':183,203,229,266,320,330,342,363 'defin':27 'deleg':145 'depend':84,102,111,425,476,479 'design':18,52 'detail':92,439,513,529 'differ':279 'direct':477,527 'discount':185 'domain':28,50,118,133,148,294,378,442,488 'domain-driven':49 'driven':51 'edg':452 'effect':10,71,87 'els':361 'encapsul':172,192,428 'entiti':107,117,134,139,150,168,194,215,234,393,427,433,443,456,490,505,516 'exampl':95,151,246,413,530 'expos':511 'extern':83 'featur':410 'first':419 'flow':103 'follow':43,98 'fromrequest':125 'frozen':253,463 'function':8,44,61,72,75,418 'get':321,343 'getters/setters':493 'god':514 'handl':85,144 'hide':437 'http':143 'id':174,177,209,218,221,223,238,324,346,354 'ident':170,261 'immut':259,458 'imper':46,63,80 'implement':30,341,483 'import':155,159,163,250,305,310 'insid':432 'interfac':131,301,317 'intern':381 'io':26,79,424,526 'json':390 'keep':429 'layer':20,96,110,114,469,504 'leaki':508 'librari':385 'lightweight':383 'logic':24,68,77,382,422,495,501,524 'mani':519 'materi':538 'mix':521 'model':15,29,58,119,149,376,379,489 'modern':39 'money':256,270,271,282 'none':189,335,362,368 'object':245,258,460,515 'one':471 'openapi':392 'option':311,326,348 'orchestr':138 'order':167,211,323,327,333,334,345,349,353,366,367 'order.from':356 'order.to':370 'orderrecord':352 'orderrepositori':313,339 'other.amount':284 'other.currency':274 'pass':328,336 'pattern':48,93,297,408,486,531,548 'pend':197,228 'postgresorderrepositori':338 'practic':415 'principl':60 'pure':22,66,74,417 'pydant':386,409,449,555 'python':2,4,36,40,152,247,302 'python-architectur':1 'rais':275 'rate':187,201 'reason':472 'record':350,357,358,360,369,371,373,400,402 'refer':537 'references/data-modeling.md':404,405,552,553 'references/ddd.md':287,288,545,546 'references/functional-core.md':89,90,539,540 'repositori':106,128,141,296,316,435,510 'req':207 'request':205,214,396 'respons':116,231,236,398,467,520 'return':132,216,237,281,355 'router/handler':104,142 'rule':122,191,431 'safe':56 'save':331,364 'schema':391 'script':499 'see':88,286,403,535 'self':186,232,268,322,332,344,365 'self.amount':283 'self.currency':273,285 'self.id':239 'self.session.commit':374 'self.session.get':351 'self.session.merge':372 'self.status':196,243 'self.total':198,199,241 'separ':21,65,544 'servic':105,135,147,295,497,503 'shell':11,47,64,81,543 'side':70,86 'simpl':453 'singl':466 'skill' 'skill-python-architecture' 'source-martinffx' 'standard':384 'status':181,227,242 'storag':130,299,438 'str':182,265 'structur':33 'topic-agent-skills' 'topic-agentic-coding' 'topic-anthropic' 'topic-claude-code' 'topic-claude-skills' 'topic-code-review' 'topic-codex' 'topic-codex-skill' 'topic-opencode' 'topic-prompt-engineering' 'topic-sdd' 'topic-spec-driven-development' 'torecord':126 'torespons':127 'total':179,224,240 'transact':498 'transform':124,212,233,394,412,556 'tree':534 'true':254,464 'type':55,309 'type-saf':54 'use':16,448,462 'uuid':158,160,175,178,210,325,347 'uuid4':219 'valid':31,120,389,407,445,454 'valu':244,257,459 'valueerror':276 'vs':542 'without':423 'work':440 'workflow':137 'write':420","prices":[{"id":"a3a13125-0e0d-43a6-957b-50f7f1af1929","listingId":"c90065c2-eb97-4228-8439-98d8220add79","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"martinffx","category":"atelier","install_from":"skills.sh"},"createdAt":"2026-05-10T07:03:11.974Z"}],"sources":[{"listingId":"c90065c2-eb97-4228-8439-98d8220add79","source":"github","sourceId":"martinffx/atelier/python-architecture","sourceUrl":"https://github.com/martinffx/atelier/tree/main/skills/python-architecture","isPrimary":false,"firstSeenAt":"2026-05-10T07:03:11.974Z","lastSeenAt":"2026-05-18T19:05:23.127Z"}],"details":{"listingId":"c90065c2-eb97-4228-8439-98d8220add79","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"martinffx","slug":"python-architecture","github":{"repo":"martinffx/atelier","stars":23,"topics":["agent-skills","agentic-coding","anthropic","claude-code","claude-skills","code-review","codex","codex-skill","opencode","prompt-engineering","sdd","spec-driven-development"],"license":"mit","html_url":"https://github.com/martinffx/atelier","pushed_at":"2026-05-18T06:56:45Z","description":"An atelier for Opencode, Claude Code, and other coding agents: spec-driven workflows, deep thinking, and code quality.","skill_md_sha":"720ad1315f872594316b6ab8ab6710da69468091","skill_md_path":"skills/python-architecture/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/martinffx/atelier/tree/main/skills/python-architecture"},"layout":"multi","source":"github","category":"atelier","frontmatter":{"name":"python-architecture","description":"Python application architecture with functional core, effectful shell, DDD, and data modeling. Use when designing application layers, separating pure business logic from IO, defining domain models, implementing validation, or structuring bounded contexts."},"skills_sh_url":"https://skills.sh/martinffx/atelier/python-architecture"},"updatedAt":"2026-05-18T19:05:23.127Z"}}