Trilha de aprendizado · Nível 4 · Tutorial 6

Decompor um programa em funções com responsabilidades claras

Transforme um programa concentrado em um único bloco em pequenas funções que cooperam por meio de entradas e resultados explícitos.

  • Nível: Intermediário
  • Duração: 22 min
  • 8 passos
Decompor um programa em funções com responsabilidades claras

O que você vai percorrer

  1. Enxergar as responsabilidades dentro do bloco Execute um relatório concentrado em um único bloco, registre seu comportamento e identifique as responsabilidades já presentes no código. 2 min
  2. Escolher o que merece virar função Defina funções a partir de responsabilidades reconhecíveis e planeje entradas e resultados explícitos antes de alterar o programa. 3 min
  3. Extrair o processamento em pequenas mudanças Extraia a seleção e o resumo de forma incremental, substituindo cada trecho por uma chamada e conferindo o resultado após cada mudança. 4 min
  4. Separar cálculo de interação Isole a leitura e a apresentação para reutilizar as funções de processamento sem depender do terminal. 3 min
  5. Conectar as funções com uma coordenadora Organize leitura, seleção, resumo e apresentação em uma função coordenadora que encaminha resultados por variáveis locais. 3 min
  6. Ajustar o tamanho das responsabilidades Compare organizações sobrecarregadas, coesas e excessivamente fragmentadas para escolher funções pelo propósito, não pela quantidade de linhas. 2 min
  7. Conferir se o comportamento foi preservado Compare resultados esperados e observados, verifique retornos intermediários e confirme que as funções não alteram as listas recebidas nem acumulam estado. 3 min
  8. Consolidar a decomposição e encerrar Finalize o relatório, revise as fronteiras entre as funções e registre as evidências de que a reorganização preservou o comportamento. 3 min

O que você vai aprender

  • Identificar operações com responsabilidades distintas em um programa existente.
  • Extrair regras de processamento para funções reutilizáveis, separadas de input e print.
  • Organizar uma função coordenadora que use os resultados de outras funções sem depender de estado global.
  • Conferir manualmente se a reorganização preservou os resultados para entradas representativas.

Antes de começar

  • Controlar o escopo e o estado das funções
  • Documentar funções com docstrings e tipos simples
  • Transformar e filtrar dados com compreensões

Passo 1 de 8

Enxergar as responsabilidades dentro do bloco

Execute um relatório concentrado em um único bloco, registre seu comportamento e identifique as responsabilidades já presentes no código.

Conheça o programa-base

Um relatório de sessões de estudo

O programa recebe durações inteiras não negativas, separadas por espaços, e um mínimo também não negativo. Ele seleciona as sessões com duração maior ou igual ao mínimo e informa a quantidade e o total de minutos selecionados.

Crie um único arquivo Python no seu computador e copie o código abaixo. Por enquanto, não reorganize nada. Se a primeira entrada ficar em branco, o programa considera uma lista vazia.

Programa-base completo

Salve e execute este código como um script Python. Ele não usa dependências externas.

python
entrada_duracoes = input("Durações em minutos: ")
duracoes = [int(valor) for valor in entrada_duracoes.split()]
minimo = int(input("Duração mínima: "))

selecionadas = [
    duracao
    for duracao in duracoes
    if duracao >= minimo
]

quantidade = len(selecionadas)
total = 0
for duracao in selecionadas:
    total += duracao

print(f"Sessões selecionadas: {quantidade}")
print(f"Total de minutos: {total}")

Registre o comportamento atual

Crie uma referência antes de mudar

Uma refatoração muda a organização interna sem mudar as regras nem o comportamento observável. Antes de reorganizar o programa, execute-o com as entradas abaixo e registre o resultado. Essa referência permitirá comparar a versão atual com as próximas versões.

Exemplo

Execução de referência

Entrada de durações: 25 40 60 15

Duração mínima: 40

Resultado esperado:

Sessões selecionadas: 2

