sexta-feira, 30 de setembro de 2016

Debug #12 - Executar arquivo externo em ADVPL


Fala galera!


Esses dias precisei fazer uma modificação no sistema no qual efetuaria um sinal sonoro para alertar o usuário sobre alguma entrada incorreta de dados. 


O problema principal é: a cada notificação de erro ou dados inválidos o sistema irá emitir um som que alertará o usuário que algo está errado.

Primeiramente vamos criar uma função de usuário simples com o nome alarme() e seu retorno será uma variável - lRet - do tipo booleano. Caso alguma inconsistência seja encontrada o alerta será emitido.

user function alarme

local lRet := .T.
local nQtd := 3
local cDirCli := "C:\\Media\\"

if nQtd = 3
 shellExecute("Open", cDirCli+"sound.bat", "", "", 0) 
 msgInfo("Qtd = 3")
else
 shellExecute("Open", cDirCli+"sound_2.bat", "", "", 0)
 msgInfo("Qtd <> 3")
 lRet := .F.
endIf

return lRet

Além da variável de retorno e outra variável de teste (nQtd), temos uma variável que nos mostra o diretório onde se encontra os arquivos de áudio que usaremos em nossa rotina.

Utilizaremos o método shellExecute() para que possamos chamar nosso arquivo .bat que ficará responsável por abrir e executar o áudio.

Vejamos nosso arquivo .bat:

start wmplayer /play /close c:\Media\sound136.wav 
timeout /t 1
TASKKILL /IM wmplayer.exe


Na primeira linha temos o comando start que inicia o player wmplayer - em nosso caso será o windows media player - então usamos os comandos /play e /close e informamos o diretório do arquivo de áudio a ser executado.

Usei também o comando timeout com o tempo (/t) de 1 segundo. Após esse tempo o comando TASKKILL irá encerrar a tarefa do windows media player.

É isso ai galera! Espero que tenho curtido essa dica.

Até mais!

;)

quinta-feira, 29 de setembro de 2016

Tipos de Code Smells


Fala galera que acompanha o blog...

Antes de continuar lendo esse post sobre os Tipos de Code Smells, eu sugiro que caso não saiba o que são Code Smells, leia o post que fizemos sobre o que são Code Smells.

Bom, com o paradigma de orientação a objetos existem duas categorias de code smells: Within Classes (dentro de classes) e Between Classes (Entre classes).



Tipos de Code Smells


Code Smells within classes



Comments:
     É evidenciado pelo excesso de comentários que não necessariamente precisariam ser escritos e, ao invés de auxiliar, acabam por prejudicar o entendimento do código-fonte. Sempre atentar para que as explicações deixadas nos comentários e ter em mente que o comentário está sendo escrito para as pessoas, e não para as máquinas.

Long Method:
    Não importa qual o paradigma escolhido, mas saiba-se que métodos, funções ou procedimentos extremamente longos são difíceis de entender. Quanto maiores eles são e quanto mais parâmetros e variáveis eles usam, os tornam mais propensos a fazer mais do que seu nome sugere. Métodos curtos são mais “entendíveis” em relação ao que o seu código-fonte faz, permite um maior reuso de código e mais flexibilidade. Claro que, com métodos mais curtos há mais elementos para cuidar, e ter mais chamadas aos métodos curtos significa mais vezes tendo que verificar o que o método chamado realmente faz. Entretanto, se é dado aos métodos bons nomes, que mostram quais os seus propósitos, elimina-se muito a necessidade de olhar para o corpo dos métodos e a necessidade de adicionar comentários para esclarecer o código-fonte.

Too many parameters (Long Parameter List):
     Em programação orientada por objetos, a maioria dos dados necessários a um método pode ser diretamente obtida a partir dos próprios objetos, caso eles sejam visíveis para o método, ou eles podem ser derivados através de um pedido de outro parâmetro. Portanto, as listas de parâmetros devem ser curtas, pois quanto mais extensas se tornam mais difíceis de ler, difícil de usar e elas mudam muito quando mais dados são necessários. Fazer uma mudança para uma lista de parâmetros significa mudar todas as referências ao método envolvido. E assim, mantê-lo curto.

Duplicated Code:
     É caracterizado quando um código idêntico ou muito semelhante existe em mais de um local. Deve-se atentar para eliminar toda e qualquer duplicação sempre que possível. Procurando sempre casos mais sutis de quase duplicação no código-fonte escrito.

Large Class:
    As classes grandes são caracterizadas por deterem muitas responsabilidades, com muitos dados e/ou métodos demais. O que torna isto um problema, porque essas classes são difíceis de manter e compreender devido ao seu tamanho. As classes grandes muitas vezes recai nas situações que exemplificam “Duplicated Code” ou “Shotgun Surgery”. A solução é encontrar partes de dados e métodos que parecem estar bem relacionados e refatorar utilizando Extract Class.

Type Embedded in Name:
     Situação onde se coloca nomes de tipos em nomes de métodos. Isto não é apenas redundante, mas o obriga a mudar o nome, se as mudanças de tipo se fizerem necessárias, ou numa opção pior ainda: nome “tipado” divergente do tipo definido permanece inalterado no código-fonte.

Uncommunicative Name:
     Ocorre quando se opta por colocar nomes em métodos que não descreve sucintamente o que ele faz. O ideal é que os métodos procurem sempre passar de forma simplista, a função que o mesmo detém, apenas no nome que lhe é dado. Fazendo isso, evita-se no futuro em uma refatoração ter que renomeá-lo ou reescrevê-lo.

Inconsistent Names:
     Comumente acontece quando não se atenta para o conjunto de nomes dados aos métodos, de uma forma mais ampla, e só se detém a uma escolha que descreve minimamente tal método, sem transparecer a correlação com que ele tem com os demais criados. Para resolver isso, basta na hora da escolha optar por um conjunto de terminologia padrão e cumpri-lo em todos os seus métodos. Por exemplo, se existe Open(), provavelmente deve ter Close().

Dead Code:
     Acontece quando o desenvolvedor não elimina trechos de código-fonte que não está sendo utilizado pelo sistema, pensando que o mesmo poderá ser preciso futuramente. A boa prática prega que se deve apagar tal código-fonte que não está sendo usado e, se necessário, obtê-lo a partir do controle de versão do projeto.

Speculative Generality:
     Fica explicito quando se escreve código-fonte que não atende nenhum propósito no momento e se pensa em expandi-lo para efetivamente representar algo no sistema apenas no futuro. Para isso deve-se manter o foco e apenas escrever código para resolver os problemas de hoje, não se preocupando com os problemas de amanhã, quando realmente se concretizar. Atenção para isso: Não quer dizer que a abordagem é escrever código-fonte sem pensar no uso futuro dele, pois certo é escrever o que precisa hoje de modo a ser expansível, e errado é criar “esqueletos” de código-fonte inacabados (ou até acabados mas sem ligação alguma) e que existe uma definição real de que o mesmo será utilizado um dia.

Conditional Complexity:
     Lógica condicional é relativamente fácil de ser compreendida quando bem aplicada e contida dentro de algumas linhas de código-fonte. Infelizmente, isso raramente acontece. Ocorre geralmente quando são implementados vários recursos novos e de repente a lógica condicional torna-se bastante complexa e confusa. Portanto deve-se ter cautela com os grandes blocos lógicos condicionais, particularmente blocos que tendem a crescer ou mudar significativamente ao longo do tempo.

Combinatorial Explosion:
     Trata de uma forma sutil de duplicação. Ela existe quando há vários trechos de código-fonte que fazem a mesma coisa usando diferentes tipos ou quantidades de dados ou objetos. Por exemplo: existem vários métodos em uma classe para executar consultas. Cada um destes métodos executa uma consulta usando condições específicas, podendo o desenvolvedor recair numa condição de explosão de métodos ao criar inúmeros deles para lidar com as muitas maneiras de realizar consultas.

Oddball Solution:
     É caracterizado quando um dado problema é resolvido de duas maneiras diferentes no mesmo sistema, uma das soluções é tida como a excêntrica ou solução inconsistente. A presença dessa constatação geralmente indica sutilmente código duplicado. Para remover essa duplicação, primeiro determine a maneira preferida, e depois pode se aplicar o “Substitute Algorithm” para produzir uma solução consistente em todo o sistema. Dada uma solução consistente, É possível mover todas as instâncias da solução para um lugar, eliminando assim a duplicação.

Temporary Field:
     É evidenciado quando a variável está no escopo da classe, quando deveria estar no escopo do método. Violando o princípio ocultação de informação. Por meio do Extract Class é possível sanar tal situação.

Code Smells between classes

Alternative Classes with Different Interfaces:
     Classes similares por dentro, mas diferente por fora. Elas podem ser modificadas para partilhar uma interface comum.

Primitive Obsession:
    Usar muitas variáveis primitivas para representar tipos complexos. Se o tipo de dados é bastante complexo, escreve-se uma classe para representá-lo.

Data Class:
     Usar classes só para conter dados. Classes com campos, getters e setters e nada mais.

Data Clumps (Aglomerados de dados):
    Os mesmos dados sendo manipulados em diferentes níveis podem estar relacionados. Considera-se colocar os dados relacionados acima em uma classe maior.

Refused Bequest:
     Herda mas não usa nada, então não se faz necessário a herança, pois está apenas contribuindo para o alto acoplamento.

Inappropriate Intimacy:
     Comportamento de uma classe influenciado por aspectos internos de outra classe. As classes deve saber o mínimo possível sobre de uma sobre a outra.

Indecent Exposure:
     Demasiado uso de public.

Feature Envy:
     Método que usa muito, mas muito mesmo, uma outra classe. Em geral, tenta-se colocar um método na classe que contém a maioria dos dados que o método necessita.

Lazy Class:
     Classe que não atende a si mesma e joga parte de sua responsabilidade para outras.

Message Chains:
     Métodos com muita execução ou variáveis temporárias para dados de rotina.

Middle Man:
     Classes delegando toda sua responsabilidade para outras.

Divergent Change:
     Uma alteração pontal afeta aspectos completamente diferentes.

Shotgun Surgery:
    Oposto da mudança divergente, pois para uma alteração pontal tem que mexer em várias classes.

Parallel Inheritance Hierarchies:
     Ao herdar uma classe tem que criar uma subclasse similar à subclasse presente na herdada.

Incomplete Library Class:
     Não é possível alterar a biblioteca e o método acaba indo para uma classe qualquer.

Solution Sprawl:
     Se precisar de 5 ou mais classes para fazer algo útil, precisa simplificar e consolidar.


Esta lista foi obtida a partir do arquivo  Smells to Refactorings PDF, e do Wiki Smells to Refactorings Wiki,, que também fornecem orientações adicionais sobre as refatorações específicas que podem ser úteis em cada caso.

Não fique encabulado com todos esses problemas que podem ser encontrados no código, é claro que um código limpo é sempre bem vindo, mas o mais importante é saber identificar esses mau cheiros do código e assim aplicar a refatoração adequada para cada caso.

É isso pessoal até a próxima!

Code Smells


Fala galera que acompanha o blog...

Você já sentiu um cheiro enquanto programava, refatorava ou reutilizava o código de alguém? Aquele cheiro, que na verdade é uma sensação de código ruim, aquele trecho que você olha e pensa "humm isso aqui pode dar m3#d@!", ou então, aquele comentário explicando o código e pior ainda aquele comentário "Se remover esse trecho o sistema para de funcionar", sabe?


Code Smells

Esses exemplos citados (e vários outros) são chamados de Code Smells, ou "Mau cheiro no código".

Na literatura é possível verificar que alguns autores preferem dividir a lista de code smells em duas partes, os que estão em uma classe e os que envolvem mais de uma classe. Veja esse post sobre os Tipos de Code Smells.

Hoje existem vários padrões já identificados e difundidos. A partir destes padrões você pode avaliar seu código e verificar se ele está "muito mau cheiroso".


A Industrial Logic disponibilizou uma lista dos padrões de code smells mais conhecidos e das possíveis técnicas de refatoração que você pode utilizar para eliminar estes problemas.

É uma lista muito interessante e bastante útil para ser consultado naquele momento em que queremos alterar o código fonte e tentar melhorá-lo.


No entanto antes de iniciar o processo de refatoração, lembre-se de criar testes unitários e/ou de integração para garantir que as alterações realizadas não "quebraram" a sua aplicação.
Sem dúvida, o exemplo de code smells mais simples e corriqueiro que acontece no código, são as linhas em branco dentro de um método. Muitas vezes achamos que a linha em branco esta sendo usado para melhorar a leitura do código, usamos como uma forma de indentação, mas que na verdade, ao analisar melhor o trecho, percebemos que essa linha em branco está separando duas atividades dentro de um mesmo método, ou seja, poderíamos converter tudo que está abaixo dessa linha em branco em um outro método.

A linha em branco não é o problema em si. Ela só indica que há um problema.

Não saia refatorando todo o seu código de uma só vez, na medida que for utilizando as classes e seus métodos vá fazendo as correções necessárias.
Você pode seguir os seguintes passos:


  1. Encontre um Método;
  2. Caso não exista testes que garantam a funcionalidade, crie-os;
  3. Verifique se há linhas em branco separando blocos;
  4. Para cada bloco, extraia o código criando um novo Método;
  5. Faça a chamada do novo Método no mesmo lugar que extraiu o código;
  6. Repita o processo enquanto for necessário.

Se você gostou do assunto e se interessou em saber mais em como manter seu código limpo, pode começar lendo um livro muito bacana do autor Robert C. Martin ou "Uncle Bob" ( Tio Bob ), que é uma grande personalidade na comunidade de desenvolvimento de software, métodos ágeis e vários outros ramos, até porque o Tio Bob ai, atua na área desde 1970, e seu livro se chama Clean Code (Código Limpo).

"O renomado especialista em software, Robert C. Martin, apresenta um paradigma revolucionário com Código limpo: Habilidades Práticas do Agile Software. Martin se reuniou com seus colegas do Mentor Object para destilar suas melhores e mais ágeis práticas de limpar códigos “dinamicamente” em um livro que introduzirá gradualmente dentro de você os valores da habilidade de um profissional de softwares e lhe tornar um programador melhor –mas só se você praticar.

Que tipo de trabalho você fará? Você lerá códigos aqui, muitos códigos. E você deverá descobrir o que está correto e errado nos códigos. E, o mais importante, você terá de reavaliar seus valores profissionais e seu comprometimento com o seu ofício."

Mais informações sobre o livro acesse o site AltaBooks:


Bom pessoal é isso... parece bobeira mas a verdade é que escrever código qualquer um faz, existem diversos tutoriais sobre programação e tudo mais, mas escrever um bom código, no entanto, não é pra qualquer um. Pense no longo prazo, no acoplamento, na coesão, no design, deixe as coisas simples.



Até a próxima!

quarta-feira, 28 de setembro de 2016

O que é Podcast?


Fala galera que acompanha o blog...

Nesse post, vou estar explicando o que são podcast e como é a dinâmica durante a gravação de um episódio.

Bom, Podcast não é nada mais que um modelo de conteúdo compartilhado, normalmente em formato de áudio, onde a maioria das vezes é gravado em formato MP3.
Esses arquivos podem ser disponibilizados para download ou através de um player, seja no próprio navegador do usuário ou através de aplicativos que funcionam como gerenciadores de podcast, trazendo uma lista com os mais diversos assuntos de podcast.

O que é Podcast?

Então, assim como o rádio, a TV e o jornal, o podcast acaba funcionando como uma mídia de transmissão de informações, onde a diferença e vantagem principal são conteúdos sob demanda. Você pode ouvir ouvir o que quiser e na hora que quiser.
A forma de comunicação durante o podcast, funciona como uma mesa redonda, onde os apresentadores e convidados conversam sobre determinado assunto, cada um apresentando sua opinião ou historia particular, dependendo do assunto em pauta, e a conversa vai acontecendo de forma natural.

Hoje existem podcasts sobre diversos temas. Utilizando a ferramenta Keyword Tool, preenchendo o campo "type keyword" com a busca "podcast sobre", veja o resultado:

O que é Podcast? Pesquisa palavra chave


Ou seja, utilizando o buscador do google, foram encontrados mais de 377 resultado ÚNICOS... tem podcast sobre os mais diversos temas, e você pode estar ouvindo todos eles e acompanhar diferentes opiniões, mandar a sua opinião, contribuir e isso tudo com um conteúdo educacional de qualidade... eu particularmente sou apaixonado por podcast, dos mais diversos assuntos.

Outro ponto muito bacana sobre podcast e que você não precisa ficar "assistindo"... é colocar o fone e continuar a sua vida/atividade normalmente, seja no trabalho, em casa, na rua, na academia, no busão rs

Dependendo do tema abordado no podcast é muito comum que além dos "apresentadores" do canal, sejam convidadas outras pessoas com conhecimento sobre o assunto para agregar mais qualidade e informações no episódio.
No fim das contas, o podcast poderá ser uma importante porta de entrada para que novas pessoas conheçam o trabalho que você realiza.

Pessoal é isso... espero que tenha ficado claro o que são podcast e como funcionam e até a próxima!

terça-feira, 27 de setembro de 2016

[MucilaCast - 001] Origins


Fala galera que acompanha o blog...

E hoje vocês poderão ouvir o primeiro podcast do MucilaCast, que demos o nome de Origins.

Nesse primeiro podcast, você vai ouvir um pouco sobre cada um de nós, com o que trabalhávamos antes de sermos programadores, quando tivemos contato pela primeira vez com um computador (e acredite demorou rs), insight para iniciar a faculdade, um pouco sobre a faculdade e vários outros assuntos.


[MucilaCast] Origins

Ficamos bastante contente com o resultado final, esperamos que vocês gostem e participem nos ajudando com assuntos, melhorias, reclamações e nos corrigindo, caso seja falado alguma "bobagem" durante a gravação rs.

Faça o download ou ouça em seu navegador:

Participação:
  • Felipe Pereira de Souza;
  • Luiz Fagner Zordan;
  • Renan Rodrigues Ramos.
Música e efeitos:

As músicas utilizadas nesse podcast podem ser encontrados nos endereços:

DanoSongs
  • Crazy from the Message;
  • Great World;
  • Heart Quake.
  • The impossebulls - 5 x 5.

Capa: Felipe Pereira de Souza
Edição: Renan Rodrigues Ramos

É isso pessoal, até a próxima!

sexta-feira, 23 de setembro de 2016

GO GO! Semana Desenvolvimento Android


Fala galera que acompanha o blog...

"Chegou a Hora de dar um Upgrade de Carreira com Desenvolvimento Android.

O mercado mobile está bombando e muito aquecido mesmo com a famosa crise no Brasil. São mais de 40 milhões de smartphones ativos em nosso pais com usuários sedentos por aplicativos que resolvam seus problemas.

GO GO! Semana Desenvolvimento Android

E sabe para quem isso é bom? Quem ganha as oportunidades no mercado?

Os desenvolvedores Android!

Se quer aprender todos os passos para se tornar um desenvolvedor Android, dar um upgrade na sua carreira e ainda se divertir muito, tenho um convite para você.

Dia 26, próxima segunda-feira começa a Semana do Desenvolvimento Android, onde o programador Fillipe Cordeiro vai ensinar GRATUITAMENTE:
  • Os principais erros que todo mundo comete na hora de estudar desenvolvimento Android ou qualquer outra linguagem, e que, provavelmente, você esteja cometendo também, o que acaba "travando" o seu progresso. 
  • Os conceitos básicos e o caminho que você deve seguir para se tornar um desenvolvedor de aplicativos Android profissional. 
Para garantir uma das últimas vagas e participar desse excelente evento, basta fazer rapidamente o seu cadastro aqui."

É isso ai pessoal, até a próxima.

quinta-feira, 22 de setembro de 2016

Compilando e executando Código Java pela linha de comando


Fala pessoal, blz?

Há alguns dias decidi que iria me aprofundar mais sobre a linguagem Java afim de chegar a certificação (Oracle Certified Associate, Java SE 8 Programmer) e talvez em um futuro as próximas certificações posteriores.




Comecei a ler este livro (https://www.casadocodigo.com.br/products/livro-certificacao-java-associate) como guia e recomendo. :)

Já de início o autor da algumas dicas e a primeira dica é:
Lembre-se de usar a linha de comando do Java, não use o Eclipse ou qualquer outra IDE: os erros que o compilador da linha de comando mostra podem ser diferentes dos da IDE, e você não quer que isso atrapalhe seu desempenho. 

Hum...legal. Mas, como eu faço isso mesmo?

Calma, calma vou demonstrar aqui é bem fácil e até divertido.

Primeiramente certifique-se que esteja com a Java Development Kit (JDK) instalada.
O link para o download é este Download JDK.

Depois de instalado a JDK devemos configurar as variáveis de ambiente, caso tenha dúvidas acesse este artigo (Variáveis de Ambiente) está muito bem explicado. ;)

Certo, JDK instalada e variáveis de ambiente configuradas. Vamos então a parte divertida.

- Crie sua classe Java e salve em uma pasta:

class Teste {

static int i = 3;

     public static void main(String[] a) {

       for (new Teste().i = 10; new Teste().i < 30; new Teste().i++) {

           System. out. println(i) ;

       }

    }

}




- Abra o prompt de comando e navegue até a pasta onde está sua classe:

E:\cd Projetos\certificacao

- Para compilar o arquivo vamos utilizar o comando javac da seguinte maneira :

E:\ javac Teste.java

E pressione “ENTER”, caso tenha um erro no seu código a linha de comando ira informar dessa maneira.



Caso não informe nada, fique feliz, a sua classe foi compilada com sucesso.

- Após executando o comando javac com sucesso, verifique que na sua pasta ira conter um arquivo de mesmo nome da sua classe porém com a extensão “.class” .

Para executar a sua classe uilize o comando “java” e o nome da sua classe da seguinte forma :

E:\Projetos\certificacao>java Teste



Fácil né?
Então é isso pessoal, espero ter ajudado vocês. Qualquer dúvida deixe nos comentários!
Abraço,  Cheers!
Felipe de Souza Desenvolvedor

Bacharel em sistemas de informação. Apaixonado por música e fascinado pela natureza. Entusiasta em compartilhar informação a fim de facilitar a vida das pessoas.

quarta-feira, 21 de setembro de 2016

[MucilaCast] Podcast


Fala galera que acompanha o blog...

Se você não entendeu nada sobre o titulo desse post, pode ficar tranquilo que eu vou explicar certinho do que se trata rs

É o seguinte...

Durante algumas conversas com uns amigos, ambos escrevem aqui no blog DevIsComing, resolvemos criar um canal de podcast, e é claro, um podcast sobre tecnologia. No entanto, não ficaremos focado apenas nisso! Vamos falar também sobre jogos, filmes, séries e diversos outros assuntos que forem interessantes e/ou que sejam relevantes para ser tratado no podcast.


[MucilaCast] Podcast


Esperamos que vocês possam estar nos enviando sugestões de novos podcasts, para que possamos fazer um conteúdo bastante diversificado e dessa forma criar um "ambiente" divertido para todos que nos acompanham.

A principio estaremos gravando cada um em sua casa, com seus próprios equipamentos (lê-se fones de celular e skype rs). Sempre que possível convidaremos alguns amigos para participar de algum podcast. Dessa forma, será possível diversificar mais ainda nos assuntos e convidar pessoas que dominem determinados assuntos que serão abordados do podcast.

Sobre a frequência dos podcasts, ainda estamos verificando. Visto que cada um dos integrantes possuem seus cronogramas e atividades diferentes, ainda é um pouco difícil conciliar os horários, além do fato de ter que editar, colocar os efeitos e todo trabalho que acontece na gravação para que seja disponibilizado para vocês.

Eee por último a logo/mascote do nosso projeto!




Depois de algumas ideias, alguns desenhos e várias votações, chegamos em um acordo (seja por democracia ou pelo cansaço rs) que esse seria nossa logo/mascote, e essa trajetória para definir a logo com certeza daria um episódio de podcast.

Um detalhe bastante importante que ainda não mencionei... onde e como vocês poderão ouvir nossos episódios?
Ainda não sabemos! Estamos pesquisando e avaliando qual será o melhor local para disponibilizarmos o acesso, até então sem definição. Tão logo definindo onde serão disponibilizados informaremos e para quem ainda não conhece ou acompanha outros podcast, explicaremos passo a passo de como nos acompanhar.

Mas é isso ai pessoal!
Estamos bastante animados com esse novo projeto... esperamos que seja tão divertido para vocês como está sendo pra gente, montar a pauta, pensar em assuntos e principalmente a hora da gravação rsrs

Espero logo estar publicando aqui o nosso primeiro podcast!
Abraço!

sexta-feira, 16 de setembro de 2016

[JAVA] Java Collections Framework | Set - LinkedHashSet


Fala galera!

Em continuação a nossa sequência de posts sobre Java Collections Framework, hoje trataremos de falar a respeito do LinkedHashSet.


Assim como a classe HashSet, a classe LinkedHashSet é uma implementação da interface Set, porém os elementos são mantidos em ordem de inserção, ou seja, continuam na mesma sequência em que são adicionados ao conjunto.

Esta classe tem todos as operações opcionais existentes na interface Set e também permite elementos nulos. Fornece um desempenho "constant-time" para as operações básicas como: add(), contains() e remove().

Abaixo é apresentado um código simples para representação:

package com.deviscoming;

import java.util.LinkedHashSet;

public class DevIsComingLinkedHashSet {

 public static void main(String[] args) {
  
  LinkedHashSet linked = new LinkedHashSet();
  
  //método add() : adiciona elementos 
  linked.add("Brasil");
  linked.add("Alemanha");
  linked.add("Estados Unidos");
  linked.add("México");
  linked.add("Argentina");
  
  System.out.println(linked.toString());
  
  //método remove() : retira elementos
  linked.remove("Argentina");
  
  System.out.println(linked.toString());
  
 }
}

E a nossa saída será:

[Brasil, Alemanha, Estados Unidos, México, Argentina]
[Brasil, Alemanha, Estados Unidos, México]

Até mais!

;)

Fontes:
          Docs Oracle: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

quarta-feira, 14 de setembro de 2016

[JAVA] Java Collections Framework | Set - HashSet


Fala galera!

Após falarmos um pouco a respeito do List em Java Collections Framework, hoje abordaremos outra coleção chamada Set.



A interface Set não contém elementos duplicados e possui três principais implementações, que são:
  • HashSet;
  • LinkedHashSet;
  • TreeSet.
HashSet

Esta classe não possui nenhuma garantia em relação a ordem de iteração do conjunto, ou seja, não pode-se acreditar que a mesma sequencia/ordem que os elementos foram adicionados serão os mesmos ao longo do tempo. Esta classe possui a característica de permitir a inserção de elementos nulos (null) e também não é sincronizada.

Mais informações importantes sobre a classe HashSet:

  • a classe HashSet não mantém a ordem, os elementos podem ser retornados em ordem aleatória;
  • não é possível inserir elementos duplicados. Caso isso aconteça, o elemento "antigo" será sobrescrito pelo novo elemento;
  • conforme mencionado anteriormente, a classe HashSet aceita a inclusão de elementos nulos, mas, como descrito no item anterior, ele não permite elementos duplicados, então retornará somente um elemento nulo;
  • a classe é não-sincronizada;
  • a classe possui um método para remoção de elementos, mas se um elemento for removido de outra forma, uma exceção será lançada.
Alguns métodos interessantes de se abordar:
  • add(Element e): adiciona um elemento a lista;
  • clear(): remove todos os elementos da lista;
  • clone(): efetua uma cópia superficial da lista;
  • contains(Object o): retorna falso se um objeto (Object o) não está na lista. Caso encontre, o retorno será verdadeiro;
  • isEmpty(): retorna verdadeiro caso não tenha elementos na lista;

Nos próximos posts vamos falar um pouco sobre as outras duas classes LinkedHashSet e TreeSet.

Att

;)

segunda-feira, 5 de setembro de 2016

[JAVA] Convenções de nomenclatura


Fala galera que a acompanha o blog...

Nesse post vou falar um pouco sobre algumas regras e convenções adotadas quando estamos trabalhando com a linguagem de programação Java. É importante deixar claro que estas convenções não atrapalham o desempenho do seu código, ou a interpretação do seu código para o compilador. Elas estão relacionadas a legibilidade do código, facilidade de enter o código e em muitos casos podem ser utilizadas como uma documentação do projeto.


Convenções de nomenclatura


Embora esse post se torne trivial a medida que vamos programando e ganhando experiência e nos acostumando com as nomenclaturas adotadas, é muito importante que as regras e nomenclaturas sejam respeitadas, possibilitando que qualquer desenvolver, mesmo com pouco conhecimento em Java, possa facilmente identificar métodos, classes, atributos e constantes, e utilizar/refatorar seu código de forma eficiente.

Muitos compiladores, entre eles Eclipse e NetBeans, dão um grande auxilio durante o desenvolvimento do nosso projeto, nos informando sobre as convenções de nomenclatura no momento de criação de pacotes, classes, atributos...

Abaixo utilizarem bastante a expressão CamelCase, e já adiantarei a explicação:
CamelCase é uma expressão em inglês para a prática de escrever frase ou palavras compostas, onde cada palavra é iniciada com letra maiúscula e unidas sem espaços. É utilizada em várias linguagens de programação e por ser associada a tecnologia, o marketing se apropriou dessa maneira de escrever para criar produtos e serviços como: StarCraft, iPod, OpenOffice e muitos outros. O sentido do termo CamelCase se dá pelo fato de que as letras maiúsculas no inicio das palavras "saltam", como corcovas de um camelo.

Exemplos: DevIsComing, AtualizarBlog(), postNovo, isValid. 

Bom, vamos entender as convenções:

Nome de Pacotes

Pacotes devem começar com uma letra minúscula e jamais deve conter letras não ASCII (caracteres de língua de origem latina, como caracteres acentuados), de caracteres especiais (@, #, $, %, &, *, _, etc...) ou número.

Caso o nome do pacote seja composto por mais de uma palavra, todas as letras devem ser minusculas evitando o uso do CamelCase.

Pense nos pacotes como sendo realmente as pastas do seu computador que separam arquivos específicos que fazem sentido estarem dentro daquela pasta/pacote.
Para um pacote com.devic.usuario, não faria sentido nenhum ter uma classe chamando SalvaHistoricoCompra, espera-se que dentro do pacote mencionado exista classes como Login, Logout, CarregaUsuario...

Pacotes também são muito importantes quando possuímos classes de mesmo nome. Imagine que em um projeto onde você tenha uma classe chamada ConverteData que possui uma implementação, seu amigo de projeto também criou a mesma classe ConverteData, para um outro propósito e alguma biblioteca que você esteja usando em seu projeto também possua a classe ConverteData.
Essas classes nunca poderiam ser criadas em um mesmo pacote, assim como dois arquivos do mesmo tipo e extensão não podem ser criados dentro da mesma pasta. Dessa forma os pacotes facilitam a separação, sendo possível realizar a importação do pacote especifico que se deseja utilizar.

Nome de Classes


Toda classe DEVE começar com uma letra maiúscula e, de preferencia, não devem conter letras ASCII (caracteres de língua de origem latina, como caracteres acentuados), caracteres especiais (@, #, $, %, &, *, _, etc...) ou número.

Caso o nome da classe seja composto por mais de uma palavra, deve-se adotar o "padrão" CamelCase.

As classes devem ser vistas como o agrupamento de objetos com a mesma estrutura de dados, é uma abstração ou definições de coisas do mundo real.
Exemplo: Pessoa, Carro, Animal, PessoaJuridica.


Nome de atributos ou variáveis


Atributos (variáveis) podem começar com qualquer letra ou com os caracteres $ ou_, porém não devem começar com números.

Caso o nome do atributos seja composto por mais de uma palavra, deve-ser adotar o "padrão" CamelCase.

A definição e diferença entre atibuto e variavel, você pode encontrar aqui.
Exemplo: nome, endereco, isValido, orgaoTecnico.


Nome de atributos finais ou constantes


Os atributos finais (constantes) devem ser escritos em letra maiúscula;

Caso o nome do atributo final seja composto por mais de uma palavra, utilizamos o underline (_) para separar uma palavra da outra.

Exemplo: BASE_CALCULO, FIND_BY_ID.

Nesse post vimos algumas regras e convenções de nomenclatura que foram adotadas pra a linguagem java, essa convenção muda de uma linguagem para outra (mesmo que não totalmente). Se você está começando agora a programar em java, não se preocupe em decorar essas convenções, com o tempo (e em pouco tempo) você estará, de forma natural, adotando essas convenções no seu código.

É isso ai pessoal, até a próxima!

quinta-feira, 1 de setembro de 2016

[ADVPL] Desenvolvendo classes


Fala galera!

Uma das coisa mais interessantes de se aprender durante o desenvolvimento de algumas rotinas em ADVPL, é o uso de classes. Confesso que para mim isso é um pouco recente, mas estou aplicando sempre que possível em meus fontes.




Com o uso de classes, você tem a possibilidade de reduzir as linhas código do seu fonte, evitar repetição de funções e centralizar uma atividade específica em um único arquivo.
Para ficar melhor exemplificado, vou passar à vocês uma forma que utilizei para simplificar/facilitar o processo de envio de emails (worflow) do Protheus. Anteriormente em nossa base havia um fonte onde possuía uma função de usuário que era chamada sempre que fosse necessário enviar os e-mails, ou seja,  em meio ao meu código fonte - caso eu precisasse enviar e-mail - chamaria a função desta forma:
user function envioMail(cMsg, cDe, cPara, cAssunto)

local cCc := ""
local cBcc := ""
local cAnexo := ""
local cTitulo := ""

cEnvMail := u_EnvMail(  cDe,;      //cDe - origem
   cPara,;    //cPara
   cCc,;    //cCc
   cBcc,;     //cBCC
   cAssunto,; //cTitulo
   cAssunto,; //cAssunto
   cAnexo,;   //cAnexo
   cMsg)    //cMsg

return

A função envioMail() é do fonte que estou desenvolvendo e para enviar o e-mail, preciso "chamar" a outra função (outro fonte/arquivo) chamado u_EnvMail() definindo todos os parâmetros.
Tudo bem! Desta forma é funcional, mas nosso objetivo é tornar o acesso a atividade de envio de e-mail através de uma classe, onde poderíamos - futuramente - trabalhar com objetos e configurar outras funções para nossa classe.

Vamos aos códigos!

Primeiramente vamos adicionar um novo arquivo ao projeto e salvá-lo com o nome ClassMail e adicionaremos o código abaixo:

class ClassMail

      //dados de conexão com o server
      data cServer    //Nome do servidor de envio de e-mail
      data cEmail     //Conta a ser utilizada no envio de e-mail
      data cEmailA    //Usuário para autenticação no servidor de e-mail
      data cPass      //Senha para autenticação no servidor de e-mail
      data lAuth      //Verifica se servidor necessita de autenticação
      data lResulConn //Flag de conexão com o servidor
      data lResulSend //Flag de sucesso de envio de e-mail
      data cError     //Mensagem de erro

      //variáveis para envio do email
      data cDe      //E-mail de origem
      data cPara    //E-mail de destino
      data cCc      //E-mail de cópia
      data cBcc     //E-mail de cópia oculta
      data cTitulo  //Título do e-mail
      data cAssunto //Assunto do e-mail
      data cAnexo   //Arquivo que será anexado
      data cMsg     //Mensagem/Conteúdo do e-mail

      //metodo construtor da classe com as variáveis que são enviadas por parâmetro
      method new(cDe, cPara, cCc, cBcc, cTitulo, cAssunto, cAnexo, cMsg) CONSTRUCTOR

      //método de validação dos dados recebidos
      method valDados()

      //método de validação de conexão com o servidor de envio de e-mail
      method valConn()

      //método responsável para efetuar o envio do e-mail
      method sendMail()

endClass
Nesse primeiro ponto, temos a definição das variáveis e métodos de nossa classe. Temos as variáveis responsáveis para efetuar, autorizar e obter o retorno de conexão com o servidor de e-mails e as variáveis que receberemos por parâmetro através do método construtor da nossa classe. depois temos os métodos da classe que utilizaremos durante a execução como validação de dados, conexão e o envio de e-mail.

Em nosso método construtor, vamos receber os dados e atribuir as variáveis da nossa classe. Observe que, quando for referenciar uma variável da classe deve-se utilizar o '::' na frente dela, ou seja, seria algo como ::cEmail. É importante também adicionar ao final do método o nome da classe.

Os métodos podem e devem obter um retorno, somente o tipo do conteúdo/variável que será retornado dependendo da sua aplicação. Veja que em nosso método construtor, não há necessidade retorno, então inserimos a palavra reservada self.

method new(cDe, cPara, cCc, cBcc, cTitulo, cAssunto, cAnexo, cMsg) class ClassMail

 ::cDe      := cDe
 ::cPara    := cPara
 ::cCc      := cCc
 ::cBcc     := cBcc
 ::cTitulo  := cTitulo
 ::cAssunto := cAssunto
 ::cAnexo   := cAnexo
 ::cMsg     := cMsg

return self

Agora vamos aplicar a validação dos dados principais de nossa classe. através do método valDados() Não é possível enviar um e-mail sem um e-mail de origem, destino e assunto - ou qualquer outro campo que você desejar.

method valDados() class ClassMail

local lRet := .T.

if empty(::cDe) .or. empty(::cPara) .or. empty(::cAssunto)
 msgAlert("Os campos 'De','Para' ou 'Assunto' devem ser preenchidos corretamente!","ERRO")
 lRet := .F.
endIf

return lRet

Precisamos agora do método responsável por efetuar a conexão com o servidor de e-mails e, para isso, vamos definir outro método nomeado valConn().

method valConn() class ClassMail

local lRet := .T.

::cServer := allTrim(getMv("MV_RELSERV")) //Nome do servidor de envio de e-mail
::cEmail  := allTrim(getMv("MV_RELACNT")) //Conta a ser utilizada no envio de e-mail
::cEmailA := allTrim(getMv("MV_RELAUSR")) //Usuário para autenticação no servidor de e-mail
::cPass   := allTrim(getMv("MV_RELAPSW")) //Senha para autenticação no servidor de e-mail
::lAuth   := getMv("MV_RELAUTH") //Verifica se servidor necessita de autenticação

if (empty(::cServer) .or. empty(::cEmail) .or. empty(::cEmailA) .or. empty(::cPass)) .and. ::valDados()
 msgAlert("Não foi possível obter os dados dos parâmetros de envio de e-mail do Protheus!","Erro envio de e-mail")
 lRet := .F.
else
 //Efetua a conexão com o servidor
 CONNECT SMTP SERVER ::cServer ACCOUNT ::cEmail PASSWORD ::cPass RESULT ::lResulConn

 //se necessita a autenticação do servidor
 if ::lAuth
  lOk := MailAuth(::cEmailA, ::cPass)
  if !lOk
   lOk := QAGetMail()
  endIf
 endIf

 if !::lResulConn
  get MAIL ERROR ::cError
  msgAlert("Falha na conexão: " + ::cError,"Erro - Problema de conexão")
  lRet := .F.
 endIf
endIf

return lRet

Depois desses métodos desenvolvidos precisamos fazer o envio do e-mail. Então o método sendMail() fará isso para nós.

method sendMail() class ClassMail

//se as validações (conexão e dados) estiverem ok. Efetua o envio do e-mail
if ::valConn() .and. ::valDados()

 SEND MAIL from ::cDe;
  to         ::cPara;
  CC         ::cCc;
  BCC        ::cBcc;
  SUBJECT    ::cAssunto;
  BODY       ::cMsg;
  ATTACHMENT allTrim(::cAnexo);
  RESULT     ::lResulSend

 get MAIL ERROR ::cError

 if !::lResulSend
  msgAlert("Falha no envio do e-mail: " + ::cError,"Erro - E-mail não enviado")
 endif

 DISCONNECT SMTP SERVER
else
 msgInfo("Email não enviado!")
endIf

return self

Bom, com o intuito de evitar tentativa de conexão desnecessária, condicionaremos essa ação ao retorno dos métodos valConn() e valDados() - Note que, assim como as variáveis, os métodos devem ser tratados dentro da classe com '::'.

Assim que testarmos o nosso fonte e compilarmos, podemos substituir a chamada na função original onde precisamo enviar o email. Então ele ficará modificado da seguinte forma:

user function envioMail(cMsg, cDe, cPara, cAssunto)

local cCc := ""
local cBcc := ""
local cAnexo := ""
local cTitulo := ""

objMail := ClassMail():new(cDe, cPara, cCc, cBcc, cTitulo, cAssunto, cAnexo, cMsg)
objMail:sendMail()

return

Em nossa função de usuário teremos um objeto - objMail - que será uma instancia da nossa classe ClassMail() e passará em seu método construtor as informações para o envio do e-mail. Após isso, basta chamar o método sendMail(). 

Com o desenvolvimento de classes podemos incrementar nossas possibilidades de uso de funções e aplicações específicas do sistema, tornando mais fácil o desenvolvimento e manutenção do fonte. Claro que aqui foi dado um exemplo simples, mas é possível adicionar mais funcionalidades de acordo com o que precisar.

Até mais!

;)