ABAP Oberdan

March 20, 2017 | Author: Oberdan Oliveira Fonseca | Category: N/A
Share Embed Donate


Short Description

Download ABAP Oberdan...

Description

ABAP 101 Sua porta de entrada para o mundo ABAP. Pular para o conteúdo 

INÍCIO



SOBRE O ABAP 101



SOBRE O AUTOR

← Criando o Programa ABAP Hello World Criando um Programa Calculadora – Versão Report →

Criando Uma Transação de Report Publicado em setembro 7, 2007 | 1 comentário

PROBLEMA Criar uma transação e associar o programa ZHELLO.

SOLUÇÃO Vá até o Object Navigator (SE80). Na área de navegação, escolha o tipo de objeto Program. Digite o nome do programa ZHELLO e tecle enter. O programa ZHELLO aparacerá logo abaixo da área de navegação. Clique com o botão direito e acesse Create -> Transaction:

Escolha um nome para a transação: ZTHELLO e escolha o tipo de transaçãoProgram and Selection Screen (Report Transaction):

Entre com o nome do programa, marcar todas as opções de GUI Support e salve:

Nota: Para finalizar a gravação, é necessário associar um pacote (***1) e uma change request. (***2)

EXECUÇÃO E TESTE Para testar, abra uma nova sessão (Menu: System -> Create Session) e na área de comando, entre com o nome da nova transação e tecle Enter:

DISCUSSÃO Existem diversos tipos de programas em ABAP, o programa que criamos é um relatório. Devemos escolher o tipo correcto de programa, caso contrário a transação não funcionará. O número da screen do relatório é 1000, valor padrão para programas do tipo report. É possível associar uma variante padrão, ou seja, quando a transação foi chamada, o programa será executado usando a variante especificada. As opções de GUI Support, ativa o suporte da transação aos 3 tipos de SAP GUI, para HTML, Java e Windows.

Criando o Programa ABAP Hello World Publicado em agosto 30, 2007 | 5 Comentários

PROBLEMA Criar um programa ABAP e imprimir na tela “Hello World!”.

SOLUÇÃO Vá até o Object Navigator (SE80). Na área de navegação, escolha o tipo de objeto Program. Digite o nome do programa ZHELLO e tecle enter.

Se não existir nenhum programa com o nome escolhido, será aberto uma nova janela perguntando se deseja criar.

Se você escolher a opção Yes, para criar um novo programa, outra janela é aberta. Tire o flag “Whit TOP-Include” e confirme. Será aberto mais outr janela para escolher os atributos do novo programa.

Entre com uma descrição e escolha o tipo de programa executável. Salve o programa em uma request e inclua o o seguinte código no programa: Write 'Hello World!'.

Salve (Ctrl-S), ative (Shift-F8), e se não houver nenhum erro, execute o programa (F8).

DISCUSSÃO Esse é o programa mais simples em ABAP. Todos os objetos criados pelo usuário começam com Z ou Y (comumente usado para programas de sistema). O comando write, é responsável por imprimir na saída do programa. Para ver maiores detalhes do comando, posicione o cursor sobre o comando e pressione “F1”. Você também pode usar a transação SE38 para criar e modificar seus programas.

***1

Criando Packages Publicado em agosto 29, 2007 | 1 comentário

PROBLEMA Criar um package (pacote) ZP_ABAP101 para organizar os programas desenvolvidos do ABAP 101.

SOLUÇÃO Vá até o Object Navigator (SE80). Na área de navegação, escolha o tipo de objeto Package. Digite o nome do package ZP_ABAP101 e tecle enter.

Se não existir nenhum pacote com o nome escolhido, será aberto uma nova janela perguntando se deseja criar.

Se você escolher a opção de criar um novo pacote, outra janela é aberta para escolher os atributos do novo pacote. Escolha os atributos e salve o pacote em uma request.

DISCUSSÃO Os objetos SAP são organizados em packages ou pacotes. Geralmente, os projetos possuem um pacote por módulo (FI, MM, SD etc.). Também podemos ter vários pacotes para o mesmo módulo ou qualquer outro critério decidido pelo gerente ou lider do projeto. Por exemplo, na criação de um novo ambiente, pode-se escolher quais pacotes farão parte do novo ambiente. Ou seja, os packages são uma subdivisão lógica dos objetos dentro do repositório de objetos no sistema. O package o qual um objeto pertence, não tem a menor influência em seu funcionamento, sendo assim, um programa do módulo de FI, pode ser gravado em um pacote do módulo de MM por engano, sem que isso afete o funcionamento do programa.

Os atributos de um package podem ser: Application Component – Determina qual application component dentro da hierarquia de componentes do repositóri, o pacote fará parte. Software Component – Para desenvolvimentos customizados (que comecem com a letra Z), deve ser sempre “HOME”. Transport Layer – Determina se o package pode ser transportado para outro ambiente e define qual é esse ambiente. Package Type – Você pode escolher entre: 

Standard Package: pode conter objetos do repositório e outros packages;



Main Package: contém apenas outros packages;



Structure Package: contém apenas outros packages to tipo Main Package.

VEJA TAMBÉM 

Criando Change Requests de Workbench

***2 Criando Change Requests de Workbench Publicado em agosto 28, 2007 | 3 Comentários

PROBLEMA Criar uma change request para ser usada por novos programas.

SOLUÇÃO Acessar o Transport Organizer (SE09 ou SE10):

Clicar no botão Create ou F6, e escolher Workbench request:

Atributos da change request:

Change request criada:

DISCUSSÃO Os sistemas SAP são geralmente separados em um ambiente de desenvolvimento, outro de Qualidade e outro de Produção. Esses ambientes são totalmente independentes, na maior parte dos casos instalados em máquinas diferentes. Para se transportar um objeto do repositório de um ambiente para o outro, usase as chamadas change requests. No dia-a-dia do desenvolvedor ABAP, as change requests mais usadas podem ser do tipo “Customazing” ou “Workbench”. As change requests do tipo Customazing são reservadas para transportar conteúdo de tabelas do tipo customazing. Essas tabelas contém informações de configuração dos módulos funcionais (FI, MM, SD etc.) ou configurações do sistema. Já as chage requests do tipo Workbench são para os outros tipos de objetos do repositório, como packages, tabelas transparentes e, no nosso problema, programas. Os objetos são criados ou modificados no ambiente de desenvolvimento. Após os devidos testes, a request deve ser liberada (released) e o time que cuida da infraestrutura do sistema SAP, também conhecido como Basis, é responsável por efetuar o transporte para o sistema subsequente.

VEJA TAMBÉM 

Criando Change Request na Criação de um Objeto

Criando um Programa Calculadora – Versão Report Publicado em setembro 8, 2007 | 2 Comentários

PROBLEMA Criar um programa ABAP que receba dois valores digitados pelo usuário e execute as quatro operações (adição, subtração, divisão e multiplicação) entre os dois valores.

SOLUÇÃO Passo 1: Criar um programa executável chamado ZRCALC. Passo 2: Definir os dois parâmetros nos quais o usuário irá utilizar para digitar os valores para o cálculo e também outro para indicar a operação desejada.

Passo 3: Definir uma variável local do tipo package, com duas casas decimais, para atribuir o valor calculado.

Passo 4: Definir uma estrutura CASE para escolher a operação escolhida pelo usuário.

Passo 5: Imprima o valor na saída do relatório.

Passo 6 (opcional): Inclua uma verificação se a operação escolhida é válida e se escolhido a divisão, verificar se o valor 2 é diferente de zero.

A listagem completa do programa, você encontra na seção Anexos.

EXECUÇÃO E TESTE Execute o programa (F8) e entre os seguintes na tela de seleção:

Execute o relátorio (F8) e você deverá obter uma saída parecida com a descrita abaixo:

Não esqueça de testar também o caso de uma operação inválida e um caso de divisão por zero.

DISCUSSÃO Nesse simples programa já vemos uma séria de elementos comuns em programa ABAP. A primeira tela do programa é chamada de Tela de Seleção (Selection Screen), onde o usuário entra com os parâmetros que serão utilizados no relatório. Um dos comandos usados para desenhar a tela de seleção é a instrução PARAMETERS. Usamos a forma mais simples, ainda há muitas outras possibilidades, que discutiremos mais a frente. Declaramos variáveis com o comando DATA, indicando o nome da variável e o tipo. No nosso programa, usamos somente tipos primitivos, mas as possibilidades são ilimitadas, já que o ABAP Objects é fortemente tipado. Os tipos padrão usados no ABAP Object são: Tipos completos, sem necessidade de complemento:



D – Data, no formato AAAAMMDD, com tamanho fixo de 8;



T – Tempo, no formato HHMMSS, com tamanho fixo de 8;



I – Inteiro, tamanho fixo de 4;



F – Número de ponto flutuante, tamanho fixo de 8;



STRING – Cadeia de caracteres, sem tamanho fixo;



XSTRING – Cadeia de caracteres (Hexadecimal), sem tamanho fixo;

Tipos incompletos:



C – Caracter string, podendo ter um complemento, por exemplo a intrução “DATA vl_var(4) TYPE C.“;



N – Caracter numérico, com características de caracter e número;



X – Seqüência de bytes (Hexadecimal);



P – Package.

Para imprimir o valor na tela, usamos a instrução WRITE.

Usamos duas estruturas de decisão, a IF/ELSEIF/ELSE/ENDIF para verificar a operação escolhia e se há divisão por zero e CASE para escolher a operação. Essa verificação de divisão por zero é necessária para evitar um possível erro em tempo de execução no caso de uma divisão por zero. Poderíamos também usar Exceptions, mas discutiremos no futuro. No caso de uma operação inválida, também poderíamos usar a seguinte construção no lugar o IF: CASE p_op. … WHEN OTHERS. WRITE: ‘No valid operation'(iop). ENDCASE. A opção OTHERS significa que se nenhuma das alternativas do WHEN foi satisfeita, o opção OTHERS é executada. Então, se a operação escolhida não foi válida, o WHEN OTHERS é executado e a mensagem de erro é impressa na saída do programa. A segunda tela, é onde é apresentado a saída do programa, comandos WRITE.

Modelo de Dados do SAP Flight Model Publicado em setembro 21, 2007 | Comentários desativadosem Modelo de Dados do SAP Flight Model

O SAP Flight Model é o modelo de dados usado em um sistema muito simplificado de controle de reservas de vôos. Esse modelo é utilizado em quase todos os exercícios e demonstrações do treinamento ABAP Workbench. Ele está disponível em todas as implementações e por isso é também usado em todos os exemplos do ABAP 101, salvo algum caso específico onde será necessário o uso de outras tabelas que não as do SAP Flight Model (SFM).

O SFM é composto por 4 tabelas transparentes, SCARR, SPFLI, SFLIGHT e SBOOK, com o seguinte relacionamento:

SCARR – Contém as informações das companhias aéreas, como código, nome etc. SPFLI – Contém as rotas ou conecções oferecidas pelas companhias aéreas da tabela SCARR. SFLIGHT – Contém os vôos que servem as rotas ou conecções da tabela SPFLI. SBOOK – Contém as reservas para os vôos disponíveis na tabela SFLIGHT. Nas várias versões de Application Server (WAS), incluindo minisap e Linux testdriver, essas tabelas já vem preenchidas com alguns dados, facilitando os exercícios.

Quando Usar Type, Like e Begin Of? Publicado em setembro 25, 2007 | 1 comentário

A principal tarefa de qualquer programa, independente da linguagem, é trabalhar com dados. Cada linguagem possui as suas formas de criar e manipulá-los. ABAP utiliza tipos como base para criação dos dados que o programa manipulará.

Para criar algum objeto de dado no ABAP, você utiliza o comando DATA: DATA v_texto(20) TYPE c VALUE ‘Objeto de Dados’. Nessa declaração, é criado um objeto de dado (uma variável) v_texto, de comprimento 20 caracteres, com valor inicial “Objeto de Dados”. Da mesma maneira para criar variáveis para operações matemáticas. Nesse caso, criamos variáveis do tipo numéricas, como no exemplo da listagem 1. A saída desse programa será:

Além dos tipos fundamentais da linguagem ABAP (veja mais na discussão dessepost), podemos criar qualquer tipo de estrutura de dados, como por exemplo, workareas (área de trabalho) e internal tables (tabelas internas). Veja a listagem 2. Esse programa irá calcular a diferença entre os campos SFLIGHT-SEATSMAX e SFLIGHT-SEATSOCC, de todo as linhas da tabela SFLIGHT. Como solução, criamos uma tabela interna que contenha as chaves da tabela

SFLIGHT e também um o campo DIFF, quem contém a diferênça. Depois de todas as diferênças calculadas, imprimimos o resultado na saída do programa:

Na listagem 2, temos o uso da intrução TYPES, que é usada para criar tipos locais. Esses tipos somente podem ser utilizados no program no qual ele foi declarado, nesse caso ZTYPE1. Como tipos locais, temos ty_s_sflight_dif, descreve uma estrutura de dados ety_t_sflight_dif uma tabela interna com a estrutura de ty_s_sflight_dif. Para declararmos um tipo estruturado local, usando BEGIN OF / END OF. Já os tipos globais podem ser provenientes do dicionário de dados do SAP. No programa ZTYPE1, usamos alguns tipos globais, como a tabela SFLIGH e alguns de seus campos, como sflight-carrid, sflight-connid etc. Os tipos globais podem ser usados (DATA… TYPE….) em qualquer programa o sistema, não há necessidade de nenhuma declaração no programa.

Quando usamos o TYPE com uma tabela transparente (tabela de banco de dados), o objeto de dado declarado será uma workarea, com a estrutura da tabela transparente. Por outro lado, quando usamos TYPE TABLE OF, estamos declarando uma tabela interna, com estrutura da tabela transparente. Veja essa parte do programa ZTYPE1. … DATA: w_sflight TYPE sflight,mas t_sflight TYPE TABLE OF sflight, … Temos uma workarea w_sflight e uma internal table t_sflight, com estrutura da tabela transparente SFLIGHT. Por último, temos a seguinte declaração de variável: DATA: v_diff LIKE w_sflight_dif-diff. O LIKE indica que o objeto de dado declarado possui o mesmo tipo de outro objeto de dado já declarado, podendo este ser local ou global. No caso acima, a variável v_dif, possui o mesmo tipo do campo da workareaw_sflight_dif-dif, ou seja, sflight-seatsmax. Agora já sabemos quando usar TYPE, LIKE e BEGIN OF.

Você tem medo de ensinar? Publicado em janeiro 11, 2008 | 2 Comentários

Trabalho com projetos SAP, especificamente ABAP, há cerca de 7 anos. Uma prática muito comum é a figura do “sombra”. O sombra é aquele consultor júnior (geramente no seu primeiro projeto), que é alocado a um projeto, sem cobrar as suas horas do cliente. Com isso, a sua consultoria consegue treinar um novo consultor em situações reais da rotina de um projeto.Isso pode ser ótimo para o sombra, pois esse treinamento on-the-job é uma maneira de dar a ele alguma experiência sem a responsabilidade de um consultor cobrado do cliente.

