Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
May 14, 2021 06:09 pm GMT

Anotaes Captulo 3: Functions

  • As funes permaneceram durante a evoluo da programao;

  • O que torna uma funo fcil de ler e entender?

Pequenas!

  • A primeira regra para funes que elas devem ser pequenas. A segunda que precisam ser mais espertas do que isso.
  • Funes devem ter no mximo 20 linhas;
  • Kent Beck escreveu um programa (Java/Swing) que ele chamava de Sparkle e cada funo desse programa tinha duas, ou trs, ou quatro linhas e essa deve ser o tamanho das nossas funes.

Blocos e Indentao

  • Os blocos dentro de if, else, while e outros devem ter apenas uma linha. Possivelmente uma chamada de funo.
  • O nvel de indentao de uma funo deve ser de, no mximo, um ou dois nveis.
  • Facilita a leitura de compreenso das funes.

Faa uma Coisa

  • AS FUNES DEVEM FAZER UMA COISA. DEVEM FAZ-LA BEM. DEVEM FAZER APENAS ELA.
  • Uma forma de saber se uma funo faz mais de uma coisa se voc pode extrair outra funo dela a partir de seu nome que no seja apenas uma reformulao de sua implementao.

Sees Dentro de Funes

  • Se temos sees, como declaraes, inicializaes, um sinal de est fazendo mais de uma coisa;
  • No d para dividir em sees as funes que fazem apenas uma coisa.

Um Nvel de Abstrao por Funo

  • Vrios nveis dentro de uma funo sempre geram confuso.
  • Leitores podem no conseguir dizer se uma expresso determinada um conceito essencial ou um mero detalhe.

Ler o Cdigo de Cima para Baixo: Regra Decrescente

  • Queremos que o cdigo seja lido de cima para baixo, como uma narrativa.
  • Regra Decrescente: Cada funo seja seguida pelas outras no prximo nvel de modo que possamos ler o programa descendo um nvel de cada vez conforme percorremos a lista de funes.
  • Acaba sendo muito difcil para programadores aprenderem a seguir essa regra e criar funes que fiquem em apenas um nvel.
  • muito importante aprender esse truque, pois ele o segredo para manter funes curtas e garantir que faam apenas uma coisa.
  • Fazer com que a leitura do cdigo possa ser feita de cima para baixo como uma srie de pargrafos TO uma tcnica eficiente para manter o nvel consistente.

Estrutura Switch

  • difcil criar uma estrutura switch pequena;
  • Tambm difcil criar uma que faa apenas uma coisa.
  • Por padro, os switch sempre fazem muitas coisas.
  • Mas podemos nos certificar se cada um est em uma classe de baixo nvel e nunca repetido, usando o polimorfismo.
  • A seguinte funo mostra apenas uma das operaes que podem depender do tipo de funcionrio:
public Money calculatePay(Employee e) throws InvalidEmployeeType {    switch (e.type) {        case COMMISSIONED:            return calculateCommissionedPay(e);        case HOURLY:            return calculateHourlyPay(e);        case SALARIED:            return calculateSalariedPay(e);        default:            throw new InvalidEmployeeType(e.type);    }}
  • Essa funo acima tem vrios problemas:
    • Primeiro: Ela grande, e quando adicionarmos novos tipos de funcionrios ela crescer mais ainda;
    • Segundo: Ela faz mais de uma coisa;
    • Terceiro: Ela viola o Princpio da Responsabilidade nica (SRP - SOLID) por haver mais de um motivo para alter-la;
    • Quarto: Ela viola o Princpio de Aberto-Fechado (OCP - SOLID), porque ela precisa ser modificada sempre que novos tipos forem adicionados;
    • E possivelmente o pior problema a quantidade ilimitada de outras funes que tero a mesma estrutura, por exemplo:
isPayday(Employee e, Date date),

Ou

deliverPay(Employee e, Money pay),
  • A soluo nesse caso inserir uma estrutura switch no fundo de uma ABSTRACT FACTORY:
    • Assim, a factory usar o switch para criar instncias apropriadas derivadas de Employee;
    • As funes: calculatePay, isPayday e deliverPay, sero enviadas de forma polifrmica atravs da interface Employee.
  • A regra geral para estruturas switch que so aceitveis se aparecerem apenas uma vez para a criao de objetos polimrficos, e se estiverem escondidas atrs de uma relao de herana de modo que o resto do sistema no possa enxerg-la. Mas cada caso um caso e podem haver casos de no respeitar todas essas regras.
  • Assim temos como soluo o seguinte cdigo:
