design de código: princípios e práticas para ter um código          sustentável           @andrewsmedina
existem muitos códigos ruins...globo .com
o trileando é um deles...globo .com
mas eles já tem um lugar         reservado para eles:globo .com
codecrap.comglobo .com
trileano?globo .com
if variavel == True:            return “cara”        else variavel == False:            return “coroa”        else:       ...
design de código: sustentável
design  códigosustentável
design?
design = forma de demonstrar        ‣   como você está organizado os componentes de sua aplicação e como            eles s...
design = forma de demonstrar        ‣   diagramas (uml, fluxo)        ‣   desenhos        ‣   códigoglobo .com
código?
sustentável?
códigoglobo .com
código nasceglobo .com
classglobo .com
cresceglobo .com
class1   class2globo .com
reproduzglobo .com
globo .com
morreglobo .com
globo .com
sustentavelglobo .com
from random import suffle        VaRiAvEl = 8        variavelZoada = 10        class classe_zoada:           pass        c...
pep8        from random import suffle        variavel = 8        variavel_zoada = 10        class ClasseZoada(object):    ...
pyflakes         class ClasseZoada(object):            def foo(self, x):               return x / 2globo .com
testes         classe_zoada = ClasseZoada()         assert classe_zoada.foo(10) == 5globo .com
tdd        ‣   testes primeiro!globo .com
globo .com
tdd        classe_zoada = ClasseZoada()        assert classe_zoada.dobro(10) == 20globo .com
tdd - baby steps        class ClasseZoada(object):           def dobro(self, x):              return 20globo .com
tdd - baby steps        classe_zoada = ClasseZoada()        assert classe_zoada.dobro(10) == 20globo .com
tdd - refactoring        classe_zoada = ClasseZoada()        assert classe_zoada.dobro(10) == 20globo .com
tdd - refactoring        class ClasseZoada(object):           def dobro(self, x):              return x * 2globo .com
tdd - refactoring        classe_zoada = ClasseZoada()        assert classe_zoada.dobro(10) == 20globo .com
the zen of python        ‣   by Tim Peters        ‣   import thisglobo .com
the zen of python        ‣   simples é melhor que complexo        ‣   bonito é melhor que feio        ‣   explícito é melh...
é possível escrever um código            “não sustentável” usando tdd,            seguindo pep8, flakes e o zen?globo .com...
#Iglobo .com
for texto in leia():           imprima(texto)globo .com
for texto in leia():         if fonte == “impressora”:             imprima(texto)         if fonte == “tela”:             ...
for texto in leia():           if fonte == “impressora”:               imprima(texto)           if fonte == “tela”:       ...
interfacesglobo .com
interfaces em python?globo .com
interfaces em python?        interface Writer:           write(msg)        class EmailWriter implements Writer:           ...
interfaces em python!         reader = MyReader()         writer = Emailer()         for text in reader.read():           ...
interfaces em python!         reader = MyReader()         writer = Printer()         for text in reader.read():           ...
interfaces em python?        interface Writer:           write(msg)        class EmailWriter implements Writer:           ...
interfaces em python!         class Printer(object):            def write(self, text):               print(text)         c...
interfaces em python!         class Writer(object):            def write(self, text):               raise NotImplementedEr...
#2globo .com
o que esse código faz?         def timeout_handler(signum, frame):           raise TimeoutException()         signal.signa...
o que esse código faz?         def last_commit(username):           def timeout_handler(signum, frame):               rais...
o que esse código faz?         def last_commit(username):           def timeout_handler(signum, frame):              raise...
mais de uma responsabilidade!globo .com
difícil de explicarglobo .com
difícil de lerglobo .com
classes com muitas        responsabilidades        ‣   muitos métodosglobo .com
funções/métodos com muitas        responsabilidades        ‣   método/função muito grandeglobo .com
def last_commit(username):          timeout(seconds=3)          url = "http://github.com/{0}/last-commit/"          respon...
@timeout(seconds=3)        def last_commit(username):          url = "http://github.com/{0}/last-commit/"          respons...
#3globo .com
def extract_context(content):          all_tags = list(content.tags.all())          keywords = ", ".join([t.name for t in ...
domain driver developmentglobo .com
def page_metadata(content):          return {             keywords: content.keywords,             page_title: content.brea...
domain driver development        2 a missãoglobo .com
class Content(object):          @property          def metadata(self):            return {               keywords: self.ke...
content.metadataglobo .com
#4globo .com
def get_plugin_by_id(id):          plugins = [plugin for plugin in get_plugins() if plugin.id == id]          plugin = plu...
e se get_plugins() retornar []?globo .com
get_plugin_by_id(1)globo .com
e se get_plugins() retornar o plugin        com id 1 como primeiro na lista?globo .com
def plugin_by_id(id):          for plugin in get_plugins():              if plugin.id == id:                  return plugi...
e se o plugin não existir?globo .com
plugin = get_plugin_by_id(1)        plugin.run()globo .com
plugin = get_plugin_by_id(1)        if plugin:            plugin.run()globo .com
def plugin_by_id(id):          for plugin in get_plugins():              if plugin.id == id:                  return plugi...
#5globo .com
class Actions(object):           def save_file(self, filename, content):              file = open(filename, "w")          ...
actions = Actions() ???        actions.save_file(“foo.txt”, “foo”)globo .com
actions = Actions() ???        print actions.read_file(“foo.txt”)globo .com
class Controllers(object):           def index(self, request):              items = Itens()              return render("in...
controllers = Controller() ???        controllers.index(request)globo .com
controllers = Controller() ???        controllers.add_comment(request)globo .com
classes para “agrupar” métodos?globo .com
você pode usar módulo!globo .com
#controller.py        def index(request):          items = Itens()          return render("index.html", items)        def ...
import controllers        controllers.index(request)globo .com
#6globo .com
>>> “andrews” + “medina”        “andrews medina”globo .com
>>> imagem1 + imagem2globo .com
>>> sprite.do( Jump(10, 1) + Move(10, 10) )globo .com
class Action(object):           def __add__(self, action):              return sequence(self, action)          def __or__(...
globo .com
globo .com
globo .com
globo .com
globo .com
Agora é melhor que nuncaglobo .com
obrigado! @andrewsmedina
Próximos SlideShares
Carregando em…5
×

Design de código: princípios e práticas para ter um código sustentável

1.958 visualizações

Publicada em

Escrever código é algo fácil o difícil é manter seu código limpo, legível por muito tempo sem transformá-lo em um código legado. Irei abordar várias práticas, princípios e padrões que nos ajudam a escrever e manter o código limpo.

Publicada em: Tecnologia
  • Seja o primeiro a comentar

Design de código: princípios e práticas para ter um código sustentável

  1. 1. design de código: princípios e práticas para ter um código sustentável @andrewsmedina
  2. 2. existem muitos códigos ruins...globo .com
  3. 3. o trileando é um deles...globo .com
  4. 4. mas eles já tem um lugar reservado para eles:globo .com
  5. 5. codecrap.comglobo .com
  6. 6. trileano?globo .com
  7. 7. if variavel == True: return “cara” else variavel == False: return “coroa” else: return “moeda cai em pe”globo .com
  8. 8. design de código: sustentável
  9. 9. design códigosustentável
  10. 10. design?
  11. 11. design = forma de demonstrar ‣ como você está organizado os componentes de sua aplicação e como eles se comunicam entre si.globo .com
  12. 12. design = forma de demonstrar ‣ diagramas (uml, fluxo) ‣ desenhos ‣ códigoglobo .com
  13. 13. código?
  14. 14. sustentável?
  15. 15. códigoglobo .com
  16. 16. código nasceglobo .com
  17. 17. classglobo .com
  18. 18. cresceglobo .com
  19. 19. class1 class2globo .com
  20. 20. reproduzglobo .com
  21. 21. globo .com
  22. 22. morreglobo .com
  23. 23. globo .com
  24. 24. sustentavelglobo .com
  25. 25. from random import suffle VaRiAvEl = 8 variavelZoada = 10 class classe_zoada: pass classe_zoada.foo = lambda self, x: x / 2globo .com
  26. 26. pep8 from random import suffle variavel = 8 variavel_zoada = 10 class ClasseZoada(object): def foo(self, x): return x / 2globo .com
  27. 27. pyflakes class ClasseZoada(object): def foo(self, x): return x / 2globo .com
  28. 28. testes classe_zoada = ClasseZoada() assert classe_zoada.foo(10) == 5globo .com
  29. 29. tdd ‣ testes primeiro!globo .com
  30. 30. globo .com
  31. 31. tdd classe_zoada = ClasseZoada() assert classe_zoada.dobro(10) == 20globo .com
  32. 32. tdd - baby steps class ClasseZoada(object): def dobro(self, x): return 20globo .com
  33. 33. tdd - baby steps classe_zoada = ClasseZoada() assert classe_zoada.dobro(10) == 20globo .com
  34. 34. tdd - refactoring classe_zoada = ClasseZoada() assert classe_zoada.dobro(10) == 20globo .com
  35. 35. tdd - refactoring class ClasseZoada(object): def dobro(self, x): return x * 2globo .com
  36. 36. tdd - refactoring classe_zoada = ClasseZoada() assert classe_zoada.dobro(10) == 20globo .com
  37. 37. the zen of python ‣ by Tim Peters ‣ import thisglobo .com
  38. 38. the zen of python ‣ simples é melhor que complexo ‣ bonito é melhor que feio ‣ explícito é melhor que implícito ‣ legibilidade conta ‣ Casos especiais não são especiais o suficiente para quebrar as regras ‣ Se a implementação é difícil de explicar, é uma má idéia ‣ Se a implementação é fácil de explicar, pode ser uma boa idéiaglobo .com
  39. 39. é possível escrever um código “não sustentável” usando tdd, seguindo pep8, flakes e o zen?globo .com plataformas de conteúdo e vendas
  40. 40. #Iglobo .com
  41. 41. for texto in leia(): imprima(texto)globo .com
  42. 42. for texto in leia(): if fonte == “impressora”: imprima(texto) if fonte == “tela”: exiba(texto)globo .com
  43. 43. for texto in leia(): if fonte == “impressora”: imprima(texto) if fonte == “tela”: exiba(texto) if fonte == “fax”: envie_fax(texto) if fonte == “email”: envie_email(texto)globo .com
  44. 44. interfacesglobo .com
  45. 45. interfaces em python?globo .com
  46. 46. interfaces em python? interface Writer: write(msg) class EmailWriter implements Writer: def write(self, msg): send_email(msg)globo .com
  47. 47. interfaces em python! reader = MyReader() writer = Emailer() for text in reader.read(): writer.write(text)globo .com
  48. 48. interfaces em python! reader = MyReader() writer = Printer() for text in reader.read(): writer.write(text)globo .com
  49. 49. interfaces em python? interface Writer: write(msg) class EmailWriter implements Writer: def write(self, msg): send_email(msg)globo .com
  50. 50. interfaces em python! class Printer(object): def write(self, text): print(text) class Emailer(object): def write(self, text) smtp_send(text)globo .com
  51. 51. interfaces em python! class Writer(object): def write(self, text): raise NotImplementedError() class Printer(Writer): def write(self, text): print(text) class Emailer(Writer): def write(self, text) smtp_send(text)globo .com
  52. 52. #2globo .com
  53. 53. o que esse código faz? def timeout_handler(signum, frame): raise TimeoutException() signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(3) url = "http://github.com/{0}/last-commit/" response = requests.get(url.format(username)) return response.jsonglobo .com
  54. 54. o que esse código faz? def last_commit(username): def timeout_handler(signum, frame): raise TimeoutException() signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(3) url = "http://github.com/{0}/last-commit/" response = requests.get(url.format(username)) return response.jsonglobo .com
  55. 55. o que esse código faz? def last_commit(username): def timeout_handler(signum, frame): raise TimeoutException() signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(3) url = "http://github.com/{0}/last-commit/" response = requests.get(url.format(username)) return response.jsonglobo .com
  56. 56. mais de uma responsabilidade!globo .com
  57. 57. difícil de explicarglobo .com
  58. 58. difícil de lerglobo .com
  59. 59. classes com muitas responsabilidades ‣ muitos métodosglobo .com
  60. 60. funções/métodos com muitas responsabilidades ‣ método/função muito grandeglobo .com
  61. 61. def last_commit(username): timeout(seconds=3) url = "http://github.com/{0}/last-commit/" response = requests.get(url.format(username)) return response.jsonglobo .com
  62. 62. @timeout(seconds=3) def last_commit(username): url = "http://github.com/{0}/last-commit/" response = requests.get(url.format(username)) return response.jsonglobo .com
  63. 63. #3globo .com
  64. 64. def extract_context(content): all_tags = list(content.tags.all()) keywords = ", ".join([t.name for t in all_tags]) return { keywords: keywords, page_title: _build_breadcrumb(content) }globo .com
  65. 65. domain driver developmentglobo .com
  66. 66. def page_metadata(content): return { keywords: content.keywords, page_title: content.breadcrumb }globo .com
  67. 67. domain driver development 2 a missãoglobo .com
  68. 68. class Content(object): @property def metadata(self): return { keywords: self.keywords, page_title: self.breadcrumb }globo .com
  69. 69. content.metadataglobo .com
  70. 70. #4globo .com
  71. 71. def get_plugin_by_id(id): plugins = [plugin for plugin in get_plugins() if plugin.id == id] plugin = plugins[0] return pluginglobo .com
  72. 72. e se get_plugins() retornar []?globo .com
  73. 73. get_plugin_by_id(1)globo .com
  74. 74. e se get_plugins() retornar o plugin com id 1 como primeiro na lista?globo .com
  75. 75. def plugin_by_id(id): for plugin in get_plugins(): if plugin.id == id: return plugin return Noneglobo .com
  76. 76. e se o plugin não existir?globo .com
  77. 77. plugin = get_plugin_by_id(1) plugin.run()globo .com
  78. 78. plugin = get_plugin_by_id(1) if plugin: plugin.run()globo .com
  79. 79. def plugin_by_id(id): for plugin in get_plugins(): if plugin.id == id: return plugin raise NotFound()globo .com
  80. 80. #5globo .com
  81. 81. class Actions(object): def save_file(self, filename, content): file = open(filename, "w") file.write(content) file.close() def read_file(self, filename): file = open(filename) return file.read()globo .com
  82. 82. actions = Actions() ??? actions.save_file(“foo.txt”, “foo”)globo .com
  83. 83. actions = Actions() ??? print actions.read_file(“foo.txt”)globo .com
  84. 84. class Controllers(object): def index(self, request): items = Itens() return render("index.html", items) def posts(self, request): posts = Posts() return render("posts.html", posts) def add_comment(self, request): post = Post(request.POST or {}) if post.is_valid(): post.save() return render("add_comment.html", post)globo .com
  85. 85. controllers = Controller() ??? controllers.index(request)globo .com
  86. 86. controllers = Controller() ??? controllers.add_comment(request)globo .com
  87. 87. classes para “agrupar” métodos?globo .com
  88. 88. você pode usar módulo!globo .com
  89. 89. #controller.py def index(request): items = Itens() return render("index.html", items) def posts(request): posts = Posts() return render("posts.html", posts)globo .com
  90. 90. import controllers controllers.index(request)globo .com
  91. 91. #6globo .com
  92. 92. >>> “andrews” + “medina” “andrews medina”globo .com
  93. 93. >>> imagem1 + imagem2globo .com
  94. 94. >>> sprite.do( Jump(10, 1) + Move(10, 10) )globo .com
  95. 95. class Action(object): def __add__(self, action): return sequence(self, action) def __or__(self, action): return spawn(self, action)globo .com
  96. 96. globo .com
  97. 97. globo .com
  98. 98. globo .com
  99. 99. globo .com
  100. 100. globo .com
  101. 101. Agora é melhor que nuncaglobo .com
  102. 102. obrigado! @andrewsmedina

×