Arquitetura - Declarativa. Implementação - Imperativo. Tudo o mais é burocracia

O que é arquitetura? Como a arquitetura é diferente do design? Onde está a fronteira entre Arquitetura e Implementação? Você pode ver a arquitetura? A arquitetura pode ser testada? Qual é a diferença entre as abordagens de Engenharia e Evolucionária para Arquitetura? O que é uma boa arquitetura? Qual é o trabalho de um arquiteto? Como isso difere do trabalho do Desenvolvedor? Quais ferramentas estão disponíveis para o arquiteto? É possível alterar a Arquitetura separadamente da Implementação? A arquitetura tem DNA?







Imagem do blog tomaszjaniak



Mostre-nos sua arquitetura



Acontece que você está trabalhando em um projeto há alguns anos e agora está sentado até os cotovelos no código, os testes estão queimando, o cooler do laptop está fazendo barulho, tentando esfriar o calor do processador superaquecido pelo compilador, apenas mais algumas horas - e a refatoração estará concluída. E então precisamos largar tudo com urgência e desenhar a Arquitetura do projeto. Um grande cliente é planejado e, para fechar o negócio, é necessário passar por uma auditoria. E, neste caso, não há nenhum lugar sem diagramas arquitetônicos. E daí se o projeto ainda é pequeno e uma dúzia de seus desenvolvedores em trabalho real não precisa de nenhuma arquitetura lá. Aqui está o código - tudo está claro. Mas não há saída. É necessário - então é necessário.



Se você sabe como tudo funciona, a arquitetura de qualquer produto pode ser desenhada em uma hora. E isso geralmente é o suficiente para uma auditoria. Afinal, o objetivo da auditoria não é que estranhos realmente entendam a arquitetura do seu produto. O ponto principal da questão é determinar se os próprios desenvolvedores de produto têm uma compreensão do que estão fazendo. E se você falar com confiança suficiente e responder às perguntas sem hesitação, tudo correrá bem. Mesmo assim, quando esta história terminar, em algum lugar nas profundezas um verme se estabelecerá, o que tornará a questão mais aguda: mas ainda assim, que tipo de Arquitetura o produto realmente tem? Afinal, se perguntarem, provavelmente outros têm Arquitetura. E se não tivermos, isso é claramente uma bagunça. Há uma grande vontade de fazer tudo bem para ser responsável pela Arquitetura da próxima vez como deve ser.



Como você faz isso certo? Você precisa desenhar diagramas, descrever os recursos nos documentos e, em seguida, manter tudo atualizado. Então será Arquitetura. Mas, tendo apresentado o escopo do trabalho, rapidamente percebe-se que tudo isso não vale o tempo despendido. Aqui está o código - tudo está claro. E se vier outro cliente, daqui a uma hora será possível desenhar um novo diagrama.



E depois de alguns anos, você pode se encontrar na situação oposta, e os documentos que irão descrever a arquitetura de outro produto não serão melhores. Claro, é útil saber que outras pessoas também têm uma arquitetura muito ruim. Mas quando o tamanho de um projeto começa a medir em milhões de linhas de código, e o número de desenvolvedores em centenas, a questão da necessidade de uma Arquitetura ainda se torna significativa.



Aqui, como parte do fluxo de trabalho, vários diagramas de arquitetura começam a aparecer, as propostas de arquitetura começam a escrever sobre os recursos, tudo isso é discutido, revisado, validado, aprovado e, é claro, fica desatualizado antes mesmo que esses processos terminem. Não há necessidade de dizer que tais documentos refletem a estrutura real do código do aplicativo. E quando se trata de implementação, acontece que os desenvolvedores não leem esses documentos. Ou algo completamente diferente do que foi escrito está sendo implementado. Alguém entendeu mal alguém, ou era urgente fazê-lo e não havia tempo para discutir.



Talvez seja assim que deva ser. Talvez Arquitetura seja a Burocracia em torno de documentos especulativos, divorciados da realidade? Mas a intuição nos diz que, afinal, não. Então, o que é "Arquitetura"?



Arquitetura é ...



O que acontece se você fizer a pergunta "O que é arquitetura?" dez desenvolvedores profissionais? Se você não vasculhar a Wikipedia, eles darão a mesma resposta?



