Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Aplicações web que permanecem: uma abordagem arquitetural Java que vai além do último framework JS da moda

Aplicações web que permanecem: uma abordagem arquitetural Java que vai além do último framework JS da moda

Incomodado com a velocidade das mudanças e obsolescência em frameworks JavaScript? E se você precisa construir uma aplicação corporativa que precisa durar mais que a vida curta destes frameworks? Nessa palestra vamos discutir uma abordagem arquitetural web com Java utilizada no desenvolvimento dos projetos Drools e jBPM da Red Hat. Entre os principais pontos explorados:

- Vantagens de uma arquitetura baseada em contratos e não baseada na arquitetura de um framework específico;
- A importância da construção de uma API poliglota;
- Como utilizar o modelo de programação Java EE no seu browser;
- A Importância de tipagem estática em grande bases de código;
- Vantagens de utilizar um framework de UX unificado em uma arquitetura corporativa.
Serão compartilhadas essas e outras técnicas, para manter uma aplicação web desenvolvida ao longo dos últimos sete anos, aplicando as tecnologias mais recentes do desenvolvimento web a uma base de código legada de mais de 1 milhão de linhas – de maneira sustentável, ágil e evolutiva.

Eder Ignatowicz

April 24, 2017
Tweet

More Decks by Eder Ignatowicz

Other Decks in Programming

Transcript

  1. Aplicações web que permanecem:
    uma abordagem arquitetural Java que vai
    além do último framework JS da moda
    Eder Ignatowicz
    Sr. Software Engineer Red Hat

    View Slide

  2. View Slide

  3. Qual arquitetura
    e frameworks para o backend?

    View Slide

  4. Java 9 modular, Reactive,
    Microservices, Vert.x
    Drools, Spring Boot,
    Zookeeper, Spark

    View Slide

  5. E o front-end?

    View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. View Slide

  10. Desenvolvimento JavaScript
    é complexo

    View Slide

  11. Desenvolvimento JavaScript
    Web é complexo

    View Slide

  12. Desenvolvimento Web vai
    continuar sendo complexo

    View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. Qual stack web escolher?

    View Slide

  17. Qual a arquitetura
    mais viável para este problema?

    View Slide

  18. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  19. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  20. Aplicação de Larga Escala
    1mi+ de linhas código web
    5 produtos
    ~150 sub-projetos
    ~30 devs
    7+ anos de base de código

    View Slide

  21. Aplicação de Larga Escala
    Static
    Typing

    View Slide

  22. Aplicação de Larga Escala
    Refactoring

    View Slide

  23. View Slide

  24. View Slide

  25. Aplicação de Larga Escala
    Transpilers
    para JS

    View Slide

  26. View Slide

  27. .java
    javac .class

    View Slide

  28. View Slide

  29. View Slide

  30. View Slide

  31. GWT
    The Good Parts

    View Slide

  32. GWT GOOD PARTS
    Java to JavaScript

    View Slide

  33. GWT GOOD PARTS
    java.* emulation

    View Slide

  34. GWT GOOD PARTS
    DOM APis

    View Slide

  35. GWT GOOD PARTS
    Java 8
    “client side"

    View Slide

  36. GWT GOOD PARTS
    Dev Tools

    View Slide

  37. View Slide

  38. GWT GOOD PARTS
    JS Interop

    View Slide

  39. JS INTEROP - CONSUME
    Java
    @JsType(isNative = true)
    public abstract class JQuery {
    @JsMethod(namespace=GLOBAL)
    public native static JQuery $(String selector);
    public native JQuery css(String prop, String val);
    public native JQuery attr(String name, String val);
    }
    Java
    import static jquery.JQuery.$;
    // ...
    $("ul > li").css("color", "red").attr("data-level", "first");

    View Slide

  40. JS INTEROP - EXPOSE
    Java
    package foo;
    @JsType
    public class Dora {
    public boolean late = true;
    public Dora() {}
    public String auAu() { return "Hello QCon!";}
    }
    JavaScript
    var dora = new foo.Dora();
    if (dora.late) {
    alert(dora.auAu());
    }

    View Slide

  41. Aplicação de Larga Escala
    Refactoring

    View Slide

  42. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  43. Devs Full Stack
    Desenvolvedores “end-to-end"

    View Slide

  44. Devs Full Stack
    Shared Codebase

    View Slide

  45. Devs Full Stack
    "Java EE” no browser

    View Slide

  46. View Slide

  47. ERRAI
    CDI no Browser

    View Slide

  48. @Dependent
    public class ProjectsView {
    @Inject
    Document document;
    @Inject
    @DataField( "projects-view" )
    Div view;
    @Inject
    @DataField( "new-project" )
    Button newProject;
    @Inject
    @DataField( "projects-list" )
    UnorderedList projectsList;
    @Inject
    Instance projects;
    CDI NO BROWSER

    View Slide

  49. if (!filter.doFilter(event)) {
    if (event.kind().equals(StandardWatchEventKind.ENTRY_ADD)) {
    resourceAddedEvent.fire(buildEvent(ResourceAddedEvent.class,
    event).getK2());
    }

    }

    View Slide

  50. public void onNewFile(@Observes ResourceAddedEvent event)
    {
    Window.alert(
    "ResourceAddedEvent:" +
    event.getPath().toURI() +
    " ['" + event.getMessage() + “‘]");
    }

    View Slide

  51. View Slide

  52. Server
    Browser
    Browser Browser
    Browser
    Long Polling
    Web Sockets
    SSE
    ERRAI BUS

    View Slide

  53. Devs Full Stack
    Shared Programming Model

    View Slide

  54. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide


  55. Pizza Types


    <% for ( Pizza pizza : pizzaTypes ) { %>


    <%=pizza.getName()%>
    <%=pizza.getPrice()%>$

    <% } %>


    Size



    Small

    Medium ( + 2$ )

    Large ( + 3$ )


    Extra Toppings

    <% for ( int j = 0; j < 3; j++ ) { %>


    <% for ( int i = sliceSize * j; i < ( j + 1 ) * sliceSize; i++ ) { %>


    <%=pizzaToppings.get( i )%>

    <% }
    if ( j == 0 && remainder > 0 ) {
    %>


    <%=pizzaToppings.get( pizzaToppings.size() - 2 )

    <% } else if ( j == 1 && remainder > 1 ) { %>


    <%=pizzaToppings.get( pizzaToppings.size() - 1 )%>

    <% } %>


    <% } %>

    Each extra topping is 0.65$


    ...

    View Slide

  56. {{title}}
    My favorite hero is: {{myHero}}
    Heroes:


    {{ hero }}


    View Slide




  57. data-field="new-project">
    New Project


    View Slide

  58. @Dependent
    @Templated
    public class ProjectsView {
    @Inject
    @DataField( "projects-view" )
    Div view;
    @Inject
    @DataField( "new-project" )
    Button newProject;
    @Inject
    @DataField( "projects-list" )
    UnorderedList projectsList;
    }
    ERRAI UI

    View Slide

  59. View Slide





  60. Toggle navigation












    Home



    Design
    Processes & Tasks
    Runtime
    Settings







    Messages: 0





    Modified Datasources ExampleDS


    Error: System Failure



    Clear Messages






    Brian Johnson



    Preferences
    Logout








    Settings


    Welcome to BPM Suite


    Business Process Management (BPM) Suite offers a set of flexible, process management tools that support the way you need to work. Select a BPM tool below to get started.


    View Slide

  61. View Slide

  62. Integração com UX
    Deixe o HTML/CSS em paz

    View Slide

  63. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  64. View Slide

  65. Arquitetura
    Hexagonal Architecture - Alistair Cockburn
    Onion Architecture - Jeffrey Palermo
    DCI - James Coplien e Trygve Reenskaug.
    BCE - Ivar Jacobson
    Clean Architecture - Robert C. Martin

    View Slide

  66. Princípios
    Independente de Frameworks
    Testável
    Independente de UI
    Independente de Database
    Independente de Agentes Externos

    View Slide

  67. View Slide

  68. "Architecture is about intent.
    We have made it about
    frameworks and details”
    Robert C. Martin

    View Slide

  69. UBERFIRE VFS
    Use Cases
    VFS
    API
    Regular FS
    Clustering
    GIT FS

    View Slide

  70. View Slide

  71. Qual framework Web escolher?

    View Slide

  72. Qual framework JS escolher?

    View Slide

  73. Escolha do
    framework JS
    Anos
    1 2 3 4 5 6
    Primeiro
    Release
    Perigo
    0

    View Slide

  74. What’s next for Angular 1.x?

    "In all honesty, no one really knows what will happen"
    https://toddmotto.com/future-of-angular-1-x

    View Slide

  75. 1 2 3 4 5 6
    Anos
    Entrega
    Escolha do
    Framework
    JS
    Curva de
    Aprendizado
    Projeto Encerrado
    ou a nova versão
    não tem retrocompatibilidade
    Reescrita
    novo Framework JS
    Curva de
    Aprendizado
    Projeto Encerrado
    ou a nova versão
    não tem retrocompatibilidade
    Reescrita
    novo Framework JS
    Curva de
    Aprendizado

    View Slide

  76. "A good architecture allows
    volatile decisions to be easily
    changed”
    Robert C. Martin

    View Slide

  77. E se eu tratasse a volatilidade dos
    frameworks JS como fato?

    View Slide

  78. View Slide

  79. View Slide

  80. Modelo de Programação
    Componentes:
    - Screen
    - Editors
    - Perspectives
    - Popups

    View Slide

  81. Modelo de Programação
    LifeCycle:
    - OnStart
    - OnSave
    - IsDirty
    - OnClose
    - OnFocus
    - OnLostFocus
    - OnMayClose
    - OnReveal

    View Slide

  82. Perspective
    Editor
    Screen Screen

    View Slide

  83. Baseado em Contratos
    Screen -> Interface WorkbenchScreenActivity
    Editor -> Interface WorkbenchEditorActivity
    Perspective -> Interface PerspectiveActivity

    View Slide

  84. Perspectives
    Uberfire
    Lookup
    Perspective
    ERRAI
    CDI BEAN
    MANAGER
    Scan all
    Perspective Activity
    Implementations
    GWT
    Perspective
    Adapter
    OLD GWT
    WIDGET
    ERRAI UI
    Perspective
    Adapter
    Plain HTML Errai
    UI

    View Slide

  85. Código de 7 anos atrás
    com GWT “old school"

    View Slide

  86. Código da semana passada
    HTML 5 canvas

    View Slide

  87. Live-Span de 5~10 anos
    Trate a arquitetura Web com o
    mesmo respeito que você trata seu
    backend.

    View Slide

  88. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  89. @WorkbenchPerspective(identifier = "HomePerspective",
    isDefault = true)
    @Templated
    public class HomePerspective implements IsElement {
    @Inject
    @DataField
    @WorkbenchPanel(parts = "MoodScreen?uber=fire&uber1=fire1")
    Div moodScreen;
    @Inject
    @DataField
    @WorkbenchPanel(parts = "HomeScreen?uber=fire")
    Div homeScreen;
    @Inject
    @DataField
    @WorkbenchPanel(parts = "AnotherScreen")
    Div anotherScreen;
    } @JsType
    public interface PerspectiveActivity{
    PerspectiveDefinition getDefaultPerspectiveLayout();
    @Override
    default String getName() {
    return getDefaultPerspectiveLayout().getName();
    }
    boolean isDefault();
    Menus getMenus();
    ToolBar getToolBar();
    }

    View Slide

  90. View Slide

  91. function TodoCtrl($scope) {
    $scope.placeText = "MiscellaneousFeatures";
    $scope.todos = [
    {text: 'learn angular', done: true},
    {text: 'build an angular app', done: false}
    ];
    $scope.addTodo = function () {
    $scope.todos.push({text: $scope.todoText, done: false});
    $scope.todoText = '';
    };
    $scope.remaining = function () {
    var count = 0;
    angular.forEach($scope.todos, function (todo) {
    count += todo.done ? 0 : 1;
    });
    return count;
    };
    $scope.archive = function () {
    var oldTodos = $scope.todos;
    $scope.todos = [];
    angular.forEach(oldTodos, function (todo) {
    if (!todo.done) {
    $scope.todos.push(todo);
    }
    });
    };
    $scope["goto"] = function () {
    $goToPlace($scope.placeText);
    };
    }



    {{remaining()}} of {{todos.length}} remaining [
    archive ]

    Todos


    {{todo.text}}
























    $registerPlugin({
    id: "my_angular_js",
    type: "angularjs",
    templateUrl: "angular.sample.html",
    title: function () {
    return "angular " + Math.floor(Math.random() * 10);
    },
    on_close: function () {
    alert("this is a pure JS alert!");
    }
    });

    View Slide

  92. Perspectives
    Uberfire
    Lookup
    Perspective
    ERRAI
    CDI BEAN
    MANAGER
    Scan all
    Perspective Activity
    Implementations
    GWT
    Perspective
    Adapter
    OLD GWT
    WIDGET
    ERRAI UI
    Perspective
    Adapter
    Plain HTML Errai
    UI
    Angular
    Perspective
    Adapter
    Angular native
    Perspective
    Any JS
    Perspective
    Adapter
    Any JS
    Framework

    View Slide

  93. Angular JS Screen

    View Slide

  94. Criação de
    Componentes em
    Runtime

    View Slide

  95. View Slide

  96. View Slide

  97. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  98. Desenvolvimento Web
    é complexo

    View Slide

  99. Aplicações Web são parte da
    nossa arquitetura

    View Slide

  100. Princípios
    Independente de Frameworks
    Testável
    Independente de UI
    Independente de Database
    Independente de Agentes Externos

    View Slide

  101. Arquitetura de software é
    exercício de trade-offs

    View Slide

  102. 5 pilares:
    Aplicação de Larga Escala
    Desenvolvedores full stack
    Integração com UX
    Life-Span de 5~10 anos
    Interoperabilidade

    View Slide

  103. Eder Ignatowicz
    @ederign
    http://bit.ly/5-pilares-web

    View Slide