Total de minutos: 100

Faça também uma execução deixando a entrada de durações em branco e informando mínimo 30. O resultado deve ser quantidade 0 e total 0.

Veja quatro responsabilidades no mesmo bloco

Uma sequência, quatro propósitos

Embora o código ainda esteja concentrado, suas operações têm propósitos diferentes: leitura recebe e converte os dados; seleção aplica o critério mínimo; resumo calcula quantidade e total; apresentação mostra o relatório.

Reconhecer essas fronteiras vem antes de criar funções. Nas próximas etapas, a organização mudará, mas o critério duracao >= minimo, os cálculos e as mensagens deverão continuar produzindo o mesmo comportamento.

Mapa das responsabilidades

Fluxo com quatro áreas conectadas: entrada no terminal, filtro das durações, cálculo de quantidade e total e apresentação no terminal.

Leitura → seleção → resumo → apresentação. Cada área tem um propósito, mesmo enquanto todas permanecem no mesmo bloco.

Associe código e responsabilidade

Mapa do bloco

Associe cada trecho ou compromisso à sua função no programa.

Toque em um item e depois no par correspondente.

Passo 2 de 8

Escolher o que merece virar função

Defina funções a partir de responsabilidades reconhecíveis e planeje entradas e resultados explícitos antes de alterar o programa.

Bons motivos para extrair uma função

Responsabilidade antes de tamanho

Um trecho merece virar função quando contém uma regra repetida ou uma operação com significado próprio. A operação não precisa aparecer várias vezes: selecionar sessões ou produzir um resumo já são responsabilidades reconhecíveis, mesmo com uma única chamada.

Prefira nomes que expressem a finalidade, como selecionar_sessoes e resumir_sessoes. Nomes como fazer_parte_1 ou processar_dados descrevem pouco sobre o trabalho realizado.

Exemplo

Duas candidatas no relatório

A seleção aplica uma regra do domínio: manter cada duração maior ou igual ao mínimo. O resumo responde a duas perguntas relacionadas: quantas sessões foram selecionadas e quantos minutos elas totalizam. Cada operação tem um propósito que pode ser explicado sem mencionar sua posição no arquivo.

Desenhar as fronteiras

Entradas e resultados explícitos

Antes de implementar, defina quais dados atravessam a fronteira de cada função. Tudo de que a operação precisa deve chegar por parâmetros; tudo o que o restante do programa precisa deve sair pelo retorno. Assim, a função não depende de variáveis externas ocultas.

Fluxo entre as responsabilidades

A seleção recebe a lista de durações e o mínimo. A lista resultante alimenta o resumo, que produz quantidade e total.

Diagrama em que durações e um limite entram em um filtro; as durações aprovadas seguem para um resumidor, que gera uma contagem e uma soma.

Cada bloco conhece somente suas entradas e entrega resultados explícitos ao próximo uso.

Exemplo

Contratos planejados

selecionar_sessoes(duracoes, minimo)

Docstring planejada: “Retorna as durações maiores ou iguais ao mínimo.”

Exemplo: com durações [25, 40, 15, 40] e mínimo 30, o retorno esperado é [40, 40].

resumir_sessoes(sessoes_selecionadas)

Docstring planejada: “Retorna a quantidade e o total de minutos selecionados.”

Exemplo: com [40, 40], o retorno esperado é (2, 80). Esses são contratos de entrada e saída; a implementação será feita depois.

Escolha um contrato suficiente

Planeje a função de resumo

O programa precisa obter a quantidade e o total de minutos das sessões já selecionadas. Embora essa operação apareça apenas uma vez, ela tem significado próprio. Qual é o melhor contrato?

Passo 3 de 8

Extrair o processamento em pequenas mudanças

Extraia a seleção e o resumo de forma incremental, substituindo cada trecho por uma chamada e conferindo o resultado após cada mudança.

O ciclo de uma extração segura

Mude uma responsabilidade por vez

