Escolher a arquitetura certa é uma parte essencial da construção de um serviço front-end. A desenvolvedora Anna Karpelevich disse aos alunos
da Escola de Desenvolvimento de Interface o que é arquitetura, quais funções ela desempenha e quais problemas resolve. Na palestra, você pode aprender sobre as abordagens arquitetônicas mais populares no front-end: Model-View- * e Flux.
Boa noite Meu nome é Anya Karpelevich. Hoje falaremos sobre a arquitetura do front-end de nível superior.
Eu trabalho no Yandex.Direct. Fazemos interfaces para anunciantes. Eles publicam anúncios, os personalizam. Este é um sistema muito complexo e interessante, com muitos componentes interconectados, eles crescem um no outro, têm uma funcionalidade comum e própria. "As calças se transformam em shorts elegantes." Tudo isso tem que ser cuidadosamente controlado. E a arquitetura em nossos aplicativos é muito complexa. Esta é uma das razões pelas quais estou dando esta palestra hoje. Eu realmente amo esse tópico.
O que é arquitetura? O fato é que provavelmente não há resposta para essa pergunta. Ou existe, mas cada um tem o seu. Este é um tópico muito controverso. Isso causa muita controvérsia, muitos holivares. E muito do que vou falar hoje é minha opinião. Em parte, é apoiado pelo meu grupo de trabalho, em parte não muito. E todo mundo, quando ele escreve a arquitetura de seu aplicativo, decide por si mesmo como e o que fazer.
É por isso que a arquitetura é um dos lugares mais criativos no trabalho de um programador. E, portanto, nossa apresentação hoje também começará com criatividade.

Vamos olhar para a foto da esquerda. Ficarei muito feliz se alguém reconhecer o edifício que é mostrado nele. Esta é a igreja de Saint-Sulpice em Paris. Preste atenção nas torres, por causa delas esta igreja foi colocada aqui. Espero que sejam diferentes. Eles são bem diferentes, e há uma razão interessante para isso. Entre eles 130 anos de diferença. Em seguida, a torre esquerda foi demolida e reconstruída durante a guerra franco-prussiana.
Por que ela está aqui? Olhe para esta foto. As torres têm a mesma arquitetura e todo o ambiente, essas vinhetas, luminárias e estruturas em arco são diferentes. Porque Porque o objetivo dessas torres é o mesmo. Nenhum deles, por exemplo, era uma torre sineira. Estas são apenas torres. Algo estava guardado neles e todo o resto era diferente. Porque Porque a arquitetura dessas torres é a mesma. Ambos têm um cofre, apenas uma janela, e é uma lanceta. As janelas têm aproximadamente a mesma altura. E a ideia é que a arquitetura, tanto edifícios quanto aplicativos, seja uma estrutura de suporte. Isso não é uma vinheta, não é uma cintilação, não é uma implementação. É isso que está no centro. E essa base, via de regra, depende do ambiente, do solo, quando se trata do edifício, da meta que o arquiteto estabelece para si, mas quase nunca depende de aprimoramentos de design.
O exemplo de construção para o tema da arquitetura é bastante óbvio. Mas a imagem certa é mais interessante. "Arquitetura é música entorpecida." "Architektur ist gefrorene Musik", disse Johann Wolfgang Goethe no século XVIII. Goethe provavelmente não sabia nada sobre a arquitetura dos edifícios, ele era um poeta. E ele tinha certeza de não saber nada sobre arquitetura de aplicativos. Mas ele expressou uma ideia muito valiosa e interessante.
A música existe na dinâmica. Isso não é algo estático. Este é um processo. E assim, um aplicativo é um processo. Ele tem um momento de lançamento, ele tem um momento de desenvolvimento, quando fazemos algo com ele, trabalho. E ele finalmente tem um momento de conclusão. A arquitetura do aplicativo é sua fatia a qualquer momento. A qualquer momento, nossa aplicação, como tema musical, deve ser clara, clara, compreensível, previsível etc. Caso contrário, tudo desmoronará.
Com esta introdução criativa, terminamos, passamos a coisas mais mundanas, mais próximas da prática de criar aplicativos.
O que é arquitetura e por que é necessário?

Primeiro, temos a organização de uma grande quantidade de códigos, algo que nós no Direct, e não apenas no Direct, encontramos o tempo todo. Há tanto código que você pode se perder nele. Não queremos nos perder no código.
Em segundo lugar, duplicação de funcionalidade. Esse também é um problema eterno que você sempre encontrará, e hoje esse tópico da duplicação passará pela linha vermelha por toda a palestra. A mesma funcionalidade que podemos precisar em vários lugares na interface. Se for necessário em vários locais, deve ser fisicamente o mesmo código usado em vários locais, não uma cópia. Porque Falaremos mais sobre isso. Mas a arquitetura deve nos ajudar a evitar copiar e colar.
Terceiro é o apoio. É óbvio que, se temos um aplicativo, precisamos apoiá-lo de alguma forma, e é aconselhável que todos os recursos da equipe não sejam desperdiçados nisso.
Mude a composição da equipe. Também é algo que encontramos na vida real com mais frequência do que gostaríamos. Alguém vem, alguém sai, e se uma pessoa passa seis meses para inserir o código, isso é ruim. Se o conhecimento do código for armazenado em apenas um cabeçalho e transmitirá esse conhecimento por seis meses em caso de saída, isso é ainda pior. Em geral, aqui a arquitetura também nos ajuda a tornar tudo isso mais compreensível e a manter o compartilhamento de conhecimento.
Adicionando e expandindo funcionalidade. Também é uma coisa bastante óbvia. O gerente vem correndo até nós e diz que isso é urgentemente necessário. E se, para fazer isso com urgência, você precisa gastar muito tempo e esforço, essa é uma solução arquitetônica ruim. E nós precisamos do bem.
E, finalmente, erros. Quanto mais compreensível, previsível nossa arquitetura, mais fácil é procurar erros, menos bugs.
Como tudo isso pode ser chamado? Tudo isso pode ser chamado - os problemas de um sistema complexo. Um aplicativo é um sistema complexo; a arquitetura nos ajuda a resolver um problema.

Em suma, de alguma forma. Aqui está uma imagem de macarrão à minha direita, e é isso que acontece se você não segue a arquitetura, se não a constrói, pensa e projeta. E a segunda imagem é o que acontece se a arquitetura for pensada de alguma forma. Este não é Saint-Sulpice, mas pelo menos um designer infantil, ele se mantém firme e não desmorona. Hoje jogaremos muito construtor também.

Formalmente sobre tudo isso. A arquitetura é uma maneira de resolver os problemas de um sistema complexo abstraindo a implementação da interface e diferenciando os poderes entre os blocos de código. Além disso, analisaremos essa longa frase em detalhes.
Quais são os recursos da arquitetura de aplicativos como um campo de conhecimento? Ela tem uma área específica com a qual trabalhamos. Ou seja, não é algo abstrato, é uma coisa muito específica. Aqui está a tarefa: selecionamos a arquitetura para ela, e não para que, oooh, uma abordagem arquitetônica interessante, devemos tentar. Então não. Você pode experimentar algo pequeno, mas para um projeto sério, a arquitetura é selecionada, algumas vezes composta para um projeto específico.
A história da questão, quando, em geral, surgiu a idéia de que a arquitetura deveria ser feita. Devo dizer que, certa vez, uma idéia extraordinária foi expressa em 1968 por Edsger Dijkstra, um programador maravilhoso. Ele provavelmente é mais conhecido como o autor do algoritmo Dijkstra, a busca pelo caminho mais curto em um gráfico. Mas ele tem muitas idéias inovadoras para o seu tempo. E um deles é um artigo, então darei uma referência aos materiais, você pode ler, existem apenas duas páginas, um pequeno ensaio. Parece “Operador GOTO considerado prejudicial”, na tradução “Operador GOTO - operador de transição incondicional - mal”. Foi o primeiro pensamento que vamos dizer oficialmente que precisamos escrever arquitetura, não macarrão.
Nos anos 70, essa idéia já foi desenvolvida por Dijkstra em colaboração com Parnassus, e por conta própria, individualmente. O primeiro livro detalhado sobre arquitetura de aplicativos em geral foi escrito em 1996 por Mary Shaw e David Garlan. Depois disso, de fato, esses livros detalhados sobre arquitetura de software não foram escritos precisamente por causa do escopo, de modo que cada campo de conhecimento tem suas próprias abordagens arquitetônicas, em algum lugar, em algum lugar mais popular, em geral não aplicável em alguns lugares. E como a arquitetura é um processo criativo, você não encontrará livros específicos sobre como escrever arquitetura. Talvez depois de 1996 não houvesse nada particularmente detalhado sobre esse assunto.
Quais são os requisitos para a arquitetura do projeto agora. Em primeiro lugar, e mais importante, o que é necessário é, de fato, extensibilidade, porque se o seu projeto não se expandir, ele estará morto.
Reutilizando código. É sobre a própria cópia e colagem. Se você tiver dois blocos usados em dois locais diferentes, precisará da mesma funcionalidade, reutilizar o mesmo código e a arquitetura deverá ser tal que qualquer parte do código possa ser usada e reutilizada assim que necessário .
Separação de autoridade entre os módulos de código. Falaremos sobre isso hoje em mais detalhes, por que isso é necessário. A idéia é a seguinte: cada módulo, cada bloco, cada pedaço de código deve executar uma ação específica, realizar exatamente uma função. E essa função deve ser colocada no título deste método, classe, seja lá o que for, módulo. Um módulo - uma função.
E, finalmente, a qualidade das aplicações. Gostaria de fazer muitas coisas - confiabilidade e compatibilidade com versões anteriores. Na realidade, novamente, ele é selecionado para a tarefa. Em algum lugar, a compatibilidade com versões anteriores é necessária para que, em nenhum caso, algo se mova. Em algum lugar, a confiabilidade é necessária para que Deus não permita que senhas, códigos PIN de cartões ou CVVs não vazem para lugar algum. Em algum lugar, você precisa estar livre de problemas se for um satélite ou outra coisa. Em geral, escolha alguns. Quanto mais você deseja oferecer suporte, mais complexidade você provavelmente encontrará na arquitetura.
Além disso, falaremos com você sobre algumas definições, exatamente essas coisas enciclopédicas. Por que isso é importante? Porque a terminologia na arquitetura é muito importante e precisamos falar o mesmo idioma com você. As definições na maioria das vezes são tiradas do paradigma de programação chamado OOP. Mas, de fato, eles surgiram em outros paradigmas, com os termos “classe, objeto, interface” que operam não apenas dentro da estrutura da OOP. No entanto, essas definições e entendimento são retirados precisamente do mundo da OOP.

