-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrationale.html
More file actions
85 lines (83 loc) · 9.86 KB
/
Copy pathrationale.html
File metadata and controls
85 lines (83 loc) · 9.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Why complate?</title><meta name="title" content="Why complate?"><meta name="og:image" content="https://complate.org/complate_banner_sm.png"><meta name="viewport" content="width=device-width, initial-scale=1"><link href="/assets/fonts.css" rel="stylesheet"><link href="/assets/index.css" rel="stylesheet"></head><body><div class="title-block"><div class="container"><img class="logo" src="complate.png"><div class="title-area"><h1>Why complate?</h1><p>Benefits of designing front-end code using a component abstraction</p><p></p></div></div></div><nav class="breadcrumb"><ol><li><a href="/index.html">Home<svg class="icon" role="presentation"><use href="#icon-arrow-right"></use></svg></a></li><li><a href="/rationale.html" aria-current="page">Why complate?</a></li></ol></nav><div class="container"><p>One of the main goals for complate is to create a templating engine which
allows us to write our front end using components. Why would we want to do
that? Let’s look at some of the major benefits of a component based templating
engine.</p>
<h2>Abstraction</h2>
<p>When we are developing our front-end components, we can use complate markup
abstractions (“macros”) as an encapsulation layer for our component. Consider
the following macro:</p>
<pre><code class="language-jsx">function Avatar({ src, alt }) {
return <div class="avatar">
<img src={src} alt={alt} />
</div>
}
</code></pre>
<p>We can then use our macro in our application and it will be replaced with the
markup we have defined.</p>
<pre><code class="language-jsx"><Avatar src="profile.jpg" alt="Portrait of Me" />
</code></pre>
<p>This is <em>extremely powerful</em> and solves a major pain point when writing
maintainable front-end code. Requirements change constantly. When a new
requirement comes up, or I want to modify and improve existing markup, I can
change the markup of my component and all instances are updated automatically.
Here I need to be careful about pieces of my application which depend on the
structure of my markup (e.g. CSS, JavaScript, tests), but with care many
unnecessary breaking changes can be avoided.</p>
<p>Another major benefit is that it reduces the cognitive overhead necessary for
<em>using</em> the component. In a team environment this can be especially useful
because it is easy to use components even without the technical expertise to
write them. However, when using a component it is always a good idea to be
aware of the underlying markup.</p>
<h2>Composition</h2>
<p>complate allows us to write components and then explicitly compose them
together.</p>
<p>Composition in complate looks very similar to that
inherent in HTML: child components are passed into the parent component
by placing them within the parent’s tags.</p>
<p>This allows us to focus on the definition of the component itself without
worrying about the surrounding boilerplate or any details of the children
components. If we need to change the children later, we can do this without
influencing the parent component.</p>
<p>Here we use a navigation-bar component as an example of how components can be
composed together:</p>
<pre><code class="language-jsx">function NavbarItem ({ href, current }, ...children) {
const className = current ? "current" : null
return <a class={className} href={href}>
{children}
</a>
}
function Navbar (_params, ...children) {
return <nav class="navbar">
{children}
</nav>
}
<Navbar>
<a href="#profile">
<Avatar src="profile.jpg" alt="User Avatar" />
</a>
<NavbarItem href="/">Home</NavbarItem>
<NavbarItem href="/about" current>About</NavbarItem>
</Navbar>
</code></pre>
<p>Composition allows us to keep component definitions simple. If we need more
complicated UI elements, we can compose several components together to get
the desired effect.</p>
<p>Composition in complate is also powerful because we pass the children in
explicitly in the macro definition. If we want to render the component
differently when there are no children passed in, we can do this. If we
want to destructure the list of children and place them in different parts
of our component, we can do this. If we want to iterate over the list of
children and wrap each one in another component, we can do this.</p>
<h2>Reusability</h2>
<p>Another huge benefit of using complate is that we can reuse our components
not only within our project, but also accross multiple platforms. These platforms
include:</p>
<ul>
<li><a href="https://github.com/complate/complate-express">Express</a> (Node.js)</li>
<li><a href="https://github.com/complate/complate-ruby">Ruby on Rails</a> (Ruby)</li>
<li><a href="https://github.com/complate/complate-spring-mvc">Spring MVC</a> (Java)</li>
<li><a href="https://github.com/tmehnert/complate-cpp">C++</a></li>
<li><a href="https://github.com/complate/complate-fractal">Fractal</a></li>
</ul>
</div><footer><a href="https://innoq.com/en/impressum/">imprint</a><a href="https://innoq.com/en/datenschutz">privacy</a></footer><svg class="icon-definitions" hidden><defs><symbol id="icon-arrow-right" viewBox="0 0 24 24"><defs><style>.cls-1{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;fill-rule:evenodd;}</style></defs><title>arrow-right-1</title><path class="cls-1" d="M5.5.75,16.22,11.47a.749.749,0,0,1,0,1.06L5.5,23.25"></path></symbol><symbol id="icon-server-heart" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>server-heart</title><path class="a" d="M5.25,4.875a.375.375,0,1,0,.375.375.375.375,0,0,0-.375-.375h0"></path><path class="a" d="M5.25,13.875a.375.375,0,1,0,.375.375.375.375,0,0,0-.375-.375h0"></path><path class="a" d="M21.75,5.25a4.5,4.5,0,0,1-4.5,4.5h-12a4.5,4.5,0,0,1,0-9h12A4.5,4.5,0,0,1,21.75,5.25Z"></path><path class="a" d="M9,18.75H5.25a4.5,4.5,0,0,1,0-9h12"></path><line class="a" x1="10.5" y1="5.25" x2="17.25" y2="5.25"></line><path class="a" d="M17.251,23.25l-5.114-5.335a3.025,3.025,0,0,1-.567-3.492h0a3.026,3.026,0,0,1,4.846-.786l.835.835.835-.835a3.025,3.025,0,0,1,4.845.786h0a3.023,3.023,0,0,1-.566,3.492Z"></path></symbol><symbol id="icon-component" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>module-three-2</title><path class="a" d="M1.723,13.033A1.5,1.5,0,0,0,.75,14.438v5.625a1.5,1.5,0,0,0,.973,1.4l4.5,1.687a1.5,1.5,0,0,0,1.054,0l4.5-1.687a1.5,1.5,0,0,0,.973-1.4V14.438a1.5,1.5,0,0,0-.973-1.405l-4.5-1.687a1.5,1.5,0,0,0-1.054,0Z"></path><polyline class="a" points="1.008 13.597 6.75 15.75 12.492 13.597"></polyline><line class="a" x1="6.75" y1="15.75" x2="6.75" y2="23.25"></line><path class="a" d="M22.95,3.85l-8.7,2.9-8.7-2.9"></path><line class="a" x1="14.25" y1="6.75" x2="14.25" y2="10.5"></line><path class="a" d="M5.25,8.25V4.75A1.5,1.5,0,0,1,6.276,3.327l7.5-2.5a1.493,1.493,0,0,1,.948,0l7.5,2.5A1.5,1.5,0,0,1,23.25,4.75v8.5a1.5,1.5,0,0,1-1.026,1.423L15.75,16.831"></path></symbol><symbol id="icon-jsx" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>monitor-code-send</title><path class="a" d="M3.822,8.25v-6A1.65,1.65,0,0,1,5.589.75h15.9a1.65,1.65,0,0,1,1.766,1.5v10.5a1.65,1.65,0,0,1-1.766,1.5H17.25"></path><line class="a" x1="3.822" y1="5.25" x2="23.25" y2="5.25"></line><path class="a" d="M.75,22.05a1.32,1.32,0,0,0,1.413,1.2H12.837a1.32,1.32,0,0,0,1.413-1.2v-9.6a1.32,1.32,0,0,0-1.413-1.2H2.163A1.32,1.32,0,0,0,.75,12.45Z"></path><polyline class="a" points="6.048 15 9.581 17.325 6.048 19.65"></polyline><path class="a" d="M18.8,23.25c1.137,0,1.8-1.256,1.8-2.25V17.25"></path><polyline class="a" points="23.25 19.65 20.533 17.25 17.815 19.65"></polyline></symbol><symbol id="icon-getting-started" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>startup-launch</title><path class="a" d="M17.25,5.25h1.5a1.5,1.5,0,0,1,1.5,1.5v7.5a1.5,1.5,0,0,1-1.5,1.5H16.5"></path><path class="a" d="M7.5,15.75H5.25a1.5,1.5,0,0,1-1.5-1.5V6.75a1.5,1.5,0,0,1,1.5-1.5h1.5"></path><path class="a" d="M18.571,15.75a3,3,0,0,1,2.683,1.658l1.836,3.671a1.5,1.5,0,0,1-1.342,2.171H2.252A1.5,1.5,0,0,1,.91,21.079l1.836-3.671A3,3,0,0,1,5.429,15.75"></path><path class="a" d="M14.25,3.956C14.25,2.185,12,.75,12,.75S9.75,2.185,9.75,3.956v7.481h4.5Z"></path><path class="a" d="M9.75,11.437H7.012a.6.6,0,0,1-.445-.186.432.432,0,0,1-.1-.416A5.118,5.118,0,0,1,9.75,7.687"></path><path class="a" d="M14.25,11.437h2.738a.6.6,0,0,0,.444-.186.43.43,0,0,0,.1-.416A5.129,5.129,0,0,0,14.25,7.687"></path><line class="a" x1="10.5" y1="14.25" x2="10.5" y2="16.5"></line><line class="a" x1="13.5" y1="14.25" x2="13.5" y2="18.75"></line></symbol><symbol id="icon-faq" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>conversation-question-warning-1</title><path class="a" d="M19.707,6.747A9.1,9.1,0,1,0,3.422,14.638L.75,20.25l5.612-2.672A9.079,9.079,0,0,0,9.75,18.841"></path><path class="a" d="M8.25,7.125A1.875,1.875,0,1,1,10.125,9"></path><line class="a" x1="10.125" y1="11.25" x2="10.125" y2="11.25"></line><path class="a" d="M10.125,11.25a.375.375,0,1,0,.375.375.375.375,0,0,0-.375-.375"></path><path class="a" d="M17.882,10.5a5.344,5.344,0,0,1,4.026,8.886l.671,3.864-3.5-2.158a5.364,5.364,0,1,1-1.2-10.592Z"></path><line class="a" x1="17.25" y1="14.25" x2="17.25" y2="17.25"></line></symbol></defs></svg><script src="https://unpkg.com/prismjs@1.15.0/prism.js"></script><script src="https://unpkg.com/prismjs@1.15.0/components/prism-jsx.min.js"></script></body></html>