SlideShare a Scribd company logo
1 of 57
Download to read offline
Pague o aluguel
Trabalhando efetivamente com código em débito
Eu sou…
• Desenvolvedor;
• PHP, Ruby, Python e JavaScript. Um pouco de Java e C# (Xamarin);
• Trabalho na BriteCore;
• Trabalho remotamente desde 2016;
• @nelson_senna
Dívida
“…fazendo as
coisas de
maneira rápida e
suja cria-se um
débito técnico…”
–Martin Fowler
Débito técnico é…
Código usado para protótipos, provas de
conceito ou até uma pequena correção.
Classificação de débito técnico
Imprudente Prudente
Deliberado
Negligente
“Não temos tempo!” “Precisamos entregar,
depois vemos isso.”
“O que é OOD? OOP? Design?”
“Agora sabemos que
devíamos ter feito isso.”
Débito técnico é…
Código que deveríamos jogar fora…
–Martin Fowler
“Como uma dívida
financeira, o débito
técnico incorre em
pagamentos de juros,
que vêm na forma de
esforço extra que
temos que fazer no
futuro...”
Efeitos da dívida
“…esse código muitas
vezes ganha vida
própria… Funciona,
então por que
consertar?”
–Brian Foote
E algum tempo e “ifs”
depois…
“Um Big Ball of Mud
tem estrutura
desordenada,
espalhada, desleixada,
remendada e, código
espaguete”
–Brian Foote
Big Ball of Mud
• Os nomes de variáveis e funções pouco informativos ou enganosos
• Uso extensivo de variáveis globais
• Métodos com longas listas de parâmetros mal definidos
• Métodos longos e complicados e, executam várias tarefas não relacionadas
• Código duplicado
• O fluxo de controle é difícil de entender e difícil de seguir
• A intenção do programador é quase impossível de discernir
• O código é simplesmente ilegível e espalhado sem modularização clara
• O código exibe os sinais inconfundíveis de patch após patch nas mãos de vários
mantenedores, cada um dos quais mal entendeu as conseqüências do que estava
fazendo
• Sem documentação
Big Ball of Mud
A estrutura rígida que faz com que o
código fique difícil de entender, caro e
suscetível a erros.
“Da sinonímia dos termos organização e
conhecimento, retira-se que a síntese mais
produtiva, ou mais instigadora, para a
construção de uma idéia acerca da
organização do conhecimento na sociedade é
aquela que abstrai de organização, pelo verbo
organizar, os sentidos de ORGANIZAR, que
são os seguintes: estabelecer as bases de;
arrumar de determinado modo; colocar em
certa ordem.”
–Renato Rocha Souza
Entender é…
Organizar ideias e conceitos, atribuindo
uma ordem, classificando os mesmos.
Então…
if (organizacao) {
entendimento++;
bigBallOfMud--;
}
Pagando a dívida
Entender é…
Organizar ideias e conceitos, atribuindo
uma ordem, classificando os mesmos.
Nome é…
Palavra ou locução com que se designa
uma classe de coisas, pessoas, animais,
um lugar, um acidente geográfico, um
astro etc.
“Existem duas coisas
difíceis em computação:
invalidação de cache e
nomear coisas.”
–Phil Karlton
Nomes são…
DESCOBERTOS!
Nomes são descobertos!
Sem nome
Sem
sentido
Honesto
Honesto e
Completo
Faz o que o
nome diz
Intenção
↪ ↪ ↪ ↪ ↪ ↪
Abstração de
domínio
Nomes são descobertos!
Sem nome
Sem
sentido
Honesto
Honesto e
Completo
Faz o que o
nome diz
Intenção
↪ ↪ ↪ ↪ ↪ ↪
Abstração de
domínio
@arlobelshee
var rootJquery,
// A simple way to check for HTML strings
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
// Strict HTML recognition (#11290: must start with <)
// Shortcut simple #id case for speed
rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/,
init = jQuery.fn.init = function( selector, context, root ) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}
// Method init() accepts an alternate rootjQuery
// so migrate can support jQuery.sub (gh-2101)
root = root || rootjQuery;
// Handle HTML strings
if (typeof selector === "string") {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
…
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
return (context || root).find(selector);
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor(context).find(selector);
}
// HANDLE: $(DOMElement)
} else if (selector.nodeType) {
this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
} else if (isFunction(selector)) {
return root.ready !== undefined ? root.ready(selector) :
// Execute immediately if ready is not present
selector(jQuery);
}
return jQuery.makeArray(selector, this);
};
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
// HANDLE: $(#id)
} else {
elem = document.getElementById(match[2]);
if (elem) {
// Inject the element directly into the jQuery object
this[0] = elem;
this.length = 1;
}
return this;
}
var rootJquery,
// A simple way to check for HTML strings
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
// Strict HTML recognition (#11290: must start with <)
// Shortcut simple #id case for speed
rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/,
init = jQuery.fn.init = function( selector, context, root ) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}
// Method init() accepts an alternate rootjQuery
// so migrate can support jQuery.sub (gh-2101)
root = root || rootjQuery;
// Handle HTML strings
if (typeof selector === "string") {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
…
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
return (context || root).find(selector);
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor(context).find(selector);
}
// HANDLE: $(DOMElement)
} else if (selector.nodeType) {
this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
} else if (isFunction(selector)) {
return root.ready !== undefined ? root.ready(selector) :
// Execute immediately if ready is not present
selector(jQuery);
}
return jQuery.makeArray(selector, this);
};
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
// HANDLE: $(#id)
} else {
elem = document.getElementById(match[2]);
if (elem) {
// Inject the element directly into the jQuery object
this[0] = elem;
this.length = 1;
}
return this;
}
jQuery( selector [, context ] )
jQuery( element )
jQuery( elementArray )
jQuery( object )
jQuery( selection )
jQuery()
jQuery( html [, ownerDocument ] )
jQuery( html, attributes )
jQuery( callback )
var rootJquery,
// A simple way to check for HTML strings
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
// Strict HTML recognition (#11290: must start with <)
// Shortcut simple #id case for speed
rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/,
init = jQuery.fn.init = function( selector, context, root ) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}
// Method init() accepts an alternate rootjQuery
// so migrate can support jQuery.sub (gh-2101)
root = root || rootjQuery;
// Handle HTML strings
if (typeof selector === "string") {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
…
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
return (context || root).find(selector);
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor(context).find(selector);
}
// HANDLE: $(DOMElement)
} else if (selector.nodeType) {
this[0] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
} else if (isFunction(selector)) {
return root.ready !== undefined ? root.ready(selector) :
// Execute immediately if ready is not present
selector(jQuery);
}
return jQuery.makeArray(selector, this);
};
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
// HANDLE: $(#id)
} else {
elem = document.getElementById(match[2]);
if (elem) {
// Inject the element directly into the jQuery object
this[0] = elem;
this.length = 1;
}
return this;
}
Sem nome!
var handleHTMLStrings = function (selector, context, root) {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
// ...
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
// ...
}
return this;
// HANDLE: $(#id)
} else {
// ...
}
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
// ...
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
// ...
}
}
Sem sentido!
var handleHTMLStrings = function (selector, context, root) {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
// ...
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
// ...
}
return this;
// HANDLE: $(#id)
} else {
// ...
}
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
// ...
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
// ...
}
}
var handleHTMLStringsAndElementIds = function (selector, context, root) {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
// ...
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
// ...
}
return this;
// HANDLE: $(#id)
} else {
// ...
}
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
// ...
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
// ...
}
}
Honesto!
var handleHTMLStringsAndElementIds = function (selector, context, root) {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
// ...
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
// ...
}
return this;
// HANDLE: $(#id)
} else {
// ...
}
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
// ...
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
// ...
}
}
var handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root) {
if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec( selector );
}
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
// ...
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
// ...
}
return this;
// HANDLE: $(#id)
} else {
// ...
}
// HANDLE: $(expr, $(...))
} else if (!context || context.jquery) {
// ...
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
// ...
}
}
Honesto e
completo!
handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root)
handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root)
handleHTMLStrings = function (selector, context, root)
handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root)
handleHTMLStrings = function (selector, context, root)
handleElementIds = function (selector, context, root)
handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root)
handleHTMLStrings = function (selector, context, root)
handleElementIds = function (selector, context, root)
handleCSSSelectors = function (selector, context, root)
handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root)
handleHTMLStrings = function (selector, context, root)
handleElementIds = function (selector, context, root)
handleCSSSelectors = function (selector, context, root)
var handleHTMLStrings = function (match, context, root) {
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
}
}
}
Sem sentido?
Características de bons nomes de métodos
• Use verbos*;
• Sem abreviações;
• Conciso (mas, não muito!);
• Use perguntas quando o método retornar um boolean (isEmpty(), canDo());
• Não use “And” e “Or” nos seus nomes;
• Não deixe o nome redundante com o argumento