public abstract class Employee {    public abstract boolean isPayday();    public abstract Money calculatePay();    public abstract void deliverPay(Money pay);}-----------------public interface EmployeeFactory {    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;}-----------------public class EmployeeFactoryImpl implements EmployeeFactory {    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {        switch (r.type) {            case COMMISSIONED:                return new CommissionedEmployee(r) ;            case HOURLY:                return new HourlyEmployee(r);            case SALARIED:                return new SalariedEmploye(r);            default:                throw new InvalidEmployeeType(r.type);        }    }}

Use Nomes Descritivos

  • muito importante ter bons nomes;
  • Lembre-se do princpio de Ward: Voc sabe que est criando um cdigo limpo quando cada rotina que voc l como voc esperava;
    • Metade do esforo para satisfazer esse princpio escolher bons nomes para funes pequenas que fazem apenas uma coisa.
    • Quanto menor e mais centralizada a funo, mais fcil pensar em um nome descritivo.
  • No tenha medo de criar nomes extensos, pois eles so melhores do que um pequeno e enigmtico. Um nome longo e descritivo melhor do que um comentrio extenso e descritivo.
  • Experimente diversos nomes at encontrar um que seja bem descritivo.
  • Seja consistente nos nomes. Use as mesmas frases, substantivos e verbos nos nomes de funes de seu mdulo.
  • Exemplos:
    • includeSetup-AndTeardownPages, includeSetupPages, includeSuiteSetupPage , e includeSetupPage.

Parmetros de Funes

  • A quantidade ideal de parmetros para uma funo zero. Depois vem um, seguido de dois. Sempre que possvel devem-se evitar trs parmetros. Para mais de trs deve-se ter um motivo muito especial, mesmo assim no devem ser usados.
  • Parmetros so complicados. Eles requerem bastante conceito.
  • Os parmetros so mais difceis ainda a partir de um ponto de vista de testes:
    • Imagina a dificuldade de escrever todos os casos de testes para se certificar de que todas as vrias combinaes de parmetros funcionem adequadamente.;
    • Se no houver parmetros, essa tarefa simples;
    • Se houver um, no to difcil assim;
    • Com dois, a situao fica um pouco desafiadora. Com mais de dois, pode ser desencorajador testar cada combinao de valores apropriados.
    • Os parmetros de sada so mais difceis de entender do que os de entrada.
  • Por fim, um parmetro de entrada a melhor coisa depois de zero parmetro!

Formas Mondicas (Um parmetro) Comuns

  • Duas razes para se passar um nico parmetro a uma funo:
    • Voc pode estar fazendo uma pergunta sobre aquele parmetro, exemplo: boolean fileExists(MyFile).
    • Ou voc pode trabalhar parmetro, transformando-o em outra coisa e retornando-o, exemplo: InputStream fileOpen(MyFile) transforma a String do nome de um arquivo em um valor retornado por InputStream.
    • Outro uso menos comum para uma funo de evento, neste caso h um parmetro de entrada, mas nenhum de sada. Cuidado ao usar essa abordagem!
  • Se uma funo vai transformar seu parmetro de entrada, a alterao deve aparecer como o valor retornado. Por exemplo:
StringBuffer transform(StringBuffer in)

melhor do que:

void transform(StringBuffer out)

Parmetros Lgicos

  • Esses parmetros so feios.
  • Passar um booleano para uma funo certamente uma prtica horrvel, pois ele complica imediatamente a assinatura do mtodo, mostrando explicitamente que a funo faz mais de uma coisa.
  • Ela faz uma coisa se o valor for verdadeiro, e outra se for falso!