Arquitetura é um conjunto de decisões importantes e a estrutura de elementos e suas interfaces e um sistema de disposições, regras e acordos e abordagens formadas que mantêm a ordem e soluções para problemas globais e decomposição com interação e uma descrição de alto nível do sistema e seu ciclo de vida. partes e padrões de estrutura e comportamento, e o que é difícil ou caro de mudar ou remover, e decisões e trade-offs fundamentais e muito mais.



Arquitetura também é como um aplicativo cumpre seu propósito pretendido.



API é uma Arquitetura, um esquema de dados também é uma Arquitetura e uma estrutura de módulos e serviços. Há uma arquitetura de escalonamento de aplicativo, uma arquitetura de confiabilidade de aplicativo, uma arquitetura de interação de componentes e uma arquitetura de segurança. E, claro, cada recurso tem sua própria arquitetura. E tudo isso junto também é Arquitetura.



Tudo isso pode ser considerado uma resposta à pergunta "O que é arquitetura?" - talvez sim. Tudo parece estar correto, tudo parece claro. Mas essa resposta é praticamente útil, algo que pode ser usado em um fluxo de trabalho real? Na verdade não.



Como você sabe se uma decisão é importante ou fundamental? Quais são os desafios globais? O que significa caro ou barato? Como avaliar a complexidade? Onde fica a fronteira entre alto e baixo nível? O que é ordem? Qual é o propósito do sistema?



Todas essas são perguntas que você também pode tentar responder. Formule definições, explique com exemplos; na pior das hipóteses, organize o processo de tomada de decisão. Mas continuará sendo algo polêmico, algo intuitivo, dependendo da percepção pessoal e entendido por cada um um pouco à sua maneira. Isso significa que sempre haverá conflitos baseados no fato de que diferentes pessoas interpretam a mesma situação de maneiras radicalmente diferentes. Os desenvolvedores reclamarão que os arquitetos estão adulterando os detalhes da implementação, que os desenvolvedores estão violando a Arquitetura. Se não houver um limite claro, os conflitos são inevitáveis.



Todos provavelmente têm algum conhecimento geral do que é Arquitetura. Mas é difícil nomear uma definição única, formalmente verificada e matematicamente precisa.



Por outro lado, se você perguntar "O que é realização?" - a resposta provavelmente não será ambígua: "Aqui está um link para o repositório de código!" E você não pode argumentar contra isso. E não há dúvidas ou ambigüidades na interpretação dessa resposta. 1 + 1 = 2, Implementação é código.



E é muito fácil trabalhar com o código. Se você quiser entender a implementação, pode abrir o projeto no ambiente de desenvolvimento. Se as mudanças no código precisam ser revisadas, então existem ramificações no repositório. Se for hora de lançar uma nova versão do aplicativo, os testes são iniciados.



Obviamente, a estrutura do projeto pode ser confusa, as revisões são de baixa qualidade e a cobertura do teste é incompleta. Mas, pelo menos ao trabalhar com código, é sempre claro o que e quando fazer.



Mas e se a Arquitetura fosse expressa em código, assim como a Implementação?





Muitas linguagens de programação convencionais são usadas no desenvolvimento moderno. A maioria deles apareceu há muito ou muito tempo. E enquanto eles ainda estão bons, eles estão ficando um pouco desatualizados. Estas são linguagens de tipagem fraca: JavaScript, Python, PHP, Ruby e linguagens de tipagem forte: Java, C / Objective-C / C ++, C #. Eles estão sendo substituídos por novas linguagens que, dentro da estrutura da mesma plataforma, tentam resolver problemas antigos, borrifando-os com açúcar sintático, mas sem introduzir conceitos fundamentalmente novos se você olhar globalmente: Swift, Kotlin, TypeScript, Go. Todas essas são linguagens construídas no paradigma Orientado a Objetos. Além disso, a abordagem funcional para programação ganhou popularidade madura, que é implementada nas linguagens listadas e apresentada em linguagens especializadas, mas menos populares: Erlang, F #.Linguagens que implementam conceitos substancialmente novos também estão começando a ganhar popularidade: Rust, Haskell.



Toda essa diversidade tem uma coisa em comum: são todas linguagens de implementação. Nenhuma dessas linguagens de programação são expressões da Arquitetura. Mas há uma exceção - SQL.



SQL é a única linguagem de programação predominante que é declarativa. É construído em um modelo de álgebra relacional e tem uma especialização estreita - trabalhar com dados armazenados. Mesmo assim, por que o SQL pode ser considerado a linguagem da Arquitetura?



Em primeiro lugar, o SQL dá acesso a metainformações sobre o esquema de dados. Você pode obter facilmente uma lista de tabelas, colunas, relacionamentos, índices, visualizações, funções e muito mais do banco de dados. A documentação do esquema de armazenamento e a capacidade de visualizá-lo é uma grande ajuda para entender a estrutura de um aplicativo. Uma descrição de esquema de dados é um tipo de descrição de arquitetura de alto nível.



Em segundo lugar, o SQL fornece uma linguagem de consulta de dados que permite ao cliente consultar qualquer combinação de dados descrita no esquema. Se não houvesse linguagem de consulta, para cada modelo de dados exigido pelo cliente, um método de API separado teria que ser implementado ou o cliente teria que fazer várias chamadas de API para diferentes partes do esquema de dados e combinar o modelo necessário em seu lado. A presença da linguagem de consulta permite excluir da descrição da Arquitetura detalhes de implementação associados à enumeração de métodos API para obtenção de modelos de dados específicos de acordo com o esquema geral. A linguagem de consulta exclui detalhes de implementação da descrição da Arquitetura.



O SQL fornece três propriedades principais que são importantes para descrever a arquitetura:



  1. Declaratividade - SQL permite separar a descrição da Arquitetura de sua Implementação.
  2. Analisabilidade - o SQL fornece acesso a meta-informações de um esquema de dados, permitindo que você visualize, documente e analise suas representações.
  3. Correção - o SQL permite definir as restrições do modelo de dados, o que torna possível prevenir uma variedade de violações de integridade de dados pela Implementação.


Talvez o SQL possa ser chamado de ferramenta para descrever a Arquitetura em termos de armazenamento de dados, mas claramente não é o suficiente para descrever a Arquitetura completa de um produto.



Outros meios de descrever a Arquitetura



O análogo direto do SQL é o GraphQL, que também permite definir o esquema de dados e fornece acesso a ele por meio da linguagem de consulta. Ao mesmo tempo, GraphQL é baseado na teoria dos grafos, não em um modelo de álgebra relacional. Isso torna possível trabalhar com modelos de dados hierárquicos de uma forma mais natural, ao contrário do SQL, onde trabalhar com hierarquias pode ser difícil.



O GraphQL é frequentemente promovido como uma solução de comunicação cliente-servidor, mas esta não é a única área de sua aplicação. Da mesma forma, por meio do GraphQL, você pode fornecer comunicação servidor a servidor e até mesmo servidor a base. O fato de bancos de dados modernos fornecerem apenas uma interface SQL, mas não fornecerem uma API conveniente para trabalhar com consultas hierárquicas, é uma omissão ofensiva.



Se SQL é um meio de descrever a Arquitetura do esquema de armazenamento de dados, então GraphQL permite que você descreva a Arquitetura do esquema de dados já no nível de negócios, em termos de uma área de aplicação específica. Nesse sentido, GraphQL permite definir a Arquitetura em um nível superior, mais próximo da área real de aplicação do produto.



Módulos de código e microsserviços, junto com suas APIs e dependências, também são veículos para expressar a Arquitetura em termos de estrutura e relacionamentos.



Arquitetura e Implementação



Para um pequeno projeto com uma dúzia de desenvolvedores trabalhando, uma descrição separada da Arquitetura geralmente não é necessária. Se o código do projeto for escrito ordenadamente e bem estruturado, isso pode ser o suficiente para entender o quadro geral e as direções de desenvolvimento.



Conforme o projeto cresce, vários documentos aparecem, descrevendo sua arquitetura geral e detalhes de novas peças e melhorias principais. Esta é uma abordagem bastante funcional quando várias dezenas de pessoas estão trabalhando em um projeto.



Mas para um projeto bastante grande, quando há centenas de desenvolvedores, essa abordagem começa a falhar. Existem muitos documentos e seu conteúdo começa a divergir cada vez mais da implementação. Torna-se cada vez mais difícil expressar pensamentos da mesma maneira para todos. Comícios para dezenas de pessoas são organizados para discutir uma variedade de tópicos privados, enquanto mudanças realmente importantes podem ser implementadas sem qualquer discussão. Tudo isso leva à necessidade de organizar cada vez mais processos, quando uns têm que oferecer, outros seguem, outros revisam e outros ainda fazem. Burocracia. Como resultado, os desenvolvedores começam a escrever mais documentos e menos código, e este não é o problema mais significativo.



Claro, não há nada de errado com a burocracia como tal. Em qualquer trabalho, sua organização é importante. O problema é a quantidade de burocracia por unidade de trabalho útil. Se, para fazer um, você precisa realizar mais dois, três, quatro, cinco comícios, isso não é mais bom em qualquer lugar.



Até a simples questão de que mudança o próprio desenvolvedor pode fazer, por se tratar de uma Implementação, e sobre o que precisa fazer um pedido de revisão, por se tratar de uma Arquitetura, começa a causar dificuldades. Você tem que criar uma variedade de gatilhos arquitetônicos, que se você alterar o esquema de dados ou tocar em criptografia e questões de segurança, isso precisa ser revisado Arquiteturalmente, e outros tópicos parecem não ser, mas isso não é certo. Tudo isso precisa não apenas ser formulado e explicado a centenas de desenvolvedores, mas também garantir que as regras descritas sejam seguidas. Esse processo falhará constantemente.



Todos esses problemas estão relacionados à falta de uma definição clara da Arquitetura.



Assim como alterar um arquivo ".java" em um repositório indica sem ambigüidade uma mudança na implementação, alterar um arquivo ".architecture" pode indicar uma mudança na arquitetura. É claro que os arquivos ".architecture" não existem na natureza. Mas, para cada projeto, você pode definir quais aspectos específicos dele se relacionam com sua arquitetura e torná-lo explícito.



Se uma mudança no esquema de dados for considerada uma mudança na Arquitetura, então os arquivos contendo as migrações SQL devem pertencer à Arquitetura. Se a API também faz parte da Arquitetura, você pode definir a API na forma dos mesmos arquivos swagger e confiar neles. Se a estrutura dos módulos for Arquitetura, a mudança na descrição dos módulos é uma mudança na Arquitetura. Etc.



Nem todos os aspectos da Arquitetura podem ser expressos por meios padrão. Cada projeto tem suas especificidades. Por exemplo, se o produto usa um modelo específico de direitos, funções, tipos de assinaturas, complementos e assim por diante, você deve pensar em definir a Arquitetura desse aspecto do produto em alguma forma Declarativa adequada, destacando assim a essência da Arquitetura a partir dos detalhes de implementação. Claro, essas mudanças podem exigir retrabalho significativo do código. Mas este é um investimento substancialmente melhor na definição de uma Arquitetura de Produto do que tentar descrever seu modelo de direitos em um documento.



A representação formal da Arquitetura em código é possível, e somente isso dá uma definição clara do que é uma Arquitetura. Esta visualização permite analisar a Arquitetura e gerar automaticamente a documentação sobre ela, que estará sempre atualizada. Todo o resto: documentos, diagramas e diagramas feitos à mão - Burocracia.



Uma Arquitetura pode ter uma expressão formal no código, e somente isso define um limite claro entre Arquitetura e Implementação. E essa fronteira é necessária.



Engenharia e abordagens evolucionárias em arquitetura



Ao longo do último meio século, a indústria de desenvolvimento percorreu um longo caminho desde os modelos em cascata até o desenvolvimento iterativo. E agora parece que a indústria foi longe demais nesse assunto. Em alguns lugares, o trabalho de um arquiteto não se parece mais com o trabalho de um engenheiro ou mesmo de um jardineiro, e cada vez mais começa a se parecer com o trabalho de um trabalhador sazonal contratado com o único propósito de arrancar canteiros de ervas daninhas.



O que distingue a engenharia do artesanato é a compreensão das leis da natureza, das regularidades, com base nas quais se pode fazer cálculos e conclusões, projetar soluções, e não experimentar. Qualquer carpinteiro pode fazer um banquinho perfeitamente aceitável, mas é necessário conhecimento de engenharia para torná-lo ideal: leve, confiável, estável, simples e barato de fabricar. Uma abordagem de engenharia permite que você obtenha o resultado ideal rapidamente e com o mínimo esforço. Infelizmente, no desenvolvimento de software, uma abordagem de engenharia nem sempre é possível.



Freqüentemente, o resultado que se deseja alcançar é definido de forma muito vaga, muitos fatores que afetam significativamente a arquitetura da solução são obscuros ou desconhecidos de todo e o trabalho na implementação da própria solução pode ser mais rápido e barato do que a elaboração detalhada de sua Arquitetura. Essa é uma das razões pelas quais a abordagem iterativa do desenvolvimento ganhou tanta popularidade. Às vezes, até além da medida.



No pior caso, o desenvolvimento da Arquitetura pode resumir-se ao fato de que cada equipe de desenvolvimento simplesmente fornece ao arquiteto uma revisão de uma descrição do que eles irão implementar. Em tal situação, o trabalho de um arquiteto é reduzido à extinção. E aqui você não se esqueceu? Você levou isso em consideração? E aqui está errado. Você quer adicionar um índice aqui? E assim, iteração após iteração.



É necessário remover ervas daninhas. Mas como será um jardim se você apenas fizer isso? Canteiros de flores murcharão à sombra de árvores frutíferas, morangos e cenouras se alternarão, e tudo isso será percorrido por inúmeros caminhos que desperdiçam o espaço disponível. É difícil falar sobre qualquer Arquitetura aqui.



Para que a Arquitetura apareça, um arquiteto deve fazer pelo menos o trabalho de um jardineiro. Frutas e vegetais devem ser cultivados separadamente - a estrutura, e onde as pessoas vão com mais freqüência, você precisa estabelecer caminhos - conexões. Observando as particularidades, o arquiteto pode atuar de forma proativa, organizando e sistematizando em uma única estrutura as particularidades que surgem no processo de Realização. Assim como o paisagismo, um arquiteto pode moldar o curso natural dos eventos, reforçando tendências positivas e prevenindo tendências negativas.



E aqui precisamos de uma definição clara da Arquitetura no código. Esquemas de dados, estruturas de módulos e serviços, sua API e regras de interação. Sem definir essas ferramentas, o arquiteto ficará atolado em uma revisão da implementação ou ingenuamente terá a esperança de que os desenvolvedores realmente sigam as regras descritas em alguns documentos lá, o que, é claro, não acontecerá.



Se houver uma apresentação formal da Arquitetura e as regras para suas mudanças, isso já pode ser chamado de uma abordagem Evolucionária para o desenvolvimento da Arquitetura. E isso não é ruim. Mas devemos nos limitar a isso?



Sim, inicialmente os requisitos podem parecer vagos, os fatores podem parecer vagos e o próprio sistema é tão complexo que é mais fácil fazer do que projetar. Mas com o tempo, essas coisas começam a ficar claras. Com a experiência prática no desenvolvimento de Arquitetura, os detalhes da organização de sua área de aplicação aparecem cada vez mais claros. Torna-se claro que esta solução geral é implementada de cinco maneiras diferentes e que os usuários sofrem com essa diversidade. Que algumas coisas estão fora do lugar e precisam ser movidas, enquanto outras já estão desatualizadas e substituídas por novas soluções, por isso precisam ser removidas. E novos desenvolvimentos param de parecer tão novos - e já implementamos isso e aquilo. Você se lembra a que tudo isso levou? Vamos fazer isso imediatamente para não termos que refazer mais tarde. Afinal, fazer certo de uma vez geralmente é mais rápido do que o necessário.Mas isso só acontece se você realmente souber fazer isso direito. E com a experiência, esse tipo de compreensão costuma surgir.



A Boa Arquitetura não é algo que cresceu por si só e depois se organizou um pouco, mas algo holístico, simétrico e orgânico. Uma abordagem de engenharia para o desenvolvimento da Arquitetura é possível, apenas entender as regras e padrões pode levar algum tempo.



A definição formal da Arquitetura de um determinado projeto não precisa ser estática. Os métodos de API obsoletos podem ser declarados como obsoletos e os ausentes podem ser declarados como não implementados. As partes significativas do código podem ser marcadas para colocação em módulos separados. Você pode planejar dividir a tabela em duas ou movê-las para outro banco de dados. Etc. A arquitetura pode ser alterada sem alterar a implementação. A implementação o alcançará. E para acompanhar mais rápido, o processo pode ser ligeiramente automatizado criando lembretes automáticos em bate-papos de equipe. Da mesma forma, as alterações feitas por desenvolvedores nos arquivos de arquitetura podem ir automaticamente para o bate-papo da equipe de arquitetura.



Uma abordagem de engenharia para o desenvolvimento da Arquitetura é possível.



Ao mesmo tempo, não se deve presumir que o trabalho do arquiteto seja algo fundamentalmente melhor ou pior do que o trabalho do desenvolvedor. Ela é diferente. O desenvolvedor, em primeiro lugar, trabalha no estilo Imperativo, enquanto o trabalho do arquiteto é mais Declarativo. Acontece que é difícil trabalhar a Arquitetura, mas a Implementação é uma rotina. Também acontece vice-versa.



Arquitetura e design



Os termos Arquitetura e Design são freqüentemente usados ​​de forma intercambiável. Você pode dizer: Arquitetura do Sistema ou Projeto do Sistema. Em geral, está claro do que se trata. No entanto, existem diferenças significativas nesses termos.



Design, antes de tudo, significa algo visual, algo que pode ser imaginado ou visto. Esquemas, diagramas, modelos. O design permite que você mostre visualmente a relação entre entidades, trace cadeias de interação, veja diferenças estruturais e analogias.



Mas a arquitetura não é apenas visual, ela pode incluir regras e restrições, inferências e cálculos matemáticos. Conceitos mal visualizados.



Claro, ambos são importantes.



É bom que aspectos importantes da arquitetura sejam explicitamente definidos no código. Mas isto não é o suficiente. É importante tornar a Arquitetura visual e os princípios inerentes a ela automáticos.



Se a arquitetura inclui um esquema de dados, deve haver uma representação visual dele. Módulos têm dependências - eles também precisam ser renderizados. Se houver uma API, deve haver documentação sobre ela que esteja diretamente relacionada à estrutura dos serviços. Etc. Design é uma representação visual da Arquitetura.



Se a Arquitetura tem certos princípios, por exemplo, "as aplicações cliente só podem acessar certos tipos de microsserviços, mas não todos", então se houver um modelo de comunicação, eles podem ser verificados automaticamente. Da mesma forma, você pode controlar os links entre microsserviços e bancos de dados. Se houver certas regras para o projeto de modelos de dados, as mesmas regras para tabelas de nomes, elas também podem ser verificadas automaticamente. No desenvolvimento, são utilizadas verificações automáticas de código, o mesmo pode ser feito para a Arquitetura. Você pode escrever autotestes sobre Arquitetura.



Conclusão



O desenvolvedor moderno possui uma grande variedade de ferramentas incríveis disponíveis para tornar seu trabalho mais fácil. Ambientes de desenvolvimento, sistemas de construção, várias bibliotecas e frameworks, serviços de infraestrutura e containers. Os desenvolvedores não escrevem código no bloco de notas.



A Arquitetura também é código e, para trabalhar com a Arquitetura, existe um kit de ferramentas que é tão poderoso e rico quanto para trabalhar com a Implementação. O Google Docs não é a única ferramenta de arquitetura que você pode usar e está longe de ser a melhor. É claro que a gama de ferramentas prontas disponíveis para um arquiteto agora não é tão ampla quanto a gama de ferramentas de desenvolvedor. E nem tudo que um arquiteto pode usar funciona fora da caixa. Mesmo assim, as coisas não estão tão ruins.



Muitas ferramentas existem há décadas, como o SQL, você só precisa aprender a usá-las corretamente. Novas tecnologias, como GraphQL, estão começando a ganhar popularidade e oferecem esperança de que a tarefa de descrever um domínio de negócios se tornará tão rotineira com o tempo quanto descrever um domínio de armazenamento. Ferramentas para documentação e visualização da estrutura do aplicativo e API estão disponíveis, incluindo Swagger. Você pode usar as mesmas estruturas e ferramentas de integração para testar a Arquitetura que usaria para testar a Implementação.



Arquitetura - Declarativa. Provavelmente, a burocracia do trabalho com documentos nunca irá desaparecer completamente do trabalho de um arquiteto, mas já agora seu volume pode ser reduzido significativamente. Arquitetura também é código e, com o tempo, as ferramentas disponíveis para trabalhar na Arquitetura podem se tornar tão avançadas quanto as ferramentas para trabalhar na Implementação. Vamos ver.



-

Dmitry Mamonov,

Wrike




PS Comecei o artigo com uma lista de questões filosóficas às quais, espero, consegui dar respostas bastante específicas. Pelo menos esse é o meu ponto de vista. Você encontrou algo útil ou novo no artigo? Como você mesmo responde a essas perguntas? Escreva nos comentários.



All Articles