No entanto, para o consultor experiênte, isso representa um aumento de trabalho, pois além do trabalho normal como consultor, ele precisa explicar tudo ao sombra. Eu nunca tive um sombra para ajudar, mas já coordenei uma equipe de umas 10 pessoas totalmente inexperiêntes, onde tive de ensinar muitos macetes para que as coisas andassem no prazo determinado. Nessa semana, conversando com um consultor que trabalha comigo, ele revelou-me que já criou a maior confusão em um projeto por negar-se a ensiar um outro consultor menos experiênte. De acordo com ele, não havia sido contratado para ensinar. O seu outro argumento foi que ele não queria que o mercado SAP crescesse muito e que ele tinha medo que o seu salário diminuisse devido ao aumento do número de consultores. Vi comentário semelhante a esse no dieblinkenlights.com. De acordo com o autor, falando sobre a linguagem de programação Phyton, disse: Eu a considero uma vantagem competitiva e se você, meu leitor, não souber do que se trata, melhor para mim. Nesse projeto onde eu fui o coordenador, tive a satisfação de acompanhar o desenvolvimento profissional de alguns deles. Hoje, ainda converso com eles pelo MSN e fico orgulhoso quando leio “fulano @ USA” no nickname, indicando que está em algum projeto internacional. Por que esse medo de ensinar? Então quer dizer que se eu ensinar outras pessoas, corro risco de “saturar” o mercado de profissionais e diminuir a minha “empregabilidade”? Esse medo expressa uma mentalidade limitada. Aprendi que o meu sucesso não depende de uma ferramenta, linguagem ou plataforma. Essas vão e vêm a todo momento. O que relamente conta é qual é o seu comportamento profissional, ou seja, vontade de aprender coisas novas e procurar novos conhecimentos para se manter sempre a frente. Eu realmente adoro ensinar e sou totalmente seguro da minha empregabilidade, pois ela não depende 100% da ferramenta ou linguagem de programação que uso. Tanto que hoje, além do meu trabalho como coordenador

de desenvolvimento, sou intrutor ABAP. A vontade de ensinar, abriu-me novas portas além da consultoria. Cuidado se você pensa como meu amigo, provavelmente logo será ultrapassado por esse consultor júnior que está do seu lado, afinal de contas, para o meu amigo, a sua única preocupação é: … se meus concorrentes lerem e aprendam alguma coisa. (Texto originalmente publicado no Papel no Vaso.)

Material Inicial Sobre Orientação a Objetos Publicado em janeiro 25, 2008 | 4 Comentários

Aprender Orientação a Objeto (OO) é mudar a sua forma de resolver problemas. OO não substitui a programação procedural, mas fornece um ferramental poderoso para comunicar e solucionar problemas complexos. Não quero aqui explicar extensivamente OO, mas apresentar alguns materiais que pesquisei na internet e que julgo ser apropriados como introdução ao assunto. Sugiro o capítulo 1 do livro Think in Java ele dá uma boa base sobre OO. Esse livro é um clássico no mundo Java, pricipalmente por ser distribuido gratuitamente em PDF. O Wikipedia também pode ser uma boa fonte. Você vai ver que tem várias fontes na internet e muito livros sobre o assunto. Para aprender OO eu li muito e principalmente treinei. A chave de OO é usar, usar e usar. Não tem mágica. Nesse estudo inicial, atente para os conceitos de classe, instância, atributos, métodos e mensagens. Dependendo da sua experiência com programação, herança pode ser aprendida sem muito esforço. Já polimorfismo é mais complicado e demanda um pouco mais de esforço para entender.

Não há uma explicação final para os conceitos de orientação a objeto. Você terá que estudar várias fontes para chegar as duas próprias conclusões.

Porque todo ABAP deveria estudar Fiori (também) BY FÁBIO PAGOTI · OCTOBER 20, 2015

Compartilhe!

Alguns meses atrás publicamos aqui no ABAP101 alguns artigos comentando a importância de algumas tecnologias e ferramentas na lista de skills que um (bom e atualizado) desenvolvedor ABAP deveria ter. Para citar tais artigos, temos o post “Porque todo ABAPer deveria começar a aprender UI5 (SAPUI5/OpenUI5) já“, escrito por mim mesmo (e plegiado por um mané, mas isso é outra história) e os artigos “Porque todo ABAP deveria estudar HANA” e “BRFplus: a ferramenta que

todo profissional SAP deve conhecer“, escritos pelo meu amigo Thiago Ourives que agora nos lê diretamente do futuro. Não é preciso muita visão para notar que tal lista de exigências só cresce. É fato que algumas exigências estrapolam para coisas não-relacionadas a área de atuação normal de um ABAP, como já citado no polêmico post “Verdade Seja Dita – “Oportunidades ABAP ALL”. A ideia deste post é abordar a importância do Fiori, que na minha humilde opinião, se encaixaSIM na lista de skills que um ABAP deve ter.

Mas o que é o Fiori? Google it. SCN it.

Justificativas Agora que você já sabe o que é o Fiori, gostaria de dar algumas justificativas para embasar a ideia de que isso é problema do ABAP.

No fundo, é Front End Fiori é famoso pela sua simplicidade (para o usuário), na experiência (de novo, para o usuário) e no foco do trabalho (para quem? Para o usuário). Para que o dito cujo tenha isso tudo, alguns tem que pagar algum preço. Para fazer uma aplicação responsiva, de bom gosto, que aplique as melhores práticas de acordo com o Fiori Design Guidelines é preciso algum conhecimento de desenvolvimento front end, obviamente incluindo UI5. E quem você acha que está mais perto em conhecer desenvolvimento na esfera SAP do que o desenvolvedor ABAP? Não vou entrar no mérito de “pessoas novas”, por exemplo desenvolvedores front end de outras tecnologias,

entrarem no mundo SAP – este tipo de discussão além de não ser o foco é simplificar demais o assunto. Fiori não é feito apenas de um front end feito em UI5. Mas isso passa sim por saber desenvolver aplicações. A diferença é que as aplicações agora tem um outro foco e são construídas de outra maneira. Apesar de isso soar como uma péssima notícia para quem nem WDA aprendeu direito, existe um lado bom da moeda. Se você já desenvolveu uma aplicação com um parameter você já tem experiência em desenolvimento front end. Sim, uma experiência útil ainda porém tosca esteticamente e cada dia mais próxima de virar obsoleta se considerar o rumo que as coisas caminham.

Gateway O Fiori funciona com o Gateway por trás dos panos. E não só nos aplicativos! Os próprios serviços base para o Fiori Launchpad que exportam por exemplo os catálogos do usuário, foram criados no Gateway. Entendendo isso é possível se virar muito bem na hora de fazer muito troubleshooting. Além disso, a principal transação do Gateway começa com as letras SE (SEGW). Se isso não soa como um argumento válido para justificar a relação com desenvolvedores ABAP, os projetos criados nesta transação são feitos usando o dicionário, funções, BAPIs e código totalmente customizado. Se você achava que poderia surgir um novo tipo de profissional chamado de “Fiori” que era totalmente segregado do mundo ABAP você …

Errou do faustão

… Afinal.. se houvesse mesmo este perfil profissional novo entitulado “Fiori”, ele deveria conhecer Gateway.. e conhecer Gateway passa por conhecer ABAP (e REST, diga-se de passagem). Logo, é mais fácil ser um ABAP que vai lá e aprende. 

Mas quantos ABAPers sabem Gateway?



Quantos ABAPers hoje conhecem UI5?



Qual a proporção de ABAPers que sabem o que é REST/oData?



Quantos conhecem os 3 itens acima juntos?

(Ahh… vamos ignorar o fato de mais da metade das aplicações Fiori requerem conhecimentos em HANA neste item) Hoje, a minha sensação é que a minoria dos profissionais tem tal perfil. E não estou buscando culpados. Estou apenas dizendo o que sinto lendo o que vejo e ouvindo o que escuto. E qual a solução? Resumo tomando emprestada parte do comentário fantástico do Custódio escrito recentemente no ABAPZombie: “(…) Pra isso a solucao eh simples: aprende fidumegua! Ou voce (empresa) contrata alguem que sabe, ou alguem que queira aprender. E fim.” (Custódio, em comentário no ABAPZombie)

Ritmo de crescimento de aplicativos Uma maneira relativamente confiável de se verificar o número de aplicações standard do Fiori é consultar o Fiori Apps Library e clicar em “All Apps”. No momento que este post é escrito, dia 20 de Outubro de 2015, há 602 aplicações nesta lista. É verdade que há aplicações

“duplicadas” para produtos diferentes mas não deixa de ser 602 aplicações. Pode não parecer muito talvez, mas considere que o Fiori tornou-se gratuito em 3 de Junho de 2013 e que até o final daquele ano mal havia documentação de qualidade e detalhada sobre Fiori. Se considerar os dias úteis que se passaram desde então, sem incluir feriado algum, a SAP entrega 0,97 apps por dia! É uma aplicação standard nova por dia! Eu acho isso muito… acho o ritmo que a SAP está empregando absurdamente frenético. Destas 602 aplicações, considere o fato de haver quase 150 que demandam o SAP Simple Finance. Considere agora que o Simple Logistics está quase saindo! Eu sou capaz de apostar que ainda terminaremos o ano de 2015 com mais de 800 aplicações. E faço uma projeção para que haja 1500 no final de 2016 (o que seria dobrar o número em 1 ano). Um dos principais motivos que me levam a crer nisso é a adoção do Fiori e dos novos recursos inseridos no UI5 1.30, como os controles de Semantic Page. Algumas coisas que já li sobre o NW 7.5 me levam a crer que a criação de serviços no Gateway também tendem a ser simplificadas… mas estas mudanças são ainda nebulosas para mim. E pensar que tem consultoria buscando gente para implantar (e não implementar) 3 ou 4 apps como parte de um projeto de meses!

Referências bibliográfica Apesar de ainda não ter lido o livro do Maurício “ABAP: O guia de sobrevivência do profissional moderno“, vale a pena mencionar o que o livro aborda no capítulo 8. Não li (ainda) mas já recomendo!

Enhancements Já fez algum enhancement na vida? User exit.. manja? Uma vez que o usuário use as aplicações Fiori (como já estão usando) … você pretende encontrar um PERFORM no meio de um código Javascript? I hope not. E por quê? As aplicações Fiori possuem pontos de enhancement também. A forma de implementação muda – exige conhecimentos ferramentais como alguns recursos do HANA, sólidos conhecimentos em UI5 e Javascript e orientação a objetos por conta do Gateway para citar o mínimo.

HANA e HCP Veja o vídeo abaixo, reflita e compare o que é mostrado com o tipo de desenvolvimento ABAP que estamos acostumados, onde consultorias vendem relatórios ALV como sendo o estado da arte.

http://abap101.com/2015/10/20/porque-todo-abap-deveria-estudar-fioritambem/

Em suma Se você quer fazer umas brincadeiras desta como visto acima, não ignore Fiori. E não ignorar Fiori é aprender muita coisa interessante de antemão e ao mesmo tempo.

Porque todo ABAPer deveria começar a aprender UI5 (SAPUI5/OpenUI5) já

BY FÁBIO PAGOTI · FEBRUARY 26, 2015

Compartilhe!

Passou o carnaval! Feliz ano novo! O ABAP101 é um site que mesmo quando um pouco parado, me surpreende. O site vai completar 8 anos em 2015. Isso mesmo, 8 anos. Uma das coisas que mais me impressiona é como até os posts mais antigos do site escritos pelo Furlan ainda tem uma quantidade imensa de acessos. Como os ensinamentos de como procurar e implementar BAdI eentendendo o For All Entries ainda são tão atuais, não é mesmo? Sem falar no vídeo de instalação do Minisap que faz com que praticamente a qualquer hora do dia alguém esteja vendo o ABAP101 mundo afora. Hoje notei que uma das páginas que mais me deu trabalho e satisfação em escrever (a famosa “MATRIZ DE CONHECIMENTO – ABAP JÚNIOR, PLENO E SÊNIOR“) igualou-se em números de acessos de uma das páginas mais simples mas que o pessoal mais dá bola (uma pesquisa salarial). Quem sabe isso seja um indício que algumas pessoas estão se importando mais com o conhecimento do que o salário. Ou que pelo menos entendam que o salário é uma consequência do conhecimento. Apesar de tantos posts serem úteis até hoje, a cada dia que passa os profissionais ABAP deveriam estar mais interessados (ou pelo menos mais preocupados) em aprender algo realmente novo e que cedo ou tarde pode vir a fazer parte do seu dia a dia. O típico conteúdo que o ABAP101 ainda não explora e que o pouco disponível está perdido em blogs na SCN ou repositórios pequenos do GitHub. Por exemplo: UI5. Atualmente na nossa matriz de conhecimento UI5 é marcado ainda como um conhecimento extra, que nem um sênior deveria obrigatoriamente ter. Ainda.

Matriz de Conhecimento – 26/02/2015

UI5 Se você atua com desenvolvimento ABAP hoje você certamente não precisa saber como criar aplicações em UI5. Todavia, certamente você já deveria saber o que o UI5 é. Caso você não saiba ainda o que é UI5 (um nome mais genérico para SAPUI5 ou OpenUI5) é sinal que você não abre a home page da SCN há mais de 1 ano. UI5 é uma biblioteca javascript para criação de aplicações usando MVC criada pela SAP. Quando falamos em UI5 estamos falando de desenvolvimento front end. Grosseiramente falando, UI5 é um concorrente do Backbone.js, AngularJS, EmberJS, Dojo ou qualquer outra biblioteca elencada na Wikipedia ou no TodoMVC.com. Grande parte dos novos produtos da SAP não são mais feitos em reports, module pools, BSPs ou Web Dynpros (apesar do último ainda ser usado pela SAP em novos desenvolvimentos). Boa parte do que a SAP desenvolve hoje em dia é feito em UI5 na parte do

front end. Se você já ouviu falar em alguns nomes como Gateway, SUP, Hana, Fiori ou HCP saiba que o UI5 está totalmente inserido nestes contextos. Você está avistando, ainda mesmo que de longe, uma oportunidade para ser desenvolvedor Hana? Então aprenda UI5 pois faz parte do que você vai precisar na sua caixa de ferramentas.

SAPUI5 vs OpenUI5 Como dito anteriormente, UI5 é um termo genérico que quer dizer ou SAPUI5 ou OpenUI5. Quando a SAP introduziu a biblioteca ela não tinha o código aberto e uma licença de uso mais restritiva (SAPUI5). Depois de muita pressão e discussão da comunidade de desenvolvedores, a SAP resolveu abrir o fonte da biblioteca e mudar a licença. Foi necessário então criar um outro nome (OpenUI5). O SAPUI5 ainda existe e tecnicamente é diferente do OpenUI5. A principal diferença técnica entre ambos hoje é o fato do SAPUI5 incluir uma biblioteca gráfica enquanto o OpenUI5 não. Veja exemplos de construção de gráficos no SAPUI5 no Hana Brasil. Felizmente para quem conhece Javascript fica fácil aprender a usar bibliotecas gráficas externas como D3 ou Raphael.

Web Dynpro vs UI5 Um argumento para não aprender UI5 é o seguinte: “O Web Dynpro fez 10 anos recentemente, eu ainda não aprendi, nunca usei nem precisei. Por que deveria aprender outra maneira de criar aplicações web?” Se você se encaixa no perfil acima, boa pergunta. O Web Dynpro não vingou como deveria. Outras tecnologias web da SAP não vingaram como deveriam. Mas pela primeira vez na história a SAP está deixando claro como a neve o que ela quer