Para extrair um trecho com segurança: delimite a operação, identifique os dados de que ela depende, crie a função, substitua o trecho original por uma chamada e confira o resultado. A regra deve existir em um único lugar: depois da substituição, não deixe uma cópia ativa do trecho original.

Ciclo incremental de extração

O percurso vai do trecho original à função e termina com uma conferência antes da próxima mudança.

Diagrama em cinco estágios mostrando um trecho delimitado, suas dependências, a criação de uma função, a substituição por uma chamada e a conferência do resultado.

Delimitar → explicitar dependências → criar a função → substituir pela chamada → conferir.

Primeira extração: selecionar sessões

Mova a regra e substitua o trecho

Substitua todo o conteúdo do seu arquivo pela versão abaixo. A compreensão que aplica duracao >= minimo agora está somente em selecionar_sessoes. No ponto em que o trecho existia, fica a chamada que fornece duracoes e minimo e recebe a nova lista.

Seleção extraída; resumo ainda no bloco principal

Execute com durações 25 40 60 15 e mínimo 40. O resultado de referência deve continuar sendo 2 sessões e 100 minutos.

python
def selecionar_sessoes(duracoes, minimo):
    """Retorna as durações que atingem o mínimo."""
    return [
        duracao
        for duracao in duracoes
        if duracao >= minimo
    ]


entrada_duracoes = input("Durações em minutos: ")
duracoes = [int(valor) for valor in entrada_duracoes.split()]
minimo = int(input("Duração mínima: "))

selecionadas = selecionar_sessoes(duracoes, minimo)

quantidade = len(selecionadas)
total = 0
for duracao in selecionadas:
    total += duracao

print(f"Sessões selecionadas: {quantidade}")
print(f"Total de minutos: {total}")

Segunda extração: resumir sessões

Extraia o resumo sem fragmentá-lo

Agora substitua todo o arquivo pela versão abaixo. Quantidade e total permanecem juntos porque respondem ao mesmo propósito: resumir as sessões selecionadas. O bloco principal apenas chama a função e desempacota seus dois resultados.

Seleção e resumo extraídos

Repita somente o caso de referência: durações 25 40 60 15 e mínimo 40. O resultado deve permanecer igual após esta segunda mudança.

python
def selecionar_sessoes(duracoes, minimo):
    """Retorna as durações que atingem o mínimo."""
    return [
        duracao
        for duracao in duracoes
        if duracao >= minimo
    ]


def resumir_sessoes(sessoes):
    """Retorna a quantidade de sessões e o total de minutos."""
    quantidade = len(sessoes)
    total = 0
    for duracao in sessoes:
        total += duracao
    return quantidade, total


entrada_duracoes = input("Durações em minutos: ")
duracoes = [int(valor) for valor in entrada_duracoes.split()]
minimo = int(input("Duração mínima: "))

selecionadas = selecionar_sessoes(duracoes, minimo)
quantidade, total = resumir_sessoes(selecionadas)

print(f"Sessões selecionadas: {quantidade}")
print(f"Total de minutos: {total}")

Dica

Observe o que não mudou

Os input e os print continuam no bloco principal por enquanto. Nesta etapa, a mudança está limitada à extração do processamento: o critério, o cálculo e as mensagens permanecem iguais.

Confira o processo e o resultado

Ordene uma extração incremental

Coloque as ações na ordem adequada para extrair uma responsabilidade sem manter duas cópias ativas da regra.

  1. Delimitar o trecho que representa uma responsabilidade.
  2. Substituir o trecho original por uma chamada à função.
  3. Executar o caso de referência e comparar o resultado.
  4. Identificar os dados necessários e os resultados produzidos.
  5. Criar a função com esses parâmetros e retorno.

Relate as duas conferências

Com o caso de referência, registre o resultado observado após extrair selecionar_sessoes e após extrair resumir_sessoes. Informe também se cada trecho original foi removido e substituído pela chamada correspondente.