Funes Dades (Dois parmetros)

  • Uma funo com um parmetro mais difcil de entender do que com um.
  • Com dois parmetros, preciso aprender a ignorar um dos parmetros, porm o local que ignoramos justamente onde os bugs se escondero.
  • Casos em dois parmetros so necessrios:
    • Por exemplo, uma classe com eixos cartesianos, como por exemplo, Point p = new Point(0, 0), preciso ter os dois parmetros;
    • Nesse caso os dois parmetros so componentes de um nico valor.
  • Mesmo funes bvias como assertEquals(expected, actual), so problemticas!
  • Quantas vezes j colocou actual on deveria ser expected?
  • Os dois parmetros no possuem uma ordem pr-determinada natural;
  • A ordem expected, actual uma conveno que requer prtica para assimil-la.
  • Funes com dois parmetros no so ruins e vamos us-las!
  • Mas devemos tentar converter essas funes em funes de um parmetro, usando outro mtodo ou variveis de classe ou ainda outra classe que recebe o parmetro no construtor.

Trades (Trs parmetros)

  • So consideravelmente mais difceis de entender do que as com dois parmetros;
  • Pense bastante antes de criar uma trade!
  • O processo de ordenao, pausa e ignorao apresenta mais do que o dobro de dificuldade.

Objetos como parmetro

  • Quando uma funo parece precisar de mais de dois parmetros, provvel que alguns desses parmetros devam ser agrupados em uma classe prpria. Por exemplo:
Circle makeCircle(double x, double y, double radius);Circle makeCircle(Point center, double radius);
  • Criar objetos para reduzir o nmero de parmetros pode parecer trapaa, mas no .

Listas como parmetro

  • Quando queremos passar um nmero varivel de parmetros para uma funo, como por exemplo:
String.format("%s worked %.2f hours.", name, hours);
  • Se os parmetros forem todos tratados da mesma forma, eles sero equivalentes a um nico parmetro do tipo List.
  • Por isso, o String.format uma funo com dois parmetros:
public String format(String format, Object... args)

Verbos e palavras-chave

  • Escolher bons nomes para uma funo pode ajudar muito a explicar a inteno da funo e a ordem e a inteno dos parmetros.
  • No caso de funo com um parmetro, a funo e o parmetro devem formar um par verbo/substantivo muito bom. Por exemplo, write(name), qualquer que seja essa coisa name est sendo write (escrito). Um nome ainda melhor poderia ser writeField(name), que indica que o name um campo.
  • Por exemplo: assertEquals pode ser melhor escrito como assertExpectedEqualsActual(expected, actual), assim diminui o problema de ter que lembrar a ordem dos parmetros.

Evite Efeitos Colaterais

  • Efeitos colaterais so mentiras.
  • Se a funo promete fazer apenas uma coisa, mas tambm faz outras coisas escondidas. Vamos ter efeitos indesejveis. Por exemplo:
public class UserValidator {    private Cryptographer cryptographer;    public boolean checkPassword(String userName, String password) {        User user = UserGateway.findByName(userName);        if (user != User.NULL) {            String codedPhrase = user.getPhraseEncodedByPassword();            String phrase = cryptographer.decrypt(codedPhrase, password);            if ("Valid Password".equals(phrase)) {                Session.initialize();                return true;            }        }        return false;    }}

Essa funo de verificar a senha, tem um efeito colateral, que a chamada do Session.initialize(), o nome checkPassword indica que verifica a senha, mas no indica que tambm inicializa a sesso. Assim, podemos correr o risco de apagar os dados da sesso existente quando ele decidir autenticar o usurio.

  • Assim, temos um efeito colateral de acoplamento. No caso o checkPassword s pode ser chamada quando realmente formos inicializar a sesso, do contrrio dados sero perdidos.
  • Se realmente queremos manter o acoplamento dessa forma, deveramos deixar explcito no nome da funo, como por exemplo, checkPasswordAndInitializeSession.

Parmetros de Sada

  • Quando precisamos reler a assinatura da funo para entender o que acontece com o parmetro de entrada, temos um problema, e isso deve ser evitado!
  • De modo geral, devemos evitar parmetros de sada. Caso a funo precise alterar o estado de algo, mude o estado do objeto que a pertence.

Separao comando-consulta

  • As funes devem fazer ou responder algo, mas no ambos. Ou alterar o estado de um objeto ou retorna informaes sobre ele.
  • Fazer as duas tarefas costuma gerar confuso. Por exemplo:
public boolean set(String attribute, String value);

Pode levar a instrues estranhas como:

if (set("username", "unclebob"))...