para usabilidade, experiência do usuário e ergonomia das duas aplicações. Tem até curso sobre o assunto na OpenSAP. E hoje o foco é claro: back end em Hana e front end em Fiori (que é HTML5, que por sua vez é criado em UI5). O argumento do Web Dynpro é embasado, mas eu não apostaria que o mesmo vai acontecer. Em outras palavras, o UI5 vai vingar. Talvez nunca vire a melhor biblioteca de Javascript para MVC, mas com certeza vai vingar muito mais que o Web Dynpro pois para desenvolver muitas aplicações em Hana, telas em ABAP ou Web Dynpro não serão alternativas possíveis. Tirando o fato de HTML5 estar se tornando cada dia mais um padrão de facto.

O ABAP da próxima geração O desenvolvedor ABAP da próxima geração, que começou com o advento do Hana, deve ter conhecimentos em desenvolvimento Web. Saber programar em Web Dynpro não requer profundos conhecimentos Web. Por exemplo: padrões, protocolos, arquiteturas ou detalhes de navegadores. No caso do UI5, é diferente. É preciso entender HTML, CSS, Javascript e ser familiar ao jQuery para então começar a engatinhar no UI5. E é para este caminho que o ABAPer da próxima geração deve seguir. No livro “Next generation ABAP development / Rich Heilman, Thomas Jung. — 2nd ed.“, que foi escrito em 2011 (antes do UI5), dos 20 capítulos do livro 8 são de alguma forma relacionados a desenvolvimento Web (MVC, web services, Web Dynpro, BSP). Desde 2013 a SAP Press está pensando na terceira edição do livro, que sinceramente não sei o andamento atual. Porém, aposto que terá algo de UI5 além de falar da integração ABAP/Hana. Pelo menos o livro “ABAP to the Future / Paul Hardy” já aborda UI5. E se ainda não está convencido, já há um livro oficial da SAP Press exclusivo de UI5.

Então é agora que o ABAP vai morrer? Esta pergunta surge de tempos em tempos mas a resposta continua sendo não. Por isso se você está começando com ABAP fique tranquilo no que tange a estar aprendendo uma linguagem nova. O ABAP ainda é e será usado. A tendência é apenas que não se use ABAP tanto como hoje para criação da interface com usuário pois o mundo moderno roda no navegador num padrão aberto. Mas que fique claro que a cada dia o ABAP que se aprende hoje se torna mais insuficiente para as futuras demandas.

E se eu não aprender UI5? Quais minhas chances no mercado? Sou da opinião de que os ABAPers que ignorarem o UI5 e que irão tentar permanecer atualizados de alguma forma deverão se aprofundar na parte do back end. O que vai envolver bastante estudo também. Trocando em miúdos, você deverá aprender Hana, oData, Gateway, Core Data Services, integração ABAP/Hana e ainda sim… web services e javascript. Não dá para ficar 100% em um dos lados. O desenvolvedor ABAP típico talvez nem conheça os termos back end e front end apesar de ter estes dois papéis no seu dia a dia. O ABAPer é um desenvolvedor full stack com bons conhecimentos de bancos de dados por natureza. Quem vai contratar desenvolvedores ABAP do futuro não irá esperar menos que isso. Talvez haja a distinção desenvolvedor front end, back end nas contratações daqui um certo tempo… mas não ignore o fato da maior parte ofertas de trabalho serem de consultorias.

Consultorias precisam de pessoas que além de outras coisas, entendam da arquitetura dos sistemas que atuam e construam soluções técnicas em cima das mesmas. Ignorar UI5 significará não ser um consultor-desenvolvedor SAP completo. Assim como ignorar o Hana terá a mesma consequência.

Por onde começo a aprender UI5? Além da SCN, livros na SAP Press ditos anteriormente e o site oficial doOpenUI5.org, eu recomendo assistir apresentação que fiz no SAP Inside Track São Paulo, no final de 2014. Ela ensina como você hospedar sua aplicação UI5 no GitHub e torná-la pública.

http://abap101.com/2015/02/26/porque-todo-abaper-deveria-comecaraprender-ui5-sapui5openui5-ja/

Claro,

você

precisará

de

um

ambiente

de

desenvolvimento.

Felizmente para montar ele no mundo de desenvolvimento Web é necessário ter uma IDE qualquer (recomendo o Sublime Text ou Eclipse) e um servidor Web (Tomcat, MAMP, Node/Grunt, etc). Ou apenas você pode usar sites como oJSBin ou JSFiddle para começar a brincar com UI5. Bons estudos! Não deixe de comentar!

Porque todo ABAP deveria estudar HANA BY FÁBIO PAGOTI · MAY 21, 2015

Compartilhe!

No último final de semana concluí um curso de ABAP on HANA. Atualmente trabalho com HANA (e UI5) no meu dia a dia mas não de maneira integrada com o NetWeaver. Em outras palavras, trabalho com desenvolvimento nativo em HANA e não como ABAP numa empresa que tem o HANA. O curso foi ótimo e quero em breve criar alguns posts aqui no ABAP101 compartilhando esta experiência. Mas por hora nada melhor de convidar o meu instrutor do curso, Thiago Ourives, que além de ter se provado um profissional fora da caixa escreveu em poucos parágrafos porque todo ABAP deveria estudar HANA. Leia na integra!

(Por Thiago Ourives) Fazem alguns anos que a SAP tem uma meta de crescimento mínimo de 10% trimestral, o “double digit quarter”, o que atrai muitos acionistas no mundo todo, não apenas pelo crescimento da empresa e consequente valorização do papel, mas também pela clara e constante margem de lucro que a empresa respeita. Mas, como bons analíticos que são nossos colegas alemães, a SAP logo notou que em poucos anos não haveria mais espaço para essa meta de crescimento apenas no mercado tradicional de ERP… era necessário expandir para novos mercados, e as escolhas foram duas: Banco de Dados e Nuvem, e com o objetivo traçado, a SAP deu início ao desenvolvimento de seu banco de dados, à época chamado de NewDB, e saiu as compras para os demais itens necessários.

A sequência de aquisições da SAP é fantástica, e com certeza pode ser assunto de outro post, mas nesse momento, falemos do desenvolvimento de seu banco de dados (que não é apenas um banco de dados!): o SAP HANA.

O que é o SAP HANA? Uma das perguntas que mais ouço, em relação ao HANA, é se ele é um Banco de Dados. A resposta é afirmativa…. mas ao mesmo tempo, usar essa definição para o HANA, em alguns círculos, pode ser uma ofensa grave! É como dizer a um Arquiteto JAVA que ele trabalha com “aquela linguagem de fazer sites” ou a um consultor PI que ele só o trabalho dele é só arrastar quadradinhos. JAVA é mais que internet, PI é mais que os quadradinhos e HANA é muito mais que um Banco de Dados. O HANA é um conjunto de ferramentas da SAP, que envolve desde a seleção dos fabricantes dos chips, a parceira com a também alemã SUSE, o seu HANA Studio e suas ferramentas de de modelarem e extração de dados (SAP BO, SLT, DxC, etc.), o suporte a suas novas opções de programação, como UI5 e o HANA XS e, por último e não menos importante, é a construção de de seus novos Data Center e a nova parceria com a IBM, que possibilitam a venda do HANA como um serviço de Plataforma (PaaS).

SAP x HANA A SAP está apostando alto no HANA. Muito Alto. Tão alto que não está satisfeita apenas em ter sua plataforma servindo de base para seu principal produto, o ECC. Ela está apostando o próprio ECC e sua sólida liderança no mercado de ERP ao escolher re-escrever sua solução

utilizando o HANA como alicerce e visando o mercado de nuvem. O futuro da SAP é o HANA e depende do sucesso dessa ferramenta. Por consequência, o futuro de todo o ecossistema SAP e de seus profissionais depende de sua agilidade na adaptação a essa nova tecnologia.

Como consultor ABAP, por que devo me preocupar? Porque o SAP não vai mudar, ele já mudou. E o ABAP, assim como seu papel de atuação, também. A linguagem do ABAP está em constante evolução, e tem caminhado para se tornar um meio-campo ideal entre o HANA (como backend) e o UI5(como frontend), seja servindo como camada protetora ou como meio de seleção e organização do repositório HANA. O ABAP de nova geração não apenas sabe UI5, ele precisa ter conceitos de modelagem em HANA, programação orientada a conjuntos e Push-Down de código. Assim como conhecer as ferramentas de segurança e geração de serviços do Stack ABAP. Claro que o Stack ABAP segue existindo e durante muito tempo ainda teremos nossa base instalada que ainda usa o 4.6C, mas se formos pensar no médio prazo, a hora de se preparar é agora!

Como se preparar e aonde estão os recursos? Bom, esse é um assunto para outra postagem. Por hora quero agradecer a paciência de todos na leitura e dizer que estou a disposição para conversar e aprender sobre SAP e HANA com todos vocês. Grande Abraço! Thiago Ourives.

BRFplus: a ferramenta que todo profissional SAP deve conhecer BY FÁBIO PAGOTI · JUNE 3, 2015

Compartilhe!

Dias atrás publicamos o artigo Porque todo ABAP deveria estudar HANA, por Thiago Ourives, que despertou a curiosidade de muitos, principalmente no Facebook e LinkedIn. Para quem não leu o último texto o Thiago trabalha com ABAP há um tempão e é um dos pioneiros a trabalhar com ABAP e HANA no Brasil. Ele escreveu mais um post, agora relacionado a BRF+ (aka BRF Plus), tópico inédito aqui no blog. Se você nunca ouviu falar no BRF+ e acha que user exit é algo mega atual, reveja seus conceitos lendo este post. (Por Thiago Ourives)

Antes de explicar o que é o BRFplus, quero falar sobre possíveis soluções para um cenário bem conhecido no mundo SAP: Determinação de IVA. Existem, dentro do SAP, diversas formas de implementar a determinação do código de imposto e que irão permitir ao cliente chegar ao resultado desejado, eis algumas formas e suas vantagens e desvantagens:

Customizing É possível criar uma condição do tipo NAVS, relacionando uma série de parâmetros que costumam atender a maioria dos requisitos. É de fácil implementação, mas nem sempre fica transparente ao usuário como funcionam as regras e as telas de manutenção da NAVS não são muito amigáveis.

Exit’s em ABAP Em ABAP, é possível escrever o conjunto de regras que for preciso! Contudo, a manutenção envolve sempre a presença de um programador… e, dependendo da documentação que foi realizada, exige um certo tempo para que o programador entenda o que o código atual está fazendo antes de começar a alteração, fazendo com que uma simples regra nova demore muito a ser implementada.

Tabelas Z A vantagem de ter tabelas Z é ter algo desenhado de forma específica para o cliente, de simples manutenção e que pode atender as exceções necessárias. A desvantagem, entretanto, fica por conta do processo de mudança nas regras, que envolve transporte por request em todos os ambientes (DEV, QAS, PRD) bem como sua validação.

BRF+

O BRFplus, que hoje faz parte da licença NetWeaver, consegue juntar o a praticidade de uma condition NAVS, a nível de atenção de um código ABAP e a flexibilidade de uma tabela Z, somando a isso uma interface amigável e sem a necessidade de validação e transporte associado a requests. Como ele faz isso? É simples! O BRFplus é o motor de regras do SAP NetWeaver. Tem como função servir de repositório, de ferramenta de construção e de motor de execução de todas as regras standard da SAP, e, desde 2010, a SAP tem trabalhado para tornar ele também a ferramenta preferencial para manutenção de regras do cliente. Nessa ferramenta podemos criar aplicações específicas que fazem uso deDecision Tables, funções com programação visual lógica e amigável, possibilidade de validação e teste na própria ferramenta e facilidade de transporte das regras. Tudo isso sem a necessidade de ABAP, o BRFplus gera todo código ABAP que for necessário. Além disso, um dos objetivos do BRFplus é que o cliente possa assumir a manutenção das regras, através de uma interface em WebDynpro customizável e de fácil utilização. Grande abraço a todos!

MANDT – Campo mandante no SAP – Entendendo de uma vez por todas BY FÁBIO PAGOTI · JANUARY 13, 2014

Compartilhe!

Ainda me surpreendendo com a confusão que o campo mandante (MANDT ou client) gera em grande parte de pessoas que trabalham com SAP. O conceito é simples mas pelo fato de poder ser aplicado em diferentes circunstâncias, creio que muita gente não esteja 100% segura do que deveria saber sobre ele. Se quiser entender tudo sobre o MANDT continue lendo este post. Se você não faz ideia o que é este campo também leia pois ele está presente na grande maioria das tabelas do SAP.

Onde está o MANDT no SAP? MANDT na tela de login O primeiro contato que temos com o campo MANDT (ou client) é logo na tela de login do sistema. Como ele vem preenchido para nós, pouco nos preocupamos com ele.

Em cada um dos ambientes (DEV, QAS, PROD, etc) podemos ter 1 ou maismandantes. Cada um dos mandantes possui um número único que pode ser usado ao fazer login no ambiente em questão.

MANDT em tabelas do SAP Caso você abra praticamente qualquer tabela de dados mestre ou transacional pela SE11 no SAP notará a presença do campo MANDT como parte da chave da tabela. Ainda, esta

coluna será a primeira coluna da tabela, antes mesmo do “id” da tabela em si. Isso vale para as tabelas MARA, MARC, BKPF, BSEG, VBAK, VBAP, EKKO, EKPO e tantas outras no sistema.

Ainda, caso você tente visualizar os dados desta tabela pela transação Se11, Se16 ou SE16 notará que não terá como definir um filtro pela coluna MANDT. Logo, tiramos nossa primeira conclusão sobre clients: eles são independentes entre si.

Como o MANDT faz parte da chave, podemos ter mais de um material com o mesmo número no MATNR. Obviamente para

isso o mesmo número do MANDT (outra parte da chave) deveria ser diferente. MANDT (mandante)

MATNR (id do material)

MAKTX (descrição)

800

M-123

Arroz

800

M-124

Feijão

810

M-123

Arroz

810

M-124

Milho

Para quê serve o MANDT? Ok… sabemos que o campo MANDT está em muitas tabelas (mas não todas). Sabemos que quando ele aparece faz parte da chave. Sabemos que ele está na tela de login por isso tem a ver com a sessão na qual o usuário usa. Mas para que serve o tal do MANDT? O MANDT serve para separar dados dentro de um mesmo ambiente sem que haja a necessidade de duplicar tabelas. E porque preciso separar dados num mesmo ambiente? Vou dar três exemplos de aplicação de mais de um mandante no mesmo ambiente. Isso não significa que todas as empresas usem todos os exemplos abaixo. Sua aplicação vai variar dependendo do tamanho da implantação da empresa em si e como funciona a manutenção e suporte do sistema.

MANDT em desenvolvimento Um ambiente de desenvolvimento pode ter 2 ou mais mandantes para separar os dados usados por desenvolvedores ABAP dos dados usados por funcionais SAP. No ambiente de desenvolvimento os ABAPers codificam enquanto funcionais configuram o sistema. A configuração

feita por funcionais nada mais envolve que a inserção, alteração e exclusão de registros em uma porção de tabelas que não são de dados mestre. Estas modificações em dados em tabelas de configuração são capazes de alterar o comportamento do sistema. Caso você (ABAP) esteja testando um enhancement (por exemplo uma user exit em SD) você pode ser impactado por uma configuração sendo feita ao mesmo tempo por um funcional. Por exemplo, a tabela TVAK é usada pelos funcionais em SD para definir documentos de vendas. Se você depender de algum documento que esteja sendo alterado por um funcional, talvez não consiga testar o que precisa. Isso SE você e o funcional estiverem compartilhando o mesmo mandante. Caso não estejam, os dados serão completamente independentes um do outro e ambos podem fazer seus testes com tranquilidade na mente. Note que a tabela TVAK possui o campo MANDT. Por isso, pode-se ter 2 mandantes em DEV: 1 para desenvolvimentos em ABAP e o outro para configuração (este último é conhecido como ambiente “gold” em alguns lugares). Como o conteúdo de tabelas de customização alteram o comportamento do sistema o ideal é que sempre depois que um funcional fizer um teste bem sucedido em sua configuração rode a transação SCC1 para equiparar a configuração entre diferentes mandantes em desenvolvimento.

MANDT em qualidade Testes são feitos no ambiente de qualidade. Testes podem ser manuais e automáticos. Testes manuais são geralmente feitos por funcionais usando dados de teste bem conhecidos por eles (por exemplo, usando a principal filial da empresa, o material mais vendido/conhecido, o centro ou depósito com mais estoque etc). Testes automatizados requerem que um

conjunto de dados de teste estejam já prontos para que o teste possa ser executado. Caso haja apenas um mandante no ambiente de qualidade em que há testes manuais e automáticos, um funcional pode deletar ou alterar um material que é usado por uma série de testes automáticos: que consequentemente irão falhar – não por fracasso do teste em si, mas por conta de dados de teste errados.

MANDT em produção Como mandantes determinam dados totalmente independente uns dos outros pode haver um mandante segregado para cada filial de uma empresa. Note que há empresas com diversas filiais que usam o mesmo mandante. Isso porque o conceito de filiais existe no SAP e a privacidade dos dados entre filiais pode ser realizado de outras formas.

Client-Independent vs ClientDependent Talvez você tenha ouvido os temos client-independent (ou independente de client /mandante) e client-dependent (ou dependente de client /mandante). Caso não tenha ouvido saiba que no help do ABAP estas definições são muito usadas. Elas são usadas para descrever tabelas do sistema de acordo com a existência ou não do campo MANDT em suas estruturas. Em outras palavras, uma tabela (standard ou Z, não importa) que possua o campo MANDT será client-dependent. Isso porque os dados que você tem acesso nesta tabela depende do client usado para fazer logon. Da mesma forma, tabelas que não possuem o campo MANDT são client-independent. Estas tabelas são as mais perigosas pois qualquer alteração nas mesmas impactarão todos os usuários do sistema, independente em que mandante estejam. Felizmente há

maioria das tabelas no sistema possuem o campo MANDT e tabelas independentes de client geralmente são de customização.

MANDT no SELECT Como o mandante está atrelado a sessão do usuário, não há necessidade de especificar esta parte da chave quando se faz um SELECT (conceito conhecido como Client Handling). Porém, caso você deve selecionar dados de todos os mandantes do sistema, deverá usar a adição “CLIENT SPECIFIED” do comando SELECT FROM – o que particularmente nunca vi alguém usar em código Z.

Quantos mandantes existem no meu ambiente? A tabela T000 guarda os mandantes do sistema. Se você notar, todas as tabelas que possuem a coluna MANDT tem uma chave estrangeira para esta tabela. Ou pelo menos deveriam ter.

Client 000 O mandante 000 é reservado pela SAP. A empresa não pode usar o client 000 pelo simples fato de ele ser “intocado”. Ou seja, ele tem a configuração 100% standard existente logo após a instalação do SAP. Empresas que tem o costume de alterar a configuração standard ao invés de criar uma cópia da mesma podem ter que recorrer a este mandante quando se perguntam “O que eu fiz/O que mudei mesmo?”.

Restou dúvidas? Comente! Falei tudo que sei sobre o campo MANDT. Se você ainda tem alguma dúvida quanto ao assunto, comente a baixo. Este post deveria encerrar possíveis dúvidas sobre o conceito. O mandante é um conceito que deve ser entendido se você estiver procurando vagas de ABAP. Aproveitando, você já se cadastrou no ABAP101?

Criando templates de código no SAP Logon e no Eclipse BY FÁBIO PAGOTI · JANUARY 7, 2014

Compartilhe!

Há sempre aquele padrão de código que vivemos escrevendo mas ele não é exatamente reutilizável. Um LOOP com alguns IFs internos de controle… um FORM com com alguns parâmetros, alguma mensagem de erro famosa ou aquela classe básica com um construtor. Por pura preguiça de digitar tudo novamente (que já está implicitamente decorado) saímos a procura de um programa que já possui um código que podemos usar como modelo. Ah.. o CTRL+C, CTRL+V é tão prazeroso não é verdade? Não, não é. Aqui vai uma excelente dica que lhe ajudará a ganhar tempo enquanto desenvolve, seja na SE80 usando o SAP Logon ou o ABAP no Eclipse. Quer saber? Leia o resto deste post.

Templates de código Alguns comandos em ABAP, até em versões um pouco mais antigas do SAP Logon, exibem um tooltip com o sinal de § logo após o comando. Provavelmente você já sabe que caso você for rápido o suficiente e apertar TAB, um template prédefinido de código será inserido automaticamente para você. Mas você sabe como criar novos?

Caso você use o SAP Logon (consequentemente o tcode SE80, a segunda melhor IDE das linguagens que começam com “A” e terminam com “BAP”) basta seguir o passo-a-passo abaixo.

Criando templates de código no SAP Logon No canto inferior direito do editor ABAP, há um pequeno ícone amarelo com uma pasta e folha desenhada. Este botão abre a configuração do editor ABAP.

Para evitar que você sempre tenha uma reação sobrenatural para apertar TAB, aconselho ir na item “Code Completion” no menu a esquerda e alterar consideravalmente o valor da opção “Automatically Hide Code Hints After”. Assim você terá mais tempo para pensar no que está fazendo e poder apertar

TAB com um certo atraso para completar o código com um template.

Em sequência, vá na opção “Code Templates”. É aqui que se define os templates de código. Dê uma olhada nos existentes. Como exemplo, você pode criar um template para quando você já sabe que precisará fazer um SELECT e jogar o resultado em uma tabela interna que ainda não foi criada. Momentaneamente feche o popup e escreva o template que você deseja em um editor aberto qualquer, como o abaixo. Note que o código não precisa ser “compilável”. Basta que ele facilite sua vida na hora de usá-lo.

Uma vez que o seu template seja escrito, copie-o no clipboard e volte na tela de configurações do editor, opção “Code Templates”. Clique em adicionar e dê um nome (que você deve lembrar facilmente) e uma descrição o mais detalhada possível.

Salve e pronto! Você tem um template de código! Para usá-lo, basta digitar o nome do template no editor (no caso, _select_into_table). Uma vez que o nome completo do template seja digitado, a descrição definida será exibida em forma de tooltip. Novamente, basta apertar TAB para que o código seja inserido de acordo com o template.

Tags É possível também usar tags no seu template. Isso é útil quando seu template necessita de informações dinâmicas, como o dia atual ou o código do chamado que você esteja atendendo. Para ilustrar este cenário, vamos supor que na sua empresa ninguém saiba como usar o versionador de código ABAP e por isso seja necessário incluir comentários de código como o abaixo englobando o trecho de código que precisa ser alterado. ” BEGIN OF TICKET-12345 – Date: dd/mm/aaaa

” … changed source code ” END OF TICKET-12345 – Date: dd/mm/aaaa.

Como o número do chamado e a data atual são dinâmicas, basta incluir tags no seu template. No dropdown exibido no botão “Insert Tag” há algumas tags pré-definidas, como %DateTime%. Pelo fato de DateTime estar entre %’s, o editor irá interpretar a informação como uma variável. Conforme abaixo.

Quando você define uma variável que o editor não é capaz de interpretar, como %Ticket ID%, um input box é exibido toda vez que o template for chamado.

* Não há uma variável pré-definida para somente a data, mas fica mais fácil remover só o horário ou deixar no fonte mesmo. Na minha opinião é melhor não usar estes comentários que poluem o código e usar o versionador quando preciso… mas, tais comentários são normas em muitas empresas.

Mas é claro que o ABAP101 não vai dar uma dica como esta sem nada mais a acrescentar não é mesmo? Vamos ver como o mesmo conceito se aplica no ABAP no Eclipse para quem já está usando.

Criando templates de código no ABAP no Eclipse O Eclipse é mais inteligente que a SE80 por isso a qualquer momento você pode apertar CRTL+SPACE para acionar a função de autocompletar. Para criar templates, vá no menu “Window” >> “Preferences”. No menu a esquerda vá em “ABAP Development” >> “Source Code Editor” >> “Templates”.

Tags Tags (variáveis) no template de código do Eclipse são denotadas com ${variável}. Existem mais possibilidades de variáveis para quem usa o Eclipse (data, hora, ano, usuário, etc). Ao usar um template com uma variável desconhecida você preencherá seu conteúdo após o template ser inserido, sem a presença de popups portanto.

Exemplos de Templates Aqui vão alguns exemplos de templates para você adicionar no seu editor predileto (adequados ao eclipse).

1 class ${class_name} definition.

2 3 4 5 6 public section. methods constructor.

7 8

9 protected section. 1 0 private section. 1 1 1 2

endclass.

1 class ${class_name} implementation. 3 1 method constructor. 4 1 5 endmethod. 1 6 1 7

endclass.

1 8

1 *&---------------------------------------------------------------------* 2 & Report ${zprogram} 3 *& 4 *&---------------------------------------------------------------------*

5 *& Autor: 6 *& Transação: 7 *& Módulo: 8 *& Decrição: 9 *&---------------------------------------------------------------------*

1 class ${zcl_class_name_test} definition deferred. 2 class zcl_tested_global_class definition local friends ${zcl_class_name_test}. 3 CLASS ${zcl_class_name_test} DEFINITION FOR TESTING 4

FINAL

5

CREATE PUBLIC

6

DURATION SHORT

7

RISK LEVEL HARMLESS

8 . 9

PUBLIC SECTION.

10 11

METHODS mut1 FOR TESTING .

12

METHODS mut2 FOR TESTING .

13

METHODS mut3 FOR TESTING .

14 15

PROTECTED SECTION.

16 17 * GIVEN 18 19 20

METHODS given_reusable IMPORTING !im_ TYPE .

21

METHODS given_1.

22

METHODS given_2.

23

METHODS given_3.

24 25 * WHEN 26

METHODS when_mut1.

27 28 * THEN 29

METHODS then_reusable

30

IMPORTING

31

!im_ TYPE .

32

METHODS then_1.

33

METHODS then_2.

34

METHODS then_3.

35 36

PRIVATE SECTION.

37

METHODS setup.

38

METHODS teardown.

39 40

DATA o_ref_to_tested_class TYPE REF TO zcl_.

41

DATA o_exception TYPE REF TO zcx_ .

42 ENDCLASS. 43 44 CLASS ${zcl_class_name_test} IMPLEMENTATION. 45 46

METHOD setup.

47

CLEAR me->o_ref_to_tested_class.

48

CLEAR me->o_exception.

49

ENDMETHOD.

"setup

50 51

METHOD teardown.

52 53

ENDMETHOD.

"teardown

54 55 ************************************************

56 * Methods Under Test 57 ************************************************ 58

METHOD mut1.

59 60

ENDMETHOD.

"mut1

61 62

METHOD mut2.

63 64

ENDMETHOD.

"mut2

65 66

METHOD mut3.

67 68

ENDMETHOD.

"mut3

69 70 ************************************************ 71 * GIVEN 72 ************************************************ 73 74

METHOD given_1.

75 76

ENDMETHOD.

"given_1

77 78

METHOD given_2.

79 80

ENDMETHOD.

"given_2

81 82

METHOD given_3.

83 84

ENDMETHOD.

"given_3

85 86 ************************************************ 87 * WHEN 88 ************************************************

89 90

METHOD when_mut1.

91 92

ENDMETHOD.

"when_mut1

93 94 ************************************************ 95 * THEN 96 ************************************************ 97

METHOD then_reusable.

98 99 10 0

ENDMETHOD.

"then_reusable

METHOD then_1.

10 1 10 2

cl_aunit_assert=>assert_equals( EXPORTING

10 3 10 4 *

exp

=

" Data Object with Expected Type

act

=

" Data Object with Current Value

msg

=

" Message in Case of Error

= CRITICAL " Error Severity 10 * level 5 * tol = " Tolerance Range for Floating Point Numbers 10 * quit = METHOD " Flow Control in Case of Error 6 * ignore_hash_sequence = ABAP_FALSE " Ignore change sequence in 10 hash tables 7 * RECEIVING 10 8 * assertion_failed = " Condition not met 10 9

).

11 0

ENDMETHOD.

11 1

METHOD then_2.

11 2 11

"then_1

cl_aunit_assert=>assert_bound(

3 11 4

EXPORTING act

=

" Reference Variable to Be Checked

*

msg

=

" Error Message

11 5 *

level

11 * quit 6 * RECEIVING 11 * 7 11 8

" Error Severity

= METHOD

" Flow Control in Case of Error

assertion_failed =

" Condition not met

).

ENDMETHOD.

11 9 12 0

"then_2

METHOD then_3. cl_aunit_assert=>assert_not_bound(

12 1 12 2

= CRITICAL

EXPORTING act

=

" Reference Variable to Be Checked

*

msg

=

" Error Message

12 3 *

level

12 * quit 4 * RECEIVING 12 * 5 12 6 12 7

13 0 13 1 13 2 13

" Error Severity

= METHOD

" Flow Control in Case of Error

assertion_failed =

" Condition not met

).

ENDMETHOD.

12 ENDCLASS. 8 12 9

= CRITICAL

"then_3

3 13 4 13 5 13 6 13 7 13 8 13 9 14 0 14 1 14 2 14 3 14 4 14 5

Envie seus templates! Caso você use templates de código, cole seus preferidos no campo de comentário. Assim, todos podem economizar tempo também! http://abap101.com/2014/01/07/criando-templates-de-codigo-no-sap-logone-no-eclipse/

Não tenho demanda em ABAP – O que fazer? BY FÁBIO PAGOTI · DECEMBER 6, 2013

Compartilhe!

Por estes dias nós do ABAP101 recebemos um email muito semelhante a “Quase uma crise existencial” de um leitor que deu seu primeiro passo em sua carreira ABAP mas anda com alguns problemas, entre eles, a falta de demanda. Apesar de haver muitos do que as consultorias entitulam como “Júniors” nas empresas muitas das demandas acabam simplesmente não caindo nas mãos deles. Engana-se os Júniors que isso acontece somente pela falta de experiência e habilidade no SAP. Se você está na mesma situação (ou quer aproveitar as dicas dadas ao nosso leitor em forma de post) não deixe de ler este post e começar a ter demandas mais desafiadoras. Antes de responder ao nosso leitor, deixo o email dele na íntegra: Bom dia! Bom, meu nome é XXXXX, me formei em Sistemas de Informação no fim de 2012. Há uns três anos fiz um workshop de 40 de ABAP, e foi ai que conheci um pouco desse “mundo”. Depois do curso comecei a trabalhar com PHP e depois fiz um estágio onde trabalhei com C# e acabei deixando o ABAP um pouco de lado.. Em Julho com o fim do estágio recebi uma proposta na empresa que trabalhava com C#, para trabalhar como ABAP JR, e é claro que aceitei! rsrs Porém nesses 5 meses tenho tido dificuldades nos meus

estudos… Acho que é mais um problema na minha cabeça… Como estou “trabalhando” as vezes fico incomodado de não receber demandas… fico “inventando” exercícios e isso me incomoda muito, parece que estou atoa! Acho que por sempre conseguir fazer e ter bons resultados nas outras linguagens, quando o key-user te pede algo que acha quase impossível e acaba conseguindo fazer e ele gosta do que fez e tal…, falta esse incentivo entende? Faço uma série de exercícios do próprio ABAP101, do SAP Technical,ABAP Zombie… mas quando chega uma especificação funcional, fico meio perdido… Me desculpe o desabafo! Mas fala aí rs me de um rumo! Pode brigar também que as vezes acho que por cabeça dura estou perdendo a oportunidade de estudar e receber por isso rsrs… Tipo o que fazer, pra complicar um pouco os exercícios… Ahh vou fazer a academia estou me programando financeiramente pra isso.. mas pretendo fazer quando estiver mais entendida pra nao perder muito ou boiar nas aulas.. Desde já agradeço! E o site é ótimo!

Caro leitor, para responder estas dúvidas vou dividir o post por partes. Vamos lá!

Formação e experiência Você apesar de recém-formada já tem um bom background (eu também sou pois me formei em Sistemas de Informação também – em 2010), e não caiu em ABAP por “sorte” – você com certeza não possui problemas com lógica de programação, estruturas de dados, desenvolvimento de software etc. Ainda mais, ABAP não é sua primeira linguagem e isso te ajuda a ver que Existe vida fora do mundo ABAP, o que é ótimo. Não ache que você não tenha demanda por

ainda não estar preparada para começar de vez e não parar mais.

Qual sua função?

Caso seu chefe não tenha nascido em 1920 ele sabe que você naturalmente não vai dar o retorno para ele nas demandas como um companheiro de trabalho seu que é contratado como “Sênior”. Como imagino que ele é uma pessoa sensata, ele espera que você se aprimore para dar um retorno para a área em que trabalha mais rápido possível. Se você aprender mais criando especificações fictícias na maior parte do tempo, tudo bem. O que ele exigirá de você é estar preparada quando ele precisar, como por exemplo, quando um pleno sair da empresa ou quando começar um projeto no qual demanda muita atenção e esforço. Portanto, garanta que você está sendo paga, para além de outras coisas, aprender. Se você não tem tempo para aprender você não está exercendo sua função em plenitude e consequentemente não está

exercendo seu trabalho. Como diria Maggie (personagem de The Walking Dead): “We all got jobs to do”.

A distribuição de trabalho no SAP é diferente Muitas vezes em outras linguagens o programador tem contato direto com o usuário. No SAP, nem sempre é assim. Você dificilmente vai ver um usuário pulando de alegria ou te xingando de raiva por alguma demanda que você tenha atendito. A nossa relação é maior com algum funcional que conhece o que o sistema faz, não faz, não pode fazer e tem que fazer. Porém o funcional pode não estar de baixo do mesmo guarda-chuva que você dependendo do porte da equipe SAP da empresa em que trabalha. Em outras palavras, o funcional não tem o mesmo chefe que você e ele pode simplesmente passar as demandas que ele tem para outra pessoa da sua área, no qual ele tem mais afinidade. Departamentos prestam serviços uns para outros no final das contas. Ainda, o ABAP tem muitas diferenças entre outras tecnologias e vai demorar um tempo até que você deixe o funcional, não o usuário primeiramente, feliz. Por isso, não busque no funcional motivação ou incentivo. Foque no seu trabalho. We all got jobs to do.

Treino é treino, Jogo é jogo

Exercícios são ótimos, mas eles tem um elemento crucial muitas vezes não encontrados em especificações funcionais em SAP: clareza. Um exercício deve ser claro para entender onde pretende-se chegar. A solução do exercício deve ser detalhada e clara para entender-se como o objetivo foi alcançado. A metodologia de desenvolvimento de quem trabalha com SAP é via de regra Waterfall, infelizmente (ainda – em pleno século 21). Quando uma especificação funcional chega nas mãos de um ABAP nestas condições ela é somente a ponta do iceberg. Não ache que pelo fato de você ter recebido um email com um documento .docx em anexo significa que você não pode conversar com o funcional que escreveu aquilo sobre a demanda. Antes de falar com ele, faça um scamming na espec. Via de regra, você não vai entender muito mas o suficiente para perguntas coisas do tipo: “Como é feito hoje? Por que tem que ser assim? Pode ser de outro jeito? Você já tentou? A clareza do requisito está na demanda que o gerou e não na especificação funcional que você recebeu. Busque no funcional também a clareza necessária para saber o que você está fazendo e porque está fazendo.

Solicite demanda Ninguém chegará na sua mesa perguntando se você está livre para alguma demanda enquanto você não provar ao menos uma vez do que é capaz. Sente-se confortável para acompanhar a resolução de um chamado juntamente com um Pleno/Sênior, ofereça sua ajuda. Caso ele negue (o que duvido), abra o programa que ele alterou, estude o que ele fez entenda o que foi feito. Depois, converse com ele sobre o que você achou do trabalho dele e agradeça pela colaboração, afinal de qualquer jeito ele te ajudou. Sente-se preparada para começar um desenvolvimento sozinho? Fale com seu chefe para ele te lançar um desafio.

Não pare na pista

Depois de um tempo, em que você começar a achar que você nasceu para isso e agora é só questão de tempo para virar Sênior, lembre-se de não parar na pista.

Participe de projetos Open Source Como você acompanha o ABAP101, com certeza você sabe que a SAP publicou uma nova licença de desenvolvimento. Isso significa que você agora pode ter um código ABAP publicado no GitHub sem correr o risco de ser preso(a). Um projeto seu ou feito juntamente com outras pessoas as quais usam o tempo livre delas para criar algo útil como o WordPress por exemplo é uma grande oportunidade de ter exercícios mais bem elaborados, além de ser um grande feito.

Quais suas dicas ao nosso amigo leitor? Caso você tenha chegado até aqui, certamente é porque está ou já esteve nesta situação. Quais os conselhos que você daria ao nosso colega de profissão? Não deixe de comentar aí em baixo! Tem algum problema relacionado? Comente também! Um grande abraço a todos e ao nosso leitor que aceitou a ideia de ter seu pedido respondido em forma de post.

Dicas para quem não consegue entrevistas no mundo SAP BY FÁBIO PAGOTI · SEPTEMBER 12, 2013

Compartilhe!

Outro dia destes recebi uma mensagem de uma pessoa (talvez leitor do blog ou não) a respeito da dificuldade que ele(a) tem em começar a atuar na área de SAP, mais especificamente com ABAP. Como a pessoa se reservou o direito de enviar esta pergunta via uma rede social, eu estou me reservando o direito de publicar minha resposta também em rede já que sei que este problema é de muitos. Apenas editei e removi o que não cabe neste post mas quanto ao assunto principal, que é se colocar no mercado SAP, o texto está na integra.

Pergunta (todas edições marcadas) Olá Fabio tudo bem? Cara estou recorrendo a alguns colegas do [Alguma Rede Social] uma dica de como atuar SAP, tenho notado que existem muitas vagas, mas como entrar?

Fiz recentemente academia na [XXXXXXXXX] e desde então não estou conseguindo nem sequer entrevista, seria meu curriculo mal elaborado? Por favor me ajuda. Abraço.

Resposta (todas edições marcadas) Olá XXXX. Vamos lá. Não entendi bem se você quis dizer isso mas primeiramente, é um erro você afirmar que você não consegue sequer entrevistas por ter feito curso na XXXXXXXXX. Tenha certeza que caso você não tivesse feito a chance de você conseguir entrevistas para atuar na área seria ainda menor. (…) Eu não sei em que você atua mas se vale a dica, procure pensar em conhecimentos extra-SAP e experiências que você pode não ter no grau desejado para as vagas que vem se candidatando. Será que o seu nível de inglês, formação acadêmica, experiência e amostra de outros trabalhos realizados faz você se destacar em meio das inúmeras pessoas que se formam em academias ABAP em SP todos os meses? Se você não consegue uma entrevista, eu só vejo 3 possibilidades: 1) Você já tem o que precisa para atuar na área mas não demonstra isso no seu CV 2) Você ainda não tem o que precisa para atuar na área e demonstra isso no seu CV

3) Você ainda não tem o que precisa para atuar na área e para agravar a situação, ainda demonstra isso mal no seu CV Tenha certeza que na ocorrência da quarta possibilidade, que seria ter o que precisa para atuar na área e demonstrar isso no CV, você já estaria no mínimo conseguindo entrevistas e muito provavelmente empregado na área e consequentemente não me enviando uma mensagem. Quanto ao seu CV, eu não posso analisar porquê (…) você não me disponibilizou. Não sei se este é o seu caso, mas mudar de área requer um mínimo de planejamento. Há muitos e muitos anos, uma academia SAP, seja oficial ou não, está bem longe de ser uma garantia de emprego na área. Ainda, há muitos e muitos anos, um emprego inicial em SAP está bem longe de remunerar o que as pessoas que fazem academia acham que se paga. Para finalizar, se você puder me falar qual o seu usuário na SDN, quando foi a última vez que apareceu por lá e quanto tempo você se dedica em se aprimorar em ABAP frente ao tempo que você manda currículos, talvez isso me ajude a entender porquê você não consegue entrevistas. Boa sorte,

Postcast sobre RH Particularmente eu abomino muitas práticas atuais de recursos humanos. Contudo, elas fazem parte do jogo. Felizmente há um excelente podcast do Max Gehringer na CBN sobre empregabilidade. Vale muito a pena conferir independente se você trabalha com SAP ou não.

15 indícios musicais que o seu programa ABAP pode melhorar http://abap101.com/2013/07/17/indicios-musicais-seu-programa-abap-podemelhorar/ http://abap101.com/2012/10/28/evolucao-do-editor-abap/

Criando Objetos / Chamando Métodos Dinamicamente BY CLAUDIA ANDRESSA · JULY 20, 2012

Compartilhe!

Na busca pela solução de um problema, debugando, debugando e debugando novamente, me deparei com a criação dinâmica de objetos. Estudando mais a fundo, eis que surge assunto para mais um post! Afinal, quanto mais dinâmicos forem os programas e API ´s, melhor será sua performance e re-usabilidade. O que faz com que consigamos criar o objeto / chamar o método dinamicamente, é a utilização de uma tabela, na qual informamos todos os parâmetros necessários (seja de importing, exporting, changing, etc), ou seja, podemos popular esta tabela de acordo com nossa necessidade em determinado ponto do programa. Utilizei como exemplo, a criação de um objeto com referência à classe ‘CL_GUI_ALV_GRID’, o qual chamei de r_grid.

Para facilitar o entendimento, segue abaixo o Pattern (modelo) da criação estática deste objeto:

1 2 3 4 5 6 7 8

CREATE OBJECT r_grid EXPORTING *

i_shellstyle

=0

*

i_lifetime

=

i_parent

i_appl_events

= space

* 1 0 *

i_parentdbg

=

1 * 1 * 1 * 2 * 1 3 *

i_graphicsparent =

9

*

= r_container

i_applogparent

i_name

=

=

i_fcat_complete = space EXCEPTIONS error_cntl_create = 1

1 * 4 * 1 5 *

error_cntl_init = 2

1 * 6

others

error_cntl_link = 3 error_dp_create = 4 = 5.

1 7

OBS: o objeto r_container é do ripo CL_GUI_CUSTOM_CONTAINER , criado estaticamente no código abaixo.

Vamos criar o objeto apenas informando o parâmetro obrigatório ‘I_PARENT’, e para isso, utilizaremos uma workarea do tipo abap_parmbind, e uma tabela tipo abap_parmbind_tab, denominadas lwa_param e lt_paramrespectivamente. Na propriedade ‘Name’ sempre informaremos o parâmetro, neste caso ‘I_PARENT’. Na propriedade ‘Kind’, o tipo (Exporting, conforme modelo estático). Para informar o tipo, precisamos utilizar os atributos da classe ‘CL_ABAP_OBJECTDESCR’, com isso, teremos:

1 lwa_param-kind = cl_abap_objectdescr=>exporting.

Por fim, necessitamos informar o valor atribuído a este parâmetro, e conforme podemos verificar no código abaixo, o valor é o objeto r_container (objeto de referência a classe CL_GUI_CUSTOM_CONTAINER). Desta forma, necessitamos incluir a referência do objeto na tabela:

1 GET REFERENCE OF r_container INTO lwa_param-value.

Agora é só inserirmos nossa workarea na tabela e criarmos o objeto / chamarmos o método (não se esqueça de utilizar o try-catch, de forma a tratar possíveis exceções).

Obs: Verifique a sintax de chamada do método / criação do objeto. Observe que cria-se o objeto do tipo de uma classe (informada na variável lv_type) com os parâmetros inseridos na tabela.

1 REPORT z_create_dinnam. 2 3

TYPE-POOLS: abap.

4 5 6

DATA: lt_param TYPE abap_parmbind_tab, lwa_param TYPE abap_parmbind.

7 8 9 1 0 1 1 1 2 1 3 1 4

DATA: lv_type

TYPE string,

lv_exc_txt TYPE string.

DATA: r_except r_grid

TYPE REF TO cx_root,

TYPE REF TO cl_gui_alv_grid,

r_container TYPE REF TO cl_gui_custom_container.

CLEAR: lt_param, lwa_param, lv_type, lv_exc_txt. REFRESH: lt_param.

1 *--------------------------------------------------------------------* 5 START-OF-SELECTION. 1 6 CREATE OBJECT r_container 1 7 EXPORTING 1 8 1

container_name

= 'CONTAINER_1'

EXCEPTIONS cntl_error

=1

9

cntl_system_error

2 0

create_error

=3

lifetime_error

=4

2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3

=2

lifetime_dynpro_dynpro_link = 5 OTHERS

= 6.

IF sy-subrc NE 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF.

*--------------------------------------------------------------------* CLASS cl_abap_objectdescr DEFINITION LOAD.

lv_type = 'CL_GUI_ALV_GRID'.

lwa_param-name = 'I_PARENT'. lwa_param-kind = cl_abap_objectdescr=>exporting. GET REFERENCE OF r_container INTO lwa_param-value. INSERT lwa_param INTO TABLE lt_param.

*--------------------------------------------------------------------*

TRY . CREATE OBJECT r_grid TYPE (lv_type) PARAMETER-TABLE lt_param.

CATCH cx_sy_create_object_error INTO r_except. lv_exc_txt = r_except->get_text( ). MESSAGE lv_exc_txt TYPE 'I'.

9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5

ENDTRY.

9

Fica o desafio: que tal chamar um método dinamicamente e utilizar uma tabela de excessão? Ela funciona da mesma maneira para recuperar as exceções lançadas pelos métodos. Pesquise, tente fazer e em caso de dúvidas, entre em contato!

Recursividade em ABAP BY FLÁVIO FURLAN · JUNE 25, 2012

Compartilhe!

Uma das técnicas de programação mais incompreendida e evitada, também é umas das mais poderosas, a Recursividade. Eu precisei usar a recursividade apenas uma única vez na vida com ABAPer e o resultado foi muito interessante. Nesse texto eu vou resolver um problema muito simples usando recursividade, exponenciação.

Exponenciação De acordo com a Wikipédia: Exponenciação ou potenciação é uma operação matemática, escrita como An, envolvendo dois números: a base a e o expoente n. Quando n é um número natural maior do que 1, a potência an indica a multiplicação da base a por ela mesma tantas vezes quanto indicar o expoente n.

A fórmula da exponenciação é simples e por isso considero um exemplo legal para mostrar a recursividade em prática.

Exponenciação Usando Recursividade No ABAP você pode usar o operador ** para fazer a exponenciação e resolver todo o problema em uma linha (veja no programa abaixo), mas esse post não é sobre exponenciação, mas recursividade. Novamente da Wikipédia: A recursão é o processo pelo qual passa um certo procedimento quando um dos passos do procedimento em questão envolve a repetição completa deste mesmo procedimento. Um procedimento que se utiliza da recursão é dito recursivo. Também é dito recursivo qualquer objeto que seja resultado de um procedimento recursivo. Em ABAP claro significa uma subrotina (form, módulo de função ou método) que efetua uma chamada dela mesmo. Por exemplo, usando a recursão para resolver um problema de potência, farei com que o método EXECUTE_EXPONENTIATION( ) seja chamado inúmeras vezes por ele mesmo, de acordo com o expoente passado para ele como parâmetro. Também poderíamos usar a estrutura de loop DO n TIMES … ENDDO, mas aí não seria recursão. Veja o programa abaixo: ZABAP101_RECURSION *&---------------------------------------------------------------------* *& Report ZABAP101_RECURSION *&

*&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zabap101_recursion.

*----------------------------------------------------------------------* *

CLASS lcl_math DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_math DEFINITION.

PUBLIC SECTION.

METHODS execute_exponentiation IMPORTING base TYPE i expoent TYPE i RETURNING value(re_power) TYPE i.

PRIVATE SECTION.

DATA: interaction TYPE i, power

ENDCLASS.

TYPE i VALUE 1.

"lcl_math DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_math IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_math IMPLEMENTATION.

METHOD execute_exponentiation. ADD 1 TO interaction. IF interaction execute_exponentiation( base = base expoent = expoent ). MULTIPLY power BY base. ENDIF. re_power = power. ENDMETHOD.

ENDCLASS.

"execute_exponentiation

"lcl_math IMPLEMENTATION

DATA: r_exp TYPE REF TO lcl_math, v_power TYPE i.

PARAMETERS: p_base TYPE i DEFAULT 2, p_exp TYPE i DEFAULT 3, p_rec AS CHECKBOX.

INITIALIZATION.

CREATE OBJECT r_exp.

START-OF-SELECTION.

IF p_rec = 'X'. v_power = r_exp->execute_exponentiation( base = p_base expoent = p_exp ). ELSE. v_power = p_base ** p_exp. ENDIF.

WRITE: / 'Power: ', v_power.

view rawgistfile1.txt hosted with

by GitHub

Execute esse programa no modo debug e veja a pilha de chamada. Veja que o método se repete várias vezes indicando que ele fora chamado de dentro dele mesmo, caracterizando uma recursividade:

Pilha de chamadas do método EXECUTE_EXPONENTIATION( ) – Recursividade

A primeira linha do método incrementa o atributo INTERECTION, daí o método chama ele mesmo se a interação for menor ou igual ao expoente. Com isso a pilha (stack) vai sendo adicionada a cada nova chamada até que o número máximo de iterações (expoente) seja alcançado. A pilha pára de ser incrementada e o restante do método começa a ser chamado, a partir do item da pilha mais novo (LIFO, Last In First Out), onde finalmente a multiplicação é feita e sendo acumulada no atributo POWER.

Explosão de Lista Técnica Existem problemas em que a recursividade é quase que obrigatória, no caso da chamada explosão de lista técnica. Imagine que você precise saber o custo de algum material que é composto por outros materiais, como por exemplo um notebook.

Partes de notebook – fonte imagem

Um notebook pode ser um materia formado por teclado, display LCD, HD, placa-mãe, memórias, carcaça etc.

O teclado é formado por uma base, uma tecla Q, outra W, outra E, outra R, outra T etc. Um HD é formado por um conjundo de discos magnéticos, placa de controle e sistema de leitura, Um sistema de leitura é formado por um braço de leitura, cabeçote de leitura e placa de leitura. E assim por diante. Se eu tivesse uma rotina que dado um material ele me retornasse uma lista de materais que formam esse material, eu precisaria chamar essa rotina n vezes, conforme eu fosse “desmontando” ou “explodindo” meu material. Dessa maneira a haveria a recursividade como exemplificado no exemplo do notebook, resolvendo o problema muito rapidamente. Claro que nem tudo são flores. Depurar um programa que usa recursividade é muito trabalhoso, bem como entender a recursividade que outra pessoa desenvolveu. Isso faz com que a recursão seja evitada, mas em alguns casos é a melhor forma de resolver um problema.

Aplicação do Design Pattern: Factory BY FLÁVIO FURLAN · JUNE 6, 2012

Compartilhe!

Depois de falarmos do Singleton, está na hora de falarmos de outro padrão de projeto, o Factory. O Factory é mais difícil de

entender do que o Singleton. Mais do que isso, mais difícil de mostrar alguma aplicação prática. Nesse post eu mostrarei as duas coisas, explicar o funcionamento do Factory, bem como sua aplicação.

Rápida Explicação … De uma maneira bem simples, o Factory é um padrão que nada mais é do que uma classe geradora de objetos, onde a decisão de qual classe o objeto será é feita pela classe “geradora”. Onde eu apliquei o Factory em ABAP?

Projeto Code Coaching Estamos trabalhando num projeto open source chamado Code Coaching que está sendo desenvolvido sob a iniciativa do ABAP101 Open Source. O objetivo do projeto é construir uma aplicação ABAP onde o Programador e Coordenador possam se comunicar pelo próprio programa ABAP. Veja esse exemplo. Esse trecho de código faz parte de outro projeto em que estávamos envolvidos. Eu queria passar instruções para a implementação de uma classe interface específica. Então ao invés de passar instruções por e-mail, eu resolvi colocar alguns comentários dentro do próprio código. Daí para evoluir para uma proto-markup-language foi um pulo (lembre-se, meu sangue é de programador, minha tendência é resolver tudo com um programa de computador). Fonte

Existem algumas linhas de comentários que são iniciadas por *@. Essas linhas contêm uma espécie de código que dá um significado especial às linhas comentadas logo na sequência. Continuando na linha do *@encontramos a seguinte instrução: “jack:task”. Isso significa que os comentários logo abaixo dessa linha, trata-se de uma tarefa designada para o programador chamado Jack. Sendo assim, o programador pode facilmente fazer uma busca no programa pelo seu nome e descobrir todos os pontos que possuam algum comentário para ele. Para facilitar eu automatizei essa busca em um programa que lê o programa e extrai todos os pontos onde a linha começa com *@ e gera um relatório, como o mostrado abaixo.

Protótipo do relatório para o Code Coaching

Esse programa é apenas um protótipo e como tal serve apenas para apresentar e testar a ideia central do projeto. O projeto final contemplará muitas outras funcionalidades bem como outros comandos, muito além dotask. É nesse ponto que o factory será usado.

O que o Factory Significa para o Code Coaching?

No protótipo do programa Code Coaching, ele consegue interpretar apenas o comando task, mas já no primeiro release, estamos planejando expandir para pelo menos três outros comandos além do task, question, answer ecomment. Para fazer a interpretação desses comandos, o programa relatório contará com um diagrama de classes semelhante ao apresentado abaixo:

Teste de Conceito do modelo do Code Coaching

Cada comando é representado por uma classe. Abaixo você verá mais um programa de teste de conceito, este usando o factory para interpretar um comando entrado pelo usuário.

Implementando o Factory em ABAP Vamos para mais um programa que simula o interpretador que usaremos no Code Coaching. Trata-se de um programa bem simples, com um parâmetro que é o nome do comando. Se o comando existe, ele mostra o texto que está na classe correspondente ao comando, caso contrário mostra uma mensagem de erro.

Tela de seleção - Comando TASK

Explicação para o comando TASK - Classe LCL_TASK

Comando JUMP não existe

Resultado do comando JUMP

Programa ZABAP101_FACTORY_PATTERN completo.

A classe LCL_COMMAND é responsável por decidir de qual classe o objeto deve ser criado. Se ocorrer um erro na criação, ou seja, se a classe que estamos querendo criar o objeto não exista, uma exceção é lançada e tratada como um erro de sintaxe. Repare que eu monto o nome da classe de acordo com o nome do comando entrado pelo usuário no parâmetro do

programa. Ou seja, para esse caso, a classe do comando precisa seguir a seguinte nomenclatura: LCL_, caso contrário haverá um erro na criação do objeto daquela classe, pois a classe não existirá. Os objetos dos comandos são criados no método FACTORY( ), com o seguinte comando: CREATE OBJECT re_instance TYPE (lv_command). O tipo do objeto é definido em tempo de execução, de acordo com o valor da variável lv_command. Colocando a variável entre parênteses, o interpretador ABAP entende que o tipo do objeto a ser criado não élv_command, mas sim o que está no conteúdo da variável entre os parênteses.

Qual a Vantagem? Por que criei uma classe para cada comando? Porque dessa forma, pode-se adicionar um novo comando de maneira MUITO fácil, apenas criando uma nova classe para o novo comando e herdando da classe LCL_COMMAND. Todo o resto não será afetado. (sim, isso cheira polimorfismo). (sim, isso é genial!!!) O padrão de projeto Factory pode ser implementado de várias maneiras, essa foi apenas uma delas. Acho sim interessante estudá-lo para ter mais essa ferramenta em sua workbench.

Importanto e Exportanto Uma Tabela Interna – Módulo de Função

BY FLÁVIO FURLAN · MAY 31, 2012

Compartilhe!

Estava procurando algum assunto para escrever, e uma luz do céu e-mail chegou com uma dúvida e que em todas as turmas da Academia ABAP tem, como importar ou exportar uma tabela interna para um módulo de função ou método. A solução pode ser respondida com uma simples frase: “Use um Table Type (Categoria de Tipos)”. Só com isso já seria suficiente para você sair do outro lado, mas fazendo jus ao “101” do nome do site, vou explicar passo a passo como fazer em um módulo de função. No próximo post, eu explicarei como fazer em um método.

Problema Precisamos criar um módulo de função para retornar dados dos vôos (tabela SPFLI), dado uma empresa aérea.

Solução A primeira coisa a fazer é criar um tipo tabela (table type) no dicionário, que define uma tabela interna do tipo standard. Vá na transação SE11 e escolha Data Type:

Clique em “Create” e escolha Table Type:

Entre com uma breve descrição e o Line Type, que define a as colunas na tabela interna. Nesse caso queremos todas as colunas da tabela SPFLI.

Certifique-se o tipo de tabela seja Standard Table.

Com o tipo global criado e ativo, vamos a criação ao módulo de função. Primeiro, é necessário criar uma Grupo de Função na transação SE80. Escolha “Function Group” e defina um nome. Pressione ENTER e confirme a criação do novo objeto.

Depois de criar o grupo, crie o módulo de função. Pressione o botão direito do mouse sobre o grupo de função, escolha Create -> Function Module.

Defina o nome a descrição para o módulo de função. O nome precisa necessariamente “Z_”.

Agora vamos definir o parâmetro de Import, IM_CARRID, com o mesmo tipo do campos CARRID da tabela SPFLI.

Para o parâmetro de EXPORT use o Table Type definido anteriormente.

Não vamos nos esquecer de definir as exceções, no nosso caso, defina apenas uma única exceção.

E para finalizar, entre o código abaixo: Z_FM_GET_CONNECTIONS FUNCTION z_fm_get_connections. *"---------------------------------------------------------------------*"*"Local Interface: *" IMPORTING *"

REFERENCE(IM_CARRID) TYPE SPFLI-CARRID

*" EXPORTING *"

REFERENCE(EX_SPFLI_T) TYPE ZTT_SPFLI

*" EXCEPTIONS *"

NO_DATA_FOUND

*"----------------------------------------------------------------------

SELECT * FROM spfli INTO TABLE ex_spfli_t WHERE carrid = im_carrid.

IF sy-subrc NE 0. RAISE no_data_found. ENDIF.

ENDFUNCTION.

view rawgistfile1.txt hosted with

by GitHub

Execução e Teste Depois de ativar o módulo de função, você pode executar um teste unitário pressionando o F8. Entre a empresa aérea “AA”.

Pressione F8 novamente para executar o módulo de função, retornando duas entradas da tabela SPFLI.

Agora usando efetivamente o módulo de função, crie um programa que chama a função e imprima o resultado na tela.ZABAP101_REPORT_CONNECTIONS *&---------------------------------------------------------------------* *& Report ZABAP101_REPORT_CONNECTIONS *& *&---------------------------------------------------------------------* *& This code was published originally on ABAP101.com *& http://abap101.com/2012/05/30/ > *&

importanto-exportanto-uma-tabela-interna-modulo-funcao

*& Author: Flávio Furlan *& E-mail: [email protected] *&---------------------------------------------------------------------*

REPORT zabap101_report_connections.

DATA: it_spfli TYPE ztt_spfli.

FIELD-SYMBOLS: TYPE LINE OF ztt_spfli.

PARAMETERS: p_car TYPE spfli-carrid.

START-OF-SELECTION.

CALL FUNCTION 'Z_FM_GET_CONNECTIONS' EXPORTING im_carrid

= p_car

IMPORTING ex_spfli_t

= it_spfli

EXCEPTIONS no_data_found = 1 OTHERS

= 2.

IF sy-subrc 0. MESSAGE 'No records found.' TYPE 'E'. ENDIF.

LOOP AT it_spfli ASSIGNING . WRITE: / -carrid, -connid, -countryfr, -cityfrom, -airpfrom, -countryto, -cityto, -airpto. ENDLOOP.

view rawgistfile1.txt hosted with

by GitHub

Discussão O principal ponto a destacar aqui é o tipo criado na SE11, ZTT_SPFLI. Antigamente usava a pasta Tables do módulo de função, onde era somente preciso especificar a estrutura que o próprio sistema entendia que deveria ser criado uma tabela interna em tempo de execução. Não usamos essa técnica pois já está obsoleto e por regra não devemos criar novos

programas com instruções ou técnicas definidas pela SAP como obsoletas. É interessante o uso do módulo de função para seleção de dados, pois assim podemos reutilizar em outros programas. Esse módulo de função serve como Model (do nosso conhecido MVC). Podemos incluir ali outras regras de negócio que poderão ser facilmente reutilizadas em outros programas. Além disso, se essa regra mudar por qualquer motivo, não é necessário alterar vários programas, mas apenas dentro do módulo de função.

Tratamento de Exceção – Propagação e CLEANUP BY FLÁVIO FURLAN · MAY 2, 2012

Compartilhe!

Quando eu explico tratamento de exceção na academia ABAP, o pessoal não dá muita bola, até porque os alunos ainda estão tentando se recuperar das aulas de polimorfismo e interface, mas entender o funcionamento dela é vital para desenvolver boas soluções usando orientação a objetos (não somente para aprender a escrever a palavra exceção). Nesse post, vou explicar dois conceitos ligado ao tratamento de exceções baseado em classes, propagação e comando CLEANUP.

Começando Pelo Básico Vamos entender primeiro o funcionamento básico do tratamento de exceções baseado em classes. Quando usamos

as classes de exceção, devemos usar a estrutura de comandos TRY-CATCH-CLEANUP. Usarei a classe LCL_EXCEPTION_DEMO que está no include ZABAP101_EXCEPTION_CLASSES nos programas de exemplo. *&---------------------------------------------------------------------* *& Include

ZABAP101_EXCEPTION_CLASSES

*&---------------------------------------------------------------------*

*----------------------------------------------------------------------* *

CLASS lcl_exception_demo DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_exception_demo DEFINITION.

PUBLIC SECTION. METHODS: dump_factory, simple_catch, cleanup_live RAISING cx_sy_zerodivide, cleanup_dead RAISING cx_sy_zerodivide, propagating RAISING cx_sy_zerodivide.

PRIVATE SECTION. DATA: result TYPE i.

ENDCLASS.

"lcl_exception_demo DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_exception_demo IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_exception_demo IMPLEMENTATION.

METHOD dump_factory. result = 1 / 0. ENDMETHOD.

"dump_factory

METHOD simple_catch. TRY . result = 1 / 0. CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do método SIMPLE_CATCH.'. ENDTRY. ENDMETHOD.

"simple_catch

METHOD cleanup_live. TRY . result = 1 / 0. CLEANUP. WRITE: / 'Executou o Cleanup do método CLEANUP_LIVE.'. ENDTRY. ENDMETHOD.

"cleanup_live

METHOD cleanup_dead. TRY . result = 1 / 0. CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do método CLEANUP_DEAD'. CLEANUP. " o programa nunca executará o CLEANUP.

WRITE: / 'Executou o Cleanup do método CLEANUP_DEAD.'. ENDTRY. ENDMETHOD.

"cleanup_dead

METHOD propagating. result = 1 / 0. ENDMETHOD.

ENDCLASS.

"propagating

"lcl_exception_demo IMPLEMENTATION

view rawZABAP101_EXCEPTION_CLASSES hosted with

by GitHub

O primeiro programa que mostrarei é um programa cuja saída é … um DUMP!? Sim, quando o sistema chega a alguma situação onde ele não consegue seguir com o programa, como por exemplo uma divisão por zero. *&---------------------------------------------------------------------* *& Report ZABAP101_EXCEPTION_DUMP *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zabap101_exception_dump.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY . r_demo->dump_factory( ). CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do programa principal.'. ENDTRY.

view rawZABAP101_EXCEPTION_DUMP hosted with

by GitHub

Quando o programa tenta fazer uma divisão por zero a seguinte tela é mostrada. Toda a pilha de execução é eliminada e toda a memória usada pelo programa é apagada.

Mas graças ao tratamento de exceção por classes, você pode dizer para o sistema “tente executar essa operação, e se caso aconteça divisão por zero, execute isso”. Nesse primeiro programa onde o DUMP é evitado, o método SIMPLE_CATCH( ) é chamado. Na implementação do método, ele tenta (TRY) executar uma divisão por zero, que é tratada (CATCH) dentro do próprio método. *&---------------------------------------------------------------------* *& Report ZABAP101_EXCEPTION_BASIC *&

*&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zabap101_exception_basic.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY . r_demo->simple_catch( ). CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do programa principal.'. ENDTRY.

view rawZABAP101_EXCEPTION_BASIC hosted with

by GitHub

Repare que a a exceção é tratada dentro do próprio método, portanto a mensagem “Executou o CATCH do método SIMPLE_CATCH.” é impressa no lugar do DUMP. A saída do

programa acima é mostrada abaixo:

Propagação de Exceção Conheço muitas equipes onde esse conceito é muito bem difundido, ou seja, uma pessoa decide não ser responsável pelo erro que cometeu e decide passar o erro para outra pessoa corrigir. Pois é, no ABAP temos algo parecido. Veja esse programa: *&---------------------------------------------------------------------* *& Report ZABAP101_EXCEPTION_PROP *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT ZABAP101_EXCEPTION_PROP.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY . r_demo->propagating( ). CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do programa principal.'. ENDTRY.

view rawZABAP101_EXCEPTION_PROP hosted with

by GitHub

Quando o método PROPAGATING( ) é chamado, uma divisão por zero é executada. Observe que esta divisão não está sendo tratada com o TRY-CATCH e veja a saída do programa:

O segredo está na declaração do método: “METHODS propagating RAISING cx_sy_zerodivide.” Existe uma instrução RAISING que diz exatamente o que algumas pessoas que conheço fazem, “olha, pode ser que uma divisão por zero aconteça e se isso acontecer você [quem está chamando o método] deverá tratar essa exceção”. Sendo assim, a exceção precisou ser tratada na chamada do método e não mais dentro do método. Qual forma usar, a do primeiro programa ou essa? Depende. Se você quer passar a responsabilidade do tratamento para quem chama o método então o segundo programa deve ser

usado. Mas se o erro é algo interno do método e precisa ser tratado de maneira transparente do usuário, então você deverá tratar a exceção dentro do próprio método, assim como fora feito no primeiro programa. O que acontece se não tratarmos a exceção na chamada do método? Experimente…

CLEANUP não é WHEN OTHERS do Tratamento de Exceções Essa é a primeira conclusão que os meus alunos chegam quando olham para definição do comando no Help do ABAP.

Não, o CLEANUP não é uma espécie de WHEN OTHERS do TRYCATCH. Para ilustrar o uso do CLEANUP, veja o programa abaixo: *&---------------------------------------------------------------------* *& Report ZABAP101_EXCEPTION_CLEAN *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT ZABAP101_EXCEPTION_CLEAN.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY . r_demo->cleanup_live( ). CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do programa principal.'. ENDTRY.

view rawZABAP101_EXCEPTION_CLEAN hosted with

by GitHub

O objetivo do CLEANUP é para a limpeza de variáveis (memória) quando acontece uma exceção que será propagada. Seria o equivalente ao “quero limpar a bagunça antes de passar a exceção para ser tratada por quem chamou

o método”.

Pela

saída do programa, você consegue entender a sequência de execução do programa. Ocorre a exceção, o CLEANUP é executado e então o CATCH no programa principal.

CLEANUP Morto O CLEANUP somente é usado para “limpar a bagunça” quando a exceção está sendo propagada. No programa abaixo, o CLEANUP nunca será chamado. *&---------------------------------------------------------------------* *& Report ZABAP101_EXCEPTION_FAKE_CLEAN *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT ZABAP101_EXCEPTION_FAKE_CLEAN.

INCLUDE zabap101_exception_classes.

DATA: r_demo TYPE REF TO lcl_exception_demo.

START-OF-SELECTION.

CREATE OBJECT r_demo.

TRY .

r_demo->cleanup_dead( ). CATCH cx_sy_zerodivide. WRITE: / 'Executou o CATCH do programa principal.'. ENDTRY.

view rawZABAP101_EXCEPTION_FAKE_CLEAN hosted with

by GitHub

Na saída do programa vemos claramente que o sistema não executou o CLEANUP, pois a divisão por zero é tratada dentro do próprio método.

Conclusão Os conceitos de tratamento de exceção por classes não fica somente nisso, mas nesse post quis apenas expor os conceitos de propagação e CLEANUP. Para o uso correto de classes de exceções, é necessário entender encadeamento de exceções, hierarquia de exceções e textos da exceção. Isso será explorado em futuros posts. Aprenda a usar corretamente as classes de exceções e você entregará programas muito elegantes e de fácil manutenção.

Falsa Programação Orientada a Objetos BY FLÁVIO FURLAN · APRIL 1, 2012

Compartilhe!

O que é um programa ABAP orientado a objetos? Se um programa usa somente CALL METHOD e nenhum PERFORM, então trata-se de um programa orientado a objetos? Acredito que não. O uso de sintaxe de orientação a objetos não é evidência suficiente de que o programa foi pensado na forma de objetos trocando mensagens entre si. Trago para vocês dois pogramas com saídas idênticas, mas um usando uma “orientação a objetos” capenga e outro que considero uma melhor forma de resolver o problema pensando em objetos.

O Requisito Relatório de impressão de pedidos, com um total e a porcentagem de cada item em relação ao total do pedido. Os itens do pedido foram criados no próprio programa por uma questão prática e didática. No mundo real esses dados estariam armazenados numa tabela no banco de dados.

Orientação a Objetos “para inglês ver” A listagem abaixo é a solução usando orientação a objetos incompleta, ou seja, o programa tem uma classe para os objetos que representam itens do pedido. Cada objeto é um item do pedido, mas ainda tem alguns problemas. ZFAKE_OO

*&---------------------------------------------------------------------* *& Report ZFAKE_OO

*& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zfake_oo LINE-SIZE 90.

TYPES: BEGIN OF lty_product, product_id TYPE c LENGTH 5, description TYPE c LENGTH 30, quantity

TYPE n LENGTH 3,

unit_price TYPE p LENGTH 5 DECIMALS 2, END OF lty_product.

*----------------------------------------------------------------------* *

CLASS lcl_product DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_product DEFINITION.

PUBLIC SECTION. METHODS: constructor IMPORTING imc_product TYPE lty_product.

METHODS: set IMPORTING im_product TYPE lty_product,

get RETURNING value(re_product) TYPE lty_product.

PRIVATE SECTION. DATA: product TYPE lty_product.

ENDCLASS.

"lcl_product DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_product IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_product IMPLEMENTATION.

METHOD constructor. me->set( imc_product ). ENDMETHOD.

"constructor

METHOD set. me->product = im_product. ENDMETHOD.

"set

METHOD get. re_product = me->product. ENDMETHOD.

ENDCLASS.

"get

"lcl_product IMPLEMENTATION

DATA: r_product TYPE REF TO lcl_product, it_prods TYPE TABLE OF REF TO lcl_product, wa_product TYPE lty_product, vg_total TYPE lty_product-unit_price, vg_total_p TYPE lty_product-unit_price, vg_perc

TYPE lty_product-unit_price.

START-OF-SELECTION.

wa_product-product_id = '025'. wa_product-description = 'Cellphone 3000'. wa_product-quantity = 3. wa_product-unit_price = 1400.

CREATE OBJECT r_product EXPORTING imc_product = wa_product. APPEND r_product TO it_prods.

wa_product-product_id = '984'. wa_product-description = 'TV 40pol'. wa_product-quantity = 6. wa_product-unit_price = 3400.

CREATE OBJECT r_product EXPORTING imc_product = wa_product. APPEND r_product TO it_prods.

wa_product-product_id = '758'. wa_product-description = 'Audio System 439'. wa_product-quantity = 2. wa_product-unit_price = 7800.

CREATE OBJECT r_product EXPORTING imc_product = wa_product. APPEND r_product TO it_prods.

LOOP AT it_prods INTO r_product. wa_product = r_product->get( ). vg_total = wa_product-unit_price * wa_product-quantity. ADD vg_total TO vg_total_p. ENDLOOP.

LOOP AT it_prods INTO r_product. AT FIRST. FORMAT COLOR COL_HEADING. WRITE: /1 'ID', 5 'Description', 30 'Quant.', 50 'Unit Price', 70 'Total', 83 'Perc.'. FORMAT COLOR OFF. ULINE. ENDAT.

wa_product = r_product->get( ).

vg_total = wa_product-unit_price * wa_product-quantity. vg_perc = vg_total / vg_total_p * 100.

WRITE: /1 wa_product-product_id, 5 wa_product-description, 30 wa_product-quantity, 50 wa_product-unit_price, 70 vg_total, 83 vg_perc.

AT LAST. ULINE. FORMAT COLOR 7. WRITE: / 'Total of Purchase Order --> ', vg_total_p. ENDAT.

ENDLOOP.

view rawgistfile1.txt hosted with

by GitHub

Qual o problema com esse programa? Minha crítica a esse programa é a presença de regras de negócio no programa principal. É no programa principal que o cálculo do total do pedido é feito bem como o cálculo do percentual de cada item em relação ao pedido total. Se seguirmos o padrão MVC, esses cálculos deveriam estar encapsulados em alguma classe, fazendo o papel do Modelo. É exatamente isso que o

próxima solução leva em conta na hora de refatorar o código.

Refatorando Para Melhorar o Código Refatoração é um conceito no desenvolvimento de software onde melhoramos o projeto de software sem alterar os requistos do mesmo. Ou seja, vou alterar o programa para que a solução fique mais robusta, elegante, melhorando a legibilidade e possibilitando o reuso. Nessa primeira rodada de refatoração, eu procurei encapsular todos os cálculos em classes, para que possam ser reutilizadas em futuros desenvolvimentos. Repare que eu criei uma nova classe onde os cálculos são executados e o próprio relatório é impresso. ZBETTER_OO *&---------------------------------------------------------------------* *& Report ZBETTER_OO *& *&---------------------------------------------------------------------* *&

*& *&---------------------------------------------------------------------*

REPORT zbetter_oo LINE-SIZE 90.

TYPES: BEGIN OF lty_product, product_id TYPE c LENGTH 5, description TYPE c LENGTH 30, quantity

TYPE n LENGTH 3,

unit_price TYPE p LENGTH 5 DECIMALS 2, END OF lty_product.

*----------------------------------------------------------------------* *

CLASS lcl_product DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_product DEFINITION.

PUBLIC SECTION. METHODS: constructor IMPORTING imc_product TYPE lty_product.

METHODS: set IMPORTING im_product TYPE lty_product,

get RETURNING value(re_product) TYPE lty_product.

PRIVATE SECTION. DATA: product TYPE lty_product.

ENDCLASS.

"lcl_product DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_product IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_product IMPLEMENTATION.

METHOD constructor. me->set( imc_product ). ENDMETHOD.

"constructor

METHOD set. me->product = im_product. ENDMETHOD.

"set

METHOD get. re_product = me->product. ENDMETHOD.

ENDCLASS.

"get

"lcl_product IMPLEMENTATION

*----------------------------------------------------------------------*

*

CLASS lcl_purchase_order DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_purchase_order DEFINITION.

PUBLIC SECTION. METHODS: add_item IMPORTING im_item TYPE REF TO lcl_product,

get_po_total RETURNING value(re_total) TYPE lty_product-unit_price,

display_report.

PRIVATE SECTION. DATA: items_list TYPE TABLE OF REF TO lcl_product.

ENDCLASS.

"lcl_purchase_order DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_purchase_order IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_purchase_order IMPLEMENTATION.

METHOD add_item. APPEND im_item TO items_list.

ENDMETHOD.

"add_item

METHOD get_po_total. DATA: r_product TYPE REF TO lcl_product, wa_product TYPE lty_product, vg_total TYPE lty_product-unit_price.

LOOP AT items_list INTO r_product. wa_product = r_product->get( ). vg_total = wa_product-unit_price * wa_product-quantity. ADD vg_total TO re_total. ENDLOOP. ENDMETHOD.

"get_po_total

METHOD display_report. DATA: r_product TYPE REF TO lcl_product, wa_product TYPE lty_product, vg_total TYPE lty_product-unit_price, vg_total_p TYPE lty_product-unit_price.

LOOP AT items_list INTO r_product. AT FIRST. FORMAT COLOR COL_HEADING. WRITE: /1 'ID', 5 'Description', 30 'Quant.', 60 'Unit Price', 80 'Total'. FORMAT COLOR OFF. ULINE. ENDAT.

wa_product = r_product->get( ). vg_total = wa_product-unit_price * wa_product-quantity.

