Prático Rx Training London 6-7 de outubro de 2015 Apresentado pelo autor da IntroToRx PARTE 1 - Começando Usuários esperam dados em tempo real. Eles querem seus tweets agora. O seu pedido confirmou agora. Eles precisam de preços precisos a partir de agora. Seus jogos online precisam ser receptivos. Como desenvolvedor, você exige mensagens de fire-and-forget. Você não quer ser bloqueado esperando por um resultado. Você quer que o resultado seja pressionado quando estiver pronto. Ainda melhor, ao trabalhar com conjuntos de resultados, você deseja receber resultados individuais, pois estão prontos. Você não quer esperar que o conjunto inteiro seja processado antes de ver a primeira linha. O mundo se moveu para empurrar os usuários estão esperando por nós para recuperar o atraso. Os desenvolvedores possuem ferramentas para empurrar dados, isso é fácil. Os desenvolvedores precisam de ferramentas para reagir ao envio de dados. Bem-vindo ao Reactive Extensions for. NET (Rx). Este livro destina-se a qualquer desenvolvedor. NET curioso sobre as interfaces IObservableltTgt e IObserverltTgt que surgiram no. NET 4. As bibliotecas das Extensões Reativas da Microsoft são as implementações dessas interfaces que estão rapidamente selecionando a tração com os desenvolvedores Servidor, Cliente e Web muito parecido. Rx é uma ferramenta de desenvolvimento poderosamente produtiva. O Rx permite aos desenvolvedores resolver problemas em um estilo elegante, familiar e declarativo, muitas vezes crucialmente com menos código do que era possível sem o Rx. Ao alavancar o LINQ, a Rx possui os benefícios padrão de uma implementação do LINQ 1. O LINQ integrado está integrado na linguagem C. Unitive O uso do LINQ permite que você aproveite suas habilidades existentes para consultar dados em repouso (LINQ to SQL, LINQ to XML ou LINQ para objetos) para consultar dados em movimento. Você poderia pensar em Rx como LINQ para eventos. O LINQ permite que você transite de outros paradigmas para um paradigma comum. Por exemplo, você pode transitar um evento. NET padrão, uma chamada de método assíncrono, uma Tarefa ou talvez uma API de middleware de terceiros em um único paradigma Rx comum. Alavancando o nosso idioma de escolha e usando operadores familiares, como Selecionar. Onde . GroupBy etc, os desenvolvedores podem racionalizar e comunicar desenhos ou códigos em uma forma comum. Extensível Você pode estender Rx com seus próprios operadores de consulta personalizados (métodos de extensão). O LINQ declarativo permite que o seu código seja lido como uma declaração do que o seu código e deixa o modo de implementação dos operadores. Os recursos LINQ compostos, como métodos de extensão, sintaxe lambda e sintaxe de compreensão de consultas, fornecem uma API fluente para os desenvolvedores consumirem. As consultas podem ser construídas com inúmeros operadores. As consultas podem então ser compostas para produzir ainda mais consultas compostas. As consultas transformativas podem transformar seus dados de um tipo para outro. Uma consulta pode traduzir um único valor para outro valor, agregado de uma seqüência de valores para um único valor médio ou expandir um único valor de dados em uma seqüência de valores. Quando Rx é apropriado, Rx oferece um paradigma natural para lidar com sequências de eventos. Uma sequência pode conter zero ou mais eventos. Rx prova ser mais valioso ao compor sequências de eventos. Deveria usar o Rx. Gerenciar eventos como este é o que o Rx foi criado para: eventos de interface do usuário como movimentação do mouse, clique no botão Eventos de domínio como propriedade alterada, coleção atualizada, Pedido preenchido, Registro aceito etc. Eventos de infra-estrutura como o monitor de arquivos, o sistema e a integração de eventos WMI Eventos como uma transmissão de um barramento de mensagens ou um evento push da API WebSockets ou outro middleware de baixa latência, como o Nirvana Integration com um mecanismo CEP como StreamInsight ou StreamBase. Curiosamente Microsofts CEP produto StreamInsight. Que faz parte da família SQL Server, também usa o LINQ para criar consultas sobre transmissão de eventos de dados. Rx também é muito adequado para a introdução e gerenciamento de concorrência para fins de descarregamento. Ou seja, executando um determinado conjunto de trabalhos simultaneamente para liberar o tópico atual. Um uso muito popular disso é manter uma UI responsiva. Você deve considerar usar o Rx se você tiver um IEnumerableltTgt existente que esteja tentando modelar os dados em movimento. Enquanto o IEnumerableltTgt pode modelar os dados em movimento (usando a avaliação preguiçosa como o retorno do rendimento), provavelmente não vai escalar. Iterating sobre um IEnumerableltTgt consumirá o bloqueio de um segmento. Você deve favorecer a natureza não bloqueadora do Rx via IObservableltTgt ou considerar os recursos assíncronos no. NET 4.5. Poderia usar Rx Rx também pode ser usado para chamadas assíncronas. Estas são efetivamente sequências de um evento. Resultado de uma tarefa ou TaskltTgt Resultado de um método de APM chamada como FileStream BeginReadEndRead Você pode achar que o uso de TPL, Dataflow ou async keyword (.NET 4.5) prova ser uma forma mais natural de compor métodos assíncronos. Embora a Rx possa definitivamente ajudar com esses cenários, se houver outros frameworks mais adequados à sua disposição, você deve considerá-los primeiro. Rx pode ser usado, mas é menos adequado para, introduzindo e gerenciando simultaneidade para fins de escala ou execução de cálculos paralelos. Outros frameworks dedicados como TPL (Task Parallel Library) ou C AMP são mais apropriados para realizar trabalhos intensivos em computação paralela. Não usar Rx Rx e especificamente IObservableltTgt não é uma substituição para IEnumerableltTgt. Eu não recomendaria tentar tomar algo que seja naturalmente baseado em atração e forçá-lo a ser baseado em push. Traduzindo valores IEnumerableltTgt existentes para IObservableltTgt apenas para que a base de código possa ser mais filas de Rx Message. As filas como no MSMQ ou uma implementação JMS geralmente têm transação e são, por definição, seqüenciais. Eu sinto que IEnumerableltTgt é um ajuste natural para aqui. Ao escolher a melhor ferramenta para o trabalho, seu código deve ser mais fácil de manter, oferecer melhor desempenho e provavelmente você terá melhor suporte. Rx em ação Adotando e aprendendo Rx pode ser uma abordagem iterativa onde você pode aplicá-lo lentamente em sua infraestrutura e domínio. Em pouco tempo você deve ter as habilidades para produzir código, ou reduzir o código existente, para consultas compostas por operadores simples. Por exemplo, este ViewModel simples é tudo que eu preciso para codificar para integrar uma pesquisa que deve ser executada como um usuário digitar. Classe pública MemberSearchViewModel. INotifyPropertyChanged Embora este fragmento de código seja bastante pequeno, ele suporta os seguintes requisitos: Mantém uma UI responsiva Suporta tempo limite Sabe quando a pesquisa está completa Permite que os resultados voltem um a cada vez Manipula erros A unidade é testável, mesmo com as preocupações de concorrência Se um usuário mudar A pesquisa, cancelar pesquisa atual e executar nova pesquisa com novo texto. Para produzir essa amostra, é quase uma questão de compor os operadores que combinam os requisitos em uma única consulta. A consulta é pequena, sustentável, declarativa e muito menos código do que ropor a sua. Existe o benefício adicional de reutilizar uma API bem testada. Quanto menos código você tiver que escrever, menor será o código que você deve testar, depurar e manter. Criar outras consultas como a seguinte é simples: calcular uma média móvel de uma série de valores, e. Acordos de nível de serviço para latências médias ou tempo de inatividade combinando dados de eventos de múltiplas fontes, e. Resultados de pesquisa de Bing, Google e Yahoo, ou dados de sensores de acelerador, giroscópio, magnetômetro ou temperatura agrupando dados, e. Tweets por tópico ou usuário, ou preços de ações por delta ou dados de filtragem de liquidez, e. Servidores de jogos online dentro de uma região, para um jogo específico ou com um número mínimo de participantes. O impulso está aqui. Armando-se com Rx é uma maneira poderosa de atender as expectativas dos usuários de um mundo push. Ao entender e compor as partes constituintes da Rx, você poderá fazer um breve trabalho de complexidades de processamento de eventos recebidos. Rx está configurado para se tornar uma parte do dia-a-dia de sua experiência de codificação. Leitura recomendada adicionalPresentada pelo autor de IntroToRx Sequências de coincidência Podemos conceituar eventos que têm duração como o Windows. Por exemplo, um servidor está subido, uma pessoa está em uma sala, um botão é pressionado (e ainda não liberado). O primeiro exemplo pode redirecionar-se para esta janela de tempo, o servidor foi configurado. Um evento de uma fonte pode ter um valor maior se coincidir com um evento de outra fonte. Por exemplo, durante um festival de música, você só pode se interessar por tweets (evento) sobre um artista enquanto eles estão jogando (janela). Em finanças, você só pode se interessar por trocas (evento) por um determinado instrumento enquanto o mercado de Nova York está aberto (janela). Nas operações, você pode estar interessado nas sessões do usuário (janela) que permaneceram ativas durante uma atualização de um sistema (janela). Nesse exemplo, estaríamos consultando por janelas coincidentes. Rx fornece o poder de consultar sequências de coincidência, às vezes chamadas de janelas deslizantes. Nós já reconhecemos o benefício que Rx oferece quando consulta dados em movimento. Ao fornecer adicionalmente o poder de consultar sequências de coincidência, Rx expõe ainda outra dimensão de possibilidades. Buffer revisited Buffer não é um novo operador para nós no entanto, agora pode ser agrupado conceitualmente com os operadores da janela. Cada um desses operadores de janelas atua em uma seqüência e uma janela de tempo. Cada operador abrirá uma janela quando a sequência de origem produzir um valor. A maneira como a janela é fechada, e quais valores estão expostos, são as principais diferenças entre cada um dos operadores. Deixe-nos rapidamente recapitular o funcionamento interno do operador Buffer e ver como isso mapeia o conceito de janelas do tempo. O buffer irá criar uma janela quando o primeiro valor for produzido. Em seguida, ele colocará esse valor em um cache interno. A janela permanecerá aberta até que a contagem de valores seja alcançada, cada um desses valores será armazenado em cache. Quando a contagem foi alcançada, a janela será fechada eo cache será publicado na seqüência de resultados como um IListltTgt. Quando o próximo valor é produzido a partir da fonte, o cache é apagado e começamos novamente. Isso significa que o Buffer terá um IObservableltTgt e retornará um IObservableltIListltTgtgt. Exemplo de Tampão com contagem de 3 Neste diagrama de mármore, eu representei a lista de valores que são retornados em um ponto no tempo como uma coluna de dados, isto é, os valores 0, 1 amp. 2 são todos retornados no primeiro buffer. O buffer de compreensão com o tempo é apenas um pequeno passo longe do buffer de compreensão com a contagem em vez de passar uma contagem, passamos um TimeSpan. O fechamento da janela (e, portanto, o cache dos buffers) é agora ditado pelo tempo em vez do número de valores. Isso agora é mais complicado, pois introduzimos algum tipo de agendamento. Para produzir o IListltTgt no momento correto, precisamos de um agendador designado para executar o tempo. Aliás, isso torna os testes muito mais fáceis. Exemplo de buffer com tempo de 5 unidades Os operadores da janela são muito semelhantes aos operadores do Buffer, eles realmente diferem apenas pelo seu tipo de retorno. Onde Buffer pegaria um IObservableltTgt e retornaria um IObservableltIListltTgtgt. Os operadores da janela retornam um IObservableltIObservableltTgtgt. Também vale a pena notar que os operadores do Buffer não renderizarão seus buffers até a janela se fechar. Aqui podemos ver as sobrecargas simples para a Janela. Existe uma simetria surpreendente com as sobrecargas Window e Buffer. Public static IObservable lt IOSbservable ltTSourcegtgt WindowltTSourcegt (esta fonte ltTSourcegt IObservable, Exemplo de Janela com tempo de 5 unidades Uma grande diferença que vemos aqui é que os operadores da Janela podem notificá-lo de valores da fonte assim que forem produzidos. Os operadores do Buffer Por outro lado, deve aguardar até a janela se fechar antes que os valores possam ser notificados como uma lista completa. Aplanar a operação da Janela. Eu acho que vale a pena notar, pelo menos do ponto de vista acadêmico, que os operadores da janela produzem o IObservableltIObservableltTgtgt. Nós temos Explorou o conceito de observáveis aninhados no capítulo anterior sobre Agregação. O Concat. Merge and Switch cada um tem uma sobrecarga que requer um IObservableltIObservableltTgtgt e retorna um IObservableltTgt. Como os operadores Window garantem que as janelas (sequências filho) não se sobreponham, podemos usar Qualquer um dos operadores Concat. Switch ou Merge para transformar uma seqüência de janelas em sua forma original. É o sam E como Observable. Interval (TimeSpan. FromMilliseconds (200)). Tome (10) var switchedWindow Observable. Interval (TimeSpan. FromMillececonds (200)). Pegue a janela (10) (TimeSpan. FromMillececonds (500)) Customizing windows As sobrecargas acima Forneça maneiras simples de quebrar uma seqüência em janelas aninhadas menores, usando uma contagem e um período de tempo. Agora vamos ver as outras sobrecargas, que proporcionam mais flexibilidade sobre a forma como o Windows é gerenciado. Projeta cada elemento de uma seqüência observável em janelas consecutivas que não se sobrepõem. WindowClosingSelector. Uma função invocada para definir os limites das janelas produzidas. Uma nova janela é iniciada quando o anterior está fechado. Público estático IObservable lt IObservable ltTSourcegtgt WindowltTSource, TWindowClosinggt esta fonte ltTSource lsTServable IObservable, Func lt IObservable ltTWindowClosinggtgt windowClosingSelector A primeira dessas sobrecargas complexas nos permite controlar quando o Windows deve fechar. A função windowClosingSelector é chamada cada vez que uma janela é criada. O Windows é criado na subscrição e imediatamente após uma janela fecha as janelas fechadas quando a seqüência do WindowClosingSelector produz um valor. O valor é desconsiderado para que ele não importe o tipo de valores de seqüência, de fato, você pode simplesmente completar a seqüência do WindowClosingSelector para fechar a janela. Neste exemplo, criamos uma janela com um seletor de fechamento. Devolvemos o mesmo assunto desse seletor toda vez, depois notifique do assunto sempre que um usuário pressionar entrar do console. Var windowIdx 0 var source Observável. Interval (TimeSpan. FromSeconds (1)). Tome (10) var close new Assunto lt Unidade gt () source. Window (() gt closer) var windowFechar index. Skip (count-1) return Shared. Window (windowOpen, gt windowClose) Podemos ver aqui que a seqüência windowClose é novamente subscrito a cada vez que uma janela é aberta, devido a ela ser retornada de uma função. Isso nos permite reaplicar o salto (Ignorar (contagem-1)) para cada janela. Atualmente, ignoramos o valor que o windowOpen empurra para o seletor windowClose, mas se você precisar de alguma lógica, está disponível para você. Como você pode ver, o operador da janela pode ser bastante poderoso. Podemos até mesmo usar a janela para replicar outros operadores, por exemplo, podemos criar nossa própria implementação do buffer dessa forma. Podemos fazer com que o operador SelectMany tome um único valor (a janela) para produzir zero ou mais valores de outro tipo (no nosso caso, um único IListltTgt). Para criar o IListltTgt sem bloquear, podemos aplicar o método Agregado e usar um novo ListltTgt como a semente. Public static IObservable ltIListltTgtgt MyBufferltTgt (esta fonte ltTgt IObservable, pode ser um exercício interessante para tentar implementar outros métodos de mudança de tempo, como Sample ou Throttle. Com Window. O operador Join permite que você se junte logicamente a duas seqüências. Considerando que o operador Zip seria emparelhado Os valores das duas sequências em conjunto pelo índice, o operador de Junção permitem que você junte seqüências ao cruzar as janelas. Como a sobrecarga da janela que acabamos de ver, você pode especificar quando uma janela deve fechar através de uma seqüência observável, esta seqüência é retornada de uma função que leva Um valor de abertura. O operador Join tem duas dessas funções, uma para a primeira seqüência de origem e outra para a segunda sequência de origem. Como o operador Zip, também precisamos fornecer uma função seletora para produzir o resultado do par de valores. Público estático IObservable ltTResultgt Participe de ltTLeft, TRight, TLeftDuration, TRightDuration, TResultando este IObservable ltTLeftgt à esquerda, IObservable ltTRight Gt Right, Func ltTLeft, IObservable ltTLeftDurationgtgt leftDurationSelector, Func ltTRight, IObservable ltTRightDurationgtgt rightDurationSelector, Func ltTLeft, TRight, TResultgt resultSelector Esta é uma assinatura complexa para tentar entender de uma só vez, então vamos tomar um parâmetro por vez. IObservableltTLeftgt à esquerda é a sequência de origem que define quando uma janela é iniciada. Isso é exatamente como os operadores de Buffer e Window, exceto que todos os valores publicados a partir desta fonte abre uma nova janela. No buffer e na janela. Em contrapartida, alguns valores acabaram de cair em uma janela existente. Eu gosto de pensar em IObservableltTRightgt direito como a seqüência de valores da janela. Enquanto a seqüência esquerda controla a abertura do Windows, a seqüência certa tentará emparelhar com um valor da seqüência esquerda. Imaginemos que nossa seqüência esquerda produz um valor, o que cria uma nova janela. Se a seqüência certa produzir um valor enquanto a janela estiver aberta, a função ResultSelector é chamada com os dois valores. Este é o ponto crucial da junção, emparelhando dois valores de uma seqüência que ocorrem na mesma janela. Isso nos leva à nossa próxima pergunta quando a janela fecha. A resposta ilustra tanto a potência quanto a complexidade do operador Join. Quando a esquerda produz um valor, uma janela é aberta. Esse valor também é passado, naquele momento, para a função RestoreSelector da esquerda, que retorna um IObservableltTLeftDurationgt. Quando essa sequência produz um valor ou completa, a janela para esse valor é fechada. Observe que é irrelevante o tipo de TLeftDuration. Isso inicialmente me deixou com a sensação de que IObservableltTLeftDurationgt era um pouco excessivo, pois você precisa efetivamente de algum tipo de evento para dizer Fechado. No entanto, ao permitir o uso do IObservableltTgt. Você pode fazer uma manipulação inteligente como veremos mais tarde. Vamos agora imaginar um cenário onde a seqüência esquerda produz valores duas vezes mais rápido que a sequência certa. Imagine que, além disso, nunca fechamos as janelas, poderíamos fazer isso sempre retornando Observable. NeverltUnitgt () a partir da função leftSurclector de esquerda. Isso resultaria na produção dos seguintes pares. Como você pode ver, os valores esquerdos são armazenados em cache e repetidos cada vez que o direito produz um valor. Agora, parece bastante óbvio que, se eu imediatamente fechasse a janela, retornando Observable. EmptyltUnitgt. Ou talvez Observable. Return (0). As janelas nunca seriam abertas, de modo que nenhum casal nunca seria produzido. No entanto, o que eu poderia fazer para garantir que essas janelas não se sobrepunham, de modo que, uma vez que um segundo valor fosse produzido, eu não veria mais o primeiro valor. Bem, se retornássemos a seqüência esquerda do RightSaintlector esquerdo. Isso poderia fazer o truque. Mas espere, quando retornamos a seqüência deixada no LeftDurationSelector. Isso tentaria criar outra assinatura e isso pode introduzir efeitos colaterais. A resposta rápida a isso é Publicar e RefCount a seqüência esquerda. Se fizermos isso, os resultados se parecem mais com isso. O último exemplo é muito semelhante ao CombineLatest. Exceto que só produz um par quando a seqüência certa muda. Podemos usar Junte-se para produzir nossa própria versão do CombineLatest. Se os valores da seqüência esquerda caducarem quando o próximo valor da esquerda foi notificado, então estaria bem no meu caminho para implementar minha versão do CombineLatest. No entanto, eu preciso da mesma coisa para a direita. Felizmente, o operador Join fornece um RightDurationSelector que funciona exatamente como LeftDurationSelector. Isso é simples de implementar tudo o que preciso fazer é retornar uma referência à mesma seqüência esquerda quando um valor esquerdo é produzido e fazer o mesmo para a direita. O código parece assim. Public static IObservable ltTResultgt MyCombineLatestltTLeft, TRight, TResultgt IObservable ltTLeftgt à esquerda, IObservable ltTRightgt right, Func ltTLeft, TRight, TResultgt resultSelector Enquanto o código acima não é qualidade de produção (precisaria ter alguns portões no local para mitigar as condições da corrida), mostra Quão poderosa é a junção, podemos usá-la para criar outros operadores. Quando o operador de Junção agrupa os valores que coincidem em uma janela, passará os valores escalares à esquerda e à direita para o ResultSelector. O operador GroupJoin dá um passo adiante passando o valor esquerdo (escalar) imediatamente para o ResultSelector com o valor direito (seqüência). O parâmetro certo representa todos os valores das seqüências direitas que ocorrem dentro da janela. Sua assinatura é muito parecida com Participar. Mas observe a diferença no parâmetro resultSelector. public static IObservable ltTResultgt GroupJoin ltTLeft, tright, TLeftDuration, TRightDuration, TResultgt este IObservable ltTLeftgt esquerda, IObservable ltTRightgt direita, Func ltTLeft, IObservable ltTLeftDurationgtgt leftDurationSelector, Func ltTRight, IObservable ltTRightDurationgtgt rightDurationSelector, Func ltTLeft, IObservable ltTRightgt, TResultgt resultSelector Se voltamos para Nosso primeiro exemplo de junção onde tínhamos a esquerda produzindo valores duas vezes mais rápido do que o direito, o esquerdo nunca expirando o direito imediatamente expirando, isso é o que o resultado pode parecer. Podemos alterná-lo e ter o direito de expirar imediatamente e o direito nunca expirar . O resultado seria assim: isto começa a tornar as coisas interessantes. Os leitores perceptivos podem ter percebido que, com o GroupJoin, você poderia efetivamente recriar seu próprio método de junção, fazendo algo como isto: IObservable público ltTResultgt MyJoinltTLeft, TRight, TLeftDuration, TRightDuration, TResultgt (IObservable ltTLeftgt à esquerda, IObservable ltTRightgt right, Func ltTLeft, IObservable ltTLeftDurationgtgt LeftDurationSelector, Func ltTRight, IObservable ltTRightDurationgtgt rightDurationSelector, Func ltTLeft, TRight, TResultgt resultSelector) Para um resumo alternativo de reduzir operadores para um conjunto primitivo, veja Bart DeSmets excelente publicação MINLINQ (e vídeo de acompanhamento). Bart é um dos principais membros da equipe que construiu Rx, por isso é ótimo ter uma visão de como os criadores da Rx pensam. Showcasing GroupJoin e o uso de outros operadores acabaram por ser um exercício acadêmico divertido. Ao assistir a vídeos e ler livros no Rx aumentará a sua familiaridade com ele, nada substitui a experiência de selecioná-lo e usá-lo com seriedade. O GroupJoin e outros operadores de janelas reduzem a necessidade de encanamento de estado e concorrência de baixo nível. Ao expor uma API de alto nível, o código que de outra forma seria difícil de escrever, torna-se uma coisa fácil de montar. Por exemplo, aqueles no setor financeiro podem usar o GroupJoin para produzir facilmente preços médios ponderados em volume ou em tempo real (VWAPTWAP). Rx oferece ainda outra maneira de consultar dados em movimento, permitindo que você interrogue sequências de coincidência. Isso permite que você resolva o problema intrinsecamente complexo de gerenciar o estado e a concorrência enquanto executa correspondência de múltiplas fontes. Ao encapsular essas operações de baixo nível, você pode aproveitar a Rx para projetar seu software de forma expressiva e testável. Usando os operadores Rx como blocos de construção, seu código efetivamente se torna uma composição de muitos operadores simples. Isso permite que a complexidade do código de domínio seja o foco, e não o código de suporte de outra forma acidental. Quando o LINQ foi lançado pela primeira vez, trouxe a capacidade de consultar fontes de dados estáticas diretamente no idioma. Com o volume de dados produzido nos tempos modernos, só pode consultar dados em repouso, limita sua vantagem competitiva. Sendo capaz de entender as informações à medida que flui, abre um espectro inteiramente novo de software. Precisamos de mais do que apenas a capacidade de reagir aos eventos, nós conseguimos fazer isso por anos. Precisamos da capacidade de construir consultas complexas em várias fontes de dados em fluxo. Rx traz processamento de eventos para as massas, permitindo que você consulte dados em movimento diretamente do seu idioma. NET favorito. Composição é rei: você compõe operadores para criar consultas e você compõe seqüências para enriquecer os dados. A Rx aproveita tipos comuns, padrões e recursos de linguagem para oferecer uma biblioteca incrivelmente poderosa que pode mudar a maneira como você escreve software moderno. Ao longo do livro você terá aprendido os tipos e princípios básicos do Rx. Você descobriu conceitos de programação funcional e como se aplicam a seqüências observáveis. Você pode identificar possíveis armadilhas de certos padrões e como evitá-los. Você entende o funcionamento interno dos operadores e até mesmo capaz de construir suas próprias implementações de muitos deles. Finalmente você é capaz de construir consultas complexas que gerenciam a concorrência de forma segura e declarativa enquanto ainda estão sendo testáveis. Você tem tudo o que precisa para criar aplicativos com confiança usando as Extensões Reativas para. NET. Se você se encontra em algum momento preso, e não sabe como resolver um problema ou precisa de ajuda, provavelmente você pode resolvê-lo sem estímulo externo. Lembre-se de primeiro desenhar um diagrama de mármore do que você acha que o espaço do problema é. Isso deve permitir que você veja os padrões no fluxo que o ajudarão a escolher os operadores corretos. Em segundo lugar, lembre-se de seguir as Diretrizes. Em terceiro lugar, escreva um pico. Use LINQPad ou um projeto Visual Studio em branco para concretizar uma pequena amostra. Finalmente, se você ainda está preso, seu melhor lugar para procurar ajuda é o fórum MSDN Rx. StackOverflow também é outro recurso útil, mas no que diz respeito às perguntas do Rx, o fórum MSDN é dedicado à Rx e parece ter uma maior qualidade de respostas. Leitura adicional recomendada Estou entrando no Rx 8211 ReactiveUp Extensiones e ReactiveUI um pouco também e estou passando pela Rx Workshop no Canal 9. O 5º episódio da série, que fala sobre agrupamento, buffers, janelas e outras manipulações avançadas de fluxo, deu origem a Um desafio que eu decidi empreender. Dado um fluxo de StockQuotes, e o código anexado ao exercício fornece a seguinte classe StockQuote, como podemos anexar uma média móvel de 5, 10 ou x dia para o ponto de alta, baixa, fechada ou outro na classe StockQuote. Eu acho que finalmente entendi. O código está abaixo, mas a abordagem é a seguinte: Adicione as propriedades médias à classe StockQuote original. Então, se você estiver com média de Alto e baixo, adicione AverageHigh e AverageLow: 2. Use o método Buffer para criar buffers deslizantes de ações que deseja agregar. Se cada cotação de estoque representa um dia na vida do estoque, a agregação de 10 instâncias do StockQuote criaria uma média móvel de 10 dias, agregando 100 delas criaria uma média móvel de 100 dias. Quanto mais dias você agrega, mais lento o programa seria executado. Use o segundo parâmetro para o método de buffer para especificar quantas instâncias das citações de ações separam um buffer do próximo. We8217ll usa o valor de 1 para criar buffers deslizantes de uma cotação de estoque para a próxima. 3. Finalmente, use a função agregada para preencher as médias correntes para as instâncias do StockQuote que aparecem em último na lista de buffer. Esta pode não ser a implementação ideal. Se alguém pode sugerir um melhor, comente.
No comments:
Post a Comment