├── .DS_Store ├── images ├── v8.jpg ├── conjunto-map.jpg ├── fb-desafio-array.png ├── fb-desafio-array1.png ├── fb-desafio-array2.png └── mas-nao-se-irrite.jpg ├── posts ├── .DS_Store ├── ensino-baseado-problematizacao.md ├── src │ ├── ehPar.js │ ├── eh.js │ ├── getName.js │ └── types.js ├── arrays-multiplos.md ├── fisica │ └── entrelacamento.js ├── sql │ ├── index.js │ └── items.js ├── fullstack-boas-praticas.md ├── vc-sabe-de-onde-vem-o-bit.md ├── privilegio-como-funciona.md ├── Strings-em-busca-da-substring-perfeita.md ├── entrelacamento-quantico.md ├── map-filter-reduce-para-iniciantes.md ├── my-atyomic-design-patterns.md ├── js-funcional-para-xofens.md ├── mobile-first-atomic-design-part-03.md ├── js-ta-bom-mas-nao-se-irrite.md ├── mobile-first-atomic-design-part-02.md ├── sql-funcional.md └── mobile-first-atomic-design.md ├── traducoes ├── .DS_Store ├── imgs │ └── recursion.png ├── Recursion, Tail Calls and Trampolines │ └── README.md ├── What does const stand for in ES6? │ └── readme.md └── Casual functional adventures in JavaScript │ └── README.md ├── .gitignore ├── node └── routes │ └── automatizando-suas-rotas.md └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/.DS_Store -------------------------------------------------------------------------------- /images/v8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/images/v8.jpg -------------------------------------------------------------------------------- /posts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/posts/.DS_Store -------------------------------------------------------------------------------- /posts/ensino-baseado-problematizacao.md: -------------------------------------------------------------------------------- 1 | # Ensino baseado em Problematização -------------------------------------------------------------------------------- /traducoes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/traducoes/.DS_Store -------------------------------------------------------------------------------- /images/conjunto-map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/images/conjunto-map.jpg -------------------------------------------------------------------------------- /images/fb-desafio-array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/images/fb-desafio-array.png -------------------------------------------------------------------------------- /images/fb-desafio-array1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/images/fb-desafio-array1.png -------------------------------------------------------------------------------- /images/fb-desafio-array2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/images/fb-desafio-array2.png -------------------------------------------------------------------------------- /images/mas-nao-se-irrite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/images/mas-nao-se-irrite.jpg -------------------------------------------------------------------------------- /traducoes/imgs/recursion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suissa/blog/HEAD/traducoes/imgs/recursion.png -------------------------------------------------------------------------------- /posts/src/ehPar.js: -------------------------------------------------------------------------------- 1 | const número = 64 2 | 3 | éPar = ( número ) => ( número % 2 === 0 ) ? true : false 4 | 5 | console.log(`O número ${número} é par? `, éPar( número )) 6 | 7 | // O número 64 é par? true -------------------------------------------------------------------------------- /posts/src/eh.js: -------------------------------------------------------------------------------- 1 | 2 | const número = 42 3 | 4 | const é = ( teste ) => { 5 | 6 | if ( teste ) return true 7 | else return false 8 | } 9 | 10 | console.log( `O número ${número} é par? ${é(número)}`) -------------------------------------------------------------------------------- /traducoes/Recursion, Tail Calls and Trampolines/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | Artigo traduzido de: 4 | http://www.datchley.name/recursion-tail-calls-and-trampolines/ 5 | 6 | ``` 7 | 8 | 9 | # Recursion, Tail Calls and Trampolines -------------------------------------------------------------------------------- /posts/arrays-multiplos.md: -------------------------------------------------------------------------------- 1 | const x = [1, 2, 3, 4, 5]; 2 | const primeira = (el, i) => Math.pow(el, 2) 3 | const segunda = (el, i) => el + '' 4 | const terceira = (el, i) => el * -1 5 | 6 | const trans = (x) => ([ 7 | Array.from(x, primeira), 8 | Array.from(x, segunda), 9 | Array.from(x, terceira), 10 | ]) 11 | 12 | console.log(trans(x)) -------------------------------------------------------------------------------- /posts/src/getName.js: -------------------------------------------------------------------------------- 1 | const getName = ( obj ) => obj.name 2 | 3 | const getResult = ( data ) => data.map ? data.map( getName ) : getName( data ) 4 | 5 | const arr = [ 6 | { name: 'Suissa', age: 32 }, 7 | { name: 'Jesus', age: 2017 } 8 | ] 9 | 10 | const obj = { name: 'Suissa', age: 32 } 11 | 12 | console.log(`Nomes: `, getResult( arr ) ) 13 | 14 | console.log(`Nome: `, getResult( obj ) ) -------------------------------------------------------------------------------- /posts/src/types.js: -------------------------------------------------------------------------------- 1 | const VALUES = [ 0, '0', false, null, undefined, 1, -1, {}, () => {} ] 2 | 3 | const MY_REAL_VALUE = 0 4 | 5 | const testMyValue = ( MY_REAL_VALUE ) => ( value ) => value == MY_REAL_VALUE 6 | 7 | const result = VALUES.filter( testMyValue( MY_REAL_VALUE ) ) 8 | 9 | console.log(`Os seguinte valores foram iguais a ${MY_REAL_VALUE}: \n `, result) 10 | 11 | /* 12 | Os seguinte valores foram iguais a 0: 13 | [ 0, '0', false ] 14 | */ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /posts/fisica/entrelacamento.js: -------------------------------------------------------------------------------- 1 | function Foton() { 2 | this.spin = 0 3 | this.mass = 0 4 | this.electric_charge = 0 5 | this.isEmited = false 6 | } 7 | 8 | Foton.prototype.observe = function() { 9 | this.isObserved = true 10 | } 11 | 12 | function FotonPar() { 13 | Foton.call(this) 14 | this.spin = 1 15 | } 16 | 17 | function FotonImpar() { 18 | Foton.call(this) 19 | this.spin = -1 20 | } 21 | 22 | function entrelaçar() { 23 | FotonPar.prototype = Object.create(Foton.prototype) 24 | FotonPar.prototype.constructor = FotonPar 25 | // FotonImpar.prototype = Object.create(Foton.prototype) 26 | // FotonImpar.prototype.constructor = FotonImpar 27 | } 28 | 29 | entrelaçar() 30 | 31 | const fotonPar = new Foton() 32 | const fotonImpar = new Foton() 33 | 34 | console.log('fotonPar', fotonPar) 35 | console.log('fotonImpar', fotonImpar) 36 | fotonPar.observe() 37 | console.log('fotonPar', fotonPar) 38 | console.log('fotonImpar', fotonImpar) 39 | // console.log('fotonImpar', fotonImpar) 40 | -------------------------------------------------------------------------------- /posts/sql/index.js: -------------------------------------------------------------------------------- 1 | // ``` 2 | // SELECT ci_cod, ci_titulo, ci_vm, ci_vr, ci_erro, ci_incerteza, ci_erro_incerteza, ci_criterio_aceitacao 3 | // FROM items 4 | // WHERE ci_vm <> "0,00" 5 | // GROUP BY ci_titulo 6 | // ORDER BY ci_vm ASC 7 | // ``` 8 | 9 | const reduzParaObjeto = (acc, cur) => Object.assign(acc, cur) 10 | 11 | const fields = ['ci_cod', 'ci_titulo', 'ci_vm', 'ci_vr', 'ci_erro', 'ci_incerteza'] 12 | 13 | const select = (e, i) => fields.map( (f, pos) => ({[f]: e[f]}) ) 14 | .reduce( reduzParaObjeto, {}) 15 | 16 | const where = (e, i) => e.ci_vm !== "0,00" 17 | 18 | const o_by = 'ci_vm' 19 | const order = {'ASC': (a, b) => a - b, 'DESC': (a, b) => a + b} 20 | const orderBy = (a, b) => 21 | order.ASC(parseFloat(a[o_by].replace(',', '.')),parseFloat(b[o_by].replace(',', '.'))) 22 | 23 | const g_by = 'ci_titulo' 24 | const groupBy = (select, element) => { 25 | (select[element[g_by]] = select[element[g_by]] || []).push(element) 26 | return select 27 | } 28 | 29 | const arr = require('./items.js') 30 | 31 | const resultado = arr.map(select).filter(where).sort(orderBy).reduce(groupBy, {}) 32 | 33 | console.log('resultado: \n', resultado) 34 | -------------------------------------------------------------------------------- /node/routes/automatizando-suas-rotas.md: -------------------------------------------------------------------------------- 1 | #PORRA ESSE BLOG ME FODEO!! 2 | 3 | 4 | #PERDI TODO O TEXTO!!!! 5 | 6 | 7 | Como eu perdi todo meu texto deixarei o código pelo menos para vocês, depois que eu me acalmar re-escrevo **essa bosta!!!** 8 | 9 | Primeiro o módulo para pegar os nomes dos módulos pelas suas pastas: 10 | 11 | ```js 12 | const fs = require('fs') 13 | const path = require('path') 14 | const MODULES_PATH = './server/modules' 15 | const IGNORE_MODULES = ['app', 'router'] 16 | 17 | const isDir = (srcpath, file) => fs.statSync(path.join(srcpath, file)).isDirectory() 18 | const getModules = (srcpath) => { 19 | return fs.readdirSync(srcpath).filter((module) => { 20 | return (isDir(srcpath, module) && !IGNORE_MODULES.includes(module.toLowerCase())) 21 | }) 22 | } 23 | 24 | module.exports = getModules(MODULES_PATH) 25 | ``` 26 | 27 | ```js 28 | const MODULES_PATH = './../../' 29 | const router = require('express').Router() 30 | 31 | router.get('/', function(request, response, next) { 32 | response.send('PONG') 33 | }) 34 | 35 | const modules = require('../../../../scripts/getModules.js') 36 | modules.map((el, i) => { 37 | router.use('/'+el.toLowerCase()+'s', require(MODULES_PATH+el+'/routes')) 38 | }) 39 | 40 | module.exports = router 41 | ``` 42 | -------------------------------------------------------------------------------- /posts/fullstack-boas-praticas.md: -------------------------------------------------------------------------------- 1 | # Boas práticas para desenvolver um sistema completo em JS 2 | 3 | Aqui irei abordar algumas boas práticas que eu sigo e sempre indico aos meus alunos. 4 | 5 | Então nosso sistema irá conter tanto o *Frontend* como o *Backend*, agora eu lhe pergunto: 6 | 7 | > Como você começaria suas pastas? 8 | 9 | **Eu começo separando em 2**: 10 | 11 | - client 12 | - server 13 | 14 | > Pronto assim já não deixamos muita bagunça na raíz! 15 | 16 | ## Server 17 | 18 | Na pasta do *Backend* é onde colocaremos nosso maravilindo Node.js, caso você queira iniciar um projeto com Express pode usar o `express-generator`: `npm i -g express-generator` 19 | 20 | Depois basta entrar na pasta `server` e executar: `express .` 21 | 22 | Você verá que ele irá criar os seguintes arquivos/pastas: 23 | 24 | - app.js 25 | - bin 26 | - package.json 27 | - public 28 | - routes 29 | - views 30 | 31 | **Agora irei dar uma dica MUITOOOO IMPORTANTE!!!** 32 | 33 | > Não separe suas pastas por funcionalidade, por exemplo: `controllers`, `schemas`, `routes`!!! 34 | 35 | > Sabe por quê? 36 | 37 | Pense comigo que temos o módulo de `User` e ele tem 1 controller.js, 1 schema.js, 1 model.js e 1 routes.js. Cada um em sua pasta separada, OK? 38 | 39 | Agora quando você for fazer o próximo sistema e quiser reutilizar esse módulo como você faria? 40 | 41 | > Entrando em cada pasta e copiando os arquivos? 42 | 43 | ![](https://media.giphy.com/media/O94iUIeEF8nwk/giphy.gif) 44 | 45 | > Podemos fazer bem melhor powww! 46 | 47 | Basta separar por módulos, por exemplo criando uma pasta `modules` e dentro dela a pasta `User` a qual conterá os seguintes arquivos: 48 | 49 | - controller.js 50 | - model.js 51 | - schema.js 52 | - routes.js 53 | 54 | Agora quando você quiser reaproveitar esse módulo basta copiar a pasta `User` e colar em `modules` do outro projeto! 55 | -------------------------------------------------------------------------------- /posts/vc-sabe-de-onde-vem-o-bit.md: -------------------------------------------------------------------------------- 1 | # Você sabe de onde vem o bit? 2 | 3 | Estava eu desafiando/ensinando alguns programadores iniciantes em um grupo no Telegram, onde questionei-os quem conseguiria inferir o que acontece [nesse exercício](https://github.com/Webschool-io/JavaScript-Obrigatorio/blob/master/docs/bitwise.md): 4 | 5 | ```js 6 | > 20..toString(2) 7 | '10100' 8 | > 20 >> 1 9 | 10 10 | > 20 >> 2 11 | 5 12 | > 20 >> 3 13 | 2 14 | > 10..toString(2) 15 | '1010' 16 | > 5..toString(2) 17 | '101' 18 | > 2..toString(2) 19 | '10' 20 | ``` 21 | 22 | > Você consegue inferir o que acontece? Bom mas esse não é foco desse artigo. 23 | 24 | ![imagine](http://www.localfoodscampus.com/explore/wp-content/uploads/2015/05/imagine.jpg) 25 | 26 | > Imagine um mundo feito apenas de 2 valores: 0 e 1. 27 | 28 | > **Se tivéssemos apenas 2 cores ia ser uma bosta né?!** 29 | 30 | > Então... toda a computação baseia-se apenas nesses valores. 31 | 32 | Se isso não deixar-lhe curioso não sei mais o que pode. 33 | 34 | > Consegue imaginar que tudo que você vê agora nessa tela pode ser resumido em agrupamentos de 0s e 1s. 35 | 36 | Para matar a sua curiosidade explicarei de forma bem simples como **o seu computador** trabalha, 37 | 38 | Deixar-lhe-eis com uma pergunta que minha mulher, química/professora, fez-me esses dias: 39 | 40 | > O que é o bit? Ele é elétrico, magnético, onda ou luz? 41 | 42 | **Ahhhhh essa é fácil né?!!!** 43 | 44 | > Depende. 45 | 46 | Antes de tudo você precisa saber de onde eles vêm. 47 | 48 | No seu computador, mais precisamente no seu processador, existem milhões de transistores, que são pecinhas, atualmente nanométricas, feitas de cristais de silício. E seu papel como protagonista é de "deixar passar" ou não uma corrente elétrica. 49 | 50 | > Como você imagina que isso seja possível? 51 | 52 | ![transistor](http://www.tandyonline.co.uk/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/b/c/bc635-transistor.png) 53 | 54 | > O transistor é considerado por muitos uma das maiores descobertas ou invenções da história moderna, tendo tornado possível a revolução dos computadores e equipamentos eletrônicos. 55 | 56 | > Por exemplo, o microprocessador Cell do console Playstation 3 tem aproximadamente 234 milhões de transistores, usando uma arquitetura de fabricação de 45 nanômetros, ou seja, a porta de controle de cada transistor tem apenas 45 milionésimos de um milímetro. 57 | 58 | 59 | ## Refêrencias teóricas 60 | 61 | - [Química Inorgânica não tão Concisa, Lee, J.D. - pag 35]() 62 | - [https://pt.wikipedia.org/wiki/Trans%C3%ADstor](https://pt.wikipedia.org/wiki/Trans%C3%ADstor) 63 | -------------------------------------------------------------------------------- /posts/privilegio-como-funciona.md: -------------------------------------------------------------------------------- 1 | # Privilégio - Como funciona 2 | 3 | 4 | **Esse artigo é uma cópia fiel de outro, porém como é deveras interessante ele merece um post só dele!** 5 | Ps: alguém lembrou da meritocracia? 6 | 7 | > Certa vez, vi um professor de ensino médio fazer um exercício simples para ensinar a seus alunos como funciona o privilégio e a mobilidade social. Ele começou dando a cada aluno um pedaço de rascunho e pediu que todos fizessem uma bolinha de papel. 8 | 9 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/11/enhanced/webdr12/enhanced-4566-1416587956-9.png?no-auto) 10 | 11 | > Então, ele apontou para a lixeira que estava na parte da frente da sala de aula. 12 | 13 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/14/enhanced/webdr10/enhanced-1247-1416597281-1.png?no-auto) 14 | 15 | > Ele disse: “A brincadeira é simples: vocês representam a população do país. E todo mundo tem a chance de ficar rico”. 16 | 17 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/14/enhanced/webdr07/enhanced-10891-1416597196-10.png?no-auto) 18 | 19 | > “Para isso, tudo o que vocês precisam fazer é acertar sua bolinha de papel na lixeira. Mas vocês não podem sair dos seus lugares.” 20 | 21 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/14/enhanced/webdr11/enhanced-22256-1416597441-1.png?no-auto) 22 | 23 | > Os alunos do fundo da sala imediatamente reclamaram, notando que os alunos das fileiras da frente tinham muito mais chances de conseguir acertar a lixeira. 24 | 25 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/14/enhanced/webdr06/enhanced-19008-1416597333-9.png?no-auto) 26 | 27 | > Todos tentaram e — conforme o esperado — a maioria dos alunos que estavam nas fileiras da frente conseguiu acertar a lixeira. No entanto, da parte de trás da sala, poucas pessoas acertaram. 28 | 29 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/14/enhanced/webdr10/enhanced-1262-1416597762-1.png?no-auto) 30 | 31 | > O professor concluiu a lição dizendo: “Quanto mais perto você estava da lixeira, maiores eram as suas chances. O privilégio é assim. Notaram que os únicos que reclamaram da injustiça estavam no fundo da sala?”. 32 | 33 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/13/enhanced/webdr05/enhanced-6523-1416593112-26.png?no-auto) 34 | 35 | > “Por outro lado, as pessoas que estavam na frente nem sempre notavam o seu privilégio. Tudo o que podiam ver eram os 3 metros entre elas e seu objetivo.” 36 | 37 | ![](https://img.buzzfeed.com/buzzfeed-static/static/2014-11/21/14/enhanced/webdr04/enhanced-20775-1416597017-2.png?no-auto) 38 | 39 | > **“A tarefa de vocês é estar ciente dos seus próprios privilégios. E utilizar esse privilégio específico que estão tendo agora, chamado ‘educação’, para fazer o seu melhor para atingir grandes feitos e defender aqueles que estão nas fileiras de trás.”** 40 | 41 | 42 | *fonte: [https://www.buzzfeed.com/nathanwpyle/este-professor-ensinou-aos-seus-alunos-uma-lieao-i](https://www.buzzfeed.com/nathanwpyle/este-professor-ensinou-aos-seus-alunos-uma-lieao-i)* 43 | -------------------------------------------------------------------------------- /posts/Strings-em-busca-da-substring-perfeita.md: -------------------------------------------------------------------------------- 1 | # Strings - Em busca da substring perfeita 2 | 3 | ![](https://string.se/wordpress/wp-content/themes/string/assets/images/logotype.png) 4 | 5 | A maioria dos programadores normalmente utiliza a função [indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) para verificar se existe uma *String* "dentro" da outra, vamos ver esse exemplo da [MDN](): 6 | 7 | ```js 8 | 'Blue Whale'.indexOf('Blue'); // returns 0 9 | 'Blue Whale'.indexOf('Blute'); // returns -1 10 | 'Blue Whale'.indexOf('Whale', 0); // returns 5 11 | 'Blue Whale'.indexOf('Whale', 5); // returns 5 12 | 'Blue Whale'.indexOf(''); // returns 0 13 | 'Blue Whale'.indexOf('', 9); // returns 9 14 | 'Blue Whale'.indexOf('', 10); // returns 10 15 | 'Blue Whale'.indexOf('', 11); // returns 10 16 | ``` 17 | 18 | Caso não encontre a substring a função retorna `-1`, caso encontre retornará sua posição em relação a *String*, porém possuimos outras funções que podem nos auxiliar nisso e, para mim, são melhores quando quero testar apenas se aquela substring exsite dentro da *String*. 19 | 20 | ## startsWith 21 | 22 | Vamos **iniciar** com a [startsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith), se você entende Inglês deve ter entendido minha tentativa de piada se você não entende então saiba que essa função serve para pesquisar se a *String* começa com a substring, por exemplo: 23 | 24 | 25 | ```js 26 | const str = 'É nóis que voa bruxão' 27 | 28 | console.log(str.startsWith('É nois')) // true 29 | console.log(str.startsWith('que voa')) // false 30 | console.log(str.startsWith('bruxão', 15)) // true 31 | ``` 32 | 33 | Você deve ter percebido que se passarmos, como segundo parâmetro, a posição de início da busca podemos fazer essa pesquisa em qualquer parte da *String*, fora que ela retorna `true/false` o que normalmente é o valor que necessito. 34 | 35 | ## endsWith 36 | 37 | Mas não vamos **terminar** por aí, ainda temos a [endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith) que é basicamente o contrário da `startsWith`, com a diferença que a posição passada como segundo parâmetro será a definição do tamanho total para a busca nessa *String*, como podemos ver abaixo: 38 | 39 | ```js 40 | const str = 'É nóis que voa bruxão' 41 | 42 | console.log(str.endsWith('É nois')) // false 43 | console.log(str.endsWith('que voa', 14)) // true 44 | console.log(str.endsWith('bruxão')) // true 45 | ``` 46 | 47 | ## includes 48 | 49 | Porém a que eu mais uso é a [includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes) que faz essa busca em qualquer posição da *String* e a posição passada no segundo parâmetro é a definição do início da busca, bem simples também: 50 | 51 | 52 | ```js 53 | const str = 'É nóis que voa bruxão' 54 | 55 | console.log(str.includes('É nois', 1)) // false 56 | console.log(str.includes('que voa')) // true 57 | console.log(str.includes('bruxão')) // true 58 | ``` 59 | 60 | Agora quando você for fazer aquele teste com `indexOf` dentro de um `if` lembre que existem outras funções, beleza?? 61 | 62 | ## Dicas 63 | 64 | Aproveitando o ensejo darei ua dica marota de como capitalizar uma palavra ou frase: 65 | 66 | ```js 67 | const s = 'suissa' 68 | s[0].toUpperCase() + s.slice(1) //'Suissa' 69 | ``` 70 | 71 | Marotagem da boa essa né?? 72 | -------------------------------------------------------------------------------- /posts/entrelacamento-quantico.md: -------------------------------------------------------------------------------- 1 | # O entrelaçamento quântico e o JavaScript 2 | 3 | ![](http://www.sciencealert.com/images/articles/processed/Quantum-Entanglement_1024.jpg) 4 | 5 | Como muitos sabem eu amo Física Quântica, não a toa adicionei o conceito de [Bóson]() e [Quark]() no [Atomic Design]() (Frontend) e no meu Atomic Design no Backend além do Quark também adicionei o [Hádron](), por isso quando estava vendo [esse vídeo](https://www.youtube.com/watch?v=NqsAMlWlhRM) no Youtube na hora me veio a cabeça duas coisas: 6 | 7 | - prototype 8 | - events 9 | 10 | Espero que você esteja se perguntando o porquê pois eu irei discorrer sobre, entretanto precisamos entender sobre esse conceito que é deveras interessante. 11 | 12 | 13 | > O entrelaçamento quântico (ou emaranhamento quântico, como é mais conhecido na comunidade científica) é um fenômeno da mecânica quântica que permite que dois ou mais objetos estejam de alguma forma tão ligados que um objeto não possa ser corretamente descrito sem que a sua contra-parte seja mencionada - mesmo que os objetos possam estar espacialmente separados por milhões de anos-luz. Isso leva a correlações muito fortes entre as propriedades físicas observáveis das diversas partículas subatômicas. 14 | Essas fortes correlações fazem com que as medidas realizadas numa delas pareçam estar a influenciar instantaneamente à outra com a qual ficou entrelaçada, e sugerem que alguma influência estaria a propagar-se instantaneamente, apesar da separação entre eles. Mas o entrelaçamento quântico não permite a transmissão a uma velocidade superior à da velocidade da luz, porque nenhuma informação útil pode ser transmitida desse modo. Só é possível a transmissão de informação usando um conjunto de estados entrelaçados em conjugação com um canal de informação clássico - aquilo a que se chama o teletransporte quântico. Isto dá a entender que tudo está conectado por "forças" que não vemos e que permanecem no tempo, ou estão fora do sistema que denominamos, entendemos ou concebemos como sistema temporal. 15 | 16 | *fonte: [https://pt.wikipedia.org/wiki/Entrela%C3%A7amento_qu%C3%A2ntico](https://pt.wikipedia.org/wiki/Entrela%C3%A7amento_qu%C3%A2ntico)* 17 | 18 | > Na teoria, o entrelaçamento acontece quando duas partículas continuam conectadas apesar de estarem separadas. Dessa forma, o que acontece em uma partícula é refletido na outra. Por exemplo, um spin no sentido horário na primeira partícula será equivalente a um spin no sentido anti-horário na segunda, com o spin combinado das duas sendo zero. No entanto, medir uma partícula pode ser uma ação sobre ela, que, por sua vez, afetaria a outra partícula. Então seria impossível saber se a ação na segunda partícula é um resultado do entrelaçamento ou da medição. 19 | 20 | *fonte: [http://revistagalileu.globo.com/Ciencia/noticia/2015/03/pesquisadores-demonstram-o-entrelacamento-quantico-entre-uma-particula-e-provam-que-einstein-estava-errado.html](http://revistagalileu.globo.com/Ciencia/noticia/2015/03/pesquisadores-demonstram-o-entrelacamento-quantico-entre-uma-particula-e-provam-que-einstein-estava-errado.html)* 21 | 22 | ![](http://cdn.zmescience.com/wp-content/uploads/2012/09/entangled_sm.jpg) 23 | 24 | Creio que depois desse embasamento físico-teórico podemos partir para o código. 25 | 26 | Inicialmente farei uma analogia entre como criar um par de fótons entrelaçados e Objetos no JavaScript, pelo nome "entrelaçamento/emaranhamento" podemos imaginar que devemos unir/juntar 2 fótons, porém na prática é o contrário. 27 | 28 | Para criarmos um par de fótons entrelaçados devemos disparar um fóton contra um espelho que deve estar a 45 graus, para que ele possa dividir o fóton em dois, onde um terá spin -1 e o outro +1, para que sua soma seja 0. 29 | 30 | Então vamos traduzir isso em código: 31 | 32 | ``` 33 | > const foton = {spin: 0} 34 | 35 | > const entrelace = (foton) => Object.create(foton) 36 | 37 | > fotonPar = entrelace(foton) 38 | {} 39 | > fotonImpar = entrelace(foton) 40 | {} 41 | > fotonPar.spin 42 | 0 43 | > fotonImpar.spin 44 | 0 45 | > fotonPar.spin = 1 46 | 1 47 | > fotonImpar.spin = -1 48 | -1 49 | > fotonPar 50 | { spin: 1 } 51 | > fotonImpar 52 | { spin: -1 } 53 | ``` 54 | 55 | 56 | https://en.wikipedia.org/wiki/Photon -------------------------------------------------------------------------------- /posts/map-filter-reduce-para-iniciantes.md: -------------------------------------------------------------------------------- 1 | # Iniciantes 2 | 3 | Explicação **didática** sobre `map`, `filter` e `reduce`, dando um exemplo de cada para todas as disciplinas escolares. Ideias são sempre bem-vindas! 4 | 5 | > Mapeie os bons momentos, filtre suas companhias e reduza o stress. 6 | 7 | ## map 8 | 9 | Mapeia cada valor do array para um valor novo. 10 | 11 | ``` 12 | const fn = (elemento, posicao) => console.log(elemento, posicao) 13 | arr.map(fn) 14 | ``` 15 | 16 | Problemas que resolve: 17 | 18 | - modificação dos valores atuais 19 | - modificação das posições atuais 20 | 21 | ```js 22 | const NUMEROS = [1, 2, 3, 4, 5, 6, 7, 8, 9] 23 | 24 | const mapear = (arr, fn) => arr.map(fn) 25 | 26 | const elevadoAoQuadrado = (num) => num * num 27 | const elevadoAoCubo = (num) => num * num * num 28 | const posicoes = (num, posicao) => { 29 | if (posicao % 2 === 0) return 'posição par: ' + posicao 30 | else return 'posição ímpar: ' + posicao 31 | } 32 | const andaUmaPosicao = (num, posicao) => { 33 | if (posicao === 0) return NUMEROS[posicao+1] 34 | if (posicao !== NUMEROS.length-1 && posicao > 0) return NUMEROS[posicao+1] 35 | else return NUMEROS[0] 36 | } 37 | // Em uma linha com IF ternário 38 | //const posicoes = (num, posicao) => (posicao % 2 === 0) ? `posição par: ${posicao}` : `posição ímpar: ${posicao}` 39 | 40 | 41 | const aoQuadrado = mapear(NUMEROS, elevadoAoQuadrado) 42 | // [ 1, 4, 9, 16, 25, 36, 49, 64, 81 ] 43 | const aoCubo = mapear(NUMEROS, elevadoAoCubo) 44 | // [ 1, 8, 27, 64, 125, 216, 343, 512, 729 ] 45 | const posicoesNoArray = mapear(NUMEROS, posicoes) 46 | /* [ 'posição par: 0', 47 | 'posição ímpar: 1', 48 | 'posição par: 2', 49 | 'posição ímpar: 3', 50 | 'posição par: 4', 51 | 'posição ímpar: 5', 52 | 'posição par: 6', 53 | 'posição ímpar: 7', 54 | 'posição par: 8' ] 55 | */ 56 | const umaPosicaoParaFrente = mapear(NUMEROS, andaUmaPosicao) 57 | // [ 2, 3, 4, 5, 6, 7, 8, 9, 1 ] 58 | 59 | const tudoJuntoEMisturado = NUMEROS.map(andaUmaPosicao).map(elevadoAoQuadrado).map(elevadoAoCubo) 60 | // [ 64, 729, 4096, 15625, 46656, 117649, 262144, 531441, 1 ] 61 | ``` 62 | 63 | ## filter 64 | 65 | Fltra cada valor do array, caso o mesmo passe pelo teste condicional ele será adicionado à resposta. 66 | 67 | ``` 68 | const fn = (elemento) => { 69 | if (elemento > 3 ) return elemento 70 | } 71 | arr.map(fn) 72 | ``` 73 | 74 | Problemas que resolve: 75 | 76 | - remoção dos elementos não desejados 77 | 78 | ```js 79 | const filtrar = (arr, fn) => arr.filter(fn) 80 | 81 | const apenasPares = (num) => (num % 2 === 0) 82 | const apenasImpares = (num) => (num % 2 !== 0) 83 | 84 | const pares = filtrar(NUMEROS, apenasPares) 85 | const impares = filtrar(NUMEROS, apenasImpares) 86 | ``` 87 | 88 | ## reduce 89 | 90 | Reduz todos os elementos em apenas 1. 91 | 92 | ``` 93 | const fn = (acumulador, atual) => acumulador + atual 94 | arr.reduce(fn) 95 | ``` 96 | 97 | Problemas que resolve: 98 | 99 | - somatória 100 | - média 101 | - criação de 1 novo Objeto ou Array 102 | - uma caralhada 103 | 104 | ```js 105 | const reduzir = (arr, fn) => arr.reduce(fn) 106 | 107 | ``` 108 | 109 | ## Exemplos didáticos 110 | 111 | ### Matemática 112 | 113 | #### map 114 | 115 | ``` 116 | 117 | O conjunto A possui números inteiros e você precisa transformar todos seus elementos para o seu quadrado, como visto na imagem abaixo: 118 | 119 | ``` 120 | 121 | ![Conjunto a ser transformado](https://raw.githubusercontent.com/suissa/blog/master/images/conjunto-map.jpg) 122 | 123 | #### filter 124 | 125 | ``` 126 | 127 | Dado o conjunto A de números inteiros e positivos, filtre apenas os números primos. 128 | 129 | ``` 130 | 131 | 132 | #### reduce 133 | 134 | 135 | ``` 136 | 137 | Dada uma PG finita qualquer com n elemento, ou seja, com a quantidade de elementos indefinida. PG finita (a1, a2, a3, ... , an). 138 | 139 | ``` 140 | 141 | 142 | ### Física 143 | 144 | #### map 145 | 146 | #### filter 147 | 148 | #### reduce 149 | 150 | ### Química 151 | 152 | #### map 153 | 154 | 155 | ``` 156 | 157 | Reação de dupla troca. 158 | 159 | ``` 160 | 161 | 162 | #### filter 163 | 164 | ``` 165 | 166 | Filtragem de sólido de uma solução aquosa. 167 | 168 | ``` 169 | 170 | 171 | #### reduce 172 | 173 | ``` 174 | 175 | Reação de síntese. 176 | 177 | ``` 178 | 179 | ### Biologia 180 | 181 | #### map 182 | 183 | #### filter 184 | 185 | #### reduce 186 | 187 | ### Português 188 | 189 | #### map 190 | 191 | #### filter 192 | 193 | #### reduce -------------------------------------------------------------------------------- /traducoes/What does const stand for in ES6?/readme.md: -------------------------------------------------------------------------------- 1 | https://medium.com/the-node-js-collection/what-does-const-stand-for-in-es6-f7ab3d9e06fc 2 | 3 | # O que significa `const` no ES6? 4 | 5 | 6 | Se você vem de uma linguagem de programação *C-like*, você pode se perguntar por que o primeiro código JavaScript ES6 é válido, mas o segundo programa C (como você bem sabe) fará com que o compilador falhe. 7 | 8 | ``` 9 | 10 | # JavaScript 11 | const numbers = [1, 2, 3, 4, 6] 12 | numbers[4] = 5 13 | console.log(numbers[4]) // print 5 14 | 15 | # C 16 | const int numbers[] = {1, 2, 3, 4, 6}; 17 | numbers[4] = 5; // error: read-only variable is not assignable 18 | printf("%d\n", numbers[4]); 19 | 20 | ``` 21 | 22 | A razão pela qual é porque em C, `const` define uma variável somente leitura que não é modificável, enquanto que em JavaScript, não se trata de imutabilidade de valor. Ele não indica que o valor de uma variável é constante ou somente leitura. Em vez disso, ele cria uma vinculação imutável (uma referência somente leitura para o valor) e garante que nenhuma reatribuição acontecerá. Com isso dito, o código a seguir irá lançar um erro em tempo de execução. 23 | 24 | ``` 25 | 26 | const numbers = [1, 2, 3, 4, 6] 27 | numbers = [7, 8, 9, 10, 11] // error: assignment to constant variable 28 | console.log(numbers[4]) 29 | 30 | ``` 31 | 32 | 33 | Para entender melhor o conceito de variável, vamos examinar a seguinte imagem onde a relação genérica entre um identificador de variável (ou nome de variável), seu valor e a memória física está sendo explicada. 34 | 35 | ![](https://cdn-images-1.medium.com/max/800/1*Rl6eVEft2iRERw3VbEkzRw.png) 36 | 37 | Como você pode ver a partir da imagem, um identificador de variável se refere a uma célula de memória física através de um endereço (referência) em que o valor atribuído à variável é armazenado. Uma variável somente leitura não permite que seu valor seja alterado. Uma referência somente leitura para o valor simplesmente não permite que o identificador de variável seja reatribuído, mas o valor mantido pelo próprio identificador ainda pode ser alterado. Por exemplo, em JavaScript, quando o valor é um objeto, o próprio objeto pode ser alterado. 38 | 39 | ## Como tornar um valor imutável 40 | 41 | 42 | [Tipos de dados primitivos](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures) são sempre imutáveis ​​por causa de sua natureza. O snippet de código a seguir explica intuitivamente o porquê. 43 | 44 | 45 | ``` 46 | 47 | # Example 1 48 | const a = 10 49 | a = a + 1 // error: assignment to constant variable 50 | # Example 2 51 | const isTrue = true 52 | isTrue = false // error: assignment to constant variable 53 | # Example 3 54 | const sLower = 'hello world' 55 | const sUpper = sLower.toUpperCase() // create a new string 56 | console.log(sLower) // print hello world 57 | console.log(sUpper) // print HELLO WORLD 58 | 59 | ``` 60 | 61 | 62 | Para tornar imutáveis ​​os valores de um objeto, você pode usar `Object.freeze()`. No entanto, ele só funciona em objetos de par de valor de propriedade, o que significa que ele não funcionará com outros objetos, como `Date`, `Map` and `Set`. 63 | 64 | ``` 65 | 66 | # Example 4 67 | const me = Object.freeze({name: “Jacopo”}) 68 | me.age = 28 69 | console.log(me.age) // print undefined 70 | # Example 5 71 | const arr = Object.freeze([-1, 1, 2, 3]) 72 | arr[0] = 0 73 | console.log(arr[0]) // print -1 74 | # Example 6 75 | const me = Object.freeze({ 76 | name: 'Jacopo', 77 | pet: { 78 | type: 'dog', 79 | name: 'Spock' 80 | } 81 | }) 82 | me.pet.name = 'Rocky' 83 | me.pet.breed = 'German Shepherd' 84 | console.log(me.pet.name) // print Rocky 85 | console.log(me.pet.breed) // print German Shepherd 86 | 87 | ``` 88 | 89 | Como você pode ver no último exemplo, objetos aninhados dentro de um objeto congelado ainda podem ser mutados. Para tornar os valores de objeto totalmente imutáveis, convém usar um método `deepFreeze()`` personalizado. Outra opção é usar [Immutable.js](https://facebook.github.io/immutable-js/), uma biblioteca que simplesmente não transforma objetos em imutáveis, mas sim fornece muitas estruturas de dados persistentes imutáveis, incluindo *List*, *Stack*, *Map*, *OrderedMap*, *Set*, *OrderedSet* e *Record*. 90 | 91 | 92 | 93 | ## var, let ou const? 94 | 95 | > **Por favor leia com atenção a afirmação abaixo! ** 96 | 97 | No ES6, os desenvolvedores **NUNCA** devem usar `var` para definir uma variável ou uma constante. Na verdade, agora é o sinal mais fraco disponível quando você define uma variável em JavaScript. 98 | 99 | 100 | 101 | Uma variável bem definida não deve ser usada para representar conceitos múltiplos. Isso garante que o código é mais limpo e mais compreensível. Como no JavaScript `const` significa que o identificador não pode ser reatribuído, é preferível usar `const` para todos os identificadores no programa que não devem ser reatribuídos. No entanto, quando os identificadores precisam ser reatribuídos, os programadores então devem usar `let`. Este é geralmente o caso de contadores em uma construção de *loop* ou troca/swap de valores em sub-rotinas de algoritmos. 102 | 103 | 104 | ## Dever de casa 105 | 106 | Recapitulando os *insights*: se você programa com ES6, use `const` por padrão, não use `var`, e use `let` onde reatribuição é necessária. 107 | 108 | 109 | 110 | ## Adendo do Suissa 111 | 112 | 113 | Como eu sempre digo aos meus alunos... -------------------------------------------------------------------------------- /posts/my-atyomic-design-patterns.md: -------------------------------------------------------------------------------- 1 | # My Atomic Design Patterns 2 | 3 | Como no Atomic Design tudo deve começar do micro para o macro precisamos pensar um pouco diferente do normal, não iniciamos pensando no objeto como um todo, mas sim nas partes que compõe o mesmo. 4 | 5 | > Quando falo sobre *Atomic* o que vem na sua mente? 6 | 7 | > Provavelmente você, pela tradução automática, deve ter falado átomo, correto? 8 | 9 | Perfeito! Agora vamos pensar qual seria sua funcionalidade maior. 10 | 11 | Tudo que "observamos" no Universo é constituído de átomos, porém se eles não se ligassem não teríamos o Universo como ele é, pois a "matéria" que realmente percebemos é uma composição desses átomos. 12 | 13 | Antes de continuarmos precisamos lembrar dos conceitos de agregação e composição, até porque eu mesmo inverto eles as vezes. 14 | 15 | Baseando-se na [UML]() podemos dizer que: 16 | 17 | > Agregação é um relacionamento onde a **parte** pode existir independentemente do **todo**. Exemplo: e Estudante, se você fechar a Escola (olá Alckmin) os Estudantes ainda existirão. 18 | > 19 | > (colcoar exemplo da Feijoada) 20 | > 21 | > > Composição é um relacionamento onde a **parte** não pode existir independentemente do **todo**. Exemplo: Porco e Bacon, se não existir o Porco o Bacon **não** existirá mais. 22 | 23 | Sabendo disso e que uma Molécula é *feita* de átomos, podemos inferir que a Molécula é uma agregação de Átomos, pois se a mesma não existisse ainda teríamos os Átomos. 24 | 25 | Farei um leve adendo químico agora. 26 | 27 | O estado fundamental do elemento é formado por 1 par de átomos, você não encontrará na natureza um átomo de Ferro sozinho, por exemplo, ele sempre estará ligado a outro igual. 28 | **Entretanto* os gases nobres não fazem ligação com ninguém**, por isso os Átomos, pelo menos dos gases nobres, podem existir sem necessitar de uma Molécula. 29 | 30 | Para demonstrar esse conceito mais facilmente vamos conferir o código abaixo: 31 | 32 | ```js 33 | let Agua = { 34 | atoms: ['H', 'H', 'O'] 35 | } 36 | 37 | const destroiAgua = () => Agua = null 38 | 39 | destroiAgua() 40 | 41 | const mostraElemento = (elemento) => console.log(elemento) 42 | 43 | mostraElemento(Agua) //null 44 | ``` 45 | 46 | Porém nesse código se destruirmos a Molécula seus átomos deixarão de existir pois foram criados "dentro delas", para colocarmos no conceito visto anteriormente precisamos separar os Átomos das Moléculas, conceitualmente podemos fazer assim: 47 | 48 | ```js 49 | let H = {protons: 1, neutrons: 0, eletrons: 1} 50 | let O = {protons: 8, neutrons: 8, eletrons: 8} 51 | let Agua = { 52 | atoms: [H, H, O] 53 | } 54 | 55 | const destroiAgua = () => Agua = null 56 | 57 | destroiAgua() 58 | 59 | const mostraElemento = (elemento) => console.log(elemento) 60 | 61 | mostraElemento(Agua) // null 62 | mostraElemento(H) // {protons: 1, neutrons: 0, eletrons: 1} 63 | mostraElemento(O) // {protons: 8, neutrons: 8, eletrons: 8} 64 | ``` 65 | 66 | Dessa forma nós estamos criando a molécula da água agregando os átomos de Hidrogênio e Oxigênio, entretanto para essa criação ocorrer existe a necessidade de uma reação chamada de síntese, onde duas ou mais substâncias se unem para formar **apenas** uma substância composta. 67 | 68 | Levando esse conceito para a programação podemos dizer que essa reação é uma construtora da molécula, para que ela seja criada é necessário que ela receba os átomos que a constituirão, por exemplo: 69 | 70 | ```js 71 | const mostraElemento = (elemento) => console.log(elemento) 72 | 73 | let H = {protons: 1, neutrons: 0, eletrons: 1} 74 | let O = {protons: 8, neutrons: 8, eletrons: 8} 75 | 76 | function Molecula (atomos) { this.atomos = atomos } 77 | 78 | let Agua = new Molecula([H, H, O]) 79 | 80 | mostraElemento(Agua) 81 | /* 82 | Molecula { 83 | atomos: 84 | [ { protons: 1, neutrons: 0, eletrons: 1 }, 85 | { protons: 1, neutrons: 0, eletrons: 1 }, 86 | { protons: 8, neutrons: 8, eletrons: 8 } ] } 87 | */ 88 | 89 | const destroiAgua = () => Agua = null 90 | 91 | destroiAgua() 92 | 93 | mostraElemento(Agua) // null 94 | mostraElemento(H) // {protons: 1, neutrons: 0, eletrons: 1} 95 | mostraElemento(O) // {protons: 8, neutrons: 8, eletrons: 8} 96 | ``` 97 | 98 | Agora possuímos uma função construtora para qualquer tipo de Molécula, entretanto essas Moléculas podem reagir com outras e também com Átomos. 99 | 100 | Na Química (Inorgânica) existem quatro reações básicas: 101 | 102 | - Síntese 103 | - Decomposição 104 | - Simples Troca 105 | - Dupla Troca 106 | 107 | Vamos inciar falando apenas das duas primeiras, já que uma é o inverso da outra, só pelo seus nomes já podemos imaginar o que fazem. 108 | 109 | Na Síntese dois ou mais átomos devem reagir para formar uma substância. 110 | Na Decomposição uma substância irá ser dividida em duas ou mais substâncias menores. 111 | 112 | Levando isso em consideração, vamos criar essas reações. (utilizando o código anterior como base) 113 | 114 | ```js 115 | // Adicionado ao código anterior 116 | const agregar = Object.assign 117 | const sintetizar = (molecula, substancia) => agregar(molecula, substancia) 118 | const Sintese = (substancias) => substancias.reduce(sintetizar, {}) 119 | 120 | 121 | let N = {protons: 7, neutrons: 0, eletrons: 7} 122 | let N2 = new Molecula([N, N]) 123 | /* Molecula { 124 | atomos: 125 | [ { protons: 4, neutrons: 0, eletrons: 4 }, 126 | { protons: 4, neutrons: 0, eletrons: 4 } ] 127 | }*/ 128 | let H2 = new Molecula([H, H])/* Molecula { 129 | atomos: 130 | [ { protons: 1, neutrons: 0, eletrons: 1 }, 131 | { protons: 1, neutrons: 0, eletrons: 1 } ] 132 | }*/ 133 | let Amonia = Sintese([N2, H2]) 134 | /* 135 | Amonia 136 | { atomos: 137 | [ { protons: 4, neutrons: 0, eletrons: 4 }, 138 | { protons: 1, neutrons: 0, eletrons: 1 } ] } 139 | */ 140 | 141 | ``` -------------------------------------------------------------------------------- /posts/sql/items.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | "ci_cod": 11122016100, 4 | "ci_titulo": "MEDIÇÕES EXTERNA", 5 | "ci_vm": "0,00", 6 | "ci_vr": "0,00", 7 | "ci_erro": "0,00", 8 | "ci_incerteza": "0,00", 9 | "ci_unidade": "mm", 10 | "ci_erro_incerteza": "0,00", 11 | "ci_criterio_aceitacao": "0,00", 12 | "ci_situacao": "------", 13 | "_id": "584e2f7a3e663748e71c1fd3", 14 | "ci_subtitulo": false 15 | }, 16 | { 17 | "ci_cod": 11122016101, 18 | "ci_titulo": "MEDIÇÕES EXTERNA", 19 | "ci_vm": "1,30", 20 | "ci_vr": "1,30", 21 | "ci_erro": "0,00", 22 | "ci_incerteza": "0,01", 23 | "ci_unidade": "mm", 24 | "ci_erro_incerteza": "0,01", 25 | "ci_criterio_aceitacao": "0,18", 26 | "ci_situacao": "aprovado", 27 | "_id": "584e2f7a3e663748e71c1fd2", 28 | "ci_subtitulo": false 29 | }, 30 | { 31 | "ci_cod": 11122016102, 32 | "ci_titulo": "MEDIÇÕES EXTERNA", 33 | "ci_vm": "100,00", 34 | "ci_vr": "100,00", 35 | "ci_erro": "0,00", 36 | "ci_incerteza": "0,01", 37 | "ci_unidade": "mm", 38 | "ci_erro_incerteza": "0,01", 39 | "ci_criterio_aceitacao": "0,18", 40 | "ci_situacao": "aprovado", 41 | "_id": "584e2f7a3e663748e71c1fd1", 42 | "ci_subtitulo": false 43 | }, 44 | { 45 | "ci_cod": 11122016103, 46 | "ci_titulo": "MEDIÇÕES EXTERNA", 47 | "ci_vm": "200,00", 48 | "ci_vr": "200,00", 49 | "ci_erro": "0,00", 50 | "ci_incerteza": "0,01", 51 | "ci_unidade": "mm", 52 | "ci_erro_incerteza": "0,01", 53 | "ci_criterio_aceitacao": "0,18", 54 | "ci_situacao": "aprovado", 55 | "_id": "584e2f7a3e663748e71c1fd0", 56 | "ci_subtitulo": false 57 | }, 58 | { 59 | "ci_cod": 11122016104, 60 | "ci_titulo": "MEDIÇÕES EXTERNA", 61 | "ci_vm": "300,00", 62 | "ci_vr": "300,00", 63 | "ci_erro": "0,00", 64 | "ci_incerteza": "0,01", 65 | "ci_unidade": "mm", 66 | "ci_erro_incerteza": "0,01", 67 | "ci_criterio_aceitacao": "0,18", 68 | "ci_situacao": "aprovado", 69 | "_id": "584e2f7a3e663748e71c1fcf", 70 | "ci_subtitulo": false 71 | }, 72 | { 73 | "ci_cod": 11122016105, 74 | "ci_titulo": "MEDIÇÕES EXTERNA", 75 | "ci_vm": "500,00", 76 | "ci_vr": "500,00", 77 | "ci_erro": "0,00", 78 | "ci_incerteza": "0,01", 79 | "ci_unidade": "mm", 80 | "ci_erro_incerteza": "0,01", 81 | "ci_criterio_aceitacao": "0,18", 82 | "ci_situacao": "aprovado", 83 | "_id": "584e2f7a3e663748e71c1fce", 84 | "ci_subtitulo": false 85 | }, 86 | { 87 | "ci_cod": 11122016106, 88 | "ci_titulo": "MEDIÇÕES EXTERNA", 89 | "ci_vm": "592,00", 90 | "ci_vr": "592,00", 91 | "ci_erro": "0,00", 92 | "ci_incerteza": "0,01", 93 | "ci_unidade": "mm", 94 | "ci_erro_incerteza": "0,01", 95 | "ci_criterio_aceitacao": "0,18", 96 | "ci_situacao": "aprovado", 97 | "_id": "584e2f7a3e663748e71c1fcd", 98 | "ci_subtitulo": false 99 | }, 100 | { 101 | "ci_cod": 11122016107, 102 | "ci_titulo": "MEDIÇÃO INTERNA", 103 | "ci_vm": "40,00", 104 | "ci_vr": "39,998", 105 | "ci_erro": "0,002", 106 | "ci_incerteza": "0,010", 107 | "ci_unidade": "0", 108 | "ci_erro_incerteza": "0,012", 109 | "ci_criterio_aceitacao": "0,18", 110 | "ci_situacao": "aprovado", 111 | "_id": "584e2f7a3e663748e71c1fcc", 112 | "ci_subtitulo": false 113 | }, 114 | { 115 | "ci_cod": 11122016108, 116 | "ci_titulo": "MEDIÇÃO PROFUNDIDADE", 117 | "ci_vm": "0,00", 118 | "ci_vr": "0,00", 119 | "ci_erro": "0,00", 120 | "ci_incerteza": "0,00", 121 | "ci_unidade": "0,00", 122 | "ci_erro_incerteza": "0,00", 123 | "ci_criterio_aceitacao": "0,00", 124 | "ci_situacao": "-------", 125 | "_id": "584e2f7a3e663748e71c1fcb", 126 | "ci_subtitulo": false 127 | }, 128 | { 129 | "ci_cod": 11122016109, 130 | "ci_titulo": "MEDIÇÃO RESSALTO", 131 | "ci_vm": "50,00", 132 | "ci_vr": "50,00", 133 | "ci_erro": "0,00", 134 | "ci_incerteza": "0,01", 135 | "ci_unidade": "mm", 136 | "ci_erro_incerteza": "0,01", 137 | "ci_criterio_aceitacao": "0,18", 138 | "ci_situacao": "aprovado", 139 | "_id": "584e2f7a3e663748e71c1fca", 140 | "ci_subtitulo": false 141 | }, 142 | { 143 | "ci_cod": 11122016110, 144 | "ci_titulo": "PARELELISMO", 145 | "ci_vm": "0,00", 146 | "ci_vr": "0,00", 147 | "ci_erro": "0,00", 148 | "ci_incerteza": "0,00", 149 | "ci_unidade": "-------", 150 | "ci_erro_incerteza": "0,00", 151 | "ci_criterio_aceitacao": "0,00", 152 | "ci_situacao": "-------", 153 | "_id": "584e2f7a3e663748e71c1fc9", 154 | "ci_subtitulo": false 155 | }, 156 | { 157 | "ci_cod": 11122016111, 158 | "ci_titulo": "EXTERNA", 159 | "ci_vm": "25,00", 160 | "ci_vr": "25,00", 161 | "ci_erro": "0,00", 162 | "ci_incerteza": "0,01", 163 | "ci_unidade": "mm", 164 | "ci_erro_incerteza": "0,01", 165 | "ci_criterio_aceitacao": "0,18", 166 | "ci_situacao": "aprovado", 167 | "_id": "584e2f7a3e663748e71c1fc8", 168 | "ci_subtitulo": false 169 | }, 170 | { 171 | "ci_cod": 11122016112, 172 | "ci_titulo": "INTERNA", 173 | "ci_vm": "0,00", 174 | "ci_vr": "0,00", 175 | "ci_erro": "0,00", 176 | "ci_incerteza": "0,00", 177 | "ci_unidade": "-------", 178 | "ci_erro_incerteza": "0,00", 179 | "ci_criterio_aceitacao": "0,00", 180 | "ci_situacao": "-------", 181 | "_id": "584e2f7a3e663748e71c1fc7", 182 | "ci_subtitulo": false 183 | } 184 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Suissa´s blog 2 | 3 | **Último POST** 4 | 5 | 6 | ![](https://raw.githubusercontent.com/suissa/blog/master/images/fb-desafio-array.png) 7 | 8 | [Link para a pergunta](https://www.facebook.com/groups/nodejsbrasil/permalink/938231559643465/) 9 | 10 | E como eu não gostei de nenhuma das respostas dadas, como podem ver abaixo, quis resolver de outra forma. 11 | 12 | **Não que seja a melhor e nem *funcional* é uma forma diferente de se resolver o mesmo problema.** O intuito aqui no  mostrar a mais correta nem a mais veloz, apenas mostrar outra opção. 13 | 14 | ![](https://raw.githubusercontent.com/suissa/blog/master/images/fb-desafio-array1.png) 15 | 16 | ![](https://raw.githubusercontent.com/suissa/blog/master/images/fb-desafio-array2.png) 17 | 18 | ## Minha Solução 19 | 20 | Como eu não sou bobo nem nada reaproveitei as funções puras [de uma das repostas](https://jsfiddle.net/y6obeg0t/): 21 | 22 | 23 | ```js 24 | const primeira = (el, i) => Math.pow(el, 2) 25 | const segunda = (el, i) => el + '' 26 | const terceira = (el, i) => el * -1 27 | ``` 28 | 29 | Beleza já temos as três funções que irão gerar os novos valores. 30 | 31 | > E agora? Uso o `map`, `reduce`, `forEach`? 32 | 33 | Como eu tenho um grande apreço pelo [Array.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), fiz há algum tempo esse módulo do npm [atomic-array](https://www.npmjs.com/package/atomic-array) utilizando-o, escolhi ele. 34 | 35 | > **Não se engane!** 36 | > 37 | > Não foi apenas uma questão de gosto pessoal. 38 | 39 | 40 | Entre na [documentação do Array.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) e leia essa parte: *Using arrow functions and Array.from*. 41 | 42 | ```js 43 | // Using an arrow function as the map function to 44 | // manipulate the elements 45 | Array.from([1, 2, 3], x => x + x); 46 | // [2, 4, 6] 47 | 48 | 49 | // Generate a sequence of numbers 50 | Array.from({length: 5}, (v, k) => k); 51 | // [0, 1, 2, 3, 4] 52 | ``` 53 | 54 | > E aí já entendeu o porquê escolhi o `Array.from`? 55 | 56 | 57 | Se analisarmos a primeira função veremos que passamos um *Array* e na sequência uma *arrow function* que irá gerar os novos valores. 58 | 59 | > Muito fácil né? 60 | 61 | 62 | Logo podemos fazer o seguinte: 63 | 64 | ```js 65 | Array.from([1, 2, 3, 4, 5], (el) => Math.pow(el, 2)) 66 | ``` 67 | 68 | ps: poderia passar o índice **também**, `(el, i)`, como no `map`, pois sabemos que é possível pelo segundo exemplo. 69 | 70 | Agora podemos criar os 3 *Arrays* como pedido no *post*! 71 | 72 | ```js 73 | Array.from([1, 2, 3, 4, 5], (el, i) => Math.pow(el, 2)) 74 | Array.from([1, 2, 3, 4, 5], (el, i) => el + '') 75 | Array.from([1, 2, 3, 4, 5], (el, i) => el * -1) 76 | ``` 77 | 78 | > Mas pera aí Suissa, vai deixar zuado assim? 79 | 80 | > **Óbvio que não né!** Venha comigo para essa mini-refatoração. 81 | 82 | 83 | ```js 84 | const x = [1, 2, 3, 4, 5]; 85 | const primeira = (el) => Math.pow(el, 2) 86 | const segunda = (el) => el + '' 87 | const terceira = (el) => el * -1 88 | 89 | const transform = (x) => ([ 90 | Array.from(x, primeira), 91 | Array.from(x, segunda), 92 | Array.from(x, terceira), 93 | ]) 94 | 95 | console.log(transform(x)) 96 | /*[ [ 1, 4, 9, 16, 25 ], 97 | [ '1', '2', '3', '4', '5' ], 98 | [ -1, -2, -3, -4, -5 ] ] 99 | */ 100 | ``` 101 | 102 | Caso o autor do *post* necessite de cada resposta em uma variável podemos fazer assim: 103 | 104 | 105 | ```js 106 | const x = [1, 2, 3, 4, 5]; 107 | const primeira = (el) => Math.pow(el, 2) 108 | const segunda = (el) => el + '' 109 | const terceira = (el) => el * -1 110 | 111 | const transform = (x) => ([ 112 | Array.from(x, primeira), 113 | Array.from(x, segunda), 114 | Array.from(x, terceira), 115 | ]) 116 | 117 | const arr2 = transform(x)[0] 118 | const arr3 = transform(x)[1] 119 | const arr4 = transform(x)[2] 120 | 121 | // OU usar destructuring com array matching: 122 | const [arr2, arr3, arr4] = transform(x) 123 | 124 | /* 125 | > arr2 126 | [ 1, 4, 9, 16, 25 ] 127 | > arr3 128 | [ '1', '2', '3', '4', '5' ] 129 | > arr4 130 | [ -1, -2, -3, -4, -5 ] 131 | */ 132 | ``` 133 | 134 | ps: esse último exemplo APENAS DIDÁTICO, pois dessa forma vc está executando 3 vezes a mesma função, quando poderia armazenar em uma variável seu resultado e apenas acessar suas posições. 135 | 136 | > E aí ficou bom? Caso tenha uma forma diferente de fazer por favor envie um PR adicionando-a abaixo. 137 | 138 | 139 | ## Refatoraçao marota 140 | 141 | 142 | ```js 143 | const x = [1, 2, 3, 4, 5]; 144 | const primeira = (el) => Math.pow(el, 2) 145 | const segunda = (el) => el + '' 146 | const terceira = (el) => el * -1 147 | 148 | const fns = [primeira, segunda, terceira] 149 | const fromTo = (x, fn, i) => { 150 | console.log(x, fn, i) 151 | // Array.from(x, fn) 152 | } 153 | const createArrays = fromTo.bind(this, x) 154 | 155 | 156 | const transform = (x, fns) => 157 | x.map(fromTo).bind(fns) 158 | 159 | console.log(transform(x, fns)) 160 | /*[ [ 1, 4, 9, 16, 25 ], 161 | [ '1', '2', '3', '4', '5' ], 162 | [ -1, -2, -3, -4, -5 ] ] 163 | */ 164 | ``` 165 | 166 | ## Outras soluções 167 | 168 | 169 | ```js 170 | var x = [1, 2, 3, 4, 5]; 171 | var retObj = { 172 | arr1: [], 173 | arr2: [], 174 | arr3: [] 175 | }; 176 | 177 | var res = x.map(function (el, idx) { 178 | this.arr1.push( Math.pow(el, 2) ); 179 | this.arr2.push( el + '' ); 180 | this.arr3.push( el * -1); 181 | return el; 182 | }, retObj); 183 | 184 | console.log(retObj); 185 | ``` 186 | [Link para a solução acima](https://jsfiddle.net/y6obeg0t/) 187 | 188 | 189 | ```js 190 | const input = [1, 2, 3, 4, 5] 191 | 192 | const square = n => n * n 193 | const negative = n => -n 194 | const string = n => String(n) 195 | 196 | const maps = [square, negative, string] 197 | 198 | const output = input.reduce((acc, val) => 199 | acc.map((arr, i) => arr.concat([maps[i](val)])), 200 | maps.map(() => []) 201 | ) 202 | 203 | console.log(output) 204 | ``` 205 | [Link para a solução acima](https://repl.it/EmaG/2) 206 | 207 | 208 | -------------------------------------------------------------------------------- /posts/js-funcional-para-xofens.md: -------------------------------------------------------------------------------- 1 | # JS Funcional - Transformação de Dados para Iniciantes 2 | 3 | Nesse artigo irei explicar sucintamente o uso de algumas funções *tão* lindas 4 | do JavaScript (Jean Suissa) para transformar dados. 5 | 6 | ![transformers](http://sad.hasbro.com/a9e79c9b34ea183cad07eb995c5f51818b6c9447/df48be66f8202ba3aa2f218209e43523.png) 7 | 8 | Você deve se perguntar: 9 | 10 | > Que tipo de dado você quer transformar fi? 11 | 12 | Imaginemos uma situação hipotética onde existe o seguinte objeto de retorno de uma requisição: 13 | 14 | ```js 15 | 16 | const data = { 17 | id: 666, 18 | name: 'Suissero Veio', 19 | password: 'p3g4n4min43Bal4n5ap3g4n4min43Bal4n5ap3g4n4min43Bal4n5a', 20 | email: 'acerto@mizera.vi' 21 | } 22 | 23 | ``` 24 | 25 | Até aí tudo bem porque o `password` está *"encriptado"*, correto? 26 | 27 | >- **Claaaaaaro que não!** 28 | 29 | Acredito que você saiba que o valor da senha **NUNCA** pode estar acessível dessa forma, 30 | logo *"achamos uma brecha de segurança"*. 31 | 32 | **Como podemos resolver essa *treta*?** 33 | 34 | Primeiramente precisamos analisar nossa entrada: ela é um Objeto. 35 | 36 | Porém o título do artigo é `JS Funcional - Transformação de Dados para Iniciantes` então 37 | vamos pensar de uma forma *mais* funcional. 38 | 39 | - um array com o nome do campo a ser *"limpado"* 40 | - uma função para limpar o valor 41 | 42 | **Entretanto, antes de criarmos a função devemos lembrar que nosssa entrada é um Objeto.** 43 | 44 | Sabendo disso, precisaremos testar se o Objeto possui os campos a serem limpados. 45 | 46 | ```js 47 | const fieldsNotAllowed = [ 'password' ] 48 | const notAllowed = ( field ) => fieldsNotAllowed.includes( field ) 49 | 50 | Object.keys( data ).filter( notAllowed ) 51 | 52 | ``` 53 | 54 | Essa mandinga do `Object.keys( obj )` nos ajuda a iniciar um encadeamento de funções pois 55 | retorna um *Array* com o nome das propriedades/chaves do Objeto. 56 | 57 | ```js 58 | 59 | > Object.keys({id: 666, active: true}) 60 | [ 'id', 'active' ] 61 | 62 | ``` 63 | 64 | Se o retorno é um *Array* podemos utilizar a função [filter]() para sabermos se o Objeto possui 65 | os campos e quais säo, pois poderemos adicionar mais campos no futuro, por isso usamos a função 66 | `` para filtrar apenas os campos corretos. 67 | 68 | ```js 69 | 70 | const notAllowed = ( field ) => fieldsNotAllowed.includes( field ) 71 | 72 | ``` 73 | 74 | 75 | Veja como o *Array* `fieldsNotAllowed` veio a calhar agora, pois bastou testar se o `field`, que é 76 | o nome de cada propriedade do Objeto, existe dentro desse *Array* com a função [includes](). 77 | 78 | Fazendo o teste de mesa dessa etapa temos o seguinte: 79 | 80 | ```js 81 | 82 | const data = { 83 | id: 666, 84 | name: 'Suissero Veio', 85 | password: 'p3g4n4min43Bal4n5ap3g4n4min43Bal4n5ap3g4n4min43Bal4n5a', 86 | email: 'acerto@mizera.vi' 87 | } 88 | 89 | const fieldsNotAllowed = [ 'password' ] 90 | 91 | const notAllowed = ( field ) => fieldsNotAllowed.includes( field ) 92 | const cleanSensitiveData = ( data ) => Object.keys( data ) 93 | .filter( notAllowed ) 94 | // .reduce( toNewObject , obj ) 95 | 96 | 97 | cleanSensitiveData( data ) 98 | // [ 'password' ] 99 | 100 | ``` 101 | 102 | Agora precisamos pensar em uma forma de limpar os campos sem mudar seu Objeto original. 103 | 104 | **Dados imutáveis <3** 105 | 106 | > **Mas como isso tio Suissa???** 107 | 108 | >- Apenas observe a malandragem. 109 | 110 | > - Se precisamos retornar um Objeto, qual função você usaria? 111 | > 112 | > - Map? Filter? Reduce? 113 | 114 | > - Posso adiantar-lhe a minha escolha: reduce. 115 | > 116 | > **Por quê tio?** 117 | 118 | 119 | ![](https://pbs.twimg.com/profile_images/680771499389763584/fjOxGHkt.jpg) 120 | 121 | > Porque iremos reduzir o Objeto de entrada em um Objeto novo de saída com os campos limpos. 122 | 123 | Para fazermos isso utilizaremos a maracutaia do `Object.assign` para criarmos um Objeto novo, 124 | o qual será uma *"junção"* (achar uma palavra melhor) de outros Objetos. 125 | 126 | > **E como isso pode nos ajudar?** 127 | 128 | 129 | Da seguinte forma: 130 | 131 | ```js 132 | 133 | const toNewObject = ( obj, notAllowed ) => Object.assign( obj, { [notAllowed]: null } ) 134 | 135 | ``` 136 | 137 | A constante `obj` é o Objeto original de entrada que virá via **segundo parâmetro** no `reduce`, logo 138 | ela entra como o acumulador, na primeira posição, e o valor de cada posição do *Array*, com o nome 139 | dos campos a serem limpos, vêm na segunda posição nomeado de `notAllowed`. 140 | 141 | Quando fazemos isso `Object.assign( obj, { [notAllowed]: null } ` estamos retornando para o acumulador 142 | um Objeto novo com a estrutura e valores do Original, `obj`, *juntado* com `{ [notAllowed]: null } `. 143 | Como a execução dessa função incia-se pelo último parâmetro, ela vem mesclando os Objetos da 144 | dirieita para esquerda o `obj` é sobrescrito com `{ [notAllowed]: null } `, limpando assim o valor dos 145 | campos definidos anteriormente. 146 | 147 | Vamos finalizar essa etapa do `reduce` assim: 148 | 149 | 150 | ```js 151 | 152 | const data = { 153 | id: 666, 154 | name: 'Suissero Veio', 155 | password: 'p3g4n4min43Bal4n5ap3g4n4min43Bal4n5ap3g4n4min43Bal4n5a', 156 | email: 'acerto@mizera.vi' 157 | } 158 | 159 | const fieldsNotAllowed = [ 'password' ] 160 | 161 | const notAllowed = ( field ) => fieldsNotAllowed.includes( field ) 162 | const toNewObject = ( obj, notAllowed ) => Object.assign( obj, { [notAllowed]: null } ) 163 | const clearSensitiveData = ( data ) => Object.keys( data ) 164 | .filter( notAllowed ) 165 | .reduce( toNewObject , obj ) 166 | 167 | 168 | clearSensitiveData( data ) 169 | // [ 'password' ] 170 | 171 | ``` 172 | 173 | 174 | > Bah Suissa mas com um Objeto só é tranquilo no mamilo, quero ver com vários! 175 | 176 | 177 | 178 | ## Links para estudo 179 | 180 | - [http://reactivex.io/learnrx/](http://reactivex.io/learnrx/) 181 | - [https://github.com/fantasyland/fantasy-land](https://github.com/fantasyland/fantasy-land) 182 | - [https://drboolean.gitbooks.io/mostly-adequate-guide/](https://drboolean.gitbooks.io/mostly-adequate-guide/) 183 | - [http://reactivex.io/learnrx/](http://reactivex.io/learnrx/) 184 | -------------------------------------------------------------------------------- /posts/mobile-first-atomic-design-part-03.md: -------------------------------------------------------------------------------- 1 | ![Parte do layout que mostra a listagem dos cursos](https://cldup.com/kaAk0gAfVr.jpg) 2 | 3 | Então vamos criar a estrutura da nossa `view`: 4 | 5 | ``` 6 | article.aulas-wrapper 7 | h3.atom-title-section Confira nossas aulas 8 | p Essa é a lista das aulas que fazem parte desse curso 9 | section.molecule-box-curso 10 | div.molecule-box-curso-wrapper 11 | img.atom-curso-thumb( src='img/thumb-video-aula.jpg', 12 | alt='Thumbnail do vídeo da aula desse curso') 13 | h4.atom-title-curso 14 | | Nome da aula 15 | p.atom-curso-resume 16 | | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Magnam, 17 | | commodi, officia... 18 | div.molecule-box-curso-wrapper 19 | img.atom-curso-thumb( src='img/thumb-video-aula.jpg', 20 | alt='Thumbnail do vídeo da aula desse curso') 21 | h4.atom-title-curso 22 | | Nome da aula 23 | p.atom-curso-resume 24 | | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Magnam, 25 | | commodi, officia... 26 | div.molecule-box-curso-wrapper 27 | img.atom-curso-thumb( src='img/thumb-video-aula.jpg', 28 | alt='Thumbnail do vídeo da aula desse curso') 29 | h4.atom-title-curso 30 | | Nome da aula 31 | p.atom-curso-resume 32 | | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Magnam, 33 | | commodi, officia... 34 | div.molecule-box-curso-wrapper 35 | button.atom-button-ver-mais ver mais 36 | 37 | ``` 38 | 39 | _Lembrando que ela pode ser refatorada quando necessário._ 40 | 41 | Sem nenhuma estilização nossa view estará assim: 42 | 43 | ![tela mostrando a listagem das aulas sem estilo](https://cldup.com/frvHn1hLU2.png) 44 | 45 | Primeiro vamos colocar a cor correta na seção, no `main.styl` criamos a seguinte regra: 46 | 47 | ``` 48 | .aulas-wrapper 49 | background-color: $azul-cinza-escuro 50 | 51 | ``` 52 | 53 | E vamos mudar a cor de cada caixa que contém a aula. 54 | 55 | ``` 56 | .molecule-box-curso-wrapper 57 | background-color: $branco 58 | 59 | ``` 60 | 61 | Porém como estamos fazendo Mobile-first vamos mudar a aquitetura dessa caixa colocando o vídeo na esquerda e o conteúdo de texto na direita, antes vamos criar o átomo da thumbnail. 62 | 63 | ``` 64 | .atom-curso-thumb 65 | @extend $atom-img 66 | 67 | ``` 68 | 69 | E depois vamos estilizar o componente no contexto dessa molécula sem precisar que modifiquemos nossos átomos. 70 | 71 | ``` 72 | .molecule-box-curso-wrapper 73 | background-color: $branco 74 | margin-bottom: 1rem 75 | padding-top: 0.2rem 76 | clear: both 77 | width: 100% 78 | max-width: 100% 79 | height: 12rem 80 | .atom-curso-thumb 81 | margin-top: 1rem 82 | display: inline-block 83 | width: 30% 84 | float: left 85 | .atom-title-curso, 86 | .atom-curso-resume 87 | float: left 88 | width: 55% 89 | margin-left: 1rem 90 | 91 | ``` 92 | 93 | ![atenção agora!](https://cldup.com/7bqkq5IjH8.jpg) 94 | 95 | Percebeu que os átomos só ganham esses estilos específicos pois estão dentros dessa molécula, que nesse contexto adiciona propriedades e/ou subistitui. 96 | 97 | Dessa forma quando finalizarmos a criação de todos os átomos não seria mais necessário mexer neles, ainda precisamos refatorar nossos outros códigos, mas essa será a etapa após a finalização da estilização visual. 98 | 99 | Trabalhando com o Atomic Design você só precisará modificar futuramente as regras específicas das suas moléculas e organismos, conseguindo re-usar os mesmos átomos sempre. 100 | 101 | Além do mais que criando-os genéricamente com variáveis em seus valores é bem simples criar um tema e mudar automaticamente, mas isso ficará para um próximo artigo. 102 | 103 | A nossa listagem agora está assim: 104 | 105 | ![Listagem das aulas atualizada com layout quase correto](https://cldup.com/0aNHug9zq1.png) 106 | 107 | Agora estilizamos os textos, sempre da molecule-box-curso-wrapper. 108 | 109 | ``` 110 | .molecule-box-curso-wrapper 111 | background-color: $branco 112 | margin-bottom: 1rem 113 | padding-top: 0.2rem 114 | clear: both 115 | width: 100% 116 | max-width: 100% 117 | height: 12rem 118 | .atom-curso-thumb 119 | margin-top: 1rem 120 | display: inline-block 121 | width: 30% 122 | float: left 123 | .atom-title-curso, 124 | .atom-curso-resume 125 | float: left 126 | width: 60% 127 | margin-left: 1rem 128 | .atom-title-curso 129 | font-size: 1.6rem 130 | margin-bottom: 0 131 | .atom-curso-resume 132 | font-size: 1.4rem 133 | 134 | ``` 135 | 136 | Pronto do jeito que queríamos. 137 | 138 | ![Listagem das aulas com o layout correto](https://cldup.com/rhdNxuhVvD-3000x3000.png) 139 | 140 | Só nos falta estilizar a caixa do ver mais. 141 | 142 | Escolhi a _font_ `Arial Black` besse exemplo por ser uma _font_ mais grossa e ser [cross-plataform](http://templates.mailchimp.com/design/typography/), mas também podemos usar svg. 143 | 144 | ``` 145 | svg.icon.icon--plus(viewBox="0 0 5 5", 146 | xmlns="http://www.w3.org/2000/svg") 147 | path(d="M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z") 148 | 149 | ``` 150 | 151 | Retirado de: [http://codepen.io/chrisnager/pen/armzk](http://codepen.io/chrisnager/pen/armzk) 152 | Dica do [Willian Justen](https://github.com/willianjusten/). 153 | 154 | Voltando ao que interessa, antes de tudo vamos refatorar o botão `ver mais`: 155 | 156 | ``` 157 | div.molecule-box-ver-mais-wrapper 158 | a.atom-button-ver-mais 159 | span.quark-icon-plus + 160 | span.quark-button-text ver mais 161 | 162 | ``` 163 | 164 | E então criar nossa base para o botão dentro de `atom-button`: 165 | 166 | ``` 167 | // Definimos nossos quarks que se agruparão 168 | // para formar o átomo do botão 169 | $boson-icon-plus 170 | font-family: 'Arial Black' 171 | 172 | $boson-button-text 173 | font-style: none 174 | font-weight: normal 175 | text-align: center 176 | 177 | // Definimos nossos quarks que se agruparão 178 | // para formar o átomo do botão 179 | .quark-icon-plus 180 | @extend $boson-icon-plus 181 | 182 | .quark-button-text 183 | @extend $boson-button-text 184 | 185 | // Definimos apenas as marcações desse contexto 186 | .atom-button-ver-mais 187 | background: none 188 | border: 0 189 | display: block 190 | text-align: center 191 | color: $verde-claro 192 | min-height: 8rem 193 | .quark-icon-plus 194 | display: block 195 | clear: both 196 | font-size: 8rem 197 | .quark-button-text 198 | display: block 199 | clear: both 200 | font-size: 1.6rem 201 | text-transform: uppercase 202 | position: relative; 203 | top: -2.2rem; 204 | 205 | ``` 206 | 207 | _Necessário refatoração_ 208 | 209 | Quero testar uma nova nomenclatura, depois refatoraremos o resto, para elementos, pois criando o botão `atom-button-ver-mais` percebi que ele possuía 2 átomo internos: 210 | 211 | * atom-icon-plus 212 | * atom-button-text 213 | 214 | Logo peguei-me perguntando: 215 | 216 | * Mas bah átomo dento de átomo? Será que não posso fazer uma outra analogia? 217 | 218 | Bom, bóson não é porque ele está "criado/instanciado", então pensei nos [Quarks](http://pt.wikipedia.org/wiki/Quark). 219 | 220 | > O quark, na física de partículas, é uma partícula elementar e um dos dois elementos básicos que constituem a matéria (o outro é o lépton). Quarks se combinam para formar partículas... 221 | 222 | No caso o botão seria nossa matéria formada por 2 quarks: 223 | 224 | * quark-icon-plus 225 | * quark-button-text 226 | 227 | Vamos ver se essa nomenclatura atenderá até o final do projeto. 228 | 229 | ![Tela mostrando a listagem das aulas e o botão ver mais](https://cldup.com/qZdl3najti.png) 230 | 231 | Repositório oficial: [https://github.com/suissa/javascript-curso-site](https://github.com/suissa/javascript-curso-site) 232 | -------------------------------------------------------------------------------- /posts/js-ta-bom-mas-nao-se-irrite.md: -------------------------------------------------------------------------------- 1 | # JavaScript - Tá bom mas não se irrite 2 | 3 | ![Tá bom mas não se irrite](https://raw.githubusercontent.com/suissa/blog/master/images/mas-nao-se-irrite.jpg) 4 | 5 | Provavelmente você já deve ter lido diversos *posts* falando o quão [difícil]() ou o quão [prazeroso]() é programar com JavaScript hoje em dia, então chegou a hora de eu dar a minha visão! 6 | 7 | ## Por onde começar? 8 | 9 | > **Agora falarei algo que uns 90% dos devs não devem concordar, mas é APENAS minha opinião como professor.** 10 | 11 | ### COMECEM PELO NODE!!! 12 | 13 | > Ai mas usando framework fica fácil Suissa! 14 | 15 | Primeiramente: 16 | 17 | > PAU NO SEU CU SE VC ACHA QUE O NODE.js EH UM FRAMEWORK!!! 18 | 19 | Bom se você não sabe ler ou lhe contaram essa lorota vamos ler lá no [site oficial](https://nodejs.org/en/): 20 | 21 | > Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world. 22 | 23 | **Queo que você leia novamente essa parte!** 24 | 25 | > Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. 26 | 27 | Agora vou lhe fazer mais uma pergunta: 28 | 29 | > No que que você acha que a PORRA do Chrome roda o JS? Dica: começa com V! 30 | 31 | ![V8](https://images-na.ssl-images-amazon.com/images/I/31-wgaUoc9L._SY300_.jpg) 32 | 33 | 34 | Então agora sabendo que tanto o Chrome como o Node.js rodam, basicamente, com o mesmo motor se você falar que o Node.js é um framework além de ser burro está falando que o Chrome também é um framework, mas sabe principalmente porque ele não é um framework? 35 | 36 | > Porque ele não tem uma arquitetura rígida que você deve seguir para que seu código funcione, como no Angular por exemplo. 37 | 38 | Eu não indico quem está começando a estudar JS começar pelo Navegador porque basicamente ele terá que aprender HTML e CSS para fazer algo decente, agora no backend não precisa. E se o aluno quer aprender a **programar** mesmo, IMHO, a melhor forma é no backend pois ele aprenderá muitos conceitos que podderá utilizar em qualquer outra linguagem de programação, agora no frontend será aplicado apenas aos navegadores. 39 | 40 | ## A melhor forma de aprender JS/programação 41 | 42 | > Não! Não comece pelo React! 43 | 44 | Eu, como professor, percebi que uma forma muito boa de ensinar JS (ou programação) é convertendo o conhecimento pré-existente do aluno em lógica e algoritmo para depois mostrar na programação. 45 | 46 | Digo isso com conhecimento de causa dando um exemplo bem simples. 47 | 48 | Então começamos a fazer [funções simples de matemática](https://github.com/fpchemical/funcoes-matematicas) que ela sempre usava. Aí que vem o interessante de estar utilizando o Node.js, pois precisei ensinar ela a trabalhar com o terminal e a **executar** um arquivo `.js` 49 | 50 | 51 | ## Exemplos 52 | 53 | ### Testar se um número é par 54 | 55 | > Muito fácil essa Suissa VSF!!! 56 | 57 | > \- Beleza! Olhe o que mais de 90% respodem: 58 | 59 | 60 |
61 | 62 | ```js 63 | 64 | const número = 64 65 | 66 | éPar = ( número ) => ( número % 2 === 0 ) ? true : false 67 | 68 | console.log(`O número ${número} é par? `, éPar( número )) 69 | // O número 64 é par? true 70 | 71 | ``` 72 | 73 | 74 |
75 |
76 | 77 | > \- Ridicularmente *(outro advérbio de modo)* fácil não? 78 | > 79 | > Para vc que ñ entendeu o código vou explicar. 80 | 81 | A função `éPar` recebe um número, que será testado **se o resultado desse número dividido por 2 dá 0**, esse é o operador de [mod (%)](), **se um número é divisível por 2 então ele é par**. 82 | 83 | Analise o seguinte teste lógico: `( número % 2 === 0 ) ? true : false`. 84 | 85 | ``` 86 | 87 | Se um número dividido por 2 é igual a 0 88 | 89 | Então retorne verdadeiro 90 | 91 | Senão retorne falso 92 | 93 | 94 | ``` 95 | 96 | Até aí nada de novo, porém temos algums peculariedades do JavaScript. 97 | 98 | 99 | > Ta certo uai 100 | > 101 | > \- Posso lhe mostrar como eu melhoraria? 102 | 103 | 104 | Perceba que a função tem a seguinte assinatura: ` Number -> Boolean `. 105 | 106 | O que significa que ela recebe um tipo `Number` e retorna um tipo `Boolean`, ou seja, é uma 107 | função de validação, nesse caso testa se o número **é PAR ou não**. 108 | 109 | Porém entenda que no JavaScript se você quiser retornar um tipo `Boolean` de um teste 110 | lógico você não precisa retornar `true` ou `false`, pois esses valores são exatamente 111 | o que um teste lógico, do tipo `if`, retorna como função. 112 | 113 | > **O que Suissa!!!? O `if` é uma função? 114 | > 115 | > \- Olha eu não posso lhe afirmar pois não li em nenhum lugar, mas pense comigo... 116 | > 117 | > \- Como é executada uma função no JavaScript?? 118 | > 119 | > **Com parêntesis e pah.** 120 | > 121 | > \- Correto, então me acompanhe... 122 | 123 | 124 | ```js 125 | 126 | const número = 42 127 | 128 | const é = ( teste ) => { 129 | 130 | if ( teste ) return true 131 | else return false 132 | } 133 | 134 | console.log( `O número ${número} é par? ${é(número)}`) 135 | // O número 42 é par? true 136 | 137 | ``` 138 | 139 | A chamada dessa função é `é(número)`, se traduzirmos para o Inglês teremos: 140 | `if(number)`. O que é exatamente o que já temos nativamente no JavaScript, logo? 141 | 142 | > Logo o `if` é uma funçnao Suissa. 143 | > 144 | > \- Muito bem! 145 | > 146 | > \- Mas porque eu dei toda essa volta? 147 | 148 | Perceba que internamente o `é/if` retorna um tipo `Boolean (true|false)`, logo: 149 | 150 |
151 | 152 | > \- Por que você precisa explicitar esse valor de retorno, 153 | > sendo que isso já acontece naturalmente? 154 | 155 |
156 | 157 | Sabendo disso, podemos refatorar para isso: 158 | 159 |
160 | 161 | 162 | ```js 163 | 164 | const número = 64 165 | 166 | éPar = ( número ) => ( número % 2 === 0 ) 167 | 168 | console.log(`O número ${número} é par? `, éPar( número )) 169 | // O número 64 é par? true 170 | 171 | ``` 172 | 173 | 174 | > E cade o nosso `é/if`? 175 | > 176 | > \- Se você não percebeu vou lhe apresentar, esse é O **if ternário**. 177 | 178 | 179 | ## IF Ternário 180 | 181 | 182 | > "O `if ternário` é uma das coisas mais lindas do JavaScript" - *Suissa* 183 | 184 |
185 | 186 | Em vez de escrever isso: 187 | 188 | ```js 189 | 190 | if ( número % 2 === 0 ) return true 191 | else return false 192 | 193 | ``` 194 | 195 | Eu posso escrever isso: 196 | 197 | ```js 198 | 199 | ( número % 2 === 0 ) ? true : false 200 | 201 | ``` 202 | 203 | > \- **Que é a mesma coisa!** 204 | 205 | Analise comigo: 206 | 207 | 208 | 209 | ```js 210 | 211 | ( número % 2 === 0 ) => // SE 212 | ? true // ENTAO 213 | : false // SENAO 214 | 215 | ``` 216 | 217 | 218 | > \- **Fácil né!?** 219 | > 220 | > Mas por que ele é uma das coisas mais lindas do JavaScript? 221 | > 222 | > Ahhhhhh... Vem comigo 223 | 224 | 225 | ## Arrow Functions 226 | 227 | Nosso `é` com *Arrow Function* fica assim: 228 | 229 | ```js 230 | 231 | const é = ( teste ) => ( teste ) ? true : false 232 | 233 | ``` 234 | 235 | Mas se ela fosse escrita com o `if` normal ela teria que ser assim: 236 | 237 | ```js 238 | 239 | const é = ( teste ) => { 240 | 241 | if ( teste ) return true 242 | else return false 243 | } 244 | 245 | ``` 246 | 247 | > \- **Sabes o porquê(*porque como sinônimo sempre é junto e com acento*) disso?** 248 | > 249 | > \- **Porque quando usamos o `if ternario` ele tem a ÚNICA função de retornar algo.** 250 | 251 |
252 | 253 | Analise esse exemplo: 254 | 255 |
256 | 257 | ```js 258 | 259 | const Component = ( config ) => { 260 | 261 | const shape = ( config.pi ) ? `circle` : `square` 262 | const color = ( config.color ) ? config.color : `white` 263 | 264 | return { shape, color } 265 | } 266 | 267 | ``` 268 | 269 | > \- **Percebeu que a resposta do `if ternário` é definida como o valor de cada `const`?** 270 | > 271 | > Porra Suissa da hora mein! Ci pah rola até com funções né? 272 | > 273 | > \- **Mermaooooo você leu meus pensamentos! Exatamente isso que vou lhe mostrar** 274 | 275 | 276 | 277 | ```js 278 | 279 | const getName = ( obj ) => obj.name 280 | 281 | const getResult = ( data ) => data.map ? data.map( getName ) : getName( data ) 282 | 283 | const arr = [ 284 | { name: 'Suissa', age: 32 }, 285 | { name: 'Jesus', age: 2017 } 286 | ] 287 | 288 | const obj = { name: 'Suissa', age: 32 } 289 | 290 | console.log(`Nomes: `, getResult( arr ) ) 291 | console.log(`Nome: `, getResult( obj ) ) 292 | // Nomes: [ 'Suissa', 'Jesus' ] 293 | // Nome: Suissa 294 | 295 | 296 | ``` 297 | 298 | > \- **Percebeu o que foi feito?** 299 | 300 | 301 | O resultado da função `getResult`, que recebe `data` sem saber se é `Array` ou `Object`, 302 | faz o seguinte teste lógico: 303 | 304 | 305 | ``` 306 | 307 | SE EXISTE a função map em data 308 | 309 | ENTÃO RETORNE data.map( getName ) 310 | 311 | SE NÃO RETORNE getName( data ) 312 | 313 | ``` 314 | 315 | Ou seja, nossa função testa se o valor de entrada é um `Array`, pois só ele 316 | 317 | 318 | ## Tipagem 319 | 320 | Como todos sabemos o JavaScript é **fracamente e dinamicamente tipado**, *note que qualquer advérvbio de modo (fraco/fracamente e dinâmico/dinamicamente) perde seu acento porque a sílaba tônica vem antes da antepenúltima sílaba, a proparoxítona, pode-se perceber essa regra com rápido/rapidamente*, logo **um Tipo no JavaScript pode mudar sua natureza, por assim dizer**. 321 | 322 | Vamos analisar o seguinte caso: 323 | 324 | ```js 325 | 326 | const VALUES = [ 0, '0', false, null, undefined, 1, -1, {}, () => {} ] 327 | 328 | const MY_REAL_VALUE = 0 329 | 330 | const testMyValue = ( MY_REAL_VALUE ) => ( value ) => value == MY_REAL_VALUE 331 | 332 | const result = VALUES.filter( testMyValue( MY_REAL_VALUE ) ) 333 | 334 | console.log(`Os seguinte valores foram iguais a ${MY_REAL_VALUE}: \n `, result) 335 | 336 | /* 337 | Os seguinte valores foram iguais a 0: 338 | [ 0, '0', false ] 339 | */ 340 | 341 | ``` 342 | 343 | Logo podemos inferir que o valor 344 | 345 | 346 | 347 | 348 | 349 | 350 | ```js 351 | 352 | éPar = ( número ) => ( número % 2 === 0 ) ? true : false 353 | 354 | 355 | -------------------------------------------------------------------------------- /posts/mobile-first-atomic-design-part-02.md: -------------------------------------------------------------------------------- 1 | 2 | ### Main 3 | 4 | ![Imagem mostrando o main do layout](https://cldup.com/crlHJwsVrE.jpg) 5 | 6 | Vamos iniciar criando uma seção para o vídeo de chamada do curso. 7 | 8 | ![Imagem mostrando a seção da chamada do vídeo](https://cldup.com/UYtqmRxICy.jpg) 9 | 10 | ``` 11 | main 12 | article 13 | h1.atom-title-primary 14 | | Quer aprender Javascript de VERDADE? 15 | .molecule-video-chamada 16 | video.atom-video(src='https://www.youtube.com/watch?v=gS7oD8r9YSY') 17 | h2.atom-title-secondary Aprenda, capacite-se e destaque-se no mercado. 18 | p 19 | | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illum, 20 | | incidunt! Quis culpa ex, provident nesciunt minima recusandae 21 | | veniam nihil accusantium, id deleniti doloremque ut sit iste 22 | | officiis commodi asperiores laudantium. 23 | 24 | ``` 25 | 26 | Encapsulamos em um article seguindo a [orientação do HTML5](http://alistapart.com/article/previewofhtml5), vamos iniciar estilizando o `atom-title-primary`: 27 | 28 | ``` 29 | .atom-title-primary 30 | @extend $atom-title 31 | color: $branco 32 | font-size: 2rem 33 | text-align: center 34 | 35 | ``` 36 | 37 | Em `bosons/boson-typo` criamos o `$atom-title`: 38 | 39 | ``` 40 | $atom-title 41 | font-weight: 800 42 | clear: both 43 | 44 | ``` 45 | 46 | ![Tela com o título primário no mobile](https://cldup.com/eXp2urUvYT.png) ![Tela com o título primário no desktop](https://cldup.com/076FJ4wOeV.png) 47 | 48 | ### Vídeo de chamada 49 | 50 | ![Imagem mostrando o vídeo e o fundo preto](https://cldup.com/yzTncJr2zA.jpg) 51 | 52 | Agora vamos chegar em um ponto crítico do nosso projeto, pois haverá uma grande mudança de layout do `mobile` para o `desktop`. 53 | 54 | ``` 55 | $atom-video 56 | width: 100% 57 | max-width: 100% 58 | min-height: 16rem 59 | @media (min-width: $tablet-size) 60 | min-height: 30rem 61 | @media (min-width: $desktop-size) 62 | min-height: 35rem 63 | 64 | .atom-video-chamada-curso 65 | @extend $atom-video 66 | 67 | ``` 68 | 69 | ![Tela mostrando o video no mobile](https://cldup.com/p04NSAcmLE.png) ![Tela mostrando o video no tablet](https://cldup.com/mjzhKzN3OC.png) ![Tela mostrando o video no desktop](https://cldup.com/HAtQJcgCQv.png) 70 | 71 | Porém no layout o vídeo fica dentro de um notebook, no `desktop`, que precisamos usar de fundo para esse vídeo. 72 | 73 | ![](https://cldup.com/dvYuOZspaT.png) 74 | 75 | Refatorando nossa view: 76 | 77 | ``` 78 | section.molecule-video-chamada 79 | iframe.atom-video-chamada-curso(src='//www.youtube.com/embed/gS7oD8r9YSY', 80 | frameborder='0', 81 | allowfullscreen='') 82 | 83 | ``` 84 | 85 | E nosso visual: 86 | 87 | ``` 88 | $atom-video 89 | width: 100% 90 | max-width: 100% 91 | min-height: 16rem 92 | display: block 93 | @media (min-width: $tablet-size) 94 | min-height: 30rem 95 | @media (min-width: $desktop-size) 96 | min-height: 340px 97 | width: 550px 98 | margin: 0 auto 99 | position: relative 100 | top: 40px 101 | 102 | .atom-video-chamada-curso 103 | @extend $atom-video 104 | 105 | ``` 106 | 107 | E precisamos adicionar o fundo na nossa `section` para que o vídeo fique inserido nele. 108 | 109 | ``` 110 | .molecule-video-chamada 111 | @media (min-width: $desktop-size) 112 | background: url('../img/video-mac-bg.png') no-repeat top center 113 | height: 500px 114 | 115 | ``` 116 | 117 | ![Tela mostrando o vídeo inserido em um notebook quando estiver no desktop](https://cldup.com/6zcl__9v9y.png) 118 | 119 | Legal porém nós estamos adicionando regras específicas para o vídeo, porém elas só serão usadas na seção da chamada do curso, logo eu vou passar essas regras para modificar esse átomo apenas nesse contexto. Bom vamos ao código que ficará mais fácil de entender: 120 | 121 | ``` 122 | .molecule-video-chamada 123 | @media (min-width: $desktop-size) 124 | background: url('../img/video-mac-bg.png') no-repeat top center 125 | height: 500px 126 | .atom-video-chamada-curso 127 | min-height: 340px 128 | width: 550px 129 | margin: 0 auto 130 | position: relative 131 | top: 40px 132 | 133 | ``` 134 | 135 | Nesse caso `atom-video-chamada-curso` apenas entrará no formato para caber nesse fundo `background: url('../img/video-mac-bg.png')` se estiver dentro da molécula `molecule-video-chamada` e com a _media query_ `@media (min-width: $desktop-size)`. 136 | 137 | **Nesse momento percebi que estava usando um azul `#4161af` setado no `background-color` do html, mudei para `$azul-claro` para utilizar do nosso padrão setado nas variáveis, por isso o fundo será diferente daqui para frente.** 138 | 139 | Agora para finalizar a parte do vídeo sua sessão possui um fundo escuro e continua com um fundo branco. Adicionei as seguintes regras no `main.styl`, depois precisamos refatorar: 140 | 141 | ``` 142 | body 143 | background-color: $azul-claro 144 | header 145 | height: 7.4rem 146 | main 147 | background-color: $branco 148 | padding-bottom: 4em 149 | 150 | ``` 151 | 152 | E refatorei a `view`: 153 | 154 | ``` 155 | main 156 | article 157 | div.molecule-curso-chamada 158 | h1.atom-title-primary 159 | | Quer aprender Javascript de VERDADE? 160 | section.molecule-video-chamada 161 | iframe.atom-video-chamada-curso(src='//www.youtube.com/embed/gS7oD8r9YSY', 162 | frameborder='0', 163 | allowfullscreen='') 164 | 165 | h2.atom-title-secondary Aprenda, capacite-se e destaque-se no mercado. 166 | p 167 | | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illum, 168 | | incidunt! Quis culpa ex, provident nesciunt minima recusandae 169 | | veniam nihil accusantium, id deleniti doloremque ut sit iste 170 | | officiis commodi asperiores laudantium. 171 | 172 | ``` 173 | 174 | ### Título secundário 175 | 176 | Vamos iniciar a criação do `atom-title-secondary`. 177 | 178 | ``` 179 | .atom-title-secondary 180 | @extend $atom-title 181 | color: $azul-claro 182 | text-align: center 183 | 184 | ``` 185 | 186 | Perceba que estamos re-usando o _placeholder_ `atom-title` e só modificamos sua cor e seu alinhamento. 187 | 188 | ![Tela mostrando o título secundário no mobile](https://cldup.com/_D6tLyQdKY.png) ![Tela mostrando o título secundário no desktop](https://cldup.com/hZuMbfXQRA.png) 189 | 190 | Antes de continuarmos vamos pegar uma font diferente no [Google Fonts](http://www.google.com/fonts) 191 | 192 | Alterando o arquivo `atom-title` deixamos ele assim: 193 | 194 | ``` 195 | @import url(http://fonts.googleapis.com/css?family=Coda) 196 | 197 | .atom-title-primary 198 | @extend $atom-title 199 | color: $branco 200 | font-family: 'Coda', cursive 201 | font-size: 2.8rem 202 | text-align: center 203 | 204 | .atom-title-secondary 205 | @extend $atom-title 206 | color: $azul-claro 207 | font-family: 'Coda', cursive 208 | font-size: 2rem 209 | text-align: center 210 | 211 | ``` 212 | 213 | _ps: não esquecer de chamar no index.jade_ 214 | 215 | ``` 216 | link(rel='stylesheet', type='text/css', href='http://fonts.googleapis.com/css?family=Coda') 217 | 218 | ``` 219 | 220 | Agora sim já está ficando com uma cara mais agradável. 221 | 222 | ![Mostrando nova fonte no mobile](https://cldup.com/JtP6y3sAYJ.png) ![Mostrando nova fonte no desktop](https://cldup.com/2U1MA2JUMb.png) 223 | 224 | Para deixar com o fundo que tem no layout precisei modificar um pouco a estrutura da `view`: 225 | 226 | ``` 227 | section.molecule-curso-chamada 228 | h1.atom-title-primary 229 | | Quer aprender Javascript de VERDADE? 230 | div.molecule-video-chamada 231 | iframe.atom-video-chamada-curso(src='//www.youtube.com/embed/gS7oD8r9YSY', 232 | frameborder='0', 233 | allowfullscreen='') 234 | div.molecule-video-text 235 | h2.atom-title-secondary Aprenda, capacite-se e destaque-se no mercado. 236 | p.atom-text-video-chamada 237 | | Não perca essa grande oportunidade de se diferenciar no mercado 238 | | tendo em vista que o Javascript só cresce cada vez mais. 239 | 240 | ``` 241 | 242 | Separando em 2 blocos pois preciso o contexto/fundo do texto da chamada será diferente do vídeo. Logo precisei criar a molécula `molecule-video-text`: 243 | 244 | ``` 245 | .molecule-video-text 246 | background-color: $branco 247 | padding-top: 2rem 248 | 249 | ``` 250 | 251 | Desse jeito nossa tela no `mobile` ficará assim: 252 | 253 | ![tela mostrando a divisão entre o vídeo e a sessão abaixo no mobile](https://cldup.com/0wgHKBQYbr.png) 254 | 255 | #### Texto de chamada do curso 256 | 257 | Vamos no `boson-typo` e criar o _placeholder_ `atom-text` e adicionar umas variáveis: 258 | 259 | ``` 260 | $font-family = 'Myriad Pro, Sans serif' 261 | $font-bold = 'normal' 262 | $font-size-base = 16px 263 | $font-align = 'left' 264 | 265 | $atom-text 266 | font-weight: $font-bold 267 | font-family: $font-family 268 | text-align: $font-align 269 | 270 | ``` 271 | 272 | Agora usamos no átomo `atom-text-video-chamada` criando o arquivo `atom-text`: 273 | 274 | ``` 275 | @import url(http://fonts.googleapis.com/css?family=Coda) 276 | 277 | .atom-text-video-chamada 278 | @extend $atom-text 279 | color: $azul-cinza-claro 280 | font-size: 1.4rem 281 | margin: 0 auto 282 | text-align: center 283 | width: 90% 284 | @media(min-width: $desktop-size) 285 | width: 80% 286 | @media(min-width: $desktop-medium-size) 287 | width: 50% 288 | 289 | ``` 290 | 291 | Já adicionei o comportamento responsivo como o Atomic Design nos diz, nesse caso o texto não ficará apenas em uma linha quando a tela for muito grande, depois podemos refatorar quando começarmos a etapa do `Template` que é onde setamos a Arquitetura da nossa página utilizando um _grid_. 292 | 293 | ![Texto mostrado no mobile](https://cldup.com/_XP28AXvA8.png) ![Texto mostrado no tablet](https://cldup.com/rj8EgulaWL.png) ![Texto mostrado no desktop](https://cldup.com/7iPyJMPN5j.png) ![Texto mostrado no desktop maior](https://cldup.com/Vfgk0A3l00.png) 294 | 295 | Agora nosso componente do texto já está finalizado com sua responsividade, porém ainda precisamos fazer mais uma coisinha ... 296 | 297 | # Hora da REFATORAÇÃO 298 | 299 | ![imagem da Hora da Aventura](http://img2.wikia.nocookie.net/__cb20130504060912/tudosobrehoradeaventura/pt-br/images/8/89/Hora_de_aventura_by_angieeditions09-d5elww0.png) 300 | 301 | Percebeu que estamos chamando a mesma _font_ em 2 arquivos diferentes? Bom como essa será a _font_ padrão do projeto vamos adicionar essa _font_, em `boson-typo`: 302 | 303 | ``` 304 | @import url(http://fonts.googleapis.com/css?family=Coda) 305 | 306 | $font-family = 'Coda', cursive 307 | $font-bold = normal 308 | $font-size-base = 16px 309 | $font-align = left 310 | 311 | // Setando a font-size base para o REM 312 | html 313 | font-size: $font-size-base 314 | font-family: $font-family 315 | 316 | ``` 317 | 318 | Aproveitamos já para setar no `html` o tamanho e a família da _font_, o interessante de usar REM é que para aumentar ou diminuirmos nossos textos basta mudar o tamanho da _font_ no `html` e retiramos a chamada de `atom-text` e `atom-title`. 319 | 320 | Com isso precisamos dar uma corrigida nos tamanhos das _fonts_ do **menu** e do **botão matricule-se**. 321 | 322 | Vamos mudar o tamanho das _fonts_ do `atom-link-menu`: 323 | 324 | ``` 325 | .atom-link-menu 326 | @extend $atom-link 327 | color: #fff 328 | text-transform: uppercase 329 | font-size: 1rem 330 | // font maior para o tablet por causa do espaço 331 | @media (min-width: $tablet-size) 332 | font-size: 1.3rem 333 | // font menor para o desktop para deixar horizontal 334 | @media (min-width: $desktop-size) 335 | font-size: 0.9rem 336 | letter-spacing: 0.0625*2rem 337 | 338 | ``` 339 | 340 | E do _placeholder_ `atom-button-matricule-se` pois como ele é extendido no átomo `atom-button-matricule-se-small` não precisamos mudar em mais nenhum lugar. 341 | 342 | ``` 343 | $atom-button-matricule-se 344 | @extend $atom-button 345 | background-color: $verde-claro 346 | color: $branco 347 | font-size: 0.8rem 348 | font-weight: 800 349 | text-transform: uppercase 350 | letter-spacing: 0.0625*1rem 351 | padding-top: 8px 352 | 353 | ``` 354 | 355 | Para corrigir o espaçamento entre as seções vamos retirar o margin de cima do `atom-title-secondary`: 356 | 357 | ``` 358 | .atom-title-secondary 359 | @extend $atom-title 360 | color: $azul-claro 361 | font-family: 'Coda', cursive 362 | font-size: 2rem 363 | margin-top: 0 364 | text-align: center 365 | 366 | ``` 367 | 368 | E mudar quando for `desktop` retirar o `padding-top` de `molecule-video-text`: 369 | 370 | ``` 371 | .molecule-video-text 372 | background-color: $branco 373 | padding-top: 2rem 374 | @media (min-width: $desktop-size) 375 | padding-top: 0 376 | 377 | ``` 378 | 379 | Ótimo agora o `header` já está ajeitadinho. 380 | 381 | ![tela mostrando o header no mobile](https://cldup.com/TEBjM8jCz0.png) ![tela mostrando o header no tablet](https://cldup.com/9g49_UKvak.png) ![tela mostrando o header no desktop](https://cldup.com/EdUUvN26UD.png) 382 | 383 | ![Voltemos ao assunto por favor](http://estragafilmes.blog.br/wp-content/uploads/2011/06/DE-VOLTA-PARA-O-FUTURO.jpg) 384 | 385 | Vamos voltar para o layout e ver qual o próximo componente a ser estilizado. 386 | 387 | [Parte 3](http://nomadev.com.br/passo-a-passo-como-desenvolver-com-atomic-design-mobile-first-e-stylus-parte-3/) 388 | -------------------------------------------------------------------------------- /traducoes/Casual functional adventures in JavaScript/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | Artigo traduzido de: 4 | https://hackernoon.com/casual-functional-adventures-in-javascript-f2baec6c38de 5 | 6 | ``` 7 | 8 | **Nota do tradutor**: 9 | 10 | > Esse artigo simplesmente me mostrou **muitas** coisas que eu nunca 11 | > tinha ouvido falar e com certeza me fez buscar mais conhecimento sobre, 12 | > espero que faça o mesmo por vocês! 13 | 14 | # Aventuras funcionais ocasionais em JavaScript 15 | 16 | ![recursion meme](https://raw.githubusercontent.com/suissa/blog/master/traducoes/imgs/recursion.png) 17 | 18 | Em uma tarde de quarta-feira aleatória, meu bom amigo Daniel Rodríguez deixa cair algumas linhas em um grupo do Telegram que compartilhamos com Adrián Obelmejias e Roberto von Schoettler, muito animado com sua nova percepção: 19 | 20 | 21 | > "Você já viu o *y-combinator* no ES6? É f*didamente lindo! " - ele escreveu. 22 | 23 | 24 | E compartilhou este trecho: 25 | 26 | 27 | ```js 28 | 29 | const y = le => (f => f(f))(f => le(x => f(f)(x))) 30 | 31 | ``` 32 | *[Link para esse gist original](https://gist.github.com/stefanmaric/689e54f7cb45e458489da3fe55c0680f#file-y-combinator-js)* 33 | 34 | Nesse ponto, eu não tinha ideia do que era um *y-combinator* ou como esse pedaço de código funcionou; foi o início de uma busca espontânea de melhores respostas na terra da fantasia do JavaScript e eu estarei compartilhando nossas descobertas ingênuas hoje. Vou assumir que você tem alguma experiência com ES2015 e conceitos de programação funcional, porque, bem, claro que você tem, JavaScript funcional é quente como o inferno (**muito foda**) ultimamente. 35 | 36 | ## y-combinator 37 | 38 | Antes dessa quarta-feira, a incubadora de startup por trás do Hacker News era a única "*y-combinator*" que eu conhecia, então eu tive que ir e ler sobre as funções de *y-combinator*; eu rapidamente compreendi a ideia e minha resposta ao trecho do Daniel não foi mais do que outro trecho: 39 | 40 | 41 | 42 | ```js 43 | 44 | (y => 45 | y(fib => n => n <= 2 ? 1 : fib(n - 1) + fib(n - 2))(7) 46 | )(le => 47 | (f => f(f))(f => le(x => f(f)(x))) 48 | ) // 13 49 | 50 | ``` 51 | *[Link para esse gist original](https://gist.github.com/stefanmaric/abd5a8070f2d1be20a5921d9b7fea57b.js)* 52 | 53 | 54 | > Fibonacci foi a primeira função recursiva que me lembrei. 55 | 56 | 57 | Você provavelmente está familiarizado com a recursão, é isso, uma função de auto-chamada, que é muito funcional e legal, certo? Não exatamente: o cálculo lambda não aceita declarações de função, ele permite apenas expressões de função anônimas e argumentos de função, o que significa que não é possível vincular funções a identificadores, portanto é impossível referir uma definição de função dentro de seu próprio corpo de função. É mais fácil entender esta limitação se você tentar escrever uma função recursiva de Fibonacci como uma *Anonymous Immediately Invoked Function Expression* vocês mesmos: 58 | 59 | 60 | ```js 61 | 62 | // Faça esta IIFE anônima calcular o sétimo número na série fibonacci 63 | // PD: Sem iteradores, deve ser um procedimento recursivo 64 | (function (n) { 65 | return // Onde está o seu Deus agora? 66 | })(7) 67 | 68 | ``` 69 | *[Link para esse gist original](https://gist.github.com/stefanmaric/a1447305b7d4df9127691a7a2e590000#file-seemingly-imposible-recursive-fib-function-js)* 70 | 71 | A [função *y-combinator*](https://en.wikipedia.org/wiki/Fixed-point_combinator) é uma prova do Haskell Curry que a recursão pode ser expressa como um conjunto de regras de reescrita quando a recursão explícita é impossível, como no cálculo lambda. Pode não ser muito útil para o desenvolvimento diário, mas é muito interessante que você possa conseguir um estilo de programação puramente funcional em JavaScript. 72 | 73 | Eu não explicarei a implementação do *y-combinator* em detalhes, você pode ler grandes explicações [aqui](http://matt.might.net/articles/implementation-of-recursive-fixed-point-y-combinator-in-javascript-for-memoization/) e [aqui](http://kestas.kuliukas.com/YCombinatorExplained/) em vez disso, mas eu posso expor isso em uma sintaxe menos [críptica](https://www.dicio.com.br/criptico/) para que você possa continuar lendo este artigo: 74 | 75 | ```js 76 | 77 | (function (y) { // use y se quiser 78 | return y(function (fib) { 79 | return function /* fib */ (n) { 80 | return n <= 2 ? 1 : fib(n - 1) + fib(n - 2) 81 | } 82 | })(7) 83 | })(function /* y */ (le) { 84 | // Eu intencionalmente fiz estes F's maiúsculo, 85 | // assim é mais fácil diferenciá-las das poucas f's linhas abaixo 86 | return (function (F) { 87 | return F(F) 88 | })(function (f) { 89 | return le(function (x) { 90 | return f(f)(x) 91 | }) 92 | }) 93 | }) // 13 94 | 95 | ``` 96 | *[Link para esse gist original](https://gist.github.com/stefanmaric/5dac3de81cd26fbf38750751509c71f5#file-pure-functional-y-combinator-in-plain-es5-js)* 97 | 98 | > Observe como é fácil eliminar a declaração de função fib; alguma função que envolve aqui e ali e você está definido. 99 | 100 | 101 | 102 | ## Tail Call Optimization 103 | 104 | I was really excited about this discovery, but I couldn’t avoid to be bothered about my poorly improvised fib function, I knew there was something growing exponentially while using that classic fib() + fib() so I started to rework the function to call itself only once: 105 | 106 | Eu estava realmente animado com essa descoberta, mas não pude evitar ser incomodado com minha função improvisada de fib, eu sabia que havia algo crescendo exponencialmente ao usar esse fib () + fib () clássico, então comecei a retrabalhar a função para chamar-se apenas uma vez: 107 | 108 | ```js 109 | 110 | // função fib original 111 | // O(2^n) complexidade 112 | function fib (n) { 113 | return n <= 2 ? 1 : fib(n - 1) + fib(n - 2) 114 | } 115 | 116 | // função fib melhorada 117 | // O(n+1) complexidade 118 | function fib (n, current = 0, next = 1) { 119 | return n ? fib(n - 1, next, current + next) : current 120 | } 121 | 122 | ``` 123 | *[Link para esse gist original](https://gist.github.com/stefanmaric/6dd9e6b034fc0cb1e4b822faad8803c9#file-fib-functions-compared-js)* 124 | 125 | > O mais tarde executa suave. O primeiro vai machucar a sua máquina, é uma *[fork bomb](https://en.wikipedia.org/wiki/Fork_bomb)*. 126 | 127 | ![fork bomb](https://upload.wikimedia.org/wikipedia/commons/5/52/Fork_bomb.svg) 128 | 129 | 130 | Ótimo! A nova função cresce linearmente para `n = 30`, fib é chamada 31 vezes, enquanto usando o código original ela **estava sendo invocada cerca de um milhão de vezes para o mesmo `n`**, fazendo sua máquina sufocar no processo. E esta não foi a única melhoria que eu apresentei; quase sem perceber, eu estava tocando em outro conceito muito funcional: 131 | 132 | > [...] uma *tail call* é uma chamada de sub-rotina realizada como a ação final de um procedimento. Se uma *tail call* pode levar à mesma sub-rotina sendo chamada novamente mais tarde na cadeia de chamada, a sub-rotina é dita ser *tail-recursive*, que é um caso especial de recursão. 133 | 134 | 135 | A última ação da função `fib` original é uma [operação aritmética](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators), uma soma de números, enquanto a nova é uma chamada de função, significando que é escrita na forma *[tail-recursive](http://stackoverflow.com/a/37010)*. Ao lado da diferença de complexidade de tempo já mostrada, ela também se beneficia do *[Tail Call Optimization](https://benignbemine.github.io/2015/07/19/es6-tail-calls/)* introduzido no [ES2015](https://kangax.github.io/compat-table/es6/), que basicamente transforma a recursão em um `while-loop` sob o capô, ignorando a criação de novas camadas na [Function Call Stack](https://www.youtube.com/watch?v=8aGhZQkoFbQ), indo da complexidade de espaço linear `O(n)` para complexidade de espaço constante `O(1)`, permitindo que fib([Number.MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)) eventualmente retorne `Infinity` (devido às [limitações](http://www.2ality.com/2012/07/large-integers.html) de número do JavaScript) sem retornar erro "***Maximum call stack size exceeded***" - melhor tarde e errado do que nunca, hein? 136 | 137 | 138 | ## trampoline 139 | 140 | Temos uma função de Fibonacci recursiva bastante performática que pode chamar-se alguns **9 quintilhões de vezes sem transbordar a *call stack***, bom, certo? Bem, não tão bom desde que, no momento da escrita, o JavaScriptCore do Safari é o único mecanismo que [implementou o TCO](https://kangax.github.io/compat-table/es6/#test-proper_tail_calls_%28tail_call_optimisation%29). Felizmente, há uma técnica chamada *[trampolining](https://en.wikipedia.org/wiki/Trampoline_%28computing%29#High-level_programming)* para superar a limitação da *Function Call Stack* em plataformas que não têm TCO, tirando o resultado de cada invocação de função fora de seu *stack frame*. 141 | 142 | 143 | ```js 144 | 145 | const trampoline = fn => (...args) => { 146 | let result = fn(...args) 147 | while (result instanceof Function) result = result() 148 | return result 149 | } 150 | 151 | trampoline(function fib (n, current = 0, next = 1) { 152 | return n ? () => fib(n - 1, next, current + next) : current 153 | })(7) // 13 154 | 155 | ``` 156 | *[Link para esse gist original](https://gist.github.com/stefanmaric/442e177a49d5912caabe9e0a9b88d6f8#file-trampoline-function-js)* 157 | 158 | > Mais alguns envolvimentos(wrapping) de função. 159 | 160 | A implementação `trampoline` acima toma uma função `fn` e retorna uma nova função (a versão "*trampolined*") que, quando chamada, invocará `fn` passando seus argumentos. `fn` deve retornar um resultado ou um "*thunk*"; Um *thunk* é uma função que retorna um resultado ou outro *thunk*; Esses *thunks* serão invocados até que um resultado saia. 161 | 162 | 163 | Observe que a função `fib` foi ligeiramente modificada para retornar um *thunk* em vez do valor que chamar a si mesmo, uma vez que o `fib` retorna sempre um valor ou um *thunk*, seu *stack frame* é descartado e sua invocação recursiva acontece fora de `fib`, no contexto da função *trampolined*, impedindo que funções de `fib` se acumulem na pilha de chamadas. Os fechamentos(closures) dos *thunks* mantêm as informações necessárias para que suas invocações internas de `fib` funcionem, `n` acabará por acertar `0` para `fib` retornar um valor, quebrando o *while loop* e encadeando o resultado fora da função *trampolined*. 164 | 165 | Lembre-se de que uma função *trampolined* com seus *thunks* duplica a quantidade total de chamadas de função e será superada por sua versão recursiva mais primitiva. Existem [muitas](https://taylodl.wordpress.com/2013/06/07/functional-javascript-tail-call-optimization-and-trampolines/) [implementações](http://www.datchley.name/recursion-tail-calls-and-trampolines/) de *[trampoline](http://blog.mattbierner.com/tail-call-implementation-and-defunctionalization-in-javascript/)* [lá fora](http://raganwald.com/2013/03/28/trampolines-in-javascript.html) e nenhuma pretendia aumentar o desempenho, mas as limitações dos motores de JavaScript requerem uma solução alternativa(gambi), assim, o suporte TCO ainda é bastante desejado. 166 | 167 |
168 | 169 | > *Making JavaScript look like Lisp, one parenthesis at a time*. — Adrián Obelmejias, 2017 170 | 171 |
172 | 173 | ## Empacotando / Wrapping up 174 | 175 | Aplicando o que foi explicado hoje e mais algum *currying* e composição de função, podemos escrever algo muito funcional como isso: 176 | 177 | ```js 178 | 179 | ( 180 | flow => y => trampoline => fib => n => flow(y, trampoline)(fib)(n) 181 | )( 182 | (...fns) => x => fns.reduce((v, f) => f(v), x) 183 | )( 184 | le => (f => f(f))(f => le(x => f(f)(x))) 185 | )( 186 | fn => (...args) => { 187 | let result = fn(...args) 188 | while (result instanceof Function) result = result() 189 | return result 190 | } 191 | )( 192 | fib => n => (current = 0) => (next = 1) => n ? () => fib(n - 1)(next)(current + next) : current 193 | )(7) // 13 194 | 195 | ``` 196 | *[Link para esse gist original](https://gist.github.com/stefanmaric/b645ff12e68bcdae30ad57f149a37813#file-recursive-fib-with-y-combinator-and-trampoline-js)* 197 | 198 | > Equivalente no [ES5](https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015&targets=&browsers=&builtIns=false&code=const%20y%20%3D%20le%20%3D%3E%20%28f%20%3D%3E%20f%28f%29%29%28f%20%3D%3E%20le%28x%20%3D%3E%20f%28f%29%28x%29%29%29%0A%0Aconst%20flow%20%3D%20%28...fns%29%20%3D%3E%20x%20%3D%3E%20fns.reduce%28%28v%2C%20f%29%20%3D%3E%20f%28v%29%2C%20x%29%0A%0Aconst%20trampoline%20%3D%20fn%20%3D%3E%20%28...args%29%20%3D%3E%20%7B%0A%20let%20result%20%3D%20fn%28...args%29%0A%20while%20%28result%20instanceof%20Function%29%20result%20%3D%20result%28%29%0A%20return%20result%0A%7D%0A%0Aconst%20yTrampoline%20%3D%20flow%28y%2C%20trampoline%29%0A%0Aconst%20fib%20%3D%20yTrampoline%28%0A%20self%20%3D%3E%20n%20%3D%3E%20%28current%20%3D%200%29%20%3D%3E%20%28next%20%3D%201%29%20%3D%3E%20n%20%3F%20%28%29%20%3D%3E%20self%28n%20-%201%29%28next%29%28current%20%2B%20next%29%20%3A%20current%0A%29%0A%0Afib%287%29%0A) aqui. 199 | 200 | 201 | E aqui o mesmo trecho, mas usando `big-integer` para realmente calcular grandes números na série Fibonacci sem chegar em `Infinity`: 202 | 203 | ```js 204 | 205 | const int = require('big-integer') 206 | 207 | const y = le => (f => f(f))(f => le(x => f(f)(x))) 208 | 209 | const flow = (...fns) => x => fns.reduce((v, f) => f(v), x) 210 | 211 | const trampoline = fn => (...args) => { 212 | let result = fn(...args) 213 | while (result instanceof Function) result = result() 214 | return result 215 | } 216 | 217 | const yTrampoline = flow(y, trampoline) 218 | 219 | const fib = n => yTrampoline( 220 | self => n => (current = int.zero) => (next = int.one) => n.isZero() 221 | ? current.toString() 222 | : () => self(n.minus(1))(next)(current.add(next)) 223 | )(int(n)) 224 | 225 | fib(99306) // very big integer (as string) 226 | 227 | ``` 228 | 229 | E, finalmente, [alguns benchmarks](https://jsperf.com/fibonacci-functions-compared/): 230 | 231 | ![](https://cdn-images-1.medium.com/max/880/1*5EYDU-Z31jVKQ6TNOXhR8g.png) 232 | 233 | 234 | ## Conclusões e leituras adicionais 235 | 236 | - Programação funcional pode ser um pouco difícil de entender, mas também pode ser viciante, uma vez que você entrar nelavxz. 237 | - Chamadas de função são caras, use-as sabiamente se você se importa. 238 | - Troca de variável com [Destructing Assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) é muito cara. 239 | - Sério, manter os procedimentos iterativos se o desempenho é importante. 240 | - Minhas [notas originais](https://gist.github.com/stefanmaric/1dfc01dd3985d5b423f22fcad7c58da2) daquela quarta-feira aleatória se você for curioso. 241 | - Não está claro sobre a composição da função? [Veja isso](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-function-composition-20dfb109a1a0). 242 | - Deve ler: [memorização automática usando y-combinator](https://matt.might.net/articles/implementation-of-recursive-fixed-point-y-combinator-in-javascript-for-memoization/). 243 | 244 | -------------------------------------------------------------------------------- /posts/sql-funcional.md: -------------------------------------------------------------------------------- 1 | # SQL 2 | 3 | Vamos usar o seguinte array: 4 | 5 | ```js 6 | const arr = [ 7 | { 8 | "ci_cod": 11122016100, 9 | "ci_titulo": "MEDIÇÕES EXTERNA", 10 | "ci_vm": "0,00", 11 | "ci_vr": "0,00", 12 | "ci_erro": "0,00", 13 | "ci_incerteza": "0,00", 14 | "ci_unidade": "mm", 15 | "ci_erro_incerteza": "0,00", 16 | "ci_criterio_aceitacao": "0,00", 17 | "ci_situacao": "------", 18 | "_id": "584e2f7a3e663748e71c1fd3", 19 | "ci_subtitulo": false 20 | }, 21 | { 22 | "ci_cod": 11122016101, 23 | "ci_titulo": "MEDIÇÕES EXTERNA", 24 | "ci_vm": "1,30", 25 | "ci_vr": "1,30", 26 | "ci_erro": "0,00", 27 | "ci_incerteza": "0,01", 28 | "ci_unidade": "mm", 29 | "ci_erro_incerteza": "0,01", 30 | "ci_criterio_aceitacao": "0,18", 31 | "ci_situacao": "aprovado", 32 | "_id": "584e2f7a3e663748e71c1fd2", 33 | "ci_subtitulo": false 34 | }, 35 | { 36 | "ci_cod": 11122016102, 37 | "ci_titulo": "MEDIÇÕES EXTERNA", 38 | "ci_vm": "100,00", 39 | "ci_vr": "100,00", 40 | "ci_erro": "0,00", 41 | "ci_incerteza": "0,01", 42 | "ci_unidade": "mm", 43 | "ci_erro_incerteza": "0,01", 44 | "ci_criterio_aceitacao": "0,18", 45 | "ci_situacao": "aprovado", 46 | "_id": "584e2f7a3e663748e71c1fd1", 47 | "ci_subtitulo": false 48 | }, 49 | { 50 | "ci_cod": 11122016103, 51 | "ci_titulo": "MEDIÇÕES EXTERNA", 52 | "ci_vm": "200,00", 53 | "ci_vr": "200,00", 54 | "ci_erro": "0,00", 55 | "ci_incerteza": "0,01", 56 | "ci_unidade": "mm", 57 | "ci_erro_incerteza": "0,01", 58 | "ci_criterio_aceitacao": "0,18", 59 | "ci_situacao": "aprovado", 60 | "_id": "584e2f7a3e663748e71c1fd0", 61 | "ci_subtitulo": false 62 | }, 63 | { 64 | "ci_cod": 11122016104, 65 | "ci_titulo": "MEDIÇÕES EXTERNA", 66 | "ci_vm": "300,00", 67 | "ci_vr": "300,00", 68 | "ci_erro": "0,00", 69 | "ci_incerteza": "0,01", 70 | "ci_unidade": "mm", 71 | "ci_erro_incerteza": "0,01", 72 | "ci_criterio_aceitacao": "0,18", 73 | "ci_situacao": "aprovado", 74 | "_id": "584e2f7a3e663748e71c1fcf", 75 | "ci_subtitulo": false 76 | }, 77 | { 78 | "ci_cod": 11122016105, 79 | "ci_titulo": "MEDIÇÕES EXTERNA", 80 | "ci_vm": "500,00", 81 | "ci_vr": "500,00", 82 | "ci_erro": "0,00", 83 | "ci_incerteza": "0,01", 84 | "ci_unidade": "mm", 85 | "ci_erro_incerteza": "0,01", 86 | "ci_criterio_aceitacao": "0,18", 87 | "ci_situacao": "aprovado", 88 | "_id": "584e2f7a3e663748e71c1fce", 89 | "ci_subtitulo": false 90 | }, 91 | { 92 | "ci_cod": 11122016106, 93 | "ci_titulo": "MEDIÇÕES EXTERNA", 94 | "ci_vm": "592,00", 95 | "ci_vr": "592,00", 96 | "ci_erro": "0,00", 97 | "ci_incerteza": "0,01", 98 | "ci_unidade": "mm", 99 | "ci_erro_incerteza": "0,01", 100 | "ci_criterio_aceitacao": "0,18", 101 | "ci_situacao": "aprovado", 102 | "_id": "584e2f7a3e663748e71c1fcd", 103 | "ci_subtitulo": false 104 | }, 105 | { 106 | "ci_cod": 11122016107, 107 | "ci_titulo": "MEDIÇÃO INTERNA", 108 | "ci_vm": "40,00", 109 | "ci_vr": "39,998", 110 | "ci_erro": "0,002", 111 | "ci_incerteza": "0,010", 112 | "ci_unidade": "0", 113 | "ci_erro_incerteza": "0,012", 114 | "ci_criterio_aceitacao": "0,18", 115 | "ci_situacao": "aprovado", 116 | "_id": "584e2f7a3e663748e71c1fcc", 117 | "ci_subtitulo": false 118 | }, 119 | { 120 | "ci_cod": 11122016108, 121 | "ci_titulo": "MEDIÇÃO PROFUNDIDADE", 122 | "ci_vm": "0,00", 123 | "ci_vr": "0,00", 124 | "ci_erro": "0,00", 125 | "ci_incerteza": "0,00", 126 | "ci_unidade": "0,00", 127 | "ci_erro_incerteza": "0,00", 128 | "ci_criterio_aceitacao": "0,00", 129 | "ci_situacao": "-------", 130 | "_id": "584e2f7a3e663748e71c1fcb", 131 | "ci_subtitulo": false 132 | }, 133 | { 134 | "ci_cod": 11122016109, 135 | "ci_titulo": "MEDIÇÃO RESSALTO", 136 | "ci_vm": "50,00", 137 | "ci_vr": "50,00", 138 | "ci_erro": "0,00", 139 | "ci_incerteza": "0,01", 140 | "ci_unidade": "mm", 141 | "ci_erro_incerteza": "0,01", 142 | "ci_criterio_aceitacao": "0,18", 143 | "ci_situacao": "aprovado", 144 | "_id": "584e2f7a3e663748e71c1fca", 145 | "ci_subtitulo": false 146 | }, 147 | { 148 | "ci_cod": 11122016110, 149 | "ci_titulo": "PARELELISMO", 150 | "ci_vm": "0,00", 151 | "ci_vr": "0,00", 152 | "ci_erro": "0,00", 153 | "ci_incerteza": "0,00", 154 | "ci_unidade": "-------", 155 | "ci_erro_incerteza": "0,00", 156 | "ci_criterio_aceitacao": "0,00", 157 | "ci_situacao": "-------", 158 | "_id": "584e2f7a3e663748e71c1fc9", 159 | "ci_subtitulo": false 160 | }, 161 | { 162 | "ci_cod": 11122016111, 163 | "ci_titulo": "EXTERNA", 164 | "ci_vm": "25,00", 165 | "ci_vr": "25,00", 166 | "ci_erro": "0,00", 167 | "ci_incerteza": "0,01", 168 | "ci_unidade": "mm", 169 | "ci_erro_incerteza": "0,01", 170 | "ci_criterio_aceitacao": "0,18", 171 | "ci_situacao": "aprovado", 172 | "_id": "584e2f7a3e663748e71c1fc8", 173 | "ci_subtitulo": false 174 | }, 175 | { 176 | "ci_cod": 11122016112, 177 | "ci_titulo": "INTERNA", 178 | "ci_vm": "0,00", 179 | "ci_vr": "0,00", 180 | "ci_erro": "0,00", 181 | "ci_incerteza": "0,00", 182 | "ci_unidade": "-------", 183 | "ci_erro_incerteza": "0,00", 184 | "ci_criterio_aceitacao": "0,00", 185 | "ci_situacao": "-------", 186 | "_id": "584e2f7a3e663748e71c1fc7", 187 | "ci_subtitulo": false 188 | } 189 | ] 190 | ``` 191 | 192 | ## select 193 | 194 | Vamos selecionar apenas o campo `ci_titulo`: 195 | 196 | ```js 197 | > const field = 'ci_titulo' 198 | > const select = (e, i) => ({ [field]: e[field] }) 199 | > arr.map(select) 200 | [ { c_titulo: 'MEDIÇÕES EXTERNA' }, 201 | { c_titulo: 'MEDIÇÕES EXTERNA' }, 202 | { c_titulo: 'MEDIÇÕES EXTERNA' }, 203 | { c_titulo: 'MEDIÇÕES EXTERNA' }, 204 | { c_titulo: 'MEDIÇÕES EXTERNA' }, 205 | { c_titulo: 'MEDIÇÕES EXTERNA' }, 206 | { c_titulo: 'MEDIÇÕES EXTERNA' }, 207 | { c_titulo: 'MEDIÇÃO INTERNA' }, 208 | { c_titulo: 'MEDIÇÃO PROFUNDIDADE' }, 209 | { c_titulo: 'MEDIÇÃO RESSALTO' }, 210 | { c_titulo: 'PARELELISMO' }, 211 | { c_titulo: 'EXTERNA' }, 212 | { c_titulo: 'INTERNA' } ] 213 | 214 | ``` 215 | 216 | Ou escolhendo vários campos: 217 | 218 | 219 | ```js 220 | > const fields = ['ci_titulo', 'ci_cod', 'ci_vm'] 221 | > const select = (e, i) => fields.map( (f, pos) => ({[f]: e[f]}) ).reduce((acc, cur) => Object.assign(acc, cur), {}) 222 | > arr.map(select) 223 | [ { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016100, ci_vm: '0,00' }, 224 | { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016101, ci_vm: '1,30' }, 225 | { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016102, ci_vm: '100,00' }, 226 | { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016103, ci_vm: '200,00' }, 227 | { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016104, ci_vm: '300,00' }, 228 | { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016105, ci_vm: '500,00' }, 229 | { ci_titulo: 'MEDIÇÕES EXTERNA', ci_cod: 11122016106, ci_vm: '592,00' }, 230 | { ci_titulo: 'MEDIÇÃO INTERNA', ci_cod: 11122016107, ci_vm: '40,00' }, 231 | { ci_titulo: 'MEDIÇÃO PROFUNDIDADE', ci_cod: 11122016108, ci_vm: '0,00' }, 232 | { ci_titulo: 'MEDIÇÃO RESSALTO', ci_cod: 11122016109, ci_vm: '50,00' }, 233 | { ci_titulo: 'PARELELISMO', ci_cod: 11122016110, ci_vm: '0,00' }, 234 | { ci_titulo: 'EXTERNA', ci_cod: 11122016111, ci_vm: '25,00' }, 235 | { ci_titulo: 'INTERNA', ci_cod: 11122016112, ci_vm: '0,00' } ] 236 | 237 | ``` 238 | 239 | ## where 240 | 241 | ```js 242 | > const where = (e, i) => parseFloat(e.ci_vm.replace(',', '.')) >= 500 243 | > arr.filter(where) 244 | [ { ci_cod: 11122016105, 245 | ci_titulo: 'MEDIÇÕES EXTERNA', 246 | ci_vm: '500,00', 247 | ci_vr: '500,00', 248 | ci_erro: '0,00', 249 | ci_incerteza: '0,01', 250 | ci_unidade: 'mm', 251 | ci_erro_incerteza: '0,01', 252 | ci_criterio_aceitacao: '0,18', 253 | ci_situacao: 'aprovado', 254 | _id: '584e2f7a3e663748e71c1fce', 255 | ci_subtitulo: false }, 256 | { ci_cod: 11122016106, 257 | ci_titulo: 'MEDIÇÕES EXTERNA', 258 | ci_vm: '592,00', 259 | ci_vr: '592,00', 260 | ci_erro: '0,00', 261 | ci_incerteza: '0,01', 262 | ci_unidade: 'mm', 263 | ci_erro_incerteza: '0,01', 264 | ci_criterio_aceitacao: '0,18', 265 | ci_situacao: 'aprovado', 266 | _id: '584e2f7a3e663748e71c1fcd', 267 | ci_subtitulo: false } ] 268 | ``` 269 | 270 | 271 | ## order by 272 | ```js 273 | > const by = 'ci_vm' 274 | > const order = {'ASC': (a, b) => a - b, 'DESC': (a, b) => a + b} 275 | > const orderBy = (a, b) => order.ASC(parseFloat(a[by].replace(',', '.')),parseFloat(b[by].replace(',', '.'))) 276 | > arr.sort(orderBy) 277 | [ { ci_cod: 11122016100, 278 | ci_titulo: 'MEDIÇÕES EXTERNA', 279 | ci_vm: '0,00', 280 | ci_vr: '0,00', 281 | ci_erro: '0,00', 282 | ci_incerteza: '0,00', 283 | ci_unidade: 'mm', 284 | ci_erro_incerteza: '0,00', 285 | ci_criterio_aceitacao: '0,00', 286 | ci_situacao: '------', 287 | _id: '584e2f7a3e663748e71c1fd3', 288 | ci_subtitulo: false }, 289 | { ci_cod: 11122016112, 290 | ci_titulo: 'INTERNA', 291 | ci_vm: '0,00', 292 | ci_vr: '0,00', 293 | ci_erro: '0,00', 294 | ci_incerteza: '0,00', 295 | ci_unidade: '-------', 296 | ci_erro_incerteza: '0,00', 297 | ci_criterio_aceitacao: '0,00', 298 | ci_situacao: '-------', 299 | _id: '584e2f7a3e663748e71c1fc7', 300 | ci_subtitulo: false }, 301 | { ci_cod: 11122016110, 302 | ci_titulo: 'PARELELISMO', 303 | ci_vm: '0,00', 304 | ci_vr: '0,00', 305 | ci_erro: '0,00', 306 | ci_incerteza: '0,00', 307 | ci_unidade: '-------', 308 | ci_erro_incerteza: '0,00', 309 | ci_criterio_aceitacao: '0,00', 310 | ci_situacao: '-------', 311 | _id: '584e2f7a3e663748e71c1fc9', 312 | ci_subtitulo: false }, 313 | { ci_cod: 11122016108, 314 | ci_titulo: 'MEDIÇÃO PROFUNDIDADE', 315 | ci_vm: '0,00', 316 | ci_vr: '0,00', 317 | ci_erro: '0,00', 318 | ci_incerteza: '0,00', 319 | ci_unidade: '0,00', 320 | ci_erro_incerteza: '0,00', 321 | ci_criterio_aceitacao: '0,00', 322 | ci_situacao: '-------', 323 | _id: '584e2f7a3e663748e71c1fcb', 324 | ci_subtitulo: false }, 325 | { ci_cod: 11122016101, 326 | ci_titulo: 'MEDIÇÕES EXTERNA', 327 | ci_vm: '1,30', 328 | ci_vr: '1,30', 329 | ci_erro: '0,00', 330 | ci_incerteza: '0,01', 331 | ci_unidade: 'mm', 332 | ci_erro_incerteza: '0,01', 333 | ci_criterio_aceitacao: '0,18', 334 | ci_situacao: 'aprovado', 335 | _id: '584e2f7a3e663748e71c1fd2', 336 | ci_subtitulo: false }, 337 | { ci_cod: 11122016111, 338 | ci_titulo: 'EXTERNA', 339 | ci_vm: '25,00', 340 | ci_vr: '25,00', 341 | ci_erro: '0,00', 342 | ci_incerteza: '0,01', 343 | ci_unidade: 'mm', 344 | ci_erro_incerteza: '0,01', 345 | ci_criterio_aceitacao: '0,18', 346 | ci_situacao: 'aprovado', 347 | _id: '584e2f7a3e663748e71c1fc8', 348 | ci_subtitulo: false }, 349 | { ci_cod: 11122016107, 350 | ci_titulo: 'MEDIÇÃO INTERNA', 351 | ci_vm: '40,00', 352 | ci_vr: '39,998', 353 | ci_erro: '0,002', 354 | ci_incerteza: '0,010', 355 | ci_unidade: '0', 356 | ci_erro_incerteza: '0,012', 357 | ci_criterio_aceitacao: '0,18', 358 | ci_situacao: 'aprovado', 359 | _id: '584e2f7a3e663748e71c1fcc', 360 | ci_subtitulo: false }, 361 | { ci_cod: 11122016109, 362 | ci_titulo: 'MEDIÇÃO RESSALTO', 363 | ci_vm: '50,00', 364 | ci_vr: '50,00', 365 | ci_erro: '0,00', 366 | ci_incerteza: '0,01', 367 | ci_unidade: 'mm', 368 | ci_erro_incerteza: '0,01', 369 | ci_criterio_aceitacao: '0,18', 370 | ci_situacao: 'aprovado', 371 | _id: '584e2f7a3e663748e71c1fca', 372 | ci_subtitulo: false }, 373 | { ci_cod: 11122016102, 374 | ci_titulo: 'MEDIÇÕES EXTERNA', 375 | ci_vm: '100,00', 376 | ci_vr: '100,00', 377 | ci_erro: '0,00', 378 | ci_incerteza: '0,01', 379 | ci_unidade: 'mm', 380 | ci_erro_incerteza: '0,01', 381 | ci_criterio_aceitacao: '0,18', 382 | ci_situacao: 'aprovado', 383 | _id: '584e2f7a3e663748e71c1fd1', 384 | ci_subtitulo: false }, 385 | { ci_cod: 11122016103, 386 | ci_titulo: 'MEDIÇÕES EXTERNA', 387 | ci_vm: '200,00', 388 | ci_vr: '200,00', 389 | ci_erro: '0,00', 390 | ci_incerteza: '0,01', 391 | ci_unidade: 'mm', 392 | ci_erro_incerteza: '0,01', 393 | ci_criterio_aceitacao: '0,18', 394 | ci_situacao: 'aprovado', 395 | _id: '584e2f7a3e663748e71c1fd0', 396 | ci_subtitulo: false }, 397 | { ci_cod: 11122016104, 398 | ci_titulo: 'MEDIÇÕES EXTERNA', 399 | ci_vm: '300,00', 400 | ci_vr: '300,00', 401 | ci_erro: '0,00', 402 | ci_incerteza: '0,01', 403 | ci_unidade: 'mm', 404 | ci_erro_incerteza: '0,01', 405 | ci_criterio_aceitacao: '0,18', 406 | ci_situacao: 'aprovado', 407 | _id: '584e2f7a3e663748e71c1fcf', 408 | ci_subtitulo: false }, 409 | { ci_cod: 11122016105, 410 | ci_titulo: 'MEDIÇÕES EXTERNA', 411 | ci_vm: '500,00', 412 | ci_vr: '500,00', 413 | ci_erro: '0,00', 414 | ci_incerteza: '0,01', 415 | ci_unidade: 'mm', 416 | ci_erro_incerteza: '0,01', 417 | ci_criterio_aceitacao: '0,18', 418 | ci_situacao: 'aprovado', 419 | _id: '584e2f7a3e663748e71c1fce', 420 | ci_subtitulo: false }, 421 | { ci_cod: 11122016106, 422 | ci_titulo: 'MEDIÇÕES EXTERNA', 423 | ci_vm: '592,00', 424 | ci_vr: '592,00', 425 | ci_erro: '0,00', 426 | ci_incerteza: '0,01', 427 | ci_unidade: 'mm', 428 | ci_erro_incerteza: '0,01', 429 | ci_criterio_aceitacao: '0,18', 430 | ci_situacao: 'aprovado', 431 | _id: '584e2f7a3e663748e71c1fcd', 432 | ci_subtitulo: false } ] 433 | 434 | ``` 435 | 436 | ## group by 437 | 438 | ```js 439 | const by = 'ci_titulo' 440 | const groupBy = (select, element) => { 441 | (select[element[by]] = select[element[by]] || []).push(element) 442 | return select 443 | } 444 | > arr.reduce(g, {}) 445 | { 'MEDIÇÕES EXTERNA': 446 | [ { ci_cod: 11122016100, 447 | ci_titulo: 'MEDIÇÕES EXTERNA', 448 | ci_vm: '0,00', 449 | ci_vr: '0,00', 450 | ci_erro: '0,00', 451 | ci_incerteza: '0,00', 452 | ci_unidade: 'mm', 453 | ci_erro_incerteza: '0,00', 454 | ci_criterio_aceitacao: '0,00', 455 | ci_situacao: '------', 456 | _id: '584e2f7a3e663748e71c1fd3', 457 | ci_subtitulo: false }, 458 | { ci_cod: 11122016101, 459 | ci_titulo: 'MEDIÇÕES EXTERNA', 460 | ci_vm: '1,30', 461 | ci_vr: '1,30', 462 | ci_erro: '0,00', 463 | ci_incerteza: '0,01', 464 | ci_unidade: 'mm', 465 | ci_erro_incerteza: '0,01', 466 | ci_criterio_aceitacao: '0,18', 467 | ci_situacao: 'aprovado', 468 | _id: '584e2f7a3e663748e71c1fd2', 469 | ci_subtitulo: false }, 470 | { ci_cod: 11122016102, 471 | ci_titulo: 'MEDIÇÕES EXTERNA', 472 | ci_vm: '100,00', 473 | ci_vr: '100,00', 474 | ci_erro: '0,00', 475 | ci_incerteza: '0,01', 476 | ci_unidade: 'mm', 477 | ci_erro_incerteza: '0,01', 478 | ci_criterio_aceitacao: '0,18', 479 | ci_situacao: 'aprovado', 480 | _id: '584e2f7a3e663748e71c1fd1', 481 | ci_subtitulo: false }, 482 | { ci_cod: 11122016103, 483 | ci_titulo: 'MEDIÇÕES EXTERNA', 484 | ci_vm: '200,00', 485 | ci_vr: '200,00', 486 | ci_erro: '0,00', 487 | ci_incerteza: '0,01', 488 | ci_unidade: 'mm', 489 | ci_erro_incerteza: '0,01', 490 | ci_criterio_aceitacao: '0,18', 491 | ci_situacao: 'aprovado', 492 | _id: '584e2f7a3e663748e71c1fd0', 493 | ci_subtitulo: false }, 494 | { ci_cod: 11122016104, 495 | ci_titulo: 'MEDIÇÕES EXTERNA', 496 | ci_vm: '300,00', 497 | ci_vr: '300,00', 498 | ci_erro: '0,00', 499 | ci_incerteza: '0,01', 500 | ci_unidade: 'mm', 501 | ci_erro_incerteza: '0,01', 502 | ci_criterio_aceitacao: '0,18', 503 | ci_situacao: 'aprovado', 504 | _id: '584e2f7a3e663748e71c1fcf', 505 | ci_subtitulo: false }, 506 | { ci_cod: 11122016105, 507 | ci_titulo: 'MEDIÇÕES EXTERNA', 508 | ci_vm: '500,00', 509 | ci_vr: '500,00', 510 | ci_erro: '0,00', 511 | ci_incerteza: '0,01', 512 | ci_unidade: 'mm', 513 | ci_erro_incerteza: '0,01', 514 | ci_criterio_aceitacao: '0,18', 515 | ci_situacao: 'aprovado', 516 | _id: '584e2f7a3e663748e71c1fce', 517 | ci_subtitulo: false }, 518 | { ci_cod: 11122016106, 519 | ci_titulo: 'MEDIÇÕES EXTERNA', 520 | ci_vm: '592,00', 521 | ci_vr: '592,00', 522 | ci_erro: '0,00', 523 | ci_incerteza: '0,01', 524 | ci_unidade: 'mm', 525 | ci_erro_incerteza: '0,01', 526 | ci_criterio_aceitacao: '0,18', 527 | ci_situacao: 'aprovado', 528 | _id: '584e2f7a3e663748e71c1fcd', 529 | ci_subtitulo: false } ], 530 | 'MEDIÇÃO INTERNA': 531 | [ { ci_cod: 11122016107, 532 | ci_titulo: 'MEDIÇÃO INTERNA', 533 | ci_vm: '40,00', 534 | ci_vr: '39,998', 535 | ci_erro: '0,002', 536 | ci_incerteza: '0,010', 537 | ci_unidade: '0', 538 | ci_erro_incerteza: '0,012', 539 | ci_criterio_aceitacao: '0,18', 540 | ci_situacao: 'aprovado', 541 | _id: '584e2f7a3e663748e71c1fcc', 542 | ci_subtitulo: false } ], 543 | 'MEDIÇÃO PROFUNDIDADE': 544 | [ { ci_cod: 11122016108, 545 | ci_titulo: 'MEDIÇÃO PROFUNDIDADE', 546 | ci_vm: '0,00', 547 | ci_vr: '0,00', 548 | ci_erro: '0,00', 549 | ci_incerteza: '0,00', 550 | ci_unidade: '0,00', 551 | ci_erro_incerteza: '0,00', 552 | ci_criterio_aceitacao: '0,00', 553 | ci_situacao: '-------', 554 | _id: '584e2f7a3e663748e71c1fcb', 555 | ci_subtitulo: false } ], 556 | 'MEDIÇÃO RESSALTO': 557 | [ { ci_cod: 11122016109, 558 | ci_titulo: 'MEDIÇÃO RESSALTO', 559 | ci_vm: '50,00', 560 | ci_vr: '50,00', 561 | ci_erro: '0,00', 562 | ci_incerteza: '0,01', 563 | ci_unidade: 'mm', 564 | ci_erro_incerteza: '0,01', 565 | ci_criterio_aceitacao: '0,18', 566 | ci_situacao: 'aprovado', 567 | _id: '584e2f7a3e663748e71c1fca', 568 | ci_subtitulo: false } ], 569 | PARELELISMO: 570 | [ { ci_cod: 11122016110, 571 | ci_titulo: 'PARELELISMO', 572 | ci_vm: '0,00', 573 | ci_vr: '0,00', 574 | ci_erro: '0,00', 575 | ci_incerteza: '0,00', 576 | ci_unidade: '-------', 577 | ci_erro_incerteza: '0,00', 578 | ci_criterio_aceitacao: '0,00', 579 | ci_situacao: '-------', 580 | _id: '584e2f7a3e663748e71c1fc9', 581 | ci_subtitulo: false } ], 582 | EXTERNA: 583 | [ { ci_cod: 11122016111, 584 | ci_titulo: 'EXTERNA', 585 | ci_vm: '25,00', 586 | ci_vr: '25,00', 587 | ci_erro: '0,00', 588 | ci_incerteza: '0,01', 589 | ci_unidade: 'mm', 590 | ci_erro_incerteza: '0,01', 591 | ci_criterio_aceitacao: '0,18', 592 | ci_situacao: 'aprovado', 593 | _id: '584e2f7a3e663748e71c1fc8', 594 | ci_subtitulo: false } ], 595 | INTERNA: 596 | [ { ci_cod: 11122016112, 597 | ci_titulo: 'INTERNA', 598 | ci_vm: '0,00', 599 | ci_vr: '0,00', 600 | ci_erro: '0,00', 601 | ci_incerteza: '0,00', 602 | ci_unidade: '-------', 603 | ci_erro_incerteza: '0,00', 604 | ci_criterio_aceitacao: '0,00', 605 | ci_situacao: '-------', 606 | _id: '584e2f7a3e663748e71c1fc7', 607 | ci_subtitulo: false } ] } 608 | 609 | ``` 610 | 611 | ## Traduzindo uma query SQL para JS 612 | 613 | Faremos a seguinte query: 614 | 615 | ``` 616 | SELECT ci_cod, ci_titulo, ci_vm, ci_vr, ci_erro, ci_incerteza, ci_erro_incerteza, ci_criterio_aceitacao 617 | FROM items 618 | WHERE ci_vm <> "0,00" 619 | GROUP BY ci_titulo 620 | ORDER BY ci_vm ASC 621 | ``` 622 | 623 | Agora reusando nossas funções anteriores: 624 | 625 | ``` 626 | const fields = ['ci_cod', 'ci_titulo', 'ci_vm', 'ci_vr', 'ci_erro', 'ci_incerteza'] 627 | 628 | const select = (e, i) => fields.map( (f, pos) => ({[f]: e[f]}) ).reduce((acc, cur) => Object.assign(acc, cur), {}) 629 | 630 | const where = (e, i) => e.ci_vm !== "0,00" 631 | 632 | const g_by = 'ci_titulo' 633 | const groupBy = (select, element) => { 634 | (select[element[g_by]] = select[element[g_by]] || []).push(element) 635 | return select 636 | } 637 | 638 | const o_by = 'ci_vm' 639 | const order = {'ASC': (a, b) => a - b, 'DESC': (a, b) => a + b} 640 | const orderBy = (a, b) => order.ASC(parseFloat(a[o_by].replace(',', '.')),parseFloat(b[o_by].replace(',', '.'))) 641 | 642 | arr.map(select).filter(where).sort(orderBy).reduce(groupBy, {}) 643 | { 'MEDIÇÕES EXTERNA': 644 | [ { ci_cod: 11122016101, 645 | ci_titulo: 'MEDIÇÕES EXTERNA', 646 | ci_vm: '1,30', 647 | ci_vr: '1,30', 648 | ci_erro: '0,00', 649 | ci_incerteza: '0,01' }, 650 | { ci_cod: 11122016102, 651 | ci_titulo: 'MEDIÇÕES EXTERNA', 652 | ci_vm: '100,00', 653 | ci_vr: '100,00', 654 | ci_erro: '0,00', 655 | ci_incerteza: '0,01' }, 656 | { ci_cod: 11122016103, 657 | ci_titulo: 'MEDIÇÕES EXTERNA', 658 | ci_vm: '200,00', 659 | ci_vr: '200,00', 660 | ci_erro: '0,00', 661 | ci_incerteza: '0,01' }, 662 | { ci_cod: 11122016104, 663 | ci_titulo: 'MEDIÇÕES EXTERNA', 664 | ci_vm: '300,00', 665 | ci_vr: '300,00', 666 | ci_erro: '0,00', 667 | ci_incerteza: '0,01' }, 668 | { ci_cod: 11122016105, 669 | ci_titulo: 'MEDIÇÕES EXTERNA', 670 | ci_vm: '500,00', 671 | ci_vr: '500,00', 672 | ci_erro: '0,00', 673 | ci_incerteza: '0,01' }, 674 | { ci_cod: 11122016106, 675 | ci_titulo: 'MEDIÇÕES EXTERNA', 676 | ci_vm: '592,00', 677 | ci_vr: '592,00', 678 | ci_erro: '0,00', 679 | ci_incerteza: '0,01' } ], 680 | EXTERNA: 681 | [ { ci_cod: 11122016111, 682 | ci_titulo: 'EXTERNA', 683 | ci_vm: '25,00', 684 | ci_vr: '25,00', 685 | ci_erro: '0,00', 686 | ci_incerteza: '0,01' } ], 687 | 'MEDIÇÃO INTERNA': 688 | [ { ci_cod: 11122016107, 689 | ci_titulo: 'MEDIÇÃO INTERNA', 690 | ci_vm: '40,00', 691 | ci_vr: '39,998', 692 | ci_erro: '0,002', 693 | ci_incerteza: '0,010' } ], 694 | 'MEDIÇÃO RESSALTO': 695 | [ { ci_cod: 11122016109, 696 | ci_titulo: 'MEDIÇÃO RESSALTO', 697 | ci_vm: '50,00', 698 | ci_vr: '50,00', 699 | ci_erro: '0,00', 700 | ci_incerteza: '0,01' } ] } 701 | ``` 702 | 703 | Então veja só como é simples trabalhar com dados no JavaScript! 704 | 705 | ```js 706 | 707 | SELECT ci_cod, ci_titulo, ci_vm, ci_vr, ci_erro, ci_incerteza, ci_erro_incerteza, ci_criterio_aceitacao 708 | FROM items 709 | WHERE ci_vm <> "0,00" 710 | GROUP BY ci_titulo 711 | ORDER BY ci_vm ASC 712 | 713 | // VIROU ISSO 714 | 715 | arr.map(select).filter(where).sort(orderBy).reduce(groupBy, {}) 716 | ``` 717 | -------------------------------------------------------------------------------- /posts/mobile-first-atomic-design.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
[Nomadev - O blog de um dev nômade](http://nomadev.com.br)
4 | 5 | 6 | 7 | # Passo-a-passo como desenvolver com Atomic Design, Mobile-first e Stylus - Parte 1 8 | 9 |
10 | 11 | 12 | 13 | ![Imagem sobre mobile first](http://designshack.net/wp-content/uploads/ds-mobilefirst-2.jpg) 14 | 15 | Bom estou escrevendo esse passo-a-passo pois me foi pedido via inbox do Facebook para que eu mostrasse como eu iria programar o site que estou desenvolvendo para um curso de Javascript que na verdade serão vários mini-cursos podendo ter outro professores. 16 | 17 | Então achei uma boa oportunidade para colocar em prática alguns estudos e experimentar coisas novas como: Stylus e Mobile-first. Juntando tudo com [Atomic Design](http://nomadev.com.br/atomic-design-por-que-usar/), esse post vai ficar gigante e muito provavelmente virará um mini-curso e uma palestra também, até porque de nada vale aprender se não ensinar, imho. 18 | 19 | ## Analisando 20 | 21 | Bom vamos ver como é o layout com o qual vamos trabalhar, vamos nos basear nele pois coisas podem ser modificadas durante o desenvolvimento. 22 | 23 | ![Layout a ser utilizado no estudo](https://cldup.com/Deq7yQ11XI.jpg) 24 | 25 | Primeiro escrevi uma lista dos componentes e a estrutura do layout mas nada de HTML ou CSS. 26 | 27 | header 28 | logo[4/12] 29 | menu[6/12] 30 | button matricule-se medium[2/12] 31 | main 32 | article 33 | title#1 34 | video //curso com fundo notebook 35 | title#2 36 | p 37 | article 38 | title#3 Confira nossos cursos 39 | box-curso*3 40 | img thumb 41 | titulo 42 | resumo 43 | box-ver-mais 44 | article 45 | p 46 | button matricule-se 47 | article 48 | title#3[1/3] Aprenda diretamente com os melhores intrutores 49 | article 50 | title#3[1/3] Pronto para começar? 51 | - p 52 | img logo[1/3] 53 | button matricule-se large[1/3] 54 | footer 55 | 56 | Fiz algumas marcações de tamanho baseado no container para facilitar na hora de setar o grid. Perceba que nem fiz o footer pq sou vagabundo ehehheheh. 57 | 58 | Depois criei a listagem dos primeiros átomos em `atoms/atoms-default.styl`: 59 | 60 | .atom-img 61 | .atom-img-logo 62 | 63 | .atom-img-logo-small 64 | .atom-img-logo-medium 65 | .atom-img-logo-large 66 | .atom-img-professor-avatar 67 | 68 | .atom-input 69 | .atom-input-email 70 | 71 | .atom-button 72 | .atom-button-matricule-se 73 | 74 | .atom-button-matricule-se-small 75 | .atom-button-matricule-se-medium 76 | .atom-button-matricule-se-large 77 | 78 | .atom-title 79 | .atom-title-primary 80 | .atom-title-secondary 81 | .atom-title-section 82 | 83 | .atom-link 84 | .atom-link-menu 85 | 86 | .atom-text 87 | .atom-text-cursos 88 | .atom-text-professor-resumo 89 | 90 | São apenas um base para iniciar, pois provavelmente adicioneremos outros dependendo da necessidade. 91 | 92 | Mas o correto era iniciar pelos `bósons` que são as menores unidades que irão "dar massa" aos átomo. Levando isso em consideração iniciei setando as variáveis das cores em `bosons/bosons-colors.styl`. 93 | 94 | $azul-claro = #1680a7 95 | $azul-cinza-escuro = #202b31 96 | $branco = #fff 97 | $verde-claro = #6ed5a2 98 | $azul-cinza-medio = #788c95 99 | 100 | $color-bg-body = $branco 101 | $color-bg-header = $azul-claro 102 | $color-bg-main = $branco 103 | $color-bg-cursos = $azul-cinza-escuro 104 | $color-bg-footer = $azul-cinza-escuro 105 | $color-bg-button = $verde-claro 106 | $color-title-main = $branco 107 | $color-title-secondary = $azul-claro 108 | $color-text = $azul-cinza-medio 109 | $color-link = $verde-claro 110 | 111 | Para criarmos variárveis no Stylus basta definir o nome depois `=` e o valor, por definição usamos o `