Skip to content

Commit 476c167

Browse files
committed
Add composable systems!
1 parent 4cf6c74 commit 476c167

File tree

11 files changed

+140
-0
lines changed

11 files changed

+140
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
defmodule ComponentsGuideWeb.ComposableSystemsController do
2+
use ComponentsGuideWeb, :controller
3+
require Logger
4+
5+
def index(conn, _params) do
6+
render(conn, "index.html", article: "intro")
7+
end
8+
9+
@articles ["opinionated-vs-flexible"]
10+
11+
def show(conn, %{"id" => article}) when article in @articles do
12+
render(conn, "index.html", article: article)
13+
end
14+
15+
def show(conn, _params) do
16+
raise Phoenix.Router.NoRouteError, conn: conn, router: ComponentsGuideWeb.Router
17+
end
18+
end

apps/components_guide_web/lib/components_guide_web/router.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ defmodule ComponentsGuideWeb.Router do
2929
AccessibilityFirstController,
3030
only: [:index, :show]
3131

32+
resources "/composable-systems",
33+
ComposableSystemsController,
34+
only: [:index, :show]
35+
3236
live "/color", ColorLive, :index
3337
live "/color/:definition", ColorLive, :show
3438
live "/color/lab/:definition", ColorLive, :lab
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<header class="text-white text-shadow" style="<%= header_styles() %>">
2+
<%= render ComponentsGuideWeb.ComposableSystemsView, "_top.html" %>
3+
</header>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<nav class="pt-6 pb-4">
2+
<ul y-y x-x=md class="text-lg font-bold" style="--link-padding: 0.75em">
3+
<li><%= link("Why?", to: '/composable-systems') %>
4+
<li><%= link("Opinionated vs Flexible", to: '/composable-systems/opinionated-vs-flexible') %>
5+
<li><%= link("Single Responsibility", to: '/composable-systems/roles') %>
6+
<li><%= link("Deterministic", to: '/composable-systems/roles') %>
7+
</ul>
8+
</nav>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<div class="mx-auto max-w-4xl">
2+
<h1 y-y x-x=md class="pt-8 row space-x-4 text-4xl text-center font-bold leading-tight">
3+
<span class="mr-2 text-4xl">🖇🍀</span>
4+
<span><%= "Composable Systems" %></span>
5+
</h1>
6+
<%= render ComponentsGuideWeb.ComposableSystemsView, "_nav.html" %>
7+
</div>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<%= render @view_module, "_header.html" %>
2+
3+
<article>
4+
<div class="text-white bg-gray-900">
5+
<div class="content max-w-4xl mx-auto py-8 text-xl">
6+
<%= render(@view_module, @article <> ".html", conn: @conn) %>
7+
</div>
8+
</div>
9+
</article>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Why Think in Composable Systems?
2+
3+
- Less to explain at once
4+
- Reuse more
5+
- Composable encourages simplicity
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Opinionated vs Flexible
2+
3+
If something is opinionated and well-designed, then it guides the user on a clear path to success. The system should inform the user as they build.
4+
5+
If something is flexible, then it allows the users to do what they like. They are not blocked from achieving essential results.
6+
7+
SwiftUI is an example of a system that is very flexible. Modifiers can be added to *any* element. Animation can be used to enhance property changes into transitions. However, it’s not flexible to the point that it’s hard to make something that looks and acts like an app. It provides opinions: system controls that adapt to the platform, the reactive Combine library, recommended font sizes that adjust to the user’s preference with Dynamic Type, just to name a few examples.
8+
9+
## Too flexible
10+
11+
If something is *too* flexible, it’s harder to learn. There’s a lot more cognitive load. It can be hard to form a picture in the mind of how it works. There could be multiple ways of making the same thing, and it could be unclear of which one is best.
12+
13+
Flexibility often begets changes to allow more flexibility. A little bit of flexibility gives way to even more, and soon the system is large enough that it’s difficult to understand.
14+
15+
Redux is an example of something that is extremely flexible. The functional style of the reducers allured to simplicity, but the rest of the system leaves a lot of questions unanswered. “Do I put this sort of code in the action or the connected component? Do I pass this state when the action is dispatched, or do I read from the store in my action? What sort of state do I store in a reducer: transient local, remote cache, local state to be sent to the remote?”
16+
17+
## Too opinionated
18+
19+
Opinionated without explanation produces confusion and frustration.
20+
21+
Too opinionated leads to an awkward or limited solution being provided when there’s an obvious, better suited approach just out of reach.
22+
23+
Too opinionated means *hacks* are needed to get the system to work as desired. Hacks often lead to bugs, or make things hard to change in the future.
24+
25+
Poorly opinionated mean that the language of the system doesn’t work well with the language of the constructors.
26+
27+
## Flexible enough
28+
29+
Enough flexibility should allow the user to achieve what they want without being overwhelmed. They shouldn’t need to resort to hacks to get something working.
30+
31+
Progressive disclosure can allow a system to provide a small surface area to get started with successfully, and then has extra discoverable aspects that allow more nuanced and specific behaviour.
32+
33+
## Opinionated enough
34+
35+
Enough opinions should be provided so that the team of constructors is able to be aligned with the manufacturers. What they make should be consistent. They should be lead into the pit of success.
36+
37+
Two people given the same problem using your system should ideally come up with similar solutions. If their solutions are completely different, then there’s a communication or flexibility or other problem with your system. A solid start to an idea should be gleamed when reading the documentation for your system.
38+
39+
Hard common problems should either be answered with a clear and convincing solution, or explicitly be highlighted as being left to the team to come up with their own solution (likely using a flexible system).

apps/components_guide_web/lib/components_guide_web/templates/landing/index.html.eex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ subhead = "Guides to accessibility, TDD, BDD, naming, performance, and the lates
5353
<%= render ComponentsGuideWeb.AccessibilityFirstView, "_top.html" %>
5454
</article>
5555

56+
<article class="text-white text-shadow py-6" style="<%= sections_styles(:orange) %>">
57+
<%= render ComponentsGuideWeb.ComposableSystemsView, "_top.html" %>
58+
</article>
59+
5660
<div hidden class="text-white">
5761
<section class="pt-20 pb-20" style="<%= sections_styles(:dark) %>">
5862
<header class="mb-8 mx-auto max-w-4xl px-2 text-center">
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
defmodule ComponentsGuideWeb.ComposableSystemsView do
2+
use ComponentsGuideWeb, :view
3+
require EEx
4+
5+
def header_styles() do
6+
l = 62
7+
a = 51
8+
b = 24
9+
10+
color = {:lab, l, a, b}
11+
12+
gradient =
13+
Styling.linear_gradient("150grad", [
14+
{:lab, l * 1.5, a * 0.7, b * 2},
15+
{:lab, l * 1.3, a * 0.8, b * 1.6},
16+
{:lab, l * 1.1, a * 0.9, b * 1.2},
17+
color,
18+
{:lab, l * 0.9, a * 1.3, b * 0.7},
19+
{:lab, l * 0.8, a * 1.7, b * 0.5}
20+
])
21+
22+
"background-color: #{color |> Styling.to_css()}; background-image: #{gradient};"
23+
end
24+
end

0 commit comments

Comments
 (0)