($list->addItem($item));
• Não deixe o nome redundante com quem chama

($list->addToList($item));
var buildFromHTMLString = function (match, context, root) {
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
}
}
}
Temos um bom nome?
• Use verbos* √
• Sem abreviações √
• Conciso (mas, não muito!) √
• Use perguntas quando o método retornar um boolean (isEmpty(), canDo()) √
• Não use “And” e “Or” nos seus nomes √
• Não deixe o nome redundante com o argumento √
• Não deixe o nome redundante com quem chama √
var fromHTMLString = function (match, context) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
}
}
var fromHTMLString = function (match, context) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
}
}
Características de bons nomes de variáveis
• Sem abreviações;
• Conciso (mas, não muito!);
• Use perguntas quando o método retornar um boolean (isEmpty, canDo);
• Não use “And” e “Or” nos seus nomes;
var fromHTMLString = function (source, context) {
if (source) {
context = context instanceof jQuery ? context[0] : context;
var runScriptsForBackCompat = true
var isNode = context && context.nodeType;
var contextDocument = isNode ? context.ownerDocument || context : document;
jQuery.merge(this, jQuery.parseHTML(source, contextDocument, runScriptsForBackCompat));
var isSingleTagWithoutAttributes = rsingleTag.test(source)
var isAttributesSuperSet = jQuery.isPlainObject(context);
if (isSingleTagWithoutAttributes && isAttributesSuperSet) {
for (attributeName in context) {
// Properties of context are called as methods if possible
if (isFunction(this[attributeName])) {
this[attributeName](context[attributeName]);
// ...and otherwise set as attributes
} else {
this.attr(attributeName, context[attributeName]);
}
}
}
return this;
}
}
var fromHTMLString = function (source, context) {
if (source) {
context = context instanceof jQuery ? context[0] : context;
var runScriptsForBackCompat = true
var isNode = context && context.nodeType;
var contextDocument = isNode ? context.ownerDocument || context : document;
jQuery.merge(this, jQuery.parseHTML(source, contextDocument, runScriptsForBackCompat));
var isSingleTagWithoutAttributes = rsingleTag.test(source)
var isAttributesSuperSet = jQuery.isPlainObject(context);
if (isSingleTagWithoutAttributes && isAttributesSuperSet) {
for (attributeName in context) {
// Properties of context are called as methods if possible
if (isFunction(this[attributeName])) {
this[attributeName](context[attributeName]);
// ...and otherwise set as attributes
} else {
this.attr(attributeName, context[attributeName]);
}
}
}
return this;
}
}
Características de bons nomes de classes
• Use substantivos e adjetivos*;
• Não use muitos adjetivos (AbstractFactoryPatternBase);
• Não use “Manager”, “Helper” e “Data” nos seus nomes;
• Não use Sufixos do seu namespace (Service, Factory, Iterator)
• Evite usar “er”, “or”, “tion”, “sion” (ObjectFinder, DataProcessor, Conversion,
DataManipulation)
–Chris Oldwood
“So, a "DateTimeProvider", that's
basically just a clock, right?”
Características de bons nomes de variáveis
Service is the new Enzo
var HTMLCreationContext = function (elementOrAttributes) {
this.elementOrAttributes = elementOrAttributes;
}
HTMLCreationContext.prototype = {
isNode: function () {
return (this.elementOrAttributes && this.elementOrAttributes.nodeType);
},
getOwnerDocument: function () {
if (this.isNode) {
return this.elementOrAttributes.ownerDocument || this.elementOrAttributes;
}
return document;
},
getAttributesSuperSet: function () {
if (jQuery.isPlainObject(this.elementOrAttributes)) {
return this.elementOrAttributes;
}
return {};
},
getMergeContext: function () {
if (this.elementOrAttributes instanceof jQuery) {
return this.elementOrAttributes[0];
}
return this.elementOrAttributes;
}
}
var HTMLCreationContext = function (elementOrAttributes) {
this.elementOrAttributes = elementOrAttributes;
}
HTMLCreationContext.prototype = {
isNode: function () {
return (this.elementOrAttributes && this.elementOrAttributes.nodeType);
},
getOwnerDocument: function () {
if (this.isNode) {
return this.elementOrAttributes.ownerDocument || this.elementOrAttributes;
}
return document;
},
getAttributesSuperSet: function () {
if (jQuery.isPlainObject(this.elementOrAttributes)) {
return this.elementOrAttributes;
}
return {};
},
getMergeContext: function () {
if (this.elementOrAttributes instanceof jQuery) {
return this.elementOrAttributes[0];
}
return this.elementOrAttributes;
}
}
var fromHTMLString = function (source, context) {
if (source) {
var creationContext = new HTMLCreationContext(context);
var runScriptsForBackCompat = true
jQuery.merge(this, jQuery.parseHTML(
source,
creationContext.getOwnerDocument(),
runScriptsForBackCompat
));
var isSingleTagWithoutAttributes = rsingleTag.test(source)
if (isSingleTagWithoutAttributes) {
var attributes = creationContext.getAttributesSuperSet();
for (attributeName in attributes) {
// Properties of context are called as methods if possible
if (isFunction(this[attributeName])) {
this[attributeName](context[attributeName]);
// ...and otherwise set as attributes
} else {
this.attr(attributeName, context[attributeName]);
}
}
}
return this;
}
}
Concluindo…
1. Procure por lugares com mais de um nível de identação
2. Extraia e dê nome para o que fizer sentido
3. Descreva o que o método realmente faz, sem vergonha, seja honesto!
4. Vá diminuindo o nome do método extraindo suas responsabilidades
5. Excesso de métodos privados para um dado contexto: Uma nova classe!
6. Procure na documentação ou fale com um amiguinho para descrever

o problema de domínio resolvido
7. Seja feliz!
OBRIGADO!
Referências
•Foto dívida: https://flic.kr/p/oiBTYX
•https://martinfowler.com/bliki/TechnicalDebt.html
•https://martinfowler.com/bliki/
TechnicalDebtQuadrant.html
•http://www.laputan.org/mud/
mud.html#ThrowAwayCode
•http://www.laputan.org/mud/
•http://revista.ibict.br/ciinf/article/view/1058/1141

More Related Content

What's hot

Analizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en BisonAnalizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en BisonEgdares Futch H.
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Wilson Su
 
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorProgramming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorFedor Lavrentyev
 
Documentacion edderson callpa_ortiz
Documentacion edderson callpa_ortizDocumentacion edderson callpa_ortiz
Documentacion edderson callpa_ortizEdderson J. Ortiz
 
Jquery Introduction Hebrew
Jquery Introduction HebrewJquery Introduction Hebrew
Jquery Introduction HebrewAlex Ivy
 
Crud secara simultan ala php myadmin
Crud secara simultan ala php myadminCrud secara simultan ala php myadmin
Crud secara simultan ala php myadminRizal Di Caprio
 
Php codigos interfaces fredy guzman cusihunca
Php codigos interfaces   fredy guzman cusihuncaPhp codigos interfaces   fredy guzman cusihunca
Php codigos interfaces fredy guzman cusihuncaTigger_Fred
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasJavier Eguiluz
 
Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3Ying-Hsiang Liao
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Wilson Su
 
Simular un next del recordset en php de forma rudimentaria
Simular un next del recordset en php de forma rudimentariaSimular un next del recordset en php de forma rudimentaria
Simular un next del recordset en php de forma rudimentariajbersosa
 

What's hot (20)

Iteratory
IteratoryIteratory
Iteratory
 
Analizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en BisonAnalizador sintáctico de Pascal escrito en Bison
Analizador sintáctico de Pascal escrito en Bison
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8
 
jQuery PLUGIN
jQuery PLUGINjQuery PLUGIN
jQuery PLUGIN
 
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorProgramming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
 
Documentacion edderson callpa_ortiz
Documentacion edderson callpa_ortizDocumentacion edderson callpa_ortiz
Documentacion edderson callpa_ortiz
 
Sis quiz
Sis quizSis quiz
Sis quiz
 
Jquery Introduction Hebrew
Jquery Introduction HebrewJquery Introduction Hebrew
Jquery Introduction Hebrew
 
Crud secara simultan ala php myadmin
Crud secara simultan ala php myadminCrud secara simultan ala php myadmin
Crud secara simultan ala php myadmin
 
Php codigos interfaces fredy guzman cusihunca
Php codigos interfaces   fredy guzman cusihuncaPhp codigos interfaces   fredy guzman cusihunca
Php codigos interfaces fredy guzman cusihunca
 
Testování prakticky
Testování praktickyTestování prakticky
Testování prakticky
 
1- Sourcecode Array
1- Sourcecode Array1- Sourcecode Array
1- Sourcecode Array
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
Index1
Index1Index1
Index1
 
Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3Handbook - From jQuery to YUI 3
Handbook - From jQuery to YUI 3
 
Wek14 mysql 2
Wek14 mysql 2Wek14 mysql 2
Wek14 mysql 2
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8
 
Jquery Framework
Jquery FrameworkJquery Framework
Jquery Framework
 
Simular un next del recordset en php de forma rudimentaria
Simular un next del recordset en php de forma rudimentariaSimular un next del recordset en php de forma rudimentaria
Simular un next del recordset en php de forma rudimentaria
 

More from iMasters

O que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
O que você precisa saber para modelar bancos de dados NoSQL - Dani MonteiroO que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
O que você precisa saber para modelar bancos de dados NoSQL - Dani MonteiroiMasters
 
Postgres: wanted, beloved or dreaded? - Fabio Telles
Postgres: wanted, beloved or dreaded? - Fabio TellesPostgres: wanted, beloved or dreaded? - Fabio Telles
Postgres: wanted, beloved or dreaded? - Fabio TellesiMasters
 
Por que minha query esta lenta? - Suellen Moraes
Por que minha query esta lenta? - Suellen MoraesPor que minha query esta lenta? - Suellen Moraes
Por que minha query esta lenta? - Suellen MoraesiMasters
 
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...iMasters
 
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalvesORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalvesiMasters
 
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...iMasters
 
Arquitetando seus dados na prática para a LGPD - Alessandra Martins
Arquitetando seus dados na prática para a LGPD - Alessandra MartinsArquitetando seus dados na prática para a LGPD - Alessandra Martins
Arquitetando seus dados na prática para a LGPD - Alessandra MartinsiMasters
 
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...iMasters
 
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana ChahoudDesenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana ChahoudiMasters
 
Use MDD e faça as máquinas trabalharem para você - Andreza Leite
 Use MDD e faça as máquinas trabalharem para você - Andreza Leite Use MDD e faça as máquinas trabalharem para você - Andreza Leite
Use MDD e faça as máquinas trabalharem para você - Andreza LeiteiMasters
 
Entendendo os porquês do seu servidor - Talita Bernardes
Entendendo os porquês do seu servidor - Talita BernardesEntendendo os porquês do seu servidor - Talita Bernardes
Entendendo os porquês do seu servidor - Talita BernardesiMasters
 
Backend performático além do "coloca mais máquina lá" - Diana Arnos
Backend performático além do "coloca mais máquina lá" - Diana ArnosBackend performático além do "coloca mais máquina lá" - Diana Arnos
Backend performático além do "coloca mais máquina lá" - Diana ArnosiMasters
 
Dicas para uma maior performance em APIs REST - Renato Groffe
Dicas para uma maior performance em APIs REST - Renato GroffeDicas para uma maior performance em APIs REST - Renato Groffe
Dicas para uma maior performance em APIs REST - Renato GroffeiMasters
 
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
7 dicas de desempenho que equivalem por 21 - Danielle MonteiroiMasters
 
Quem se importa com acessibilidade Web? - Mauricio Maujor
Quem se importa com acessibilidade Web? - Mauricio MaujorQuem se importa com acessibilidade Web? - Mauricio Maujor
Quem se importa com acessibilidade Web? - Mauricio MaujoriMasters
 
Service Mesh com Istio e Kubernetes - Wellington Figueira da Silva
Service Mesh com Istio e Kubernetes - Wellington Figueira da SilvaService Mesh com Istio e Kubernetes - Wellington Figueira da Silva
Service Mesh com Istio e Kubernetes - Wellington Figueira da SilvaiMasters
 
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto PascuttiErros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto PascuttiiMasters
 
Elasticidade e engenharia de banco de dados para alta performance - Rubens G...
Elasticidade e engenharia de banco de dados para alta performance  - Rubens G...Elasticidade e engenharia de banco de dados para alta performance  - Rubens G...
Elasticidade e engenharia de banco de dados para alta performance - Rubens G...iMasters
 
Construindo aplicações mais confiantes - Carolina Karklis
Construindo aplicações mais confiantes - Carolina KarklisConstruindo aplicações mais confiantes - Carolina Karklis
Construindo aplicações mais confiantes - Carolina KarklisiMasters
 
Monitoramento de Aplicações - Felipe Regalgo
Monitoramento de Aplicações - Felipe RegalgoMonitoramento de Aplicações - Felipe Regalgo
Monitoramento de Aplicações - Felipe RegalgoiMasters
 

More from iMasters (20)

O que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
O que você precisa saber para modelar bancos de dados NoSQL - Dani MonteiroO que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
O que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
 
Postgres: wanted, beloved or dreaded? - Fabio Telles
Postgres: wanted, beloved or dreaded? - Fabio TellesPostgres: wanted, beloved or dreaded? - Fabio Telles
Postgres: wanted, beloved or dreaded? - Fabio Telles
 
Por que minha query esta lenta? - Suellen Moraes
Por que minha query esta lenta? - Suellen MoraesPor que minha query esta lenta? - Suellen Moraes
Por que minha query esta lenta? - Suellen Moraes
 
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
 
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalvesORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
 
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
 
Arquitetando seus dados na prática para a LGPD - Alessandra Martins
Arquitetando seus dados na prática para a LGPD - Alessandra MartinsArquitetando seus dados na prática para a LGPD - Alessandra Martins
Arquitetando seus dados na prática para a LGPD - Alessandra Martins
 
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
 
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana ChahoudDesenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
 
Use MDD e faça as máquinas trabalharem para você - Andreza Leite
 Use MDD e faça as máquinas trabalharem para você - Andreza Leite Use MDD e faça as máquinas trabalharem para você - Andreza Leite
Use MDD e faça as máquinas trabalharem para você - Andreza Leite
 
Entendendo os porquês do seu servidor - Talita Bernardes
Entendendo os porquês do seu servidor - Talita BernardesEntendendo os porquês do seu servidor - Talita Bernardes
Entendendo os porquês do seu servidor - Talita Bernardes
 
Backend performático além do "coloca mais máquina lá" - Diana Arnos
Backend performático além do "coloca mais máquina lá" - Diana ArnosBackend performático além do "coloca mais máquina lá" - Diana Arnos
Backend performático além do "coloca mais máquina lá" - Diana Arnos
 
Dicas para uma maior performance em APIs REST - Renato Groffe
Dicas para uma maior performance em APIs REST - Renato GroffeDicas para uma maior performance em APIs REST - Renato Groffe
Dicas para uma maior performance em APIs REST - Renato Groffe
 
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
 
