SlideShare una empresa de Scribd logo
1 de 102
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.com



globo
 .com
trileano?



globo
 .com
if variavel == True:
            return “cara”
        else variavel == False:
            return “coroa”
        else:
           return “moeda cai em pe”




globo
 .com
design de código: sustentável
design
  código
sustentável
design?
design = forma de demonstrar
        ‣   como você está organizado os componentes de sua aplicação e como
            eles se comunicam entre si.




globo
 .com
design = forma de demonstrar
        ‣   diagramas (uml, fluxo)
        ‣   desenhos
        ‣   código




globo
 .com
código?
sustentável?
código



globo
 .com
código nasce



globo
 .com
class




globo
 .com
cresce



globo
 .com
class1   class2




globo
 .com
reproduz



globo
 .com
globo
 .com
morre



globo
 .com
globo
 .com
sustentavel



globo
 .com
from random import suffle

        VaRiAvEl = 8
        variavelZoada = 10
        class classe_zoada:
           pass
        classe_zoada.foo = lambda self, x: x / 2




globo
 .com
pep8
        from random import suffle


        variavel = 8
        variavel_zoada = 10


        class ClasseZoada(object):
           def foo(self, x):
              return x / 2

globo
 .com
pyflakes
         class ClasseZoada(object):
            def foo(self, x):
               return x / 2




globo
 .com
testes
         classe_zoada = ClasseZoada()
         assert classe_zoada.foo(10) == 5




globo
 .com
tdd
        ‣   testes primeiro!




globo
 .com
globo
 .com
tdd
        classe_zoada = ClasseZoada()
        assert classe_zoada.dobro(10) == 20




globo
 .com
tdd - baby steps
        class ClasseZoada(object):
           def dobro(self, x):
              return 20




globo
 .com
tdd - baby steps
        classe_zoada = ClasseZoada()
        assert classe_zoada.dobro(10) == 20




globo
 .com
tdd - refactoring
        classe_zoada = ClasseZoada()
        assert classe_zoada.dobro(10) == 20




globo
 .com
tdd - refactoring
        class ClasseZoada(object):
           def dobro(self, x):
              return x * 2




globo
 .com
tdd - refactoring
        classe_zoada = ClasseZoada()
        assert classe_zoada.dobro(10) == 20




globo
 .com
the zen of python
        ‣   by Tim Peters
        ‣   import this




globo
 .com
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éia
globo
 .com
é 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
#I




globo
 .com
for texto in leia():
           imprima(texto)




globo
 .com
for texto in leia():
         if fonte == “impressora”:
             imprima(texto)
         if fonte == “tela”:
             exiba(texto)




globo
 .com
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
interfaces




globo
 .com
interfaces em python?




globo
 .com
interfaces em python?
        interface Writer:
           write(msg)


        class EmailWriter implements Writer:
           def write(self, msg):
              send_email(msg)




globo
 .com
interfaces em python!
         reader = MyReader()
         writer = Emailer()
         for text in reader.read():
            writer.write(text)




globo
 .com
interfaces em python!
         reader = MyReader()
         writer = Printer()
         for text in reader.read():
            writer.write(text)




globo
 .com
interfaces em python?
        interface Writer:
           write(msg)


        class EmailWriter implements Writer:
           def write(self, msg):
              send_email(msg)




globo
 .com
interfaces em python!
         class Printer(object):
            def write(self, text):
               print(text)

         class Emailer(object):
            def write(self, text)
               smtp_send(text)




globo
 .com
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
#2




globo
 .com
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.json



globo
 .com
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.json

globo
 .com
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.json

globo
 .com
mais de uma responsabilidade!




globo
 .com
difícil de explicar




globo
 .com
difícil de ler




globo
 .com
classes com muitas
        responsabilidades
        ‣   muitos métodos




globo
 .com
funções/métodos com muitas
        responsabilidades
        ‣   método/função muito grande




globo
 .com
def last_commit(username):
          timeout(seconds=3)

          url = "http://github.com/{0}/last-commit/"
          response = requests.get(url.format(username))
          return response.json




globo
 .com
@timeout(seconds=3)
        def last_commit(username):
          url = "http://github.com/{0}/last-commit/"
          response = requests.get(url.format(username))
          return response.json




globo
 .com
#3




globo
 .com
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
domain driver development




globo
 .com
def page_metadata(content):
          return {
             'keywords': content.keywords,
             'page_title': content.breadcrumb
          }




globo
 .com
domain driver development
        2 a missão




