{
title: 'Hitchhiker's guide to frontend development',
subTitle: 'How to develop an application together',
}
const tableOfContents = [
'who am I?',
'what is so called application',
'tell designers who you are!!',
'do you really know how to develop?',
]
console.info(tableOfContents[0]);
▸ "who am I?"
{
name: 'Seokjun Kim',
email: 'colus001@me.com',
job: 'frontend developer',
country: 82,
phone: 01092836686,
}
{
name: 'Seokjun Kim',
email: 'colus001@me.com',
job: 'frontend developer',
country: 82,
phone: 01092836686,
toBe: 'product developer',
}
const career = [{
companyName: 'Studio XID',
role: 'frontend developer',
products: [{
type: 'UI Prototype Tool for Hi-fi Interactions',
name: 'Protopie',
}],
}, {
companyName: 'Streami',
role: 'frontend developer',
products: [{
type: 'Cryptocurrency Exchange',
name: 'GOPAX',
}],
}, {
companyName: 'SOCAR',
role: 'web developer',
products: [{
type: 'Car Rental',
name: 'SOCAR',
}, {
type: 'Car Sharing',
name: 'ZEROCAR',
}],
}]
{
type: SKILL_TYPE.SOFT,
for: DEVELOPERS.JUNIOR,
topic: 'How to develop application',
comment: 'this is basic, no doubt!'
}
console.info(tableOfContents[1]);
▸ "what's so called application?"
const construction = [
'standardized',
'well-structured',
'engineering-oriented',
'highly top-down approach',
]
const softwareDevelopment = [
'highly flexible',
'bottom-up approach',
'very free',
'customer-oriented',
]
const players = [
'designer',
'developer',
]
players.push('product manager');
players.push('project manager');
players.push('marketer');
players.push('sales');
players.push('dae pyo nim');
.
.
.
prompt('what is web application development?');
prompt('what is web application development?');
drawing a picture together with a few rules and no plan no sketch nothing ...
require('engineering');
require('art');
require('team/play');
console.info(tableOfContents[2]);
▸ "tell designer who you are!!"
let theTruth = 'Designer knows nothing!';
theTruth += 'especially who you're working with...';
console.log(theTruth === STATUS.NORMAL);
let theTruth = 'Designer knows nothing!';
theTruth += 'especially who you're working with...';
console.log(theTruth === STATUS.NORMAL);
▸ true
let theTruth = 'Designer knows nothing!';
theTruth += 'especially who you're working with...';
console.log(theTruth === STATUS.NORMAL);
▸ true
theTruth += 'developer doesn't know too';
.font {
/*
a set of characters of the same style and size.
*/
}
.typography {
/*
art and technique of arranging type of written material
consisting of font, font-size, font-style and etc.
*/
}
Lorem Ipsum is simply dummy text of the
printing and typesetting industry. Lorem Ipsum
has been the industry's standard dummy text
ever since the 1500s, when an unknown printer
took a galley of type and scrambled it to make a
type specimen book. It has survived not only five
centuries, but also the leap into electronic
typesetting, remaining essentially unchanged. It
was popularised in the 1960s with the release of
Letraset sheets containing Lorem Ipsum
passages, and more recently with desktop
publishing software like Aldus PageMaker
including versions of Lorem Ipsum.
Lorem Ipsum is simply dummy text of
t h e p r i n t i n g a n d t y p e s e t t i n g
industry. Lorem Ipsum has been the
industry's standard dummy text ever
since the 1500s, when an unknown
printer took a galley of type and
scrambled it to make a type specimen
book. It has survived not only five
centuries, but also the leap into
electronic typesetting, remaining
essentially unchanged. It was
popularised in the 1960s with the
r e l e a s e o f L e t r a s e t s h e e t s
containing Lorem Ipsum passages, and
m o r e r e c e n t l y w i t h d e s k t o p
publishing software like Aldus
PageMaker including versions of
Lorem Ipsum.
.font {
font-size: 18px;
font-family: Helvetica;
// Flexible width
}
.typography {
font-size: 18px;
font-family: Dejavu Sans Mono;
// Fixed width
}
<head>
<style>
@import url(http://fonts.googleapis.com/earlyaccess/notosanskr.css);
@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);
html, body {
font-family: 'Noto Sans KR', sans-serif;
}
h1, h2, h3 {
font-family: 'Nanum Gothic',
}
</style>
</head>
while (true) {
performance -= FONT_DOWNLOAD_TIME;
visual -= UGLINESS.FLICKERING;
difficulty++; // FIXME: difficult to achieve integrity
}
// NOTE: woff, woff2 still heavy for korean fonts and IE, IE, IE...
<body>
<!-- SYMANTIC TYPOGRPAHY -->
<nav>
<ul>
<li>Home</li>
<li>Profile</li>
</ul>
</nav>
<h1>What is frontend development</h1>
<section>
<h3>Frontend development is difficult</h3>
<p>It is actually not that difficult.</p>
</section>
</body>
const symantic = (
<div className="home">
<h1>
Hello World
</h1>
</div>
)
const nonSymantic = (
<div className="home>
<span className="headline">
Hello World
</span>
</div>
)
human.log(symantic === nonSymantic);
▸ true
crawler.log(symantic === nonSymantic);
▸ false
.home {

padding: 20px;
}
.headline, h1 {
font-size: 40px;
text-decoration: bold;
}
.color-management {
--red: #EE0000;
--very-important: var(--red);
color: var(--very-important);
}
.important {
color: #FF0000;
}
.important {
color: #FF0000;
color: #EE0000;
}
.moreImportant {
color: #FF0000;
}
.important {
color: #FF0000;
color: #EE0000;
color: #DD0000;
}
.moreImportant {
color: #FF0000;
color: #EE0000;
}
.mostImportant {
color: #FF0000;
}
$red: #FF0000;
$light-red: #EE0000;
$lighter-red: #DD0000;
.important {
color: $lighter-red;
}
.moreImportant {
color: $light-red;
}
.mostImportant {
color: $red;
}
$red: #FF0000;
$light-red: #EE0000;
$lighter-red: #DD0000;
$important: $lighter-red;
$more-important: $light-red;
$most-important: $red;
.important {
color: $important;
}
.moreImportant {
color: $more-important;
}
.mostImportant {
color: $most-important;
}
/* color variation */
--gray-0: #999999;
--gray-1: #AAAAAA;
--gray-2: #CCCCCC;
/* brand */
--brand-black: #111111;
--brand-red: #DD1111;
--brand-white: #EEFFFF;
/* status */
--status-danger: var(--brand-red);
--status-success: #00EE00;
/* type */
--common-background-color: var(--brand-white);
--common-padding-size: 10px;
--common-border-radius: 2px;
// with CSS preprocessor like sass
$red: #ff0000;
$dark-red: darken($red, 10%);
$darker-red: darken($red, 20%);
$footer-height: 10rem;
$navigation-margin: 5rem;
// mixins
@mixin unit-margin($unit, $direction: '') {
@if $direction == '' {
margin: $unit * 1.6rem;
} @else {
margin-#{$direction}: $unit * 1.6rem;
}
}
// extends
%container {
min-height: calc(100vh - #{$footer-height} - #{$navigation-margin});
padding: 1.6rem * 4 10rem;
@include mobile {
padding: 1.6rem * 2 2rem;
}
}
class Component extends BluePrint {
render() {
return (
<div className="Component">
Make Component <strong>not Page</strong>
</div>
)
}
}
const SomeForm = (
<form className="signin">
<input name="email" />
<button className="btn" type="submit">
SUBMIT
</button>
</form>
);
<style>
.btn {
background-color: blue;
color: white;
padding: 4px 2px;
}
</style>
const AnotherForm = (
<div className="account">
<button className="btn">
Login
</button>
</form>
);
<style>
.account .btn {
background-color: green;
color: white;
padding: 4px 2px;
}
</style>
const AnotherForm = (
<div className="home">
<div className="account">
<button className="btn">
Login
</button> <!-- What's the button color? -->
</div>
</div>
);
<style>
.home .btn {
background-color: red;
color: white;
padding: 4px 2px;
}
</style>
human.log(buttonA === buttonB);
▸ true
developer.log(buttonA === buttonB);
▸ true
human.log(buttonA === buttonB);
▸ true
developer.log(buttonA === buttonB);
▸ true
designer.log(buttonA === buttonB);
▸ false
human.log(buttonA === buttonB);
▸ true
developer.log(buttonA === buttonB);
▸ true
designer.log(buttonA === buttonB);
▸ false
frontendDeveloper.log(buttonA === buttonB);
▸ false
$ npm run storybook
if (project.hasJustStarted()) {
console.log('you have time to play with component!!');
// Designer loves it
}
const anatomy: Component = `
SignupForm
ㄴ container
ㄴ input
ㄴ type: email
ㄴ input
ㄴ type: password
ㄴ button
ㄴ theme: primary
ㄴ text: 'SignUp'
`
interface Component = Component[] | DOM[]
const { isLoggedIn } = getUserState();
const Page = (
<Container>
<Navigator />
<ContentWrapper>
{isLoggedIn ? (
<Profile />
) : (
<Account>
<LoginForm />
<SignUpForm />
</Account>
)}
</ContentWrapper>
</Container>
)
import { Component } from 'interfaces';
interface Page = Component[];
interface Product = Page[];
const product = new Product();
product.integrity++;
product.completeness++;
product.performance++;
designer.sapjil--;
developer.movePixelJjogum--;
team.hapiness++;
> Unfortunately frontend developer has to tell UI designers
what to do for both of us, team and product
developer.order(designer) !== developer.help(designer)
typeof designer.create
▸ "function"
typeof developer.realize
▸ "function"
console.info(tableOfContents[3]);
▸ "do you really know how to develop"
/**
* Represent application architecture with folder structure
* @param {Developer[]} developers - developers to work together
* @returns {view, data} Scaffolding of view and data
*/
function scaffolding(developers) {
if (developers.length === 1) return null;
return {
view: 'visual representation',
data: 'send, receive and manipulate information',
};
}
// NOTE: There's no standard but ...
class View {
constructor(type) {
if (this.codeLength > LENGTH.TOO_MANY) {
throw new Error('error: split code based on some rule');
}
if (type === 'presentational') {
this.createPresentational();
} else {
this.createControllable();
}
}
createPresentational(): PresentationalView {
this.rule = 'as neat and simple as possible';
}
createControllable(): ControllableView {
this.rule = 'life cycle should be simple enough to understand';
}
}
typeof this
▸ "view"
// NOTE: separate to component as small as possible
class Signup extends Component {
signUp(data) {
fetch('/signup', data);
}
render() {
return (
<div className="signup-form">
<Button onClick={this.signUp} label="Sign Up" />
<div>
)
}
}
const Button = (onClick, label) => (
<button onClick={onClick}>
{label}
</button>
)
typeof this
▸ "view"
// NOTE: make abstracted component when library is used
import swiper from 'swiper';
interface Carousel {
init(options: { infinite: boolean }): void;
hide(): void;
}
const abstract = (library) => {
wrap(library);
}
const Carousel = abstract(swiper);
export default Carousel;
typeof this
▸ "view"
// NOTE: functional programming applied here
import * as formatters from './formatters';
import * as calculators from './calculators';
import * as parsers from './parsers';
.
.
.
typeof this
▸ "view"
typeof this
▸ "data"
import developers from './developers/frontend';
describe('developers', () => {
you('should write test code for at least data handling', () => {
expect(developers).to.write.test.case();
const tests = developers.getTestCodes();
if (typeof tests === 'unit') {
expect(tests).not.to.be.null;
} else if (typeof tests === 'integration') {
expect(tests).to.be.null;
}
expect(test.length).to.at.least(1);
})
})
typeof this
▸ "data"
const STATUS = {
SUCCESS: 'success',
ERROR: 'error',
FAIL: 'fail',
}
const KEY_CODE = {
ESC: 27,
ENTER: 24,
BACKSPACE: 8,
}
typeof this
▸ "data"
// Do
const getMyProfile = async () => {
const result = await fetch('/me/profile');
return result;
}
// Don't
class Profile {
profile = null;
constructor() {
fetch('/me/profile')
.then(profile => {
this.profile = profile;
})
}
}
<style>
.css {
content: 'as component',
}
</style>
<!-- Don't -->
<div class="home">
<button class="button>
HOME
</button>
</div>
<style>
.home .button {
height: 30px;
}
</style>
<!-- Do -->
<div class="home">
<button class="home-button>
HOME
</button>
</div>
<style>
.home-button {
height: 30px;
}
</style>
browser.shout('avoid global!!!');
'use strict';
'use closure';
'use component-like css';
const howToChooseLibrary = (library) => {
console.warn('you will be FIRED if you choose one for popularity!');
const points =
library.hasEnoughGithubStar()
+ library.easyToUnderstand()
+ library.isEssential()
+ library.takeTimeToBuildIdentical()
if (point > POINTS.HIGH_ENOUGH) {
return true;
}
return false;

}
console.info(tableOfContents[4]);
▸ "onesome more thing"
if (developer.care(['integrity', 'stability', 'performance'])) {
designer.care(['aesthetic', 'user experience', 'completeness']);
}
product.log(developer.care(designer) === developer.care(self));
▸ true
frontendDeveloper.log(1px.valueOf() === 10px.valueOf());
▸ true
const frontendDeveloper = developer.isAmong(designer, productOwner, client)
const importance = frontendDeveloper.getImportance(now);
console.log(getImportance(tomorrow) >= importance);
▸ true
developer('should good at communication', () => {
expect(frontendDeveloper).to.be.good.at(communication);
});
interface GateKeeper {
open(): void;
close(): void;
}
class FrontendDeveloper extends Developer implements GateKeeper {
constructor() {
this.character = CHARACTERS.THINGS_GET_DONE;
}
}
const frontendDeveloper = new FrontendDeveloper();
developer('should good at delivery', () => {
expect(frontendDeveloper).to.be.good.at(delivery);
})
class ObjectOrientedProgramming extends Classic {}
function functionalProgramming() {}
const ReactiveProgramming = observable.subscribe()
redux.store.dispatch({ type: 'LEARNING_EVERYDAY' })
developer('should good at learning', () => {
expect(frontendDeveloper).to.be.good.at(learning);
})
console.info('how to raise your value');
interface Virtue {
workSmart(): any;
thingsGetDone(args: any): true;
solveProblemsNotSymptoms: any;
}
class SeniorDeveloper implements Virtue {
predictable: boolean = true;
raiseSalary() {
this.workSmart();
this.thingsGetDone();
this.solveProblemsNotSymptoms();
}

}
class SeniorDeveloper implements Virtue {
...
workSmart() {
if (this.keepYagun()) stop();
pipe(learn, write, rest, vacation, enjoy)();
}
thingsGetDone() {
if (this.keepWorkingUntilDead()) stop();
negotiate([specs, features, ...rest ]);
finish();
}
solveProblemsNotSymptoms() {
if (fix(symptom) === STATUS.NOT_ENOUGH) {
fix(problem);
}
}
...
}
class SeniorDeveloper implements Virtue {
raiseSalary() {
...
this.goTo(seaNotRiver);
console.warn('not major company nor startup');
this.meet(goodDevelopers);
this.build(career);
this.catch(luck); // If FE, you already did
}

}
interface ProductManagement {
delivery(): true;
createRoadmap(): Roadmap;
createPlan(): Plan;
}
class ProductDeveloper extends FrontendDeveloper implements ProductManagement {
predictable: boolean = true;
communication: string = LEVEL.GOOD; // NOTE: including verbal & non-verbal
alsoAs: Person = new BusinessPerson(this);
}
const CPO: ProductManager = new ProductDeveloper(experience);
prompt('any questions?');
console.log('thanks');
describe('this talk', () => {
it('should share something valuable', () => {
expect(listeners).to.applause();
})
})
<a href="https://seokjun.kim">Blog</a>

How to develop frontend application

  • 1.
    { title: 'Hitchhiker's guideto frontend development', subTitle: 'How to develop an application together', }
  • 2.
    const tableOfContents =[ 'who am I?', 'what is so called application', 'tell designers who you are!!', 'do you really know how to develop?', ]
  • 3.
  • 4.
    { name: 'Seokjun Kim', email:'colus001@me.com', job: 'frontend developer', country: 82, phone: 01092836686, }
  • 5.
    { name: 'Seokjun Kim', email:'colus001@me.com', job: 'frontend developer', country: 82, phone: 01092836686, toBe: 'product developer', }
  • 6.
    const career =[{ companyName: 'Studio XID', role: 'frontend developer', products: [{ type: 'UI Prototype Tool for Hi-fi Interactions', name: 'Protopie', }], }, { companyName: 'Streami', role: 'frontend developer', products: [{ type: 'Cryptocurrency Exchange', name: 'GOPAX', }], }, { companyName: 'SOCAR', role: 'web developer', products: [{ type: 'Car Rental', name: 'SOCAR', }, { type: 'Car Sharing', name: 'ZEROCAR', }], }]
  • 7.
    { type: SKILL_TYPE.SOFT, for: DEVELOPERS.JUNIOR, topic:'How to develop application', comment: 'this is basic, no doubt!' }
  • 8.
  • 9.
    const construction =[ 'standardized', 'well-structured', 'engineering-oriented', 'highly top-down approach', ]
  • 10.
    const softwareDevelopment =[ 'highly flexible', 'bottom-up approach', 'very free', 'customer-oriented', ]
  • 11.
    const players =[ 'designer', 'developer', ]
  • 12.
  • 13.
    prompt('what is webapplication development?');
  • 14.
    prompt('what is webapplication development?'); drawing a picture together with a few rules and no plan no sketch nothing ...
  • 15.
  • 16.
  • 17.
    let theTruth ='Designer knows nothing!'; theTruth += 'especially who you're working with...'; console.log(theTruth === STATUS.NORMAL);
  • 18.
    let theTruth ='Designer knows nothing!'; theTruth += 'especially who you're working with...'; console.log(theTruth === STATUS.NORMAL); ▸ true
  • 19.
    let theTruth ='Designer knows nothing!'; theTruth += 'especially who you're working with...'; console.log(theTruth === STATUS.NORMAL); ▸ true theTruth += 'developer doesn't know too';
  • 20.
    .font { /* a setof characters of the same style and size. */ } .typography { /* art and technique of arranging type of written material consisting of font, font-size, font-style and etc. */ }
  • 21.
    Lorem Ipsum issimply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum is simply dummy text of t h e p r i n t i n g a n d t y p e s e t t i n g industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the r e l e a s e o f L e t r a s e t s h e e t s containing Lorem Ipsum passages, and m o r e r e c e n t l y w i t h d e s k t o p publishing software like Aldus PageMaker including versions of Lorem Ipsum. .font { font-size: 18px; font-family: Helvetica; // Flexible width } .typography { font-size: 18px; font-family: Dejavu Sans Mono; // Fixed width }
  • 22.
    <head> <style> @import url(http://fonts.googleapis.com/earlyaccess/notosanskr.css); @import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css); html,body { font-family: 'Noto Sans KR', sans-serif; } h1, h2, h3 { font-family: 'Nanum Gothic', } </style> </head>
  • 23.
    while (true) { performance-= FONT_DOWNLOAD_TIME; visual -= UGLINESS.FLICKERING; difficulty++; // FIXME: difficult to achieve integrity } // NOTE: woff, woff2 still heavy for korean fonts and IE, IE, IE...
  • 24.
    <body> <!-- SYMANTIC TYPOGRPAHY--> <nav> <ul> <li>Home</li> <li>Profile</li> </ul> </nav> <h1>What is frontend development</h1> <section> <h3>Frontend development is difficult</h3> <p>It is actually not that difficult.</p> </section> </body>
  • 25.
    const symantic =( <div className="home"> <h1> Hello World </h1> </div> ) const nonSymantic = ( <div className="home> <span className="headline"> Hello World </span> </div> ) human.log(symantic === nonSymantic); ▸ true crawler.log(symantic === nonSymantic); ▸ false .home {
 padding: 20px; } .headline, h1 { font-size: 40px; text-decoration: bold; }
  • 26.
    .color-management { --red: #EE0000; --very-important:var(--red); color: var(--very-important); }
  • 27.
  • 28.
    .important { color: #FF0000; color:#EE0000; } .moreImportant { color: #FF0000; }
  • 29.
    .important { color: #FF0000; color:#EE0000; color: #DD0000; } .moreImportant { color: #FF0000; color: #EE0000; } .mostImportant { color: #FF0000; }
  • 30.
    $red: #FF0000; $light-red: #EE0000; $lighter-red:#DD0000; .important { color: $lighter-red; } .moreImportant { color: $light-red; } .mostImportant { color: $red; }
  • 31.
    $red: #FF0000; $light-red: #EE0000; $lighter-red:#DD0000; $important: $lighter-red; $more-important: $light-red; $most-important: $red; .important { color: $important; } .moreImportant { color: $more-important; } .mostImportant { color: $most-important; }
  • 32.
    /* color variation*/ --gray-0: #999999; --gray-1: #AAAAAA; --gray-2: #CCCCCC; /* brand */ --brand-black: #111111; --brand-red: #DD1111; --brand-white: #EEFFFF; /* status */ --status-danger: var(--brand-red); --status-success: #00EE00; /* type */ --common-background-color: var(--brand-white); --common-padding-size: 10px; --common-border-radius: 2px;
  • 33.
    // with CSSpreprocessor like sass $red: #ff0000; $dark-red: darken($red, 10%); $darker-red: darken($red, 20%); $footer-height: 10rem; $navigation-margin: 5rem; // mixins @mixin unit-margin($unit, $direction: '') { @if $direction == '' { margin: $unit * 1.6rem; } @else { margin-#{$direction}: $unit * 1.6rem; } } // extends %container { min-height: calc(100vh - #{$footer-height} - #{$navigation-margin}); padding: 1.6rem * 4 10rem; @include mobile { padding: 1.6rem * 2 2rem; } }
  • 34.
    class Component extendsBluePrint { render() { return ( <div className="Component"> Make Component <strong>not Page</strong> </div> ) } }
  • 35.
    const SomeForm =( <form className="signin"> <input name="email" /> <button className="btn" type="submit"> SUBMIT </button> </form> ); <style> .btn { background-color: blue; color: white; padding: 4px 2px; } </style> const AnotherForm = ( <div className="account"> <button className="btn"> Login </button> </form> ); <style> .account .btn { background-color: green; color: white; padding: 4px 2px; } </style>
  • 36.
    const AnotherForm =( <div className="home"> <div className="account"> <button className="btn"> Login </button> <!-- What's the button color? --> </div> </div> ); <style> .home .btn { background-color: red; color: white; padding: 4px 2px; } </style>
  • 37.
    human.log(buttonA === buttonB); ▸true developer.log(buttonA === buttonB); ▸ true
  • 38.
    human.log(buttonA === buttonB); ▸true developer.log(buttonA === buttonB); ▸ true designer.log(buttonA === buttonB); ▸ false
  • 39.
    human.log(buttonA === buttonB); ▸true developer.log(buttonA === buttonB); ▸ true designer.log(buttonA === buttonB); ▸ false frontendDeveloper.log(buttonA === buttonB); ▸ false
  • 40.
    $ npm runstorybook if (project.hasJustStarted()) { console.log('you have time to play with component!!'); // Designer loves it }
  • 41.
    const anatomy: Component= ` SignupForm ㄴ container ㄴ input ㄴ type: email ㄴ input ㄴ type: password ㄴ button ㄴ theme: primary ㄴ text: 'SignUp' ` interface Component = Component[] | DOM[]
  • 42.
    const { isLoggedIn} = getUserState(); const Page = ( <Container> <Navigator /> <ContentWrapper> {isLoggedIn ? ( <Profile /> ) : ( <Account> <LoginForm /> <SignUpForm /> </Account> )} </ContentWrapper> </Container> )
  • 43.
    import { Component} from 'interfaces'; interface Page = Component[]; interface Product = Page[]; const product = new Product(); product.integrity++; product.completeness++; product.performance++; designer.sapjil--; developer.movePixelJjogum--; team.hapiness++;
  • 44.
    > Unfortunately frontenddeveloper has to tell UI designers what to do for both of us, team and product developer.order(designer) !== developer.help(designer) typeof designer.create ▸ "function" typeof developer.realize ▸ "function"
  • 45.
  • 46.
    /** * Represent applicationarchitecture with folder structure * @param {Developer[]} developers - developers to work together * @returns {view, data} Scaffolding of view and data */ function scaffolding(developers) { if (developers.length === 1) return null; return { view: 'visual representation', data: 'send, receive and manipulate information', }; }
  • 47.
    // NOTE: There'sno standard but ... class View { constructor(type) { if (this.codeLength > LENGTH.TOO_MANY) { throw new Error('error: split code based on some rule'); } if (type === 'presentational') { this.createPresentational(); } else { this.createControllable(); } } createPresentational(): PresentationalView { this.rule = 'as neat and simple as possible'; } createControllable(): ControllableView { this.rule = 'life cycle should be simple enough to understand'; } } typeof this ▸ "view"
  • 48.
    // NOTE: separateto component as small as possible class Signup extends Component { signUp(data) { fetch('/signup', data); } render() { return ( <div className="signup-form"> <Button onClick={this.signUp} label="Sign Up" /> <div> ) } } const Button = (onClick, label) => ( <button onClick={onClick}> {label} </button> ) typeof this ▸ "view"
  • 49.
    // NOTE: makeabstracted component when library is used import swiper from 'swiper'; interface Carousel { init(options: { infinite: boolean }): void; hide(): void; } const abstract = (library) => { wrap(library); } const Carousel = abstract(swiper); export default Carousel; typeof this ▸ "view"
  • 50.
    // NOTE: functionalprogramming applied here import * as formatters from './formatters'; import * as calculators from './calculators'; import * as parsers from './parsers'; . . . typeof this ▸ "view"
  • 51.
    typeof this ▸ "data" importdevelopers from './developers/frontend'; describe('developers', () => { you('should write test code for at least data handling', () => { expect(developers).to.write.test.case(); const tests = developers.getTestCodes(); if (typeof tests === 'unit') { expect(tests).not.to.be.null; } else if (typeof tests === 'integration') { expect(tests).to.be.null; } expect(test.length).to.at.least(1); }) })
  • 52.
    typeof this ▸ "data" constSTATUS = { SUCCESS: 'success', ERROR: 'error', FAIL: 'fail', } const KEY_CODE = { ESC: 27, ENTER: 24, BACKSPACE: 8, }
  • 53.
    typeof this ▸ "data" //Do const getMyProfile = async () => { const result = await fetch('/me/profile'); return result; } // Don't class Profile { profile = null; constructor() { fetch('/me/profile') .then(profile => { this.profile = profile; }) } }
  • 54.
    <style> .css { content: 'ascomponent', } </style>
  • 55.
    <!-- Don't --> <divclass="home"> <button class="button> HOME </button> </div> <style> .home .button { height: 30px; } </style> <!-- Do --> <div class="home"> <button class="home-button> HOME </button> </div> <style> .home-button { height: 30px; } </style>
  • 56.
    browser.shout('avoid global!!!'); 'use strict'; 'useclosure'; 'use component-like css';
  • 57.
    const howToChooseLibrary =(library) => { console.warn('you will be FIRED if you choose one for popularity!'); const points = library.hasEnoughGithubStar() + library.easyToUnderstand() + library.isEssential() + library.takeTimeToBuildIdentical() if (point > POINTS.HIGH_ENOUGH) { return true; } return false;
 }
  • 58.
  • 59.
    if (developer.care(['integrity', 'stability','performance'])) { designer.care(['aesthetic', 'user experience', 'completeness']); } product.log(developer.care(designer) === developer.care(self)); ▸ true frontendDeveloper.log(1px.valueOf() === 10px.valueOf()); ▸ true
  • 60.
    const frontendDeveloper =developer.isAmong(designer, productOwner, client) const importance = frontendDeveloper.getImportance(now); console.log(getImportance(tomorrow) >= importance); ▸ true developer('should good at communication', () => { expect(frontendDeveloper).to.be.good.at(communication); });
  • 61.
    interface GateKeeper { open():void; close(): void; } class FrontendDeveloper extends Developer implements GateKeeper { constructor() { this.character = CHARACTERS.THINGS_GET_DONE; } } const frontendDeveloper = new FrontendDeveloper(); developer('should good at delivery', () => { expect(frontendDeveloper).to.be.good.at(delivery); })
  • 62.
    class ObjectOrientedProgramming extendsClassic {} function functionalProgramming() {} const ReactiveProgramming = observable.subscribe() redux.store.dispatch({ type: 'LEARNING_EVERYDAY' }) developer('should good at learning', () => { expect(frontendDeveloper).to.be.good.at(learning); })
  • 63.
  • 64.
    interface Virtue { workSmart():any; thingsGetDone(args: any): true; solveProblemsNotSymptoms: any; } class SeniorDeveloper implements Virtue { predictable: boolean = true; raiseSalary() { this.workSmart(); this.thingsGetDone(); this.solveProblemsNotSymptoms(); }
 }
  • 65.
    class SeniorDeveloper implementsVirtue { ... workSmart() { if (this.keepYagun()) stop(); pipe(learn, write, rest, vacation, enjoy)(); } thingsGetDone() { if (this.keepWorkingUntilDead()) stop(); negotiate([specs, features, ...rest ]); finish(); } solveProblemsNotSymptoms() { if (fix(symptom) === STATUS.NOT_ENOUGH) { fix(problem); } } ... }
  • 66.
    class SeniorDeveloper implementsVirtue { raiseSalary() { ... this.goTo(seaNotRiver); console.warn('not major company nor startup'); this.meet(goodDevelopers); this.build(career); this.catch(luck); // If FE, you already did }
 }
  • 67.
    interface ProductManagement { delivery():true; createRoadmap(): Roadmap; createPlan(): Plan; } class ProductDeveloper extends FrontendDeveloper implements ProductManagement { predictable: boolean = true; communication: string = LEVEL.GOOD; // NOTE: including verbal & non-verbal alsoAs: Person = new BusinessPerson(this); } const CPO: ProductManager = new ProductDeveloper(experience);
  • 68.
  • 69.
    console.log('thanks'); describe('this talk', ()=> { it('should share something valuable', () => { expect(listeners).to.applause(); }) })
  • 70.