Quem se importa com acessibilidade Web? - Mauricio Maujor
Quem se importa com acessibilidade Web? - Mauricio MaujorQuem se importa com acessibilidade Web? - Mauricio Maujor
Quem se importa com acessibilidade Web? - Mauricio Maujor
 
Service Mesh com Istio e Kubernetes - Wellington Figueira da Silva
Service Mesh com Istio e Kubernetes - Wellington Figueira da SilvaService Mesh com Istio e Kubernetes - Wellington Figueira da Silva
Service Mesh com Istio e Kubernetes - Wellington Figueira da Silva
 
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto PascuttiErros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
 
Elasticidade e engenharia de banco de dados para alta performance - Rubens G...
Elasticidade e engenharia de banco de dados para alta performance  - Rubens G...Elasticidade e engenharia de banco de dados para alta performance  - Rubens G...
Elasticidade e engenharia de banco de dados para alta performance - Rubens G...
 
Construindo aplicações mais confiantes - Carolina Karklis
Construindo aplicações mais confiantes - Carolina KarklisConstruindo aplicações mais confiantes - Carolina Karklis
Construindo aplicações mais confiantes - Carolina Karklis
 
Monitoramento de Aplicações - Felipe Regalgo
Monitoramento de Aplicações - Felipe RegalgoMonitoramento de Aplicações - Felipe Regalgo
Monitoramento de Aplicações - Felipe Regalgo
 