globo
 .com
class Content(object):

          @property
          def metadata(self):
            return {
               'keywords': self.keywords,
               'page_title': self.breadcrumb
            }




globo
 .com
content.metadata




globo
 .com
#4




globo
 .com
def get_plugin_by_id(id):
          plugins = [plugin for plugin in get_plugins() if plugin.id == id]
          plugin = plugins[0]
          return plugin




globo
 .com
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 plugin
          return None




globo
 .com
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 plugin
          raise NotFound()




globo
 .com
#5




globo
 .com
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
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("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
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 posts(request):
          posts = Posts()
          return render("posts.html", posts)




globo
 .com
import controllers

        controllers.index(request)




globo
 .com
#6




globo
 .com
>>> “andrews” + “medina”
        “andrews medina”




globo
 .com
>>> imagem1 + imagem2




globo
 .com
>>> sprite.do( Jump(10, 1) + Move(10, 10) )




globo
 .com
class Action(object):
           def __add__(self, action):
              return sequence(self, action)

          def __or__(self, action):
            return spawn(self, action)




globo
 .com
globo
 .com
globo
 .com
globo
 .com
globo
 .com
globo
 .com
Agora é melhor que nunca




globo
 .com
obrigado!
 @andrewsmedina

Más contenido relacionado

La actualidad más candente

Escreva aplicações web assíncronas com python3 + tornado
Escreva aplicações web assíncronas com python3 + tornadoEscreva aplicações web assíncronas com python3 + tornado
Escreva aplicações web assíncronas com python3 + tornadoWilson Júnior
 
Implementação de Aplicações Móveis e Jogos com Python - Aula 5
Implementação de Aplicações Móveis e Jogos com Python - Aula 5Implementação de Aplicações Móveis e Jogos com Python - Aula 5
Implementação de Aplicações Móveis e Jogos com Python - Aula 5Flávio Ribeiro
 
Implementação de Aplicações Móveis e Jogos com Python - Aula 4
Implementação de Aplicações Móveis e Jogos com Python - Aula 4Implementação de Aplicações Móveis e Jogos com Python - Aula 4
Implementação de Aplicações Móveis e Jogos com Python - Aula 4Flávio Ribeiro
 
Leonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional InterfacesLeonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional InterfacesDevCamp Campinas
 
Implementação de Aplicações Móveis e Jogos com Python - Aula 3
Implementação de Aplicações Móveis e Jogos com Python - Aula 3Implementação de Aplicações Móveis e Jogos com Python - Aula 3
Implementação de Aplicações Móveis e Jogos com Python - Aula 3Flávio Ribeiro
 
Palestra python
Palestra pythonPalestra python
Palestra pythonRony Cruch
 
Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)Hugo Maia Vieira
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - FlisolLeonn Leite
 
Postgresql + Python = Power!
Postgresql + Python = Power!Postgresql + Python = Power!
Postgresql + Python = Power!Juliano Atanazio
 

La actualidad más candente (20)

Linguagem Go
Linguagem GoLinguagem Go
Linguagem Go
 
Escreva aplicações web assíncronas com python3 + tornado
Escreva aplicações web assíncronas com python3 + tornadoEscreva aplicações web assíncronas com python3 + tornado
Escreva aplicações web assíncronas com python3 + tornado
 
Python 04
Python 04Python 04
Python 04
 
Implementação de Aplicações Móveis e Jogos com Python - Aula 5
Implementação de Aplicações Móveis e Jogos com Python - Aula 5Implementação de Aplicações Móveis e Jogos com Python - Aula 5
Implementação de Aplicações Móveis e Jogos com Python - Aula 5
 
Implementação de Aplicações Móveis e Jogos com Python - Aula 4
Implementação de Aplicações Móveis e Jogos com Python - Aula 4Implementação de Aplicações Móveis e Jogos com Python - Aula 4
Implementação de Aplicações Móveis e Jogos com Python - Aula 4
 
Leonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional InterfacesLeonardo Zamariola - High Order Functions e Functional Interfaces
Leonardo Zamariola - High Order Functions e Functional Interfaces
 
Implementação de Aplicações Móveis e Jogos com Python - Aula 3
Implementação de Aplicações Móveis e Jogos com Python - Aula 3Implementação de Aplicações Móveis e Jogos com Python - Aula 3
Implementação de Aplicações Móveis e Jogos com Python - Aula 3
 
Pilha e Fila Estática
Pilha e Fila EstáticaPilha e Fila Estática
Pilha e Fila Estática
 