E fica um caos a interpretao, o que significa esse trecho de cdigo, estamos perguntando se o atributo username recebeu o valor unclebob? Ou se username obteve xito ao receber o valor unclebob?
A inteno neste cdigo acima ter o set como um adjetivo, assim deveramos ler se o atributo username anteriormente recebeu o valor unclebob, porm no fica bem claro, para isso devemos usar o nome melhor como setAndCheckIfExists, mesmo assim ainda tinhamos um cdigo estranho:

if (attributeExists("username")) {setAttribute("username", "unclebob");...}

Prefira excees a retorno de cdigos de erro

  • Fazer funes retornarem cdigos de erros uma leve violao da separao comando-consulta, pois os comandos so usados como expresses de comparao em estruturas if:
if (deletePage(page) == E_OK)
  • Retornar cdigo de erro se torna um problema para quem chama a funo, j que ele vai ter que lidar com o erro e possivelmente criar estruturas aninhadas, deixando o cdigo muito ruim.
  • Mas se usarmos excees, o cdigo de tratamento de erro pode ficar separado do cdigo e ser simplificado, por exemplo:
try {    deletePage(page);    registry.deleteReference(page.name);    configKeys.deleteKey(page.name.makeKey());}catch (Exception e) {    logger.log(e.getMessage());}
  • Extraia os blocos try/catch
    • Esses blocos no tem o direito de serem feios;
    • Eles confundem a estrutura do cdigo e misturam o tratamento de erro com o processamento normal do cdigo;
    • melhor colocar esses blocos em suas prprias funes:
public void delete(Page page) {    try {        deletePageAndAllReferences(page);    }    catch (Exception e) {        logError(e);    }}private void deletePageAndAllReferences(Page page) throws Exception {    deletePage(page);    registry.deleteReference(page.name);    configKeys.deleteKey(page.name.makeKey());}private void logError(Exception e) {    logger.log(e.getMessage());}

Assim, a funo delete s faz o tratamento de erro, a funo deletePageAndAllReferences s trata de processos que excluem toda pgina, e o log apenas adicionar a mensagem do erro no console.

Tratamento de erro uma coisa s

  • Tratamento de erro uma coisa s, portanto uma funo que trata erros no deve fazer mais nada!
  • Assim, a instruo try deve ser a primeira instruo da funo e nada mais antes dela.
  • Assim, podemos evitar o uso de classe de erros como por exemplo Error.java, sendo um Enum como vrios erros e que tudo dependeria dessa classe.

Evite repetio

  • Repetio um problema.
  • Sempre ser necessrio modificar mais de um lugar quando o algoritmo mudar.
  • E nisso podemos omitir erros gerando bugs.
  • A duplicao pode ser a raiz de todo o mal no software.
  • Muitos princpios e prticas tm sido criadas com a finalidade de controlar ou eliminar a repetio de cdigo.

Programao estruturada

  • Programao estruturada de Edsger Dijkstra: Cada funo e bloco dentro de uma funo deve ter uma entrada e uma sada.
  • Apenas em funes maiores tais regras proporcionam benefcios significativos.
  • Se mantivermos funes pequenas, as vrias instrues return, break, continue no traro problemas.Mas instrues como goto s devem existir em grandes funes e devemos evit-las.

Como escrever funes como essa?

  • Talvez no seja possvel aplicar todas as regras vistas at aqui de incio.
  • Nas funes, elas comeam longas e complexas, com muitos nveis de indentaes e loops aninhados, muitos parmetros, nomes ruins e aleatrios, duplicao de cdigo.
  • Porm depois organizamos, refinamos o cdigo, dividindo em funes, trocamos os os nomes, removemos a duplicao, e no fim devemos ter uma funo que respeite as regras vistas aqui.

Concluso

  • As funes so os verbos e as classes os substantivos.
  • Essa uma verdade muito antiga.
  • A arte de programar , e sempre foi, a arte do projeto de linguagem (linguagem literal, narrativa).
  • Seguindo as regras deste captulo, suas funes sero curtas, bem nomeadas e bem organizadas.
  • Mas jamais se esquea de que seu objetivo verdadeiro contar a histria do sistema.

Original Link: https://dev.to/jonilsonds9/anotacoes-capitulo-3-functions-12gm

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To