A coisa mais simples é a classe. O que é uma aula? Este é um modelo, isto é uma amostra. Por exemplo, a classe Snake é a classe Snake. Definimos três campos particulares com ela, ou seja, um campo que não é acessível a ninguém, exceto aos métodos da própria classe - o número de objetivos, o número de caudas e o comprimento dos papagaios. Determinamos o construtor no qual colocamos essas mesmas cabeças, caudas e comprimento em papagaios. Tem a classe Snake. Tudo é simples.

Nós estamos indo além. Objeto. E um objeto é uma instância de uma estrutura específica. Além disso, novamente no POO clássico, está implícito que um objeto é um objeto de uma classe. No mundo moderno, em JavaScript, que nem sempre era uma linguagem OOP, e mesmo agora nem sempre é em todo lugar, sabemos que pode haver objetos abstratos. Ou seja, podemos criar um objeto, um literal, que não será um objeto da classe. Mas aqui está um exemplo de como criamos um objeto da classe Snake. Aqui temos uma cobra de duas caudas com 38 papagaios - uma jibóia.

Módulo Um módulo é uma unidade semântica. Isso nem sempre é uma aula. Pode ser um conjunto de classes, um conjunto de objetos, um conjunto de métodos que não são combinados em classes. Geralmente, você pode assumir que um módulo é o que você escreveu em um único arquivo. Mas, em princípio, o módulo é a pasta em que se encontram, por exemplo, o arquivo e os testes para esse módulo também são um módulo. O importante aqui é que um módulo é o que você chama de módulo, o que você considera uma unidade de semântica. Neste caso, o módulo é sobre como comemos cobras. O resultado deste módulo é o último método, eatSnake, como comemos cobras. Não sei por que comemos cobras, mas podemos fazê-lo, porque escrevemos esse módulo assim.

Foi trivial, então uma coisa um pouco mais interessante começará. Interface de classe. A interface de uma classe é, mais simplesmente, seus métodos públicos, o que ela destaca, o que podemos obter de um objeto dessa classe a partir de um objeto de fora. Esta classe implementa a interface getSnakeLength. Ele pode devolver o comprimento da cobra para nós. Observe que não há acesso externo a campos particulares. O acesso externo é apenas para o método público getSnakeLength.

E então uma coisa muito interessante. Discutimos por muito tempo como chamar isso, porque cunhei o termo "interface abstrata" quando criei essa palestra. E honestamente, nunca vi uma definição normal dessa abordagem e método. No entanto, muitas linguagens de programação permitem criar interfaces abstratas e chamá-las, assim que não abstraem classes, e interfaces abstratas também, apenas interfaces. Acontece um homônimo com a interface da classe. A idéia é que uma interface abstrata seja um conjunto de métodos que fazem alguma coisa. Quando criamos uma classe, passamos da pergunta "o que é isso?" Esta é uma cobra e ela sabe como fazer algo, ou não. Ela pode apenas dar seu comprimento.
E quando criamos a interface, partimos do que ele faz, do que ele deve ser capaz de fazer. E isso prova ser uma maneira muito poderosa de estender as classes. Podemos atribuir classes a algumas classes, expandindo-a com a ajuda de interfaces. Por exemplo, a estrutura do I-BEM pode fazer isso, uma história com interfaces abstratas é incorporada à estrutura. Infelizmente, muitas estruturas não sabem como e a coisa é poderosa.
Aqui, como exemplo, criamos a interface audiável, algo que pode soar. E sua definição é o método getNoise vazio abstrato. Expandimos nossa cobra com a classe audible, implementamos seu método getNoise e nossa cobra sibilou. A inspiração para esse conjunto de exemplos me foi dada pelo maravilhoso livro de Eric Freeman e Design Patterns.
Agora, tentaremos analisar esses exemplos um pouco mais especificamente.

