A blog about Software Engineering and other stuff not related to programming
Na minha busca por expandir o meu repertório de experiências, aproveitei a oportunidade de assistir uma apresentação de um concerto de música experimental num estúdio de gravação.
De primeira, o que mais me impressionou ao entrar no estúdio foi o silêncio absoluto proporcionado pelo isolamento acústico do ambiente, um espaço completamente isolado do barulho e do ruído externo.
Experimentar o estúdio inundado por tal intenso silêncio me abriu a mente para experimentar a música a partir de uma nova perspetiva.
A perspectiva antiga consistia em experimentar a música com o foco nas ondas sonoras produzidas pelos instrumentos. A matéria-prima são as ondas sonoras, a música é o que ocupa o espaço antes dominado pelo silêncio ou por qualquer outro barulho do qual ela chega para tomar o lugar.
A nova perspectiva coloca o silêncio como matéria-prima, as ondas sonoras cortam o silêncio e o faz assumir diversas formas. O objetivo da música não é ocupar completamente o espaço do silêncio, deve existir um equilíbrio entre os dois, um equilíbrio flexível com a possibilidade de oscilar entre a dominância de um ou outro.
O músico assume o papel de escultor, o silêncio é o bloco de mármore bruto pronto para ser desbastado, as ondas sonoras são o seu martelo e a sua talhadeira.
Se o escultor desbasta toda a pedra, não resta o que ser observado, não temos uma escultura observável.
Usando outra analogia, um chefe enquanto prepara um prato, usa a quantidade precisa de condimentos de modo que não ofusque completamente o componente principal do prato. No paladar o tempero realça o sabor, mas não deve se tornar o foco e a única coisa a ser sentida.
A beleza do trabalho artístico produzido reside em como o músico guia a experiência de percepção do silêncio.
Published: 2026-02-19
Tagged: Reflexão
Esse é o segundo texto que escrevo sobre coisas incomuns que me proporcionam um certo nível de conforto e satisfação. Hoje é a vez de escrever sobre o desgaste de canetas esferográficas.
Primeiramente vamos deixar claro o que são consequências de primeira, segunda e terceira ordem. As consequências de primeira ordem são os resultados diretos e imediatos de uma decisão tomada. Já as consequências de segunda e terceira ordem são os efeitos de longo prazo resultantes dessa mesma decisão tomada.
Observar uma caneta completamente gasta, me faz refletir no esforço dedicado para que fosse usada até a última gota de tinta. As consequências de primeira ordem decorrentes do uso da caneta são as mais evidentes, a redução do nível de tinta e as marcas de uso visíveis no seu corpo. Já as consequências de segunda e terceira ordem requerem uma reflexão mais profunda, pois dependem do contexto em que foi utilizada.
O desgaste da caneta que foi de um estudante é composto por horas de estudo e foco direcionadas ao processo de aprendizagem. A caneta gasta no final do processo é uma espécie de troféu, foi preciso pagar um preço através do esforço para fazer a caneta chegar ao estado final de desgaste. As consequências de segunda e terceira ordem são a assimilação do conteúdo estudado, a boa nota obtida nas avaliações e o projeto colocado no papel e que hoje está em execução produzindo frutos.
A imagem da caneta gasta reflete o tempo investido no seu uso, investimento esse que no longo prazo rende dividendos. Apenas o dono da caneta consegue olhar para a caneta e refletir sobre as consequências de segunda e terceira ordem, para um observador externo é apenas uma caneta antiga que precisa ser substituída por uma nova.
Published: 2026-02-07
Tagged: Reflexão
Compartilhando um pouco do que sei sobre como se dá o processo de coerção de uma estrutura de dados usando um schema como base.
É uma notação utilizada pra descrever o formato de uma estrutura de dados. Quando trabalhamos com o Clojure, é muito difundido no mercado a biblioteca Plumatic/Prismatic Schema, ela fornece uma série de helpers para facilitar a composição dos formatos de dados, o que chamamos de schemas, e também provê meios para que possamos aplicar validações dos valores contra os formatos esperados, seja na validação da estrutura de dados de entrada e saída de uma função, até mesmo o body de requisição ou de resposta de um determinado endpoint HTTP.
Exemplo do schema de um mapa (estrutura de dados) que representa uma pessoa, no exemplo definimos quais as chaves e os tipos esperados para os valores:
(require '[schema.core])
(def ColorEnum (schema.core/enum :red :green :blue))
(schema.core/defschema Person
{:name schema.core/String
:favorite-color ColorEnum})
No schema acima definimos que esperamos uma chave :name onde o valor é do tipo String, e uma chave :favorite-color onde o valor esperado é um enum de keywords com três opções de possíveis valores.
Você pode recorrer a documentação da biblioteca para encontrar exemplos de como compor schemas e de como validar os mesmos com a descrição dos cenários de sucesso e falhas na validação.
A documentação da Plumatic/Prismatic Schema que é a lib que utilizamos como base para o mecanismos de validação e transformação comumente usada em aplicações desenvolvidas em Clojure, descreve o processo de Coercion como sendo o mesmo que uma validação de um schema, mas adicionando um passo anterior a validação, a transformação aplicada no mapa de entrada usando um schema base para a transformação, após a coerção dos valores é aplicada a validação do dado retornado pela transformação com base no schema indicado.
Vamos ver na prática, como podemos fazer a transformação de um dado com base em um schema. Para o nosso exemplo ilustrativo vamos criar um FOO BAR coercer:
Começamos com a definição dos exemplos que vamos usar de input para o processo de transformação e validação (coercion):
(def valid-foor-bar-json-input {"test" "FOO"})
(def invalid-foor-bar-json-input {"test-i" "Blue Pen"})
Configuração do mecanismo de coerção/transformação: Os Matchers para o processo de transformação/coerção, são nada mais nada menos que mapas onde indicamos como cada tipo de dado deve ser adaptado a partir de um tipo X para um tipo Y.
(require '[schema.core])
(require '[schema.coerce])
(def FooBar (schema.core/eq "FOO BAR"))
(def foo-bar-coercions
{FooBar (fn [input] (if (= input "FOO") "FOO BAR" input))
schema.core/Keyword (fn [input] (if (string? input) (keyword input) input))})
(defn foo-bar-matcher
[schema]
(foo-bar-coercions schema))
(schema.core/defschema FooBarResult
{schema.core/Keyword FooBar})
(def foo-bar-coercer
(schema.coerce/coercer FooBarResult foo-bar-matcher))
Transformação/Coerção de fato:
(foo-bar-coercer valid-foor-bar-json-input)
=> {:test "FOO BAR"}
(foo-bar-coercer invalid-foor-bar-json-input)
=> #schema.utils.ErrorContainer{:error {"test-i" (not (= "FOO BAR" "Blue Pen"))}}
Quando executamos a chamada (foo-bar-coercer valid-foor-bar-json-input) temos o retorno esperado, onde o valor "FOO" foi transformado em "FOO BAR" e o resultado atende ao schema especificado.
No segundo exemplo de chamada (foo-bar-coercer invalid-foor-bar-json-input) o dado de entrada passou pelo step de transformação, mas a saída não atendeu o schema esperado gerando um erro.
Published: 2025-11-13
Tagged: Schema Data Validation Clojure Coercion