Pague o aluguel - Trabalhando efetivamente com código em débito técnico - Nelson Senna

  • 1. Pague o aluguel Trabalhando efetivamente com código em débito
  • 2. Eu sou… • Desenvolvedor; • PHP, Ruby, Python e JavaScript. Um pouco de Java e C# (Xamarin); • Trabalho na BriteCore; • Trabalho remotamente desde 2016; • @nelson_senna
  • 4. “…fazendo as coisas de maneira rápida e suja cria-se um débito técnico…” –Martin Fowler
  • 5. Débito técnico é… Código usado para protótipos, provas de conceito ou até uma pequena correção.
  • 6. Classificação de débito técnico Imprudente Prudente Deliberado Negligente “Não temos tempo!” “Precisamos entregar, depois vemos isso.” “O que é OOD? OOP? Design?” “Agora sabemos que devíamos ter feito isso.”
  • 7. Débito técnico é… Código que deveríamos jogar fora…
  • 8. –Martin Fowler “Como uma dívida financeira, o débito técnico incorre em pagamentos de juros, que vêm na forma de esforço extra que temos que fazer no futuro...”
  • 10. “…esse código muitas vezes ganha vida própria… Funciona, então por que consertar?” –Brian Foote
  • 11. E algum tempo e “ifs” depois…
  • 12. “Um Big Ball of Mud tem estrutura desordenada, espalhada, desleixada, remendada e, código espaguete” –Brian Foote
  • 13. Big Ball of Mud • Os nomes de variáveis e funções pouco informativos ou enganosos • Uso extensivo de variáveis globais • Métodos com longas listas de parâmetros mal definidos • Métodos longos e complicados e, executam várias tarefas não relacionadas • Código duplicado • O fluxo de controle é difícil de entender e difícil de seguir • A intenção do programador é quase impossível de discernir • O código é simplesmente ilegível e espalhado sem modularização clara • O código exibe os sinais inconfundíveis de patch após patch nas mãos de vários mantenedores, cada um dos quais mal entendeu as conseqüências do que estava fazendo • Sem documentação
  • 14. Big Ball of Mud A estrutura rígida que faz com que o código fique difícil de entender, caro e suscetível a erros.
  • 15. “Da sinonímia dos termos organização e conhecimento, retira-se que a síntese mais produtiva, ou mais instigadora, para a construção de uma idéia acerca da organização do conhecimento na sociedade é aquela que abstrai de organização, pelo verbo organizar, os sentidos de ORGANIZAR, que são os seguintes: estabelecer as bases de; arrumar de determinado modo; colocar em certa ordem.” –Renato Rocha Souza
  • 16. Entender é… Organizar ideias e conceitos, atribuindo uma ordem, classificando os mesmos.
  • 19. Entender é… Organizar ideias e conceitos, atribuindo uma ordem, classificando os mesmos.
  • 20. Nome é… Palavra ou locução com que se designa uma classe de coisas, pessoas, animais, um lugar, um acidente geográfico, um astro etc.
  • 21. “Existem duas coisas difíceis em computação: invalidação de cache e nomear coisas.” –Phil Karlton
  • 23. Nomes são descobertos! Sem nome Sem sentido Honesto Honesto e Completo Faz o que o nome diz Intenção ↪ ↪ ↪ ↪ ↪ ↪ Abstração de domínio
  • 24. Nomes são descobertos! Sem nome Sem sentido Honesto Honesto e Completo Faz o que o nome diz Intenção ↪ ↪ ↪ ↪ ↪ ↪ Abstração de domínio @arlobelshee
  • 25. var rootJquery, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // Shortcut simple #id case for speed rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/, init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if (!selector) { return this; } // Method init() accepts an alternate rootjQuery // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery; // Handle HTML strings if (typeof selector === "string") { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } … // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { return (context || root).find(selector); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor(context).find(selector); } // HANDLE: $(DOMElement) } else if (selector.nodeType) { this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if (isFunction(selector)) { return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present selector(jQuery); } return jQuery.makeArray(selector, this); }; // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById(match[2]); if (elem) { // Inject the element directly into the jQuery object this[0] = elem; this.length = 1; } return this; }
  • 26. var rootJquery, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // Shortcut simple #id case for speed rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/, init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if (!selector) { return this; } // Method init() accepts an alternate rootjQuery // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery; // Handle HTML strings if (typeof selector === "string") { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } … // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { return (context || root).find(selector); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor(context).find(selector); } // HANDLE: $(DOMElement) } else if (selector.nodeType) { this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if (isFunction(selector)) { return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present selector(jQuery); } return jQuery.makeArray(selector, this); }; // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById(match[2]); if (elem) { // Inject the element directly into the jQuery object this[0] = elem; this.length = 1; } return this; }
  • 27. jQuery( selector [, context ] ) jQuery( element ) jQuery( elementArray ) jQuery( object ) jQuery( selection ) jQuery() jQuery( html [, ownerDocument ] ) jQuery( html, attributes ) jQuery( callback )
  • 28. var rootJquery, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // Shortcut simple #id case for speed rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/, init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if (!selector) { return this; } // Method init() accepts an alternate rootjQuery // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery; // Handle HTML strings if (typeof selector === "string") { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } … // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { return (context || root).find(selector); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor(context).find(selector); } // HANDLE: $(DOMElement) } else if (selector.nodeType) { this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if (isFunction(selector)) { return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present selector(jQuery); } return jQuery.makeArray(selector, this); }; // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById(match[2]); if (elem) { // Inject the element directly into the jQuery object this[0] = elem; this.length = 1; } return this; } Sem nome!
  • 29. var handleHTMLStrings = function (selector, context, root) { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { // ... // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { // ... } return this; // HANDLE: $(#id) } else { // ... } // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { // ... // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { // ... } } Sem sentido!
  • 30. var handleHTMLStrings = function (selector, context, root) { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { // ... // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { // ... } return this; // HANDLE: $(#id) } else { // ... } // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { // ... // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { // ... } }
  • 31. var handleHTMLStringsAndElementIds = function (selector, context, root) { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { // ... // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { // ... } return this; // HANDLE: $(#id) } else { // ... } // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { // ... // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { // ... } } Honesto!
  • 32. var handleHTMLStringsAndElementIds = function (selector, context, root) { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { // ... // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { // ... } return this; // HANDLE: $(#id) } else { // ... } // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { // ... // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { // ... } }
  • 33. var handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root) { if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { // ... // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { // ... } return this; // HANDLE: $(#id) } else { // ... } // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { // ... // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { // ... } } Honesto e completo!
  • 35. handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root) handleHTMLStrings = function (selector, context, root)
  • 36. handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root) handleHTMLStrings = function (selector, context, root) handleElementIds = function (selector, context, root)
  • 37. handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root) handleHTMLStrings = function (selector, context, root) handleElementIds = function (selector, context, root) handleCSSSelectors = function (selector, context, root)
  • 38. handleHTMLStringsAndElementIdsAndCSSSelectors = function (selector, context, root) handleHTMLStrings = function (selector, context, root) handleElementIds = function (selector, context, root) handleCSSSelectors = function (selector, context, root)
  • 39. var handleHTMLStrings = function (match, context, root) { // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; } } } Sem sentido?
  • 40. Características de bons nomes de métodos • Use verbos*; • Sem abreviações; • Conciso (mas, não muito!); • Use perguntas quando o método retornar um boolean (isEmpty(), canDo()); • Não use “And” e “Or” nos seus nomes; • Não deixe o nome redundante com o argumento
 ($list->addItem($item)); • Não deixe o nome redundante com quem chama
 ($list->addToList($item));
  • 41. var buildFromHTMLString = function (match, context, root) { // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; } } }
  • 42. Temos um bom nome? • Use verbos* √ • Sem abreviações √ • Conciso (mas, não muito!) √ • Use perguntas quando o método retornar um boolean (isEmpty(), canDo()) √ • Não use “And” e “Or” nos seus nomes √ • Não deixe o nome redundante com o argumento √ • Não deixe o nome redundante com quem chama √
  • 43. var fromHTMLString = function (match, context) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; } }
  • 44. var fromHTMLString = function (match, context) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true )); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; } }
  • 45. Características de bons nomes de variáveis • Sem abreviações; • Conciso (mas, não muito!); • Use perguntas quando o método retornar um boolean (isEmpty, canDo); • Não use “And” e “Or” nos seus nomes;
  • 46. var fromHTMLString = function (source, context) { if (source) { context = context instanceof jQuery ? context[0] : context; var runScriptsForBackCompat = true var isNode = context && context.nodeType; var contextDocument = isNode ? context.ownerDocument || context : document; jQuery.merge(this, jQuery.parseHTML(source, contextDocument, runScriptsForBackCompat)); var isSingleTagWithoutAttributes = rsingleTag.test(source) var isAttributesSuperSet = jQuery.isPlainObject(context); if (isSingleTagWithoutAttributes && isAttributesSuperSet) { for (attributeName in context) { // Properties of context are called as methods if possible if (isFunction(this[attributeName])) { this[attributeName](context[attributeName]); // ...and otherwise set as attributes } else { this.attr(attributeName, context[attributeName]); } } } return this; } }
  • 47. var fromHTMLString = function (source, context) { if (source) { context = context instanceof jQuery ? context[0] : context; var runScriptsForBackCompat = true var isNode = context && context.nodeType; var contextDocument = isNode ? context.ownerDocument || context : document; jQuery.merge(this, jQuery.parseHTML(source, contextDocument, runScriptsForBackCompat)); var isSingleTagWithoutAttributes = rsingleTag.test(source) var isAttributesSuperSet = jQuery.isPlainObject(context); if (isSingleTagWithoutAttributes && isAttributesSuperSet) { for (attributeName in context) { // Properties of context are called as methods if possible if (isFunction(this[attributeName])) { this[attributeName](context[attributeName]); // ...and otherwise set as attributes } else { this.attr(attributeName, context[attributeName]); } } } return this; } }
  • 48. Características de bons nomes de classes • Use substantivos e adjetivos*; • Não use muitos adjetivos (AbstractFactoryPatternBase); • Não use “Manager”, “Helper” e “Data” nos seus nomes; • Não use Sufixos do seu namespace (Service, Factory, Iterator) • Evite usar “er”, “or”, “tion”, “sion” (ObjectFinder, DataProcessor, Conversion, DataManipulation)
  • 49. –Chris Oldwood “So, a "DateTimeProvider", that's basically just a clock, right?”
  • 50. Características de bons nomes de variáveis Service is the new Enzo
  • 51. var HTMLCreationContext = function (elementOrAttributes) { this.elementOrAttributes = elementOrAttributes; } HTMLCreationContext.prototype = { isNode: function () { return (this.elementOrAttributes && this.elementOrAttributes.nodeType); }, getOwnerDocument: function () { if (this.isNode) { return this.elementOrAttributes.ownerDocument || this.elementOrAttributes; } return document; }, getAttributesSuperSet: function () { if (jQuery.isPlainObject(this.elementOrAttributes)) { return this.elementOrAttributes; } return {}; }, getMergeContext: function () { if (this.elementOrAttributes instanceof jQuery) { return this.elementOrAttributes[0]; } return this.elementOrAttributes; } }
  • 52. var HTMLCreationContext = function (elementOrAttributes) { this.elementOrAttributes = elementOrAttributes; } HTMLCreationContext.prototype = { isNode: function () { return (this.elementOrAttributes && this.elementOrAttributes.nodeType); }, getOwnerDocument: function () { if (this.isNode) { return this.elementOrAttributes.ownerDocument || this.elementOrAttributes; } return document; }, getAttributesSuperSet: function () { if (jQuery.isPlainObject(this.elementOrAttributes)) { return this.elementOrAttributes; } return {}; }, getMergeContext: function () { if (this.elementOrAttributes instanceof jQuery) { return this.elementOrAttributes[0]; } return this.elementOrAttributes; } }
  • 53. var fromHTMLString = function (source, context) { if (source) { var creationContext = new HTMLCreationContext(context); var runScriptsForBackCompat = true jQuery.merge(this, jQuery.parseHTML( source, creationContext.getOwnerDocument(), runScriptsForBackCompat )); var isSingleTagWithoutAttributes = rsingleTag.test(source) if (isSingleTagWithoutAttributes) { var attributes = creationContext.getAttributesSuperSet(); for (attributeName in attributes) { // Properties of context are called as methods if possible if (isFunction(this[attributeName])) { this[attributeName](context[attributeName]); // ...and otherwise set as attributes } else { this.attr(attributeName, context[attributeName]); } } } return this; } }
  • 54.
  • 55. Concluindo… 1. Procure por lugares com mais de um nível de identação 2. Extraia e dê nome para o que fizer sentido 3. Descreva o que o método realmente faz, sem vergonha, seja honesto! 4. Vá diminuindo o nome do método extraindo suas responsabilidades 5. Excesso de métodos privados para um dado contexto: Uma nova classe! 6. Procure na documentação ou fale com um amiguinho para descrever
 o problema de domínio resolvido 7. Seja feliz!