Aula 8
Aula 8Aula 8
Aula 8
 
Python 05
Python 05Python 05
Python 05
 
Lista de exercícios em Bash (resolvida)
Lista de exercícios em Bash (resolvida) Lista de exercícios em Bash (resolvida)
Lista de exercícios em Bash (resolvida)
 
Palestra python
Palestra pythonPalestra python
Palestra python
 
Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)Introdução ao Shell Script (versão estendida)
Introdução ao Shell Script (versão estendida)
 
Acessando o MySql com o Python
Acessando o MySql com o PythonAcessando o MySql com o Python
Acessando o MySql com o Python
 
Agenda em bash e dialog
Agenda em bash e dialogAgenda em bash e dialog
Agenda em bash e dialog
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - Flisol
 
PHP 5.3 - What's new?
PHP 5.3 - What's new?PHP 5.3 - What's new?
PHP 5.3 - What's new?
 
Doctrine2 Seminário PHP
Doctrine2 Seminário PHPDoctrine2 Seminário PHP
Doctrine2 Seminário PHP
 
Mongodb: agregação
Mongodb: agregaçãoMongodb: agregação
Mongodb: agregação
 
Postgresql + Python = Power!
Postgresql + Python = Power!Postgresql + Python = Power!
Postgresql + Python = Power!
 

Destacado

CEJS 2016 - Please learn that shit
CEJS 2016 - Please learn that shitCEJS 2016 - Please learn that shit
CEJS 2016 - Please learn that shitEmerson Macedo
 
Escalando aplicações web
Escalando aplicações webEscalando aplicações web
Escalando aplicações webAndrews Medina
 
JSON Schema: Valide e navegue entre suas APIS
JSON Schema: Valide e navegue entre suas APISJSON Schema: Valide e navegue entre suas APIS
JSON Schema: Valide e navegue entre suas APISWilson Júnior
 
256 Shades of R, G and B
256 Shades of R, G and B256 Shades of R, G and B
256 Shades of R, G and BAlmir Filho
 

Destacado (6)

CEJS 2016 - Please learn that shit
CEJS 2016 - Please learn that shitCEJS 2016 - Please learn that shit
CEJS 2016 - Please learn that shit
 
Escalando aplicações web
Escalando aplicações webEscalando aplicações web
Escalando aplicações web
 
JSON Schema: Valide e navegue entre suas APIS
JSON Schema: Valide e navegue entre suas APISJSON Schema: Valide e navegue entre suas APIS
JSON Schema: Valide e navegue entre suas APIS
 
Python 3
Python 3Python 3
Python 3
 
256 Shades of R, G and B
256 Shades of R, G and B256 Shades of R, G and B
256 Shades of R, G and B
 
React Native na globo.com
React Native na globo.comReact Native na globo.com
React Native na globo.com
 

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

Grails parte 1 - introdução
Grails   parte 1 - introduçãoGrails   parte 1 - introdução
Grails parte 1 - introduçãoJosino Rodrigues
 
Turbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com KotlinTurbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com KotlinNelson Glauber Leal
 
Linguagens Poo
Linguagens PooLinguagens Poo
Linguagens PooInfogenius
 
Criando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoCriando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoronaldoferraz
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 
O que mudou no Ruby 1.9
O que mudou no Ruby 1.9O que mudou no Ruby 1.9
O que mudou no Ruby 1.9Nando Vieira
 
JS Experience 2017 - WebAssembly na Prática
JS Experience 2017 - WebAssembly na PráticaJS Experience 2017 - WebAssembly na Prática
JS Experience 2017 - WebAssembly na PráticaiMasters
 
Programação funcional com java 8
Programação funcional com java 8Programação funcional com java 8
Programação funcional com java 8Leonardo Neuwald
 
Programação Funcional com Java 8
Programação Funcional com Java 8Programação Funcional com Java 8
Programação Funcional com Java 8Cristian R. Silva
 
Minicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e PythonMinicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e PythonGuilherme Garcia
 

Similar a Design de código: princípios e práticas para ter um código sustentável (20)

Grails parte 1 - introdução
Grails   parte 1 - introduçãoGrails   parte 1 - introdução
Grails parte 1 - introdução
 
Código Limpo
Código LimpoCódigo Limpo
Código Limpo
 
Turbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com KotlinTurbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com Kotlin
 
Linguagens Poo
Linguagens PooLinguagens Poo
Linguagens Poo
 
Programando em Python - Funções
Programando em Python -  FunçõesProgramando em Python -  Funções
Programando em Python - Funções
 
Criando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoCriando sua própria linguagem de programação
Criando sua própria linguagem de programação
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 
Al sweigart, cap 3
Al sweigart, cap 3Al sweigart, cap 3
Al sweigart, cap 3
 
Minicurso groovy grails
Minicurso groovy grailsMinicurso groovy grails
Minicurso groovy grails
 
Meta-programacao em python
Meta-programacao em pythonMeta-programacao em python
Meta-programacao em python
 
Palestra cbq
Palestra cbqPalestra cbq
Palestra cbq
 
Aplicacoes Rapidas Para Web Com Django
Aplicacoes Rapidas Para Web Com DjangoAplicacoes Rapidas Para Web Com Django
Aplicacoes Rapidas Para Web Com Django
 
O que mudou no Ruby 1.9
O que mudou no Ruby 1.9O que mudou no Ruby 1.9
O que mudou no Ruby 1.9
 
JS Experience 2017 - WebAssembly na Prática
JS Experience 2017 - WebAssembly na PráticaJS Experience 2017 - WebAssembly na Prática
JS Experience 2017 - WebAssembly na Prática
 
Programação funcional com java 8
Programação funcional com java 8Programação funcional com java 8
Programação funcional com java 8
 
Programação Funcional com Java 8
Programação Funcional com Java 8Programação Funcional com Java 8
Programação Funcional com Java 8
 
Python MongoDB no MongoSP
Python MongoDB no MongoSPPython MongoDB no MongoSP
Python MongoDB no MongoSP
 
Introdução ao C#
Introdução ao C#Introdução ao C#
Introdução ao C#
 
Minicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e PythonMinicurso de Django - Desenvolvimento ágil web com Django e Python
Minicurso de Django - Desenvolvimento ágil web com Django e Python
 
Python e MongoDB - Ensol
Python e MongoDB - EnsolPython e MongoDB - Ensol
Python e MongoDB - Ensol
 

Más de Andrews Medina

testando interfaces web
testando interfaces webtestando interfaces web
testando interfaces webAndrews Medina
 
desenvolvendo jogos para android
desenvolvendo jogos para androiddesenvolvendo jogos para android
desenvolvendo jogos para androidAndrews Medina
 
técnica de desenvolvimento de jogos para web
técnica de desenvolvimento de jogos para webtécnica de desenvolvimento de jogos para web
técnica de desenvolvimento de jogos para webAndrews Medina
 
realtime - passado, presente e futuro
realtime - passado, presente e futurorealtime - passado, presente e futuro
realtime - passado, presente e futuroAndrews Medina
 
Haskell para pythonistas
Haskell para pythonistasHaskell para pythonistas
Haskell para pythonistasAndrews Medina
 
animações e jogos além do canvas
animações e jogos além do canvasanimações e jogos além do canvas
animações e jogos além do canvasAndrews Medina
 
escalando aplicações django
escalando aplicações djangoescalando aplicações django
escalando aplicações djangoAndrews Medina
 
Desenvolvimento de Jogos em Python
Desenvolvimento de Jogos em PythonDesenvolvimento de Jogos em Python
Desenvolvimento de Jogos em PythonAndrews Medina
 

Más de Andrews Medina (10)

Python 3 - tutorial
Python 3 - tutorialPython 3 - tutorial
Python 3 - tutorial
 
testando interfaces web
testando interfaces webtestando interfaces web
testando interfaces web
 
desenvolvendo jogos para android
desenvolvendo jogos para androiddesenvolvendo jogos para android
desenvolvendo jogos para android
 
técnica de desenvolvimento de jogos para web
técnica de desenvolvimento de jogos para webtécnica de desenvolvimento de jogos para web
técnica de desenvolvimento de jogos para web
 
realtime - passado, presente e futuro
realtime - passado, presente e futurorealtime - passado, presente e futuro
realtime - passado, presente e futuro
 
Haskell para pythonistas
Haskell para pythonistasHaskell para pythonistas
Haskell para pythonistas
 
animações e jogos além do canvas
animações e jogos além do canvasanimações e jogos além do canvas
animações e jogos além do canvas
 
escalando aplicações django
escalando aplicações djangoescalando aplicações django
escalando aplicações django
 
Desenvolvimento de Jogos em Python
Desenvolvimento de Jogos em PythonDesenvolvimento de Jogos em Python
Desenvolvimento de Jogos em Python
 
Django Show
Django ShowDjango Show
Django Show
 

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

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n