WRITE: /1 wa_product-product_id, 5 wa_product-description, 30 wa_product-quantity, 60 wa_product-unit_price, 80 vg_total.

ADD vg_total TO vg_total_p.

AT LAST. ULINE. FORMAT COLOR 7. WRITE: / 'Total of Purchase Order --> ', vg_total_p. ENDAT.

ENDLOOP. ENDMETHOD.

ENDCLASS.

"display_report

"lcl_purchase_order IMPLEMENTATION

DATA: r_product TYPE REF TO lcl_product, r_pur_ord TYPE REF TO lcl_purchase_order, wa_product TYPE lty_product.

START-OF-SELECTION.

CREATE OBJECT r_pur_ord.

wa_product-product_id = '025'. wa_product-description = 'Cellphone 3000'. wa_product-quantity = 3. wa_product-unit_price = 1400.

CREATE OBJECT r_product EXPORTING imc_product = wa_product. r_pur_ord->add_item( r_product ).

wa_product-product_id = '984'. wa_product-description = 'TV 40pol'. wa_product-quantity = 6. wa_product-unit_price = 3400.

CREATE OBJECT r_product EXPORTING imc_product = wa_product. r_pur_ord->add_item( r_product ).

wa_product-product_id = '758'. wa_product-description = 'Audio System 439'. wa_product-quantity = 2. wa_product-unit_price = 7800.

CREATE OBJECT r_product EXPORTING imc_product = wa_product. r_pur_ord->add_item( r_product ).

view rawgistfile1.txt hosted with

by GitHub

Próximos Passos Esse é a melhor implementação? Com certeza não. Escolhi não aplicar o MVC de maneira forte para dar chances para vocês pensarem em outras melhorias possíveis nesse programa. O que vocês fariam? Deixem nos comentários quais melhorias vocês fariam nos dois programas. Boa diversão!

Saídas dos Dois Programas Acima

Hello World Orientado a Objetos BY FLÁVIO FURLAN · FEBRUARY 7, 2012

Compartilhe!

Uma coisa que não mais iremos discutir aqui no ABAP101 é usar ou não programação orientada a objetos, por isso estamos abolindo procedural do ABAP101, caso você veja alguma coisa procedural aqui no site, por favor avise-me! Programação procedural pode parecer mais fácil, mas é porque estamos mais acostumados com esse tipo de programação do que orientada a objetos. Tome uma resolução em sua vida ABAPer, faça tudo em ABAP OO, mesmo um simples relatório. Comece com uma simples classe e daí vá evoluindo, mas fuja da “primeira dose” do procedural. Acredite a vida é bem melhor sem procedural! A orientação a objetos nos permite abstrações muito mais elegantes do que a procedural sendo os programas orientados a objetos muito mais fáceis de fazer manutenção, permitindo reuso real e muitas outras coisas que somente usando no diaa-dia podemos perceber. Pensando nisso, criei esse post onde mostro uma série de versões do famoso programa Hello World orientados a

objetos. A primeira vez que o programa Hello World em ABAP apareceu por aqui foi em 2007, nesse postaqui. A solução vai crescendo mostrando algumas formas de abstração resolvendo o mesmo problema de várias maneiras possíveis.

Primeira Versão Nessa versão temos uma classe chamada LCL_HELLO com apenas um único método DISPLAY_MESSAGE( ). *&---------------------------------------------------------------------* *& Report ZP_HELLO_OO *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zp_hello_oo NO STANDARD PAGE HEADING.

*----------------------------------------------------------------------* *

CLASS lcl_hello DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello DEFINITION. PUBLIC SECTION. METHODS: display_message. ENDCLASS.

"lcl_hello DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_hello IMPLEMENTATION

*----------------------------------------------------------------------*

* *----------------------------------------------------------------------* CLASS lcl_hello IMPLEMENTATION. METHOD display_message. WRITE: / 'Hello World OO!'. ENDMETHOD. ENDCLASS.

"display_message "lcl_hello IMPLEMENTATION

DATA: r_hello TYPE REF TO lcl_hello.

START-OF-SELECTION.

CREATE OBJECT r_hello.

r_hello->display_message( ).

view rawZP_HELLO_OO hosted with

by GitHub

ZP_HELLO_OO Nessa versão contém apenas uma única classe com um único método. Não temos muito de programação orientada a objetos aqui, mas já estamos deixando a sementinha do OO entrar em nossos programas.

Procedural Orientado a Objetos Vamos adicionar um parameter em nosso programa e começar a discutir algumas opções de abstração. A primeira opção eu chamo de “Procedural Orientado a Objetos”. Aqui não estamos pensando numa solução orientada a objetos, mas pensando em procedural.

*&---------------------------------------------------------------------* *& Report ZP_HELLO_OO_2 *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zp_hello_oo_2 NO STANDARD PAGE HEADING.

*----------------------------------------------------------------------* *

CLASS lcl_hello DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello DEFINITION. PUBLIC SECTION. METHODS: display_message IMPORTING i_name TYPE char30. ENDCLASS.

"lcl_hello DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_hello IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello IMPLEMENTATION. METHOD display_message. WRITE: / 'Hello: ', i_name. ENDMETHOD. ENDCLASS.

"display_message "lcl_hello IMPLEMENTATION

DATA: r_hello TYPE REF TO lcl_hello.

PARAMETERS: p_name TYPE char30 DEFAULT 'World OO!!'.

START-OF-SELECTION.

CREATE OBJECT r_hello.

r_hello->display_message( p_name ).

view rawZP_HELLO_OO_2 hosted with

by GitHub

ZP_HELLO_OO_2 Veja que poderíamos substituir perfeitamente por um FORM/PERFORM sem grandes mudanças na abstração, mas lembre-se que queremos evitá-los de qualquer maneira, mesmo assim essa versão é muito melhor que qualquer outra versão procedural.

Melhorando a Impressão da Mensagem Uma verão mais interessante que eu proporia seria a mostrada abaixo: *&---------------------------------------------------------------------* *& Report ZP_HELLO_OO_3 *& *&---------------------------------------------------------------------* *&

*& *&---------------------------------------------------------------------*

REPORT zp_hello_oo_3 NO STANDARD PAGE HEADING.

*----------------------------------------------------------------------* *

CLASS lcl_hello DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING i_name TYPE char30. METHODS: display_message.

PRIVATE SECTION. DATA: name TYPE char30.

ENDCLASS.

"lcl_hello DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_hello IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello IMPLEMENTATION. METHOD constructor. me->name = i_name. ENDMETHOD.

"constructor

METHOD display_message. WRITE: / 'Hello: ', name. ENDMETHOD. ENDCLASS.

"display_message "lcl_hello IMPLEMENTATION

DATA: r_hello TYPE REF TO lcl_hello.

PARAMETERS: p_name TYPE char30 DEFAULT 'World OO!!'.

START-OF-SELECTION.

CREATE OBJECT r_hello EXPORTING i_name = p_name.

r_hello->display_message( ).

view rawZP_HELLO_OO_3 hosted with

by GitHub

ZP_HELLO_OO_3 O resultado é o mesmo, mas agora temos um objeto LCL_HELLO que recebe um nome para saudação na sua construção e daí mostra a mensagem pelo método DISPLAY_MESSAGE( ). Já conseguiu imaginar um objeto que tem a responsabilidade de mostrar uma mensagem na tela?

Permitindo Operações No Objeto LCL_HELLO Ainda sim não estou contente com a solução. E se quisermos alterar o atributo NAME antes de mostrarmos a mensagem? E se quisermos saber o atributo NAME antes de mostrar para o usuário? Por isso é aconselhável criamos os métodos de acesso, os famosos SET e GET. Veja como ficaria nosso programa: *&---------------------------------------------------------------------* *& Report ZP_HELLO_OO_4 *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zp_hello_oo_4 NO STANDARD PAGE HEADING.

*----------------------------------------------------------------------* *

CLASS lcl_hello DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING ic_name TYPE char30. METHODS: set IMPORTING i_name TYPE char30, get

RETURNING value(r_name) TYPE char30.

METHODS: display_message.

PRIVATE SECTION. DATA: name TYPE char30.

ENDCLASS.

"lcl_hello DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_hello IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello IMPLEMENTATION. METHOD constructor. me->set( ic_name ). ENDMETHOD.

"constructor

METHOD set. me->name = i_name. ENDMETHOD.

"set

METHOD get. r_name = me->name. ENDMETHOD.

"get

METHOD display_message.

WRITE: / 'Hello: ', name. ENDMETHOD. ENDCLASS.

"display_message "lcl_hello IMPLEMENTATION

DATA: g_r_hello TYPE REF TO lcl_hello, g_v_hello TYPE char30.

PARAMETERS: p_name TYPE char30 DEFAULT 'World OO!!'.

START-OF-SELECTION.

CREATE OBJECT g_r_hello EXPORTING ic_name = p_name.

g_v_hello = g_r_hello->get( ).

IF g_v_hello = 'PROCEDURAL!!'. WRITE: / 'Hey, avoid first drink!'. g_r_hello->set( 'I would say... I love OO!' ). ENDIF.

g_r_hello->display_message( ).

view rawZP_HELLO_OO_4 hosted with

ZP_HELLO_OO_4

by GitHub

Pense que agora temos um objeto HELLO no qual podemos alterar seu estado (SET e GET) quantas vezes quisermos. A abstração está muito melhor agora, mas dá para melhorar ainda mais!

MVC no Hello World, Pode? Que história é essa do programa principal verificar se a mensagem é correta ou não!? Esse programa deveria cuidar apenas em receber a entrada do usuário e chamar o objeto para mostrar a mensagem. Não deveria ter nenhuma regra (de negócio). Essa verificação deveria estar no modelo, ou seja, classe LCL_HELLO. Então, vamos melhorar ainda mais o nossa classe: *&---------------------------------------------------------------------* *& Report ZP_HELLO_OO_5 *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zp_hello_oo_5 NO STANDARD PAGE HEADING.

*----------------------------------------------------------------------* *

CLASS lcl_hello DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING

ic_name TYPE char30.

METHODS: set IMPORTING i_name TYPE char30,

get RETURNING value(r_name) TYPE char30.

METHODS: display_message.

PRIVATE SECTION. DATA: name TYPE char30.

ENDCLASS.

"lcl_hello DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_hello IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello IMPLEMENTATION. METHOD constructor. CALL METHOD me->set EXPORTING i_name = ic_name. ENDMETHOD.

"constructor

METHOD set. IF i_name = 'PROCEDURAL!!'. me->name = 'I would say... I love OO!'. ELSE. me->name = i_name. ENDIF. ENDMETHOD.

"set

METHOD get. r_name = me->name. ENDMETHOD.

"get

METHOD display_message. WRITE: / 'Hello: ', name. ENDMETHOD. ENDCLASS.

"display_message "lcl_hello IMPLEMENTATION

DATA: g_r_hello TYPE REF TO lcl_hello, g_v_hello TYPE char30.

PARAMETERS: p_name TYPE char30 DEFAULT 'World OO!!'.

START-OF-SELECTION.

CREATE OBJECT g_r_hello EXPORTING ic_name = p_name.

PERFORM love_procedural.

g_r_hello->display_message( ). *&---------------------------------------------------------------------* *&

Form LOVE_PROCEDURAL

*&---------------------------------------------------------------------* *

text

*----------------------------------------------------------------------* * --> p1

text

* set EXPORTING i_name

= 'PROCEDURAL!!'.

ENDFORM.

" LOVE_PROCEDURAL

view rawZP_HELLO_OO_5 hosted with

by GitHub

ZP_HELLO_OO_5 Mesmo que algum Perform Fanboy invada seu programa na calada da noite, você já contará com uma certa proteção dentro do seu programa contra maus programadores terá protegido seu programa (já que ele não saberia alterar a classe :-p ). Além do mais, você também terá o conceito deencapsulamento aplicado aqui. Repare que a regra de não permitir o parâmetro NAME como “procedural !!” está agora embutido no método SET( ). Isso impede que o atributo seja alterado indevidamente por qualquer outro programador mal comportado que venha dar manutenção em seu código.

Ou seja, podemos alterar quantas vezes quisermos o atributo NAME, mas seguindo a regra definida no método SET( ). Mas será que daria para melhorar ainda ainda mais? Resposta é sim!

Versão Final! (Será?) *&---------------------------------------------------------------------* *& Report ZP_HELLO_OO_5 *& *&---------------------------------------------------------------------* *& *& *&---------------------------------------------------------------------*

REPORT zp_hello_oo_5 NO STANDARD PAGE HEADING.

*----------------------------------------------------------------------* *

CLASS lcl_hello DEFINITION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING ic_name TYPE char30.

METHODS: set IMPORTING i_name TYPE char30,

get RETURNING value(r_name) TYPE char30,

get_full_message RETURNING value(r_message) TYPE string.

PRIVATE SECTION. DATA: name TYPE char30.

ENDCLASS.

"lcl_hello DEFINITION

*----------------------------------------------------------------------* *

CLASS lcl_hello IMPLEMENTATION

*----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_hello IMPLEMENTATION. METHOD constructor. CALL METHOD me->set EXPORTING i_name = ic_name. ENDMETHOD.

"constructor

METHOD set. IF i_name = 'PROCEDURAL!!'. me->name = 'I would say... I love OO!'. ELSE. me->name = i_name. ENDIF.

ENDMETHOD.

"set

METHOD get. r_name = me->name. ENDMETHOD.

"get

METHOD get_full_message. CONCATENATE 'Hello:' me->name INTO r_message SEPARATED BY space. ENDMETHOD. ENDCLASS.

"get_full_message "lcl_hello IMPLEMENTATION

DATA: g_r_hello TYPE REF TO lcl_hello, g_v_hello TYPE string.

PARAMETERS: p_name TYPE char30 DEFAULT 'World OO!!'.

START-OF-SELECTION.

CREATE OBJECT g_r_hello EXPORTING ic_name = p_name.

g_v_hello = g_r_hello->get_full_message( ).

WRITE: / g_v_hello.

view rawZP_HELLO_OO_6 hosted with

by GitHub

ZP_HELLO_OO_6 Agora sim, temos uma separação bem definida entre quem é responsável por tratar com o usuário (programa principal, com PARAMETERS e WRITE) e quem cuidará das regras do texto (classe LCL_HELLO). Ainda sim, estaremos protegidos do Performa Fanboy e deixamos nosso programa reutilizável. Quando você começa a usar programação orientada a objetos você naturalmente começa a pensar nesses conceitos, como robustes, facilidade de manutenção, encapsulamento Como regra prática, procure deixa comandos WRITEs fora das classes de negócio (Model).

Conclusão Podemos ver que um simples problema de impressão do Hello World!! pode ganhar diversas soluções. Enquanto estou escrevendo esse parágrafo, já pensei mais outras duas. Isso prova que em programação orientada a objetos não existe certo ou errado, existe sim um equilíbrio, um balanço de quanto de reuso, abstração ou encapsulamento você quer aplicar ao seu problema. Isso dependerá muito de caso para caso. Mesmo assim não importa, continue programando somente em OO, acredite, um dia você irá me agradecer por isso. Será que essa é a versão final? Será que você ficou contente com apenas 6 versões? E aquelas duas que eu pensei, como seriam? Deixe sua versão do Hello World OO nos comentários. Estou muito curioso em saber como você resolveria o Hello World!! além do

WRITE: ‘Hello World!!’. Arquivo Nugget. (SAPLink)

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF