Field-Symbols: O que são e suas vantagens – Por Fábio Kazunari

Eis um post que não vemos todos os dias: um post de um leitor interessado em aprender e que compartilha suas ideias! Como eu havia dito no último post sobre o LinkedIn: (Discussão no LinkedIn: Gerenciamento de qualidade de código ABAP) estou fazendo um esforço cada vez maior para fazer parte desta rede social. E foi por lá que recebi uma mensagem semana passada do nosso leitor de longa data Fábio Kuzunari pedindo um post sobre field-symbols. Ao mesmo tempo, tinha uma lista de razões internamente que me dizia que este tópico poderia ser escrito pelo próprio Kazunari – ao escrever um post devemos nos preocupar no entendimento dos outros e consequentemente temos que mudar a forma que estamos acostumados a colocar as ideias no papel. Além disso não é sábio colocar código ABAP na web sem ao menos testá-lo. Por isso os posts que contém código são sempre os mais trabalhosos ao passo que são os que mais agregam e fixam conteúdo na minha opinião. Vocês não podem deixar de ler o resultado do trabalho do nosso leitor que topou o desafio de fazer um post sobre field-symbols.

pointer_field_symbol

Field Symbols (por Fábio Kazunari)

(agradecimentos pela revisão realizada por Fabio Ferri) – Sim, o terceiro Fabio deste post. Em programação, um ponteiro ou apontador é um tipo de dado de uma linguagem de programação cujo valor se refere diretamente a um outro valor alocado em outra área da memória, através de seu endereço. Exemplificando:

Se uma pessoa for um ponteiro e estiver apontado para um copo, ao jogar água na pessoa, o copo se encherá de água.

O ponteiro no abap é conhecido como Field-symbol e sempre são declarado entre “<>”, por exemplo :

FIELD-SYMBOLS : <fs_tabela> TYPE ANY TABLE ,
<fs_voo> like line of t_voo,
<fs_teste> TYPE any,
<fs_campo> TYPE any.

Considerações

Performance: com o ponteiro o processamento em uma velocidade Comparando com Work area obtém os seguintes resultados para 10.000 registro da BSEG

report zteste_waxfs.
data: t_bseg type standard table of bseg,
wa_bseg like line of t_bseg.
*
data: v_comeco type timestampl,
v_fim type timestampl,
v_tempo_wa type p decimals 5,
v_tempo_fs type p decimals 5,
v_economia type p decimals 5.

field-symbols: <fs_bseg> like line of t_bseg.

select *
from bseg
into table t_bseg
up to 10000 rows.

get time stamp field v_comeco.
loop at t_bseg into wa_bseg.
endloop.
get time stamp field v_fim .
v_tempo_wa = v_fim - v_comeco.
write: /(15) 'Work area', v_tempo_wa .

clear: v_comeco,
v_fim .

get time stamp field v_comeco.
loop at t_bseg assigning <fs_bseg>.
endloop.
get time stamp field v_fim .
v_tempo_fs = v_fim - v_comeco.
write: /(15) 'Field-Symbol', v_tempo_fs.
v_economia = v_tempo_wa - v_tempo_fs .
write: /(15) 'Economia de :', v_economia.

 

Outra vantagem é na modificação pois na work área há a necessidade do comando Modify. Porém use com cuidado pois uma vez alterado o valor no Field-symbol não tem volta pois você está alterando o valor diretamente na tabela interna exemplo:

report zteste_modify.

DATA: t_bseg TYPE STANDARD TABLE OF bseg,
t_aux TYPE TABLE OF sy-tabix,
wa_bseg LIKE LINE OF t_bseg,
wa_aux LIKE LINE OF t_aux.
*
DATA: v_comeco TYPE timestampl,
v_fim TYPE timestampl,
v_tempo_wa TYPE p DECIMALS 5,
v_tempo_fs TYPE p DECIMALS 5,
v_economia TYPE p DECIMALS 5.

field-symbols <fs_bseg> like line of t_bseg.

SELECT *
FROM bseg
INTO TABLE t_bseg
UP TO 10000 ROWS.

GET TIME STAMP FIELD v_comeco.
LOOP AT t_bseg INTO wa_bseg.
clear wa_aux.
wa_bseg-sgtxt = 'KAZU'.
MODIFY t_bseg FROM wa_bseg.
ENDLOOP.
GET TIME STAMP FIELD v_fim .
v_tempo_wa = v_fim - v_comeco.
WRITE: /(15) 'Work area', v_tempo_wa .

CLEAR: v_comeco,
v_fim ,
t_aux[].

GET TIME STAMP FIELD v_comeco.
LOOP AT t_bseg ASSIGNING <fs_bseg>.
<fs_bseg>-sgtxt = 'Kazu'.
ENDLOOP.
GET TIME STAMP FIELD v_fim .
v_tempo_fs = v_fim - v_comeco.
WRITE: /(15) 'Field-Symbol', v_tempo_fs.
v_economia = v_tempo_wa - v_tempo_fs .
WRITE: /(15) 'Economia de :', v_economia.

 

Na inserção de dado durante usando Field-symbol para inserir dados na tabela interna:

REPORT zteste_kazu.

DATA: t_bseg TYPE STANDARD TABLE OF bseg,
t_aux TYPE TABLE OF sy-tabix,
wa_bseg LIKE LINE OF t_bseg,
wa_aux LIKE LINE OF t_aux.
*
DATA: v_comeco TYPE timestampl,
v_fim TYPE timestampl,
v_tempo_wa TYPE p DECIMALS 5,
v_tempo_fs TYPE p DECIMALS 5,
v_economia TYPE p DECIMALS 5.

FIELD-SYMBOLS: <fs_bseg> LIKE LINE OF t_bseg,
<fs_aux> LIKE LINE OF T_aux.

SELECT *
FROM bseg
INTO TABLE t_bseg
UP TO 10000 ROWS.

GET TIME STAMP FIELD v_comeco.
LOOP AT t_bseg INTO wa_bseg.
CLEAR wa_aux.
wa_aux = sy-tabix.
APPEND wa_aux TO t_aux.
ENDLOOP.
GET TIME STAMP FIELD v_fim .
v_tempo_wa = v_fim - v_comeco.
WRITE: /(15) 'Work area', v_tempo_wa .

CLEAR: v_comeco,
v_fim ,
t_aux[].

GET TIME STAMP FIELD v_comeco.
LOOP AT t_bseg ASSIGNING <fs_bseg>.
append initial line to t_aux assigning <fs_aux>.
<fs_aux> = sy-tabix.
ENDLOOP.
GET TIME STAMP FIELD v_fim .
v_tempo_fs = v_fim - v_comeco.
WRITE: /(15) 'Field-Symbol', v_tempo_fs.
v_economia = v_tempo_wa - v_tempo_fs .
WRITE: /(15) 'Economia de :', v_economia.

 

Usando Field-symbol para inserir dados ainda a um ganho em performance, porém o que me deixou mais surpreso que com a work área e append seria muito mais rápido!!!

REPORT zteste_kazu.

DATA: t_bseg TYPE STANDARD TABLE OF bseg,
t_aux TYPE TABLE OF sy-tabix,
wa_bseg LIKE LINE OF t_bseg,
wa_aux LIKE LINE OF t_aux.
*
DATA: v_comeco TYPE timestampl,
v_fim TYPE timestampl,
v_tempo_wa TYPE p DECIMALS 5,
v_tempo_fs TYPE p DECIMALS 5,
v_economia TYPE p DECIMALS 5.

FIELD-SYMBOLS: <fs_bseg> LIKE LINE OF t_bseg,
<fs_aux> LIKE LINE OF T_aux.

SELECT *
FROM bseg
INTO TABLE t_bseg
UP TO 10000 ROWS.

GET TIME STAMP FIELD v_comeco.
LOOP AT t_bseg INTO wa_bseg.
CLEAR wa_aux.
wa_aux = sy-tabix.
APPEND wa_aux TO t_aux.
ENDLOOP.
GET TIME STAMP FIELD v_fim .
v_tempo_wa = v_fim - v_comeco.
WRITE: /(15) 'Work area', v_tempo_wa .

CLEAR: v_comeco,
v_fim ,
t_aux[].

GET TIME STAMP FIELD v_comeco.
LOOP AT t_bseg ASSIGNING <fs_bseg>.
append initial line to t_aux assigning <fs_aux>.
<fs_aux> = sy-tabix.
ENDLOOP.
GET TIME STAMP FIELD v_fim .
v_tempo_fs = v_fim - v_comeco.
WRITE: /(15) 'Field-Symbol', v_tempo_fs.
v_economia = v_tempo_wa - v_tempo_fs .
WRITE: /(15) 'Economia de :', v_economia.

 

Pontos de atenção

Dumps : Por ser um ponteiro o field-symbol não existe “fisicamente”. Ele é somente um endereço lógico , se não estiver apontando para algum “lugar” e você tentar usá-lo para atribuir algum valor ou mesmo comparar valores ocorrerá um dump .

Seguindo o exemplo : se você for um ponteiro e não estiver apontando para alguma coisa e jogarem água em você, a água não iria para lugar nenhum , ocorrendo um erro no universo … Por isso sempre é necessário verificar se o field-symbol está apontando para o endereço (com exceção no uso de LOOP AT e no insert)!

READ TABLE t_teste ASSIGNING <fs_teste> INDEX 1.
IF <fs_teste> IS assigned.

ENDIF.
ASSIGN wa_teste TO <fs_teste>.
IF <fs_teste> IS assigned.

ENDIF.

Códigos alienígenas: field-symbol permite um código dinâmico, sem um comentário adequado no código não será uma tarefa fácil de compreender o código e a manutenção será trabalhosa e nos pior caso irão descartar a rotina.

read table t_dados with table key tabname = p_tabela
transporting no fields.

loop at t_dados assigning <fs_dados> from sy-tabix.
if not <fs_dados>-tabname eq p_tabela.
exit.
endif.
clear l_estrutura.
insert initial line into table t_hr_info assigning <fs_info>.
<fs_info>-infty = <fs_dados>-tabname+1(4).

concatenate <fs_dados>-tabname <fs_dados>-fieldname
into <fs_info>-fname
separated by '-'.

concatenate c_work_area <fs_info>-type
into l_estrutura
separated by '_'.

assign (l_estrutura) to <fs_estrutura>.
if sy-subrc is initial
assign component <fs_dados>-fieldname of structure <fs_estrutura> to <fs_campo>.

if sy-subrc is initial.
<fs info>-fval = <fs_campo>.
endif.
endif.
endloop.

 

Perigo

Em algum momento da vida do consultor, será necessário consultar uma variável em um desenvolvimento Standart , por um acaso essa variável não pode ser acessada no ponto aonde queremos.

ASSIGN ('(SAPMP56T)RVDAT ') TO <fs_campo>.

O perigo ocorre quando o consultor decide muda o valor deste campo sem uma analise de aonde essa variável vai ser usado durante o processamento Standard .

Considerações finais

Com field-symbols ganhamos velocidade e flexibilidade , porém nada é de graça o custo do ponteiro é a atenção dobrada no desenvolvimento, pois um descuido pode gerar um DUMP, confusão pelos códigos dinâmicos e na pior das hipóteses gravar dados errado em uma transação Standard pois alguém mudou a variável dinamicamente!

Fábio Kuzunari


 

Minhas dicas sobre field-symbols

Como não poderia deixar de lado minha opinião sobre field-symbols solicitada pelo nosso leitor, aqui vai ela em forma de breves tópicos pois o post acima já agregou muito mais que minha opinião:

  • Use field-symbols dentro de LOOPs. Saiba exatamente onde estão as teclas < e > do seu teclado para não ter preguiça de declará-los
  • Caso queira reaproveitar um field-symbol depois de um LOOP, não o faça. Você irá esquecer cedo ou tarde o uso do UNASSIGN. Declare outro field-symbol para evitar erros.
  • Se você declarou um field-symbol globalmente no top include, deixe seu celular ligado durante a noite pois você pode precisar… ou melhor… alguém precisar de você
  • Caso você precise de mais de um field-symbol para a mesma tabela interna, dê nomes ilustrativos ao invés de e . Ainda evite copy & paste deste código.
  • Caso esteja usando ABAP Objects, sempre confiro a definição da tabela interna que usarei. Caso ela seja READ-ONLY, evito o field-symbol pois ele é mais poderoso o primeiro.

Meu estilo de programação faz uso extensivo de field-symbols. Eu raramente populo uma tabela interna registro por registro ou uso alguma estrutura auxiliar para modificá-la. Como sempre estou usando métodos pequenos, nunca faço o uso de field-symbols globais que possam ser perigosamente reaproveitados por alguém que dê manutenção no código. Caso eu veja algum field-symbol global usado num só FORM ou método, eu o movo para uma declaração local.

Escreva para o ABAP101 você também!

Gostaria de explicar algo em ABAP? Tem algum bom exemplo? Gostaria que algum recrutador ache um post interessante seu no Google ao procurar por seu nome? Faça como o Fábio Kazunari! Escreva para a gente também sobre o tópico que mais lhe agrada.

Fábio Pagoti

Formado em Sistemas de Informação pela Universidade de São Paulo. Comecei no mundo da programação com Java mas logo caí no mundo ABAP. Estagiei na Nestlé por 2 anos e foi lá onde conheci o Furlan. Depois de efetivado fui morar no Canadá por 1 ano onde pude aprender a área de testes em desenvolvimento de software. Hoje sou consultor e instrutor ABAP, amante de projetos Open Source, Wordpress, Data Mining e da esfera SAP. Siga-me no twitter: @fabiopagoti

Você pode gostar...

5 Resultados

  1. Matheus Bruno disse:

    Estou iniciando no ABAP. Este artigo foi muito útil!

  2. Paulo disse:

    Post muito interessante, valeu também pelas observações!

  3. Fábio Pagoti disse:

    Obrigado pelo comentário Paulo.

  4. Eduardo Pereira disse:

    Dicas valiosas. Parabéns pelo excelente trabalho!