Mas primeiro, vamos falar sobre por que esses exemplos foram necessários. E eles eram necessários aqui para este grande slide. O que está escrito aqui é tão importante que eu até o coloco no bloco de título amarelo. Pode-se dizer um mantra. Esse é um princípio muito importante que você precisa sempre pensar sobre isso ao projetar a arquitetura. Alta coesão, baixo acoplamento - adesão forte, conectividade fraca. Há um certo problema com o fato de que a palavra coesão e a palavra acoplamento são traduzidas para o russo e assim por diante, e assim por diante, “conexão” é traduzida, a palavra acoplamento foi especialmente inventada para esse princípio.
Essa é a ideia. Seus blocos devem ser muito compactos, muito acoplados. Eles devem implementar exatamente uma função. E entre si, eles devem ser conectados com muita facilidade, para que possam ser facilmente combinados, montados, como um designer. E então sua arquitetura será flexível o suficiente e confiável o suficiente. E também fácil de testar.
Vamos ver como podemos obter tração forte e acoplamento fraco nos pontos do que é chamado.

Especialização. Cada bloco resolve apenas um problema. Aqui temos uma boa ilustração - um designer infantil. Temos todos os blocos ou um conjunto de blocos. Eles são todos da sua forma, seu tamanho. E se precisarmos construir uma casa, tomaremos barras longas. Se precisarmos construir uma bola, pegaremos barras curtas. Cada barra tem sua própria função. E quem jogou construtores sabe: quanto mais simples o formato das peças, mais você pode construir a partir delas. Nada será construído a partir dessa zagogulina, ou apenas o que é descrito na instrução é construído. E quem precisa disso?
A mesma coisa, abstração. Trata-se da abstração da interface da implementação. A idéia é que a interface seja externa, como nossa classe é, nosso bloco se destaca, como ele interage com outros blocos não deve afetar sua implementação interna. Pelo contrário - isso acontece. A outra maneira - nunca. Em uma boa arquitetura. Aqui, como exemplo, a formação dessas espinhas não afeta a forma do próprio bloco. Selecionamos separadamente a forma do bloco e colamos colas nele.

Encapsulamento. Continuação do tópico anterior. Nos métodos privados, ou seja, de dentro de nossos blocos, percebemos o próprio significado de nosso bloco, implementação. E a interface, a maneira como eles estão conectados, é pública. Ou seja, neste caso, todos esses cruzamentos, hífens e o próprio formulário são implementados. E espinhas são a interface. E uma boa arquitetura parece um construtor.

Oh, que monstro assustador. Trata-se de reutilizar código. Inicialmente, esse monstro, na verdade, deveria mostrar um exemplo de arquitetura pobre, mas olhe para ele com cuidado. Ele é lindo Além disso, ele está claramente satisfeito com sua vida, corre com bastante vigor em suas estranhas pernas. Talvez ele até saiba voar, ou pelo menos tenha belas asas de borboleta.
Qual é a ideia? Se você tem uma implementação para um camelo e uma implementação para um crocodilo, e um gerente chega até você e diz que um camelo-crocodilo é urgentemente necessário. Você não escreve separadamente um crocodilo de camelo. Você pega o corpo de um camelo, separa-o de toda a realização do camelo. Pegue a cabeça do crocodilo, separe-a do crocodilo e reutilize os blocos. Por que isso é necessário?
Então, quando o gerente voltar correndo para você e disser que estamos nos expandindo com urgência para a América do Sul, e existem jacarés, precisamos manter um formato irregular da mandíbula ou que ali, o quarto dente do crocodilo não é assim, você não se atrapalhará com todo o projeto , onde você copiou as cabeças dos crocodilos. Porque você pode ter outro crocodilo-zebra-bisão por perto. Você apenas pega na sua classe a cabeça de um crocodilo, faz uma extensão da série da cabeça do jacaré, fornece os parâmetros, ele determina por si mesmo quais dentes desenhar para ele. E isso é tudo. Em um só lugar, e não em todos os lugares em que é usado.
Aqui, a confiabilidade aumenta às vezes, porque você tem a garantia de esquecer algumas cabeças copiadas em um projeto muito raro. Em geral, não há nada errado com esses cadáveres. Bom cadáver, útil.

- . , . TypeScript, . , . , , , TypeScript 2.7 , ( — . .).
, User. . . User , . User , , .
printLabel. User. , User User, . User User , , . - , .
, ? , . , . , − , UserWithSurname, , printLabel. ? , , , , . - ? , . , − , . . PrintLabel . ? ? , .
, . , . , , . , if, , . , , .

printLabel, , iPrintLabel , iPhone, . - getText. User, iPrintLabel. , , , - , getText iPrintLabel, , . UserWithSurname, User, Surname getText. printLabel . iPrintLabel getText.
, , , . . , , . , , , , , iPrintLabel, , , , − . printLabel . , .
. , , , front-end, , . , front-end , , .

-? . - back-end. - API, , REST API REST. — , − -. , , - PowerPoint, . .
front-end. Front-end - . - , . , - . . . , -, . , , . .
front-end, , , , , , , .
> - ( Client-server )
> ( Component-based )
> ( Event-driven )
> REST ( Representational state transfer )
> --*( MVC , MVP , MVVM )
> ( Flux )
Essas são as abordagens arquitetônicas. Alguns deles mencionamos hoje. Arquitetura do servidor cliente; arquitetura de componentes, uma de suas variações é familiar para você do React, espero familiar. Evento, que, curiosamente, também é familiar para todos, é baseado em quase todos os sistemas operacionais de computadores pessoais. REST, o que amamos no servidor, e os dois últimos, que conheceremos hoje em detalhes, são os mais front-end, com o qual trabalhamos é um modelo de apresentação * e fluxos de dados unidirecionais.
Vamos começar com o MV *. Por que um asterisco? A história, como se costuma dizer, cheia de dor e raiva. Era uma vez, nos anos 80, a maravilhosa abordagem arquitetônica do MVC foi inventada. Modelo M, Vista V, Controlador C. A abordagem foi muito conveniente. Inventou-o geralmente para aplicativos de console. Mas quando as tecnologias da web começaram a se desenvolver, quando todas começaram a usá-lo, às vezes era necessário, aqui o modelo de MV é bom, mas o Controller não é implementado da maneira correta. Como resultado, houve muitas variações diferentes da implementação do Model-View - algo que a princípio ficou confuso devido ao fato de ser chamada de MVC. Porque, se existe um modelo de MV, o terceiro é o Controller, não importa o que realmente colocamos lá.
Então, as pessoas ficam confusas e querem dizer coisas completamente diferentes pelo MVC. Por volta de agora, não mais de um ano atrás, eles começaram a compartilhar ativamente essa terminologia e a criar seus próprios nomes para cada implementação dessa abordagem. De um jeito ou de outro, esse MV * apareceu. Eu também vi o termo MVW na Internet, onde W é o que quer. Bem, estamos mudando, de fato, para as tecnologias MVC.

Como eles estão organizados? A idéia é que temos um modelo que armazena dados. Geralmente existem muitos deles. Existe algum tipo de exibição que mostra esses dados para o usuário. Eles, como regra, também são muitos. E um terceiro componente, que é um intermediário entre eles, conecta dados e exibição. Aqui, o usuário no canto superior direito trabalha com tudo isso.

MVC, tudo começou em 1980, Smalltalk. Mas é dessa forma que existe em algumas estruturas até agora. Não em alguns, em muitos. Qual é a ideia? O usuário trabalha diretamente com a visualização e o controlador. Ele insere dados em alguns campos da visualização, pressiona o botão enviar e os dados vão para o controlador. Este é um envio de formulário. Uma submissão de formulário tão honesta pelo botão enviar, familiar a todos por um longo tempo, espero.
Nós olhamos. A seta amarela do usuário para o controlador - este é o usuário transferiu os dados para o controlador usando o botão Enviar. Uma seta verde - o controle passou por lá. O controlador analisa esses dados. Talvez ele de alguma forma os processe, as sutilezas da implementação já estão aqui e as envie para o modelo desejado. O próprio controlador escolhe qual modelo enviar. Envia uma seta verde, envia dados com uma seta amarela.
O modelo também processa dados. Talvez ela os valide. Talvez ela os coloque na base. Em suma, o modelo sabe o que fazer com eles. Como regra, o resultado são novos dados. Por exemplo, podemos dizer ao usuário se ele efetuou login ou não, e o modelo verificou a senha com o login. Depois disso, o modelo transfere o controle para o controlador novamente, para que o controlador selecione qual visualização exibir. E os dados vão diretamente para o View. Como isso pode ser feito, em geral, como um modelo pode enviar dados para uma visualização?

Muito simples Se o controlador e o modelo estiverem no backend e a Visualização de modelo estiver do lado do servidor. É assim que as estruturas Ruby on Rails, ASP.NET e Django são organizadas, em geral, onde quer que você escreva modelos do lado do servidor, e o HTML coletado chega ao cliente, e os dados também retornam, com uma alta probabilidade, é essa abordagem. Quais são os problemas aqui? Em um aplicativo de página única, isso não pode ser construído. Temos constantemente dados no servidor, no servidor, a página é recarregada. Em segundo lugar, não está totalmente claro onde empurrar a validação do cliente e, em geral, o JavaScript do cliente, o AJAX e tudo isso aqui? Porque se queremos algo rápido, em lugar nenhum. Simplesmente não funciona nessa abordagem ou funciona para que não funcione melhor.
A última linha aqui, esta é uma história tão interessante, enraizada, ao que parece, em 2008. A questão era: onde armazenar a lógica de negócios - no modelo ou no controlador? Houve quem dissesse: "Armazenamos a lógica de negócios no controlador, porque é conveniente e dados limpos imediatamente são enviados ao modelo. O controlador se validará, verificará novamente, se houver, e enviará um erro ". Houve quem dissesse que "o resultado são controladores feios e estúpidos, controladores feios e grossos". Eles realmente ficaram enormes. E eles disseram que a lógica de negócios deve estar no modelo, e o controlador deve ser fino, leve, transferido os dados, o próprio modelo processado. E então, na primeira versão, o modelo, em geral, acaba sendo apenas uma API para o banco de dados.
Como, na minha opinião, realmente? De fato, você precisa observar as tarefas deles. Se você tem uma conexão entre uma visualização e um modelo que é sempre um para um, uma visualização é um modelo, é conveniente executar lógica de negócios em controladores e criar um modelo simples e limpo, que, de fato, será uma API para o banco de dados. Se suas visualizações e modelos puderem se sobrepor e uma visualização depender de muitos modelos, o modelo funcionará com muitas visualizações, é conveniente que você tenha muitos controladores finos e os multiplique em qualquer progressão, não se importa quantos existem, eles ainda são pequenos.
Devo dizer que o mundo parece ter conquistado o segundo ponto de vista, com a lógica de negócios nos modelos. Ou seja, esses controladores feios e estúpidos parecem não ser tão ativamente usados. Sinais, você pode assistir o que, na documentação do ASP.NET, a estrutura em 2013, propôs a lógica comercial nos controladores. E nas últimas versões em 2014 - nos modelos. Houve um momento muito interessante quando isso mudou.
O que o MVC tem problemas. Nós já falamos com eles, mas iremos. Testar como não está claro como implementar a validação do cliente é possível, mas difícil, o AJAX está parafusado na lateral, você precisa fazer alguma coisa. Eles vieram com uma solução. A solução foi chamada MVP e, sim, você pode conhecer o MVP na estrutura com o texto que eles são MVC. Por exemplo, estrutura do Backbone MVP. Sobre ele por um longo tempo na documentação no mesmo 2011-2012-2013, foi escrito que essa é uma estrutura MVC.

Model-View-Presenter. Seu esquema já é muito mais simples. Existem modelos. Eles interagem um com o outro. Eles fornecem dados ao Presenter, o Presenter os transfere para a visualização, os mostra ao usuário. E de volta. O usuário direciona algo para a visualização, clica no botão, o Presenter olha, o AJAX envia para o modelo ou coloca no modelo, e o modelo AJAX envia para o servidor. Ou seja, tudo já é muito mais simples e linear, mas sem a padronização do servidor já haverá dificuldades. Se você deseja um servidor, esse sistema será complicado.

Vamos comparar. Vejamos a primeira imagem, na qual tentaremos implementar uma coisa muito simples: enviar dados de entrada para o modelo. Nós inserimos algo, clicamos em um botão, ele deve aparecer no modelo, o modelo fará algo com isso e nos dirá que algo aconteceu. Entramos: “meu nome é Vasya”, clicamos em ok. Se queremos validação do lado do cliente, isso acontece aqui, quase por interceptação, em casos especialmente graves, interceptando um clique através de event.preventDefault (). E em algum lugar, um ponto zero na lateral aparafusava a validação do cliente.
Em seguida, enviamos honestamente os dados através do formulário de envio para o controlador. Os dados entram no modelo, o modelo os coloca em si, processa, parece. Nos diz que, bem, os dados são aceitos, você realmente é Vasya. A terceira seta - o controle vai para o controlador, o modelo informa ao controlador que, por favor, exiba o rótulo "Meu nome é Vasya". O controlador seleciona a visualização apropriada, exibe a etiqueta. E os dados "meu nome é Vasya", a quarta seta, amarela, o modelo coloca lá. A questão é como testar isso? Apenas um instantâneo. Não tem outro jeito. Não há nada para escrever testes funcionais.
A segunda opção, já com MVP. Dirigimos “meu nome é Vasya” e clicamos em ok. A seta sob o número um, verde, - gerenciamento foi para o Presenter. O apresentador disse: o botão está pressionado. Aparência do apresentador, seta número dois, azul, observe que esta é uma solicitação de dados. No MVP clássico, não enviando dados da exibição para o Presenter, mas uma solicitação do Presenter para dados. Isso é muito mais limpo, porque o Presenter já deve saber antecipadamente, por exemplo, que não precisa de dados, mesmo assim, tudo está ruim.
Em seguida, o terceiro parágrafo do Presenter é uma validação honesta do JS. Já podemos escrevê-lo com segurança, este é um lugar especial para ele. A quarta seta - os dados vão para o modelo, por exemplo, colocá-lo no banco de dados, disse: "Tudo está em ordem, eu coloco". A quinta seta, veja, está listrada, espero que fique claro que está verde-amarela listrada, e o gerenciamento e os dados voltaram ao Presenter. O modelo dizia “eu coloquei”, o Presenter percebeu que, como os dados foram colocados no banco de dados, significa que é necessário mostrar que tudo está em ordem, os dados são colocados. E a sexta flecha - eles a enviaram para a vista, talvez para outra, mas então eu não desenhei a segunda vista.
Qual é a vantagem aqui. A validação do JS caiu em seu devido lugar e tudo ficou bem com ele, o AJAX também se encaixou, pode ser a quarta seta, por exemplo, se o modelo estiver no servidor ou o próprio modelo AJAX for para o servidor. E, finalmente, podemos testar com segurança o Presenter, escrever testes funcionais nele.

Em segundo lugar, o que mais obtivemos no positivo, além dos testes simplificados? Temos uma separação entre a exibição visual e seu trabalho. Ou seja, ainda podemos gravar instantâneos no modo de exibição e escrever testes no Presenter separadamente. Podemos consertar o apresentador e não tocar na tela e vice-versa. Nossa especialização melhorou. É assim que estruturas como Angular1, Backbone, Ember, Knockout de versões anteriores são organizadas. Uma vez que havia muitos deles, apenas uma concorrência feroz.
Quais são os recursos. O Presenter já está colocado no cliente, o modelo pode estar lá e os aplicativos de página única são feitos silenciosamente. Acontece melhor, mas há muitos aplicativos de página única nessa história, ou pelo menos já foram feitos antes. A interação do servidor AJAX é boa. Validação do cliente em vigor. Parece que está tudo bem, por que pensar mais?
No entanto, pelo menos o MVVM foi inventado. Também é uma coisa interessante.

Em essência, esta é uma implementação do Presenter usando a estrutura. Geralmente, quando você escrevia o primeiro apresentador, o segundo apresentador e o quinto apresentador, eles eram todos iguais. E eles apenas criam uma vista e um modelo. Como você pode ver, ele é construído como o MVP.

E tantas estruturas acabaram de resolver essas tarefas vinculativas. Quais são as vantagens? Não precisamos escrever código extra. E realmente acelera a velocidade de desenvolvimento. Quais são as desvantagens. A conectividade entre Model e ViewModel foi aprimorada.
Ou seja, os problemas surgem lá precisamente por causa da forte conexão, então às vezes acontece que o MVVM não é usado. Por exemplo, eu estou pessoalmente familiarizado com o MVVM na estrutura do i-BEM, que algumas vezes usamos e outras não, porque é uma ligação inconveniente e muito rígida. No entanto, o Microsoft Silverlight é organizado por essa tecnologia e eles dizem: bom. Não sei, ainda não tentei.
Por que aconteceu que, além do MVP e MVVM, surgiu outra coisa, todos vocês familiarizados com a palavra redux, por que havia fluxos de dados unidirecionais.

Olhamos para a foto certa. Nós, com o MVP, regularmente temos esse problema. Suponha que tenhamos um sistema complexo, não um para um - muitas visões, muitos modelos. Eles estão todos interconectados. A vista de cima, amarela, mudou o modelo. O modelo mudou outro modelo. A vista inferior amarela mudou. A vista inferior também mudou o modelo. Todos eles mudaram a visão central vermelha, e algo incompreensível está acontecendo nela.
O Facebook enfrentou isso quando eles constantemente recebiam um bug devido a mensagens não lidas pop-up. Ou seja, o usuário vê "Você tem uma mensagem não lida", é aberto, mas não é. Porque as duas visões juntas corrigiram o estado desta ... Em geral, o estado da visão foi corrigido de duas fontes diferentes, e quem está certo não está claro. Eles governaram, um bug surgiu novamente, eles governaram novamente, um bug surgiu novamente. No final, eles estavam cansados e decidiram resolver o problema radicalmente, desculpe a tautologia e apenas tornar o estado da vista determinístico.
O problema do MVP está precisamente no não determinismo do estado do sistema. Nem sempre podemos prever em que condição ela está agora e quem veio primeiro, quem corrigiu o que. O fluxo resolveu esse problema, como se costuma dizer, geneticamente. Ele não pode ter isso. Eles me disseram aqui por um longo tempo que a ideia com um fluxo de dados unidirecional estava no ar, é verdade. E esse conceito foi inventado, é claro, muito antes do Facebook, muito antes de 2013, quando o publicaram. Mas eles, como dizem, patentearam, lançaram uma merda, que criamos exatamente isso, usamos.

Vejamos o Flux com mais detalhes. Aqui está a ideia. Temos uma loja, e esta loja é um data warehouse, essa é a única fonte de verdade para nossa aplicação. Tudo o resto é falso. Como ele trabalha? Inicialmente, se olharmos especificamente para o ciclo de trabalho, ele geralmente começa com o usuário fazendo algo, ou seja, a visualização está funcionando. View cria uma ação. Observe que a ação não é preenchida na imagem. Porque Porque é uma estrutura. Isso não é uma classe, não é um objeto, não é algo inteligente. Essa é a estrutura. Na web, em JavaScript, podemos escrever, é apenas esse objeto muito abstrato.
A visão cria uma estrutura, passa para o gerenciador de blocos. O gerenciador de blocos aciona um retorno de chamada. Ou seja, ele diz: “Chame a função que me disseram para chamar quando a Ação acontecer. Ele disse para ligar para a loja. " Ou seja, o método Store é chamado do despachante. O método é chamado. O método é chamado, é obtido na loja. A loja analisa o que aconteceu, de alguma forma muda a si mesma. Ele está mudando de condição. E ele é o único que pode mudar sua condição. Ninguém mais faz isso. Ou seja, ele é a única fonte de verdade. Depois disso, ele é transmitido a todas as visualizações vinculadas a ele, a todos os componentes vinculados a ele: "Eu mudei, vá buscar os dados".
As visualizações são para dados e, em seguida, um momento interessante começa. No Flux clássico, como no Facebook, a visualização é redesenhada completamente.

Aqui está o nosso formulário com um rótulo e um botão. Como ela trabalha? Nós olhamos para o ponto zero. O ponto zero também está aqui. Ele é a seta azul na parte inferior, registro de retorno de chamada. É o que acontece primeiro.
O gerente da loja liga: "Registre meu retorno de chamada, o que farei quando a Ação chegar até você". Isso aconteceu. Então podemos trabalhar com o aplicativo. Clicamos em um botão, criamos uma estrutura. Observe que, além dos dados inseridos pelo usuário, por exemplo, Vasya, Action também possui metadados, tipo. Um ponto muito importante é que a própria ação transmite que tipo de ação é, mas de qualquer maneira para o despachante. Ele joga toda a transmissão de ação. Primeira seta, o método é chamado.
O despachante chama o método, de fato, um gatilho de Ação e passa essa ação para lá. No gatilho Ação, um retorno de chamada é chamado, que registramos no ponto zero. Aqui está a seta vermelha: trata-se de uma chamada de retorno de chamada. A Store pega esses dados, parece que, huh, o tipo é change name, então eu mudo a mim mesmo no campo name para Vasya, e os envio para o back-end, e de alguma forma valida, provavelmente, em geral, a Store sabe o que fazer . Em seguida, a seta roxa apresenta o evento de alteração. Nós mudamos. Todo mundo sabe que mudamos a loja.
A seguir, um pequeno recurso do clássico Flux, que pode não ser familiar para quem trabalhou com o Redux, mais precisamente, mesmo com o React, e não com o Redux. As visualizações são para dados. Eles vão à loja e dizem: "Eu tenho este campo, este campo e este campo". Estamos acostumados ao fato de que, pelo contrário, tudo chega a pontos de vista se você trabalhou com React, Redux ou algo assim. E o sexto ponto, um redesenho completo.
Vamos olhar para este diagrama e encontrar um gargalo, por quê? Redesenhar. Um redesenho completo, motivo pelo qual o Flux começou a ser usado ativamente após 2013, quando surgiu o que? O que tornou isso possível? Casa virtual. Uma casa virtual que permite redesenhar apenas quando é realmente necessário.

Vamos nos afastar e falar sobre o React, que assim, combinado com muito sucesso ao Flux, criou o mundo que sabemos agora quando essa tecnologia é mais popular.
O mesmo 2013, o mesmo 2013, o mesmo Facebook. Inicialmente, o React foi inventado em geral, como um aviso de visualizações nas variações do MVC, MVP. E pode, de fato, ser usado lá. Qual é o seu poder. Primeiro, a casa virtual, como disseram corretamente, permite não redesenhar a casa real, porque é uma operação muito difícil, mas redesenhar a casa virtual. E somente se, de fato, houve uma mudança, redesenhamos o componente, como resultado do qual tudo funciona muito mais rápido do que poderia ser.
E - componentes imutáveis puros. Este é o mecanismo de propriedades. A implementação também é reativa, permitindo criar componentes que não possuem seu próprio estado. E se você escrever nessa arquitetura, é muito correto criar componentes limpos, sem estado, sem estado. Eles só têm dados que vieram da loja e ele os desenha. Eles são convenientes para testar, eles raramente quebram. O que é estático é muito difícil de quebrar e o teste é fácil.
Aplicativos combinados com a arquitetura Flux são poderosos. Provavelmente, muitas pessoas sabem que isso é realmente uma coisa poderosa. Qual é a importância que deve ser mencionada? Além do React Redux, existem muitos outros pacotes. E você provavelmente sabe que existe um segundo angular. É também uma combinação de estrutura reativa e arquitetura Flux. Vue, Flux Redux — Fluxxor, MobX . . React Redux. Vue, , , React Redux. .

? , React Redux . Vue, . — . — MVC-. . . - React Redux .
MVP/MVVM- . , — , , . single page application, multiple page application. - - . , -, - . , MVP, .
— single page application , , . . Flux React Redux, View, Angular, MobX, Fluxxor . .
. .
> MVC: Smalltalk-80 , General MVC , ASP.NET , MVC on Web
> MVP: MVP vs MVC , GUI Architecture , Backbone , Angular1
> MVVM: MS Silverlight , i-BEM
> Flux: Hexlet , Flux for stupid people , Flux official , ReactJS , VueJS
> : , «Javascript. » , ., « » , D.Garlain, M.Shaw, ”An introduction to Software Architecture” (1994), E.Dijkstra ”GOTO statement considered harmful” (1968)
MVC, MVP, MVVM . , . Flux . , , . , — . . JavaScript. . ES5, «JavaScript. » , ES6- — , , , .
, « ». . Java, . , , Flux, . MVP, — -. , . .
, , « ». , , , , , . «GOTO operator considered harmful». . , .
. . . , - , . , , Flux, , input Flux. — , , - . . , . ,
. Muito obrigado.