Escreva pelo menos 60 caracteres (0/60).

Passo 4 de 8

Separar cálculo de interação

Isole a leitura e a apresentação para reutilizar as funções de processamento sem depender do terminal.

Fronteiras entre interação e processamento

Cada função deve interagir ou calcular

Na etapa anterior, seleção e resumo viraram funções, mas as duas chamadas de input e os dois print ainda ficaram no bloco principal. Agora, concentre a leitura e a conversão em ler_sessoes, que retorna duracoes e minimo. Concentre a apresentação em exibir_relatorio, que recebe quantidade e total já calculados. Assim, selecionar_sessoes e resumir_sessoes continuam dedicadas ao processamento: recebem dados por parâmetros e devolvem resultados, sem solicitar entradas nem mostrar mensagens.

Entrada, processamento e saída

Diagrama com a entrada do terminal atravessando uma função de leitura, duas funções de processamento e uma função de apresentação antes de voltar ao terminal.

A interação fica nas extremidades. No centro, as funções de processamento trabalham apenas com argumentos e retornos.

Isole a leitura e a apresentação

Atualize o arquivo local

Substitua todo o conteúdo do arquivo usado nas etapas anteriores pela versão abaixo. ler_sessoes preserva os mesmos prompts e faz as mesmas conversões do programa-base. exibir_relatorio preserva as mensagens e não recalcula o resumo. O encadeamento ao final ainda é temporário; a próxima etapa organizará essa sequência.

Quatro responsabilidades separadas

Execute com durações 25 40 60 15 e mínimo 40. O resultado deve continuar sendo 2 sessões e 100 minutos.

python
def ler_sessoes():
    """Lê as durações e o mínimo e retorna os valores convertidos."""
    entrada_duracoes = input("Durações em minutos: ")
    duracoes = [int(valor) for valor in entrada_duracoes.split()]
    minimo = int(input("Duração mínima: "))
    return duracoes, minimo


def selecionar_sessoes(duracoes, minimo):
    """Retorna as durações que atingem o mínimo."""
    return [
        duracao
        for duracao in duracoes
        if duracao >= minimo
    ]


def resumir_sessoes(sessoes):
    """Retorna a quantidade de sessões e o total de minutos."""
    quantidade = len(sessoes)
    total = 0
    for duracao in sessoes:
        total += duracao
    return quantidade, total


def exibir_relatorio(quantidade, total):
    """Apresenta a quantidade e o total de minutos."""
    print(f"Sessões selecionadas: {quantidade}")
    print(f"Total de minutos: {total}")


duracoes, minimo = ler_sessoes()
selecionadas = selecionar_sessoes(duracoes, minimo)
quantidade, total = resumir_sessoes(selecionadas)
exibir_relatorio(quantidade, total)

Reutilize o cálculo sem input

Forneça os dados diretamente

Como as funções de processamento não chamam input, você pode reutilizar as regras com uma lista escrita diretamente no código. No arquivo desta etapa, substitua temporariamente apenas o bloco abaixo das definições — começando em duracoes, minimo = ler_sessoes() — pelo bloco a seguir. A execução não solicitará nenhuma entrada.

Chamadas manuais das funções de processamento

O resultado esperado é a seleção [45, 60], seguida do resumo (2, 105).

python
selecionadas = selecionar_sessoes([20, 45, 60], 40)
quantidade, total = resumir_sessoes(selecionadas)

print("Seleção:", selecionadas)
print("Resumo:", (quantidade, total))

# Resultado esperado:
# Seleção: [45, 60]
# Resumo: (2, 105)

Dica

A regra não depende do terminal

Os print deste bloco servem apenas para observar os retornos. Eles estão fora das funções de processamento. Para usar o relatório interativo novamente, restaure o bloco que começa com duracoes, minimo = ler_sessoes().

Reconheça uma separação reutilizável

Interação ou processamento?

Qual organização permite reutilizar a seleção e o resumo sem interação com o terminal?

Passo 5 de 8

Conectar as funções com uma coordenadora

Organize leitura, seleção, resumo e apresentação em uma função coordenadora que encaminha resultados por variáveis locais.

Um percurso explícito para os dados

Coordenar sem refazer o trabalho

As quatro funções já têm responsabilidades próprias. Agora, executar_relatorio organiza a ordem das chamadas: recebe os resultados da leitura, encaminha esses dados à seleção, envia a lista selecionada ao resumo e entrega quantidade e total à apresentação.

A coordenadora não contém o critério duracao >= minimo, não calcula o total e não imprime diretamente. Ela apenas conecta as funções por meio de resultados intermediários locais com nomes significativos.

Fluxo coordenado do relatório

Cada resultado produzido em uma etapa alimenta explicitamente os parâmetros da próxima chamada.

Diagrama com quatro blocos em sequência: leitura produz durações e mínimo; seleção produz sessões selecionadas; resumo produz quantidade e total; apresentação exibe o relatório.

Os dados atravessam a coordenadora por retornos, atribuições locais e argumentos, sem depender de estado global compartilhado.

Monte o corpo da coordenadora

Ordene as quatro chamadas

Coloque as instruções na ordem correta para formar o corpo de executar_relatorio. A coordenadora deve encaminhar todos os resultados sem usar variáveis globais e sem repetir regras de processamento.

  1. exibir_relatorio(quantidade, total)
  2. quantidade, total = resumir_sessoes(selecionadas)
  3. selecionadas = selecionar_sessoes(duracoes, minimo)
  4. duracoes, minimo = ler_sessoes()

Atualize e execute o arquivo completo

Definições seguidas da chamada inicial

Substitua todo o conteúdo do seu arquivo local pelo script abaixo. As funções auxiliares permanecem com as responsabilidades já definidas. A novidade é executar_relatorio, que reúne a sequência ordenada no exercício.

Após todas as definições, a chamada direta executar_relatorio() inicia o programa.

Relatório com função coordenadora

Execute com durações 25 40 60 15 e mínimo 40. O resultado deve continuar sendo 2 sessões e 100 minutos.

python
def ler_sessoes():
    """Lê as durações e o mínimo e retorna os valores convertidos."""
    entrada_duracoes = input("Durações em minutos: ")
    duracoes = [int(valor) for valor in entrada_duracoes.split()]
    minimo = int(input("Duração mínima: "))
    return duracoes, minimo


def selecionar_sessoes(duracoes, minimo):
    """Retorna as durações que atingem o mínimo."""
    return [
        duracao
        for duracao in duracoes
        if duracao >= minimo
    ]


def resumir_sessoes(sessoes):
    """Retorna a quantidade de sessões e o total de minutos."""
    quantidade = len(sessoes)
    total = 0
    for duracao in sessoes:
        total += duracao
    return quantidade, total


def exibir_relatorio(quantidade, total):
    """Apresenta a quantidade e o total de minutos."""
    print(f"Sessões selecionadas: {quantidade}")
    print(f"Total de minutos: {total}")


def executar_relatorio():
    """Coordena a leitura, o processamento e a apresentação."""
    duracoes, minimo = ler_sessoes()
    selecionadas = selecionar_sessoes(duracoes, minimo)
    quantidade, total = resumir_sessoes(selecionadas)
    exibir_relatorio(quantidade, total)


executar_relatorio()

Dica

Leia a coordenadora como um roteiro

Os nomes duracoes, minimo, selecionadas, quantidade e total tornam o percurso legível dentro de executar_relatorio. Nenhum deles precisa ser global: cada valor é produzido, armazenado localmente e encaminhado à próxima função.

Passo 6 de 8

Ajustar o tamanho das responsabilidades

Compare organizações sobrecarregadas, coesas e excessivamente fragmentadas para escolher funções pelo propósito, não pela quantidade de linhas.

Três organizações possíveis

Nem concentrar tudo, nem dividir tudo

A qualidade da decomposição não depende de produzir o maior número de funções. Uma função fica sobrecarregada quando reúne propósitos distintos, como ler entradas, selecionar sessões, calcular o resumo e imprimir. No outro extremo, dividir cada instrução em uma função obriga o leitor a saltar entre definições sem tornar a regra mais clara. A organização coesa fica entre esses extremos: cada função reúne operações que contribuem para um propósito identificável.

Comparação de granularidade

À esquerda, uma única função concentra responsabilidades diferentes. No centro, funções coesas formam um percurso legível. À direita, funções minúsculas criam etapas e saltos sem acrescentar significado.

Comparação em três colunas: um grande bloco sobrecarregado, uma sequência equilibrada de blocos coesos e uma cadeia excessiva de blocos minúsculos.

A granularidade útil torna as responsabilidades visíveis sem transformar cada instrução em uma nova fronteira.

Coesão no resumo

Quantidade e total pertencem ao mesmo propósito

resumir_sessoes responde a duas perguntas relacionadas sobre a mesma lista: quantas sessões existem e quantos minutos elas totalizam. Manter esses cálculos juntos é coeso porque ambos contribuem para o propósito declarado de resumir. Não é necessário criar uma função para cada atribuição, chamada ou linha do acumulador.

Organização coesa

Esta versão preserva o acumulador do programa-base e mantém os dois resultados relacionados na mesma função.

python
def resumir_sessoes(sessoes):
    """Retorna a quantidade de sessões e o total de minutos."""
    quantidade = len(sessoes)
    total = 0
    for duracao in sessoes:
        total += duracao
    return quantidade, total

Fragmentação sem benefício

Esta alternativa produz o mesmo resumo, mas introduz nomes vagos e repasses que dificultam acompanhar uma operação simples.

python
def etapa_1(sessoes):
    return len(sessoes)


def etapa_2(total, duracao):
    return total + duracao


def etapa_3(sessoes):
    total = 0
    for duracao in sessoes:
        total = etapa_2(total, duracao)
    return total


def resumir_sessoes(sessoes):
    quantidade = etapa_1(sessoes)
    total = etapa_3(sessoes)
    return quantidade, total

Dica

Use o propósito como medida

Desconfie de divisões que geram nomes vagos, apenas repassam dados ou exigem vários saltos para entender uma regra curta. Não existe uma quantidade fixa de linhas que determine quando criar uma função: prefira a organização que deixa cada responsabilidade mais fácil de reconhecer e acompanhar.

Escolha a decomposição mais clara

Granularidade orientada pela responsabilidade

Qual organização é mais adequada para o relatório de sessões?

Passo 7 de 8

Conferir se o comportamento foi preservado

Compare resultados esperados e observados, verifique retornos intermediários e confirme que as funções não alteram as listas recebidas nem acumulam estado.

Compare por etapas

Do resultado final à primeira divergência

Monte a conferência com três informações: entrada, resultado esperado do programa-base e resultado observado na versão refatorada. Use casos que exercitem sessões abaixo, acima e exatamente no mínimo, além de nenhuma sessão selecionada e lista vazia. Compare primeiro o retorno de selecionar_sessoes e depois o de resumir_sessoes. Se o resultado final divergir, essa ordem ajuda a localizar a primeira responsabilidade que produziu um valor diferente.

Pontos de conferência

A comparação começa pela seleção, passa pelo resumo e termina no relatório completo.

Diagrama com um conjunto de entradas alimentando a seleção e o resumo, cada etapa comparada com um resultado esperado, antes da comparação da saída completa.

Conferir resultados intermediários permite localizar a primeira divergência, em vez de observar somente a saída final.

Execute uma conferência única

Seleção, resumo e preservação das listas

No arquivo criado na etapa 5, substitua temporariamente somente a chamada final executar_relatorio() pelo bloco abaixo. Uma única execução cobre os casos representativos, chama as duas funções de processamento sucessivamente e confere se as listas entregues a elas continuam iguais ao conteúdo anterior.

Bloco de conferência manual

Em cada caso, compare as linhas “esperada” e “observada”. As três verificações finais devem mostrar True.

python
casos = [
    (
        "abaixo, exatamente no mínimo e acima",
        [20, 40, 60],
        40,
        [40, 60],
        (2, 100),
    ),
    (
        "nenhuma sessão selecionada",
        [10, 20],
        30,
        [],
        (0, 0),
    ),
    (
        "lista vazia",
        [],
        30,
        [],
        (0, 0),
    ),
]

for nome, duracoes, minimo, selecao_esperada, resumo_esperado in casos:
    duracoes_antes = duracoes.copy()

    selecao_1 = selecionar_sessoes(duracoes, minimo)
    selecao_2 = selecionar_sessoes(duracoes, minimo)

    sessoes_para_resumo = selecao_1.copy()
    sessoes_antes = sessoes_para_resumo.copy()
    resumo_1 = resumir_sessoes(sessoes_para_resumo)
    resumo_2 = resumir_sessoes(sessoes_para_resumo)

    print(f"\nCaso: {nome}")
    print("Entrada:", duracoes, "Mínimo:", minimo)
    print("Seleção esperada:", selecao_esperada)
    print("Seleção observada:", selecao_1)
    print("Resumo esperado:", resumo_esperado)
    print("Resumo observado:", resumo_1)
    print("Durações preservadas:", duracoes == duracoes_antes)
    print("Sessões do resumo preservadas:", sessoes_para_resumo == sessoes_antes)
    print("Chamadas sucessivas iguais:", selecao_1 == selecao_2 and resumo_1 == resumo_2)

Exemplo

O que deve ser observado

No primeiro caso, a seleção esperada e observada é [40, 60], e o resumo é (2, 100). Isso confirma que 40, exatamente igual ao mínimo, foi incluído. Nos outros dois casos, a seleção é [] e o resumo é (0, 0). Em todos os casos, as três verificações booleanas devem exibir True. Se uma seleção divergir, investigue selecionar_sessoes; se a seleção estiver correta e apenas o resumo divergir, investigue resumir_sessoes.

Confira a interação completa

Restaure e execute uma vez

Remova o bloco temporário e restaure a chamada final executar_relatorio(). Execute o programa com durações 25 40 60 15 e mínimo 40. Além dos valores finais — 2 sessões e 100 minutos — compare com o programa-base os prompts, as mensagens e a ordem da interação. A conferência manual encontra regressões nos casos escolhidos, mas não prova que todas as entradas possíveis produzem comportamento equivalente.

Registre as evidências

Quais resultados você observou no bloco de conferência? Inclua o caso exatamente no mínimo, um caso sem sessões selecionadas, a preservação das duas listas e o resultado das chamadas sucessivas. Depois, informe se a execução completa manteve valores, prompts, mensagens e ordem da interação.

Escreva pelo menos 120 caracteres (0/120).

Passo 8 de 8

Consolidar a decomposição e encerrar

Finalize o relatório, revise as fronteiras entre as funções e registre as evidências de que a reorganização preservou o comportamento.

Consolide o arquivo local

A versão final do relatório

Confira se o arquivo local contém a versão completa abaixo. As fronteiras devem permanecer claras: ler_sessoes cuida da entrada, selecionar_sessoes aplica o critério, resumir_sessoes calcula os resultados, exibir_relatorio apresenta as mensagens e executar_relatorio coordena as chamadas. Não acrescente novas regras ao relatório.

Programa final consolidado

Execute uma última vez com durações 25 40 60 15 e mínimo 40. O resultado deve ser 2 sessões e 100 minutos, com os mesmos prompts e mensagens do programa-base.

python
def ler_sessoes():
    """Lê as durações e o mínimo e retorna os valores convertidos."""
    entrada_duracoes = input("Durações em minutos: ")
    duracoes = [int(valor) for valor in entrada_duracoes.split()]
    minimo = int(input("Duração mínima: "))
    return duracoes, minimo


def selecionar_sessoes(duracoes, minimo):
    """Retorna as durações que atingem o mínimo."""
    return [
        duracao
        for duracao in duracoes
        if duracao >= minimo
    ]


def resumir_sessoes(sessoes):
    """Retorna a quantidade de sessões e o total de minutos."""
    quantidade = len(sessoes)
    total = 0
    for duracao in sessoes:
        total += duracao
    return quantidade, total


def exibir_relatorio(quantidade, total):
    """Apresenta a quantidade e o total de minutos."""
    print(f"Sessões selecionadas: {quantidade}")
    print(f"Total de minutos: {total}")


def executar_relatorio():
    """Coordena a leitura, o processamento e a apresentação."""
    duracoes, minimo = ler_sessoes()
    selecionadas = selecionar_sessoes(duracoes, minimo)
    quantidade, total = resumir_sessoes(selecionadas)
    exibir_relatorio(quantidade, total)


executar_relatorio()

Revise as fronteiras e o percurso

Um fluxo explícito de dados

A coordenadora recebe os resultados de uma função e os encaminha à próxima por parâmetros. As funções de processamento não usam input, não imprimem e não dependem de estado global compartilhado. A decomposição também evita fragmentar cada instrução: quantidade e total continuam reunidos na responsabilidade de resumo.

Mapa final das chamadas

Use o mapa para acompanhar o percurso desde a leitura até a apresentação. A coordenação envolve todo o fluxo, mas não substitui as responsabilidades internas.

Diagrama com leitura, seleção, resumo e apresentação conectados em sequência, sob a coordenação de uma função externa.

Os dados seguem da leitura para a seleção e o resumo; somente depois os resultados chegam à apresentação.

Resumo

Checklist da decomposição

Use estes critérios para revisar o programa final.

  • Cada função tem um propósito identificável.
  • Os dados necessários entram por parâmetros e os resultados úteis saem por retorno.
  • selecionar_sessoes e resumir_sessoes não chamam input nem print.
  • Os resultados intermediários ficam locais e não dependem de estado global compartilhado.
  • A coordenadora conecta as operações sem repetir suas regras.
  • A divisão melhora a clareza sem criar funções para cada instrução.
  • Os casos manuais e a execução completa mantêm o comportamento do programa-base.

Justifique a solução final

Relato de responsabilidades e evidências

Escreva um relato curto sobre sua implementação local. Inclua: a responsabilidade, as entradas e os resultados de selecionar_sessoes e resumir_sessoes; como executar_relatorio conecta leitura, seleção, resumo e apresentação; e as evidências observadas para o caso exatamente no mínimo, um caso sem seleção, a preservação das listas, as chamadas sucessivas e a execução completa.

Escreva pelo menos 250 caracteres (0/250).

Estratégia concluída

Resumo

Uma estratégia reutilizável

Ao reorganizar outros programas concentrados em um único bloco, repita este percurso.

  • Identifique operações com responsabilidades diferentes.
  • Planeje entradas e resultados explícitos para cada função.
  • Extraia uma responsabilidade por vez e substitua o trecho original pela chamada.
  • Separe processamento de leitura e apresentação.
  • Use uma função coordenadora para encadear resultados locais.
  • Avalie se a granularidade realmente melhora a clareza.
  • Compare o comportamento anterior e posterior com entradas representativas.

Tutorial concluído

Parabéns! Você concluiu: Decompor um programa em funções com responsabilidades claras

Você concluiu “Decompor um programa em funções com responsabilidades claras”. Agora pode aplicar a mesma estratégia para reorganizar outros programas sem ocultar o fluxo de dados nem fragmentar responsabilidades sem benefício.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso