Curso de Basic
Código Limpo
Você está em: MarMSX >> Cursos >> BASIC
O conceito de código limpo está relacionado à um conjunto de boas práticas de programação, que tem como por objetivo garantir a qualidade do software criado. Envolve aspectos como:
- Simplicidade - solução simples para um determinado problema.
- Portabilidade - um código é facilmente adaptável a outros programas.
- Flexibilidade - o programa é fácil de modificar.
- Clareza - o código é simples de entender.
- Desempenho - resultados mais rápidos e com menor uso de recursos.
Devido às características da linguagem Basic, é importante aprender desde cedo essas regras, para que o seu programa não se torne algo "monstruoso".
Aqui vão algumas dicas de como estruturar seu programa em Basic:
- Criar variáveis com nomes relacionados aos dados
- Procurar seguir o padrão da linguagem
- Evitar duplicidade de código
- Evitar sub-rotinas muito longas
- Separar as sub-rotinas em blocos contíguos no código.
- Colocar uma identificação logo no inicio das sub-rotinas, utilizando-se de comentários.
- Evitar desvios desnecessários.
Criar variáveis com nomes relacionados aos dados
O Basic do MSX tem a limitação de apenas 2 caracteres para dar nome a uma variável. Entretanto, podemos ainda assim observar essa regra.
Imagine que três variáveis deverão armazenar os seguintes dados: nome, idade e sexo. Veja o seguinte programa:
10 INPUT"NOME";G$
20 INPUT"IDADE";HJ
30 INPUT"SEXO";D$
40 PRINT G$ + " é do sexo " + D$ + " e possui" + STR$(HJ) + " anos"
Se observarmos apenas a linha 40, fica difícil identificar o significado de cada variável. Reescrevendo o programa da forma correta, ficaria:
10 INPUT"NOME";N$
20 INPUT"IDADE";I
30 INPUT"SEXO";S$
40 PRINT N$ + " é do sexo " + S$ + " e possui" + STR$(I) + " anos"
O que torna mais simples a identificação das variáveis.
Procurar seguir o padrão da linguagem
No capítulo de variáveis, vimos que podemos definir uma variável como string através do comando DEFSTR. Esse mecanismo permite que tenhamos variáveis alfanuméricas com nomes sem o sinal de dólar "$" ao final. Ex:
10 DEFSTR N
20 N="MarMSX"
Entretanto, é uma convenção do Basic utilizar o dólar ao final de variáveis ou funções do tipo string. No programa anterior, a variável "N" poderia causar uma certa confusão, forçando ao programador identificar o tipo dela através de uma análise minuciosa no código.
Quando atribuímos a uma variável do tipo string um valor numérico, ou vice-versa, acontece um erro de tipo (Type mismatch). O programador observa a variável "N" sem o dólar ao final e fica se questionando o porquê desse erro.
Evitar duplicidade de código
Escrever mais de uma vez a mesma sub-rotina é um erro muito comum para muitos principiantes. Além de deixar o código mais extenso e menos legível, ocupa memória desnecessariamente. No MSX, a área de memória do Basic é bem limitada.
Exemplo de duplicidade de código: um programa para ler 5 nomes e imprimir o resultado na tela.
10 INPUT"NOME";N$
20 PRINT"Nome 1: "+N$
30 INPUT"NOME 2";N$
40 PRINT"Nome 1: "+N$
50 INPUT"NOME";N$
60 PRINT"Nome 3: "+N$
70 INPUT"NOME";N$
80 PRINT"Nome 4: "+N$
90 INPUT"NOME";N$
100 PRIN "Nome 5: "+N$
Solução para melhorar o código acima:
10 FOR I=1 TO 5
20 INPUT"NOME";N$
30 PRINT"Nome"+STR$(I)+": ";N$
40 NEXT I
Outro exemplo é quando temos um trecho de código que é utilizado mais de uma vez pelo programa. Quando isso acontecer, separe o trecho de código que se repete em um bloco a parte (sub-rotina ou função) e o chame através do recurso de GOSUB-RETURN. O capítulo de funções entra em detalhes de como criar esse mecanismo.
Para exemplificar, seja o código abaixo que desenha 3 estrelas na tela:
10 SCREEN 2
20 LINE(50,30)-(38,35),15
30 LINE(50,30)-(38,24),15
40 LINE(36,10)-(38,24),15
50 LINE(36,10)-(26,20),15
60 LINE(13,18)-(26,20),15
70 LINE(13,18)-(20,29),15
80 LINE(13,41)-(20,29),15
90 LINE(13,41)-(26,39),15
100 LINE(36,49)-(26,39),15
110 LINE(36,49)-(38,35),15
120 LINE(148,85)-(136,90),15
130 LINE(148,85)-(136,79),15
140 LINE(134,65)-(136,79),15
150 LINE(134,65)-(124,75),15
160 LINE(111,73)-(124,75),15
170 LINE(111,73)-(118,84),15
180 LINE(111,96)-(118,84),15
190 LINE(111,96)-(124,94),15
200 LINE(134,104)-(124,94),15
210 LINE(134,104)-(136,90),15
220 LINE(220,150)-(208,155),15
230 LINE(220,150)-(208,144),15
240 LINE(206,130)-(208,144),15
250 LINE(206,130)-(196,140),15
260 LINE(183,138)-(196,140),15
270 LINE(183,138)-(190,149),15
280 LINE(183,161)-(190,149),15
290 LINE(183,161)-(196,159),15
300 LINE(206,169)-(196,159),15
310 LINE(206,169)-(208,155),15
320 GOTO 320
Observe o tamanho do código resultante. Além disso, dá para identificar aqui que são 3 estrelas sendo desenhadas na tela?
O código acima poderia ser melhorado:
10 SCREEN 2
20 X=30:Y=30:R=20:RI=10:GOSUB 100
30 X=128:Y=85:R=20:RI=10:GOSUB 100
40 X=200:Y=150:R=20:RI=10:GOSUB 100
50 GOTO 50
100 '
110 ' Desenha estrela
120 '
130 PI=3.14159:AN=PI*2/5
140 FOR A=0 TO 2*PI-.1 STEP AN
150 LINE(X+R*COS(A), Y-R*SIN(A))-(X+RI*COS(A-AN/2), Y-RI*SIN(A-AN/2)),15
160 LINE(X+R*COS(A), Y-R*SIN(A))-(X+RI*COS(A+AN/2), Y-RI*SIN(A+AN/2)),15
170 NEXT A
180 RETURN
Agora o código é mais elegante, além do programador poder facilmente desenhar quantas estrelas quiser e do tamanho que quiser. Basta forncer as coordenadas centrais X e Y, os raios externos e interno R e RI e chamar a sub-rotina de desenhar a estrela.
O primeiro código é específico para cada estrela. Já o segundo é genérico e serve para desenhar uma estrela em qualquer lugar da tela. Um bom exemplo de simplicidade de código.
Evitar sub-rotinas muito longas
Uma sub-rotina deve tentar preocupar-se somente com as suas responsabilidades. Quando esta possuir muitas tarefas, deverão ser criadas outras sub-rotinas que realizem essas tarefas, desafogando a sub-rotina em questão.
Exemplo:
10 OP=1:S=100:T=10:GOSUB 100
20 PRINT"Velocidade:";V
30 END
100 '
110 ' Rotina geral
120 '
130 IF OP=1 THEN V = S/T ELSE 150
140 RETURN
150 IF OP=2 THEN M = (A+B)/2 ELSE 170
160 RETURN
170 A = L^2
180 RETURN
Correção:
10 S=100:T=10:GOSUB 100
20 PRINT"Velocidade:";V
30 END
100 '
110 ' Calcula a velocidade
120 '
130 V = S/T
140 RETURN
150 '
160 ' Calcula a média
170 '
180 M = (A+B)/2
190 RETURN
200 '
210 ' Calcula a área do quadrado
220 '
230 A = L^2
240 RETURN
Agora cada sub-rotina é responsável por sua tarefa específica.
Separar as sub-rotinas em blocos contíguos no código
Devemos evitar trechos de códigos relacionados à solução de um determinado problema intercalados, pois assim fica muito mais difícil entender a lógica do programa.
Exemplo: o programa a seguir denha um hexágono e um quadrado.
10 SCREEN 2
20 LINE(50,30)-(40,47),15
30 LINE(40,12)-(50,30),15
40 LINE(100,100)-(150,100),15
50 LINE(20,12)-(40,12),15
60 LINE(150,100)-(150,120),15
70 LINE(10,29)-(20,12),15
80 LINE(150,120)-(100,120),15
90 LINE(100,120)-(100,100),15
100 LINE(19,47)-(10,29),15
110 LINE(40,47)-(19,47),15
O código de desenho do hexágono está misturado com o código de desenho do quadrado. Que confusão!
Corrigindo:
10 SCREEN 2
20 ' Hexágono
30 LINE(50,30)-(40,47),15
40 LINE(40,12)-(50,30),15
50 LINE(20,12)-(40,12),15
60 LINE(10,29)-(20,12),15
70 LINE(19,47)-(10,29),15
80 LINE(40,47)-(19,47),15
90 ' Quadrado
100 LINE(100,100)-(150,100),15
110 LINE(150,100)-(150,120),15
120 LINE(150,120)-(100,120),15
130 LINE(100,120)-(100,100),15
Colocar uma identificação logo no inicio das sub-rotinas, utilizando-se de comentários
A listagem do código do Basic do MSX não possui etiquetas de marcação para que possamos discriminar trechos de código. Dessa forma, utilizamos o recurso de comentários para marcar o inicio de sub-rotinas. O comentário no Basic é feito através do comando REM ou do símbolo de aspas simples '.
Um exemplo de código com sub-rotinas sem marcação:
10 S=100:T=10:GOSUB 100
20 PRINT"Velocidade:";V
30 A=2:B=4:GOSUB 120
40 PRINT"Média:";M
50 L=10:GOSUB 140
60 PRINT"Área:";A
70 END
100 V = S/T
110 RETURN
120 M = (A+B)/2
130 RETURN
140 A = L^2
150 RETURN
Agora, com a marcação:
10 S=100:T=10:GOSUB 100
20 PRINT"Velocidade:";V
30 A=2:B=4:GOSUB 150
40 PRINT"Média:";M
50 L=10:GOSUB 200
60 PRINT"Área:";A
70 END
100 '
110 ' Calcula a velocidade
120 '
130 V = S/T
140 RETURN
150 '
160 ' Calcula a média
170 '
180 M = (A+B)/2
190 RETURN
200 '
210 ' Calcula a área do quadrado
220 '
230 A = L^2
240 RETURN
Agora fica mais fácil discriminar o código e localizar as sub-rotinas.
Evitar desvios desnecessários
O Basic é uma linguagem não estruturada, de execução seqüêncial e que utiliza bastante instruções de desvio. Dessa forma, o programa poderá se tornar um "código espaguete".
Um "código espaguete" é aquele que possui diversos desvios de forma desordenada, onde o fluxo de execução se assemelha a um prato de espaguete, onde os fios de macarrão estão todos entrelaçados.
Exemplo de código espaguete:
10 CLS
20 GOSUB 90
30 PRINT"Nome: "+N$
40 GOSUB 110
50 PRINT"Idade:";I
60 GOSUB 130
70 PRINT"Profissão: "+P$
80 END
90 INPUT"Nome";N$
100 RETURN
110 INPUT"Idade";I
120 RETURN
130 INPUT"Profissão";P$
140 RETURN
O código reescrito sem desvios:
10 CLS
20 INPUT"Nome";N$
30 INPUT"Idade";I
40 INPUT"Profissão";P$
50 PRINT"Nome: "+N$
60 PRINT"Idade:";I
70 PRINT"Profissão: "+P$
Preferir utilizar comandos prontos da linguagem
O Basic é uma linguagem interpretada, ou seja, cada comando do programa é lido e convertido para linguagem de máquina em tempo de execução. Assim, quando desenvolvemos algoritmos em Basic, há a necessidade de se interpretar cada comando dele. Entretanto, se uma função já existir, seus procedimentos são todos feitos em linguagem de máquina, aumentando a performance do MSX.
No exemplo a seguir, o programa realiza a troca de valores entre duas variáveis em três passos (linhas 30, 40 e 50).
10 TIME=0:A=1:B=2
20 FOR N=1 TO 1000
30 AUX=A
40 A=B
50 B=AUX
60 NEXT N
70 PRINT "Tempo: ";TIME/60;" segundos"
Saída:
Tempo: 6.98 segundos
Reescrevendo o programa e utilizando o comando SWAP do Basic, substituimos os três comandos anteriores por um. Observe o ganho de performance.
10 TIME=0:A=1:B=2
20 FOR N=1 TO 1000
30 SWAP A,B
40 NEXT N
50 PRINT "Tempo: ";TIME/60;" segundos"
Saída:
Tempo: 3.68 segundos
A troca que antes era feita em Basic agora é toda realizada em Assembly.
Aumento de performance com variáveis do tipo inteiro
Encontramos essa dica na revista argentina Load MSX #1, no qual a utilização de variáveis de controle do tipo inteiro aumenta a performance do MSX.
Vamos reescrever o programa de troca de variáveis da seção anterior, substituindo a variável de controle N por N%.
10 TIME=0:A=1:B=2
20 FOR N%=1 TO 1000
30 SWAP A,B
40 NEXT N%
50 PRINT "Tempo: ";TIME/60;" segundos"
Saída:
Tempo: 2.55 segundos
Ao substituir as variáveis A e B por A% e B%, respectivamente, o tempo gasto foi de 2.23 segundos.