Aniversário!
Dia 31 na Drinkeria Maldita!
...do cansaço dessa vida, e do peso de ter que ser alguém...
Dia 31 na Drinkeria Maldita!
Escrito por
P.
às
15:26
0
comentários
Links para este post
Hoje vi em uma base de código-fonte uma função cujo nome é "signalCatcher" -- um substantivo. A regra geral de estilo é: dados são chamados por substantivos, funções por verbos no infinitivo.
Mas faz sentido que "signalCatcher" seja o nome daquilo que você vai entregar ao mecanismo de sinais para tratar os sinais da aplicação, certo?
Eu acredito que a linguagem de programação do futuro não deve fazer distinção entre objetos-dados e objetos-função, mesmo sintaticamente; ambos ocupam espaço na memória e portanto exigem alocação, e são mencionados através de referências.
Em C, todas as funções são efetivamente objetos imutáveis, mas houve o tempo em que funções não eram imutáveis; esse tempo poderia voltar. E apesar de a maioria dos objetos ser mutável, alguns objetos são propositalmente imutáveis, e seus projetistas procuram maneiras de armazená-los em ROM.
Uma função deve ser um objeto cujo tipo é função, um tipo genérico variando na lista de parâmetros e na lista de resultados. O valor de um objeto do tipo função deve ser interpretado como uma sequência de instruções para o processador alvo, organizada de acordo com uma convenção de chamada apropriada. Esta convenção apóia a operação fundamental que o programa realiza sobre o objeto, chamar.
É claro que, ainda assim, uma função é um objeto bem especial. Em particular porque não é um objeto cujo tamanho é regular -- não se pode saber qual é o tamanho de um objeto função apenas conhecendo seu tipo.
Escrito por
P.
às
14:14
0
comentários
Links para este post
Tópicos: software
Estou procurando apartamento no Rio de Janeiro.
Se souber de algo, avise!
Escrito por
P.
às
15:43
0
comentários
Links para este post
Um novo exemplo para diminuir o tédio dos leitores e usar esses conceitos para entender o processamento de texto nos computadores.
Falemos sobre um programa que, por sua vez, deseja falar sobre textos em linguagem natural. Este programa fará referência a objetos cujo interpretante é "texto em linguagem de gente".
O que é texto em linguagem de gente? É uma sequência de símbolos que os seres humanos são capazes de entender como caracteres do seu idioma, que por sua vez se agrupam para formar palavras, frases etc. Nos idiomas latinos dizemos que as letras se agrupam para formar palavras; em idiomas como o japonês muitas vezes apenas um caracteres já é uma palavra inteira.
Mas o computador não sabe nada sobre caracteres, apenas sobre números. Com certeza o computador é capaz de representar na memória números uns na frente dos outros.
A intuição fundamental é a possibilidade de estabelecer um mapa de caracteres onde cada caractere está mapeado para um número e vice-versa. Formalmente, o mapa é uma função bijetora entre os conjuntos "números inteiros" e "caracteres".
Assim, um programa processador de texto faz referência a objetos cujo primeiro tipo é "número inteiro" e cujo segundo tipo é "caractere do mapa tal".
Suponha o seguinte mapa: a = 1, b = 2, c = 3 etc. O texto "abc" seria um objeto composto por três objetos numéricos contíguos 123.
Como poderia um programa colocar palavras em ordem alfabética? Toma dois objetos "palavra" e compara os dois caracteres iniciais como números; se forem diferentes, a ordem é numérica; se forem iguais fazemos a mesma coisa com o segundo caractere e assim por diante. Essa é a ordenação lexicográfica.
Esse esquema é interessante quando podemos usar um objeto de tamanho fixo e tipo "número" para todos os caracteres desejados. Mas com o advento da Internet e a interligação entre sistemas de todo o mundo se tornou inviável usar mapas de caracteres pequenos.
O que acontece quando um sistema do Japão envia 123 para um sistema do Brasil? Que mapa de caracteres o sistema do Brasil deve tomar como interpretante desses números? Essa dificuldade é a causa de muitos fenômenos bizarros na Internet, onde páginas mostram um monte de lixo onde deveriam estar caracteres latinos acentuados ou coisa parecida.
A primeira lição da interligação de sistemas processadores de texto é que não existe objeto "texto" compreensível sem um interpretante "mapa de caracteres" associado. Essa associação é um problema que sempre deve ser resolvido, mesmo que a solução seja um contrato entre todas as partes definindo um e apenas um mapa válido. Esse tipo de contrato não se mostrou viável a longo prazo.
Alguns sistemas de programação experimentaram construir tipos mais complexos para objetos; não apenas "texto" mas "texto ASCII" ou "texto ISO-8859-1" -- embutindo no tipo do objeto também o tipo do mapa de caracteres. Isso é interessante para apoiar contratos como o anterior, mas um pouco estranho quando o sistema deve aceitar diversos tipos de texto de diversas partes do mundo.
Estas parecem as coisas básicas que sempre queremos fazer com texto: contar o número de caracteres, decidir se dois textos são iguais, decidir qual de dois textos deve aparecer antes na ordem do dicionário, e inspecionar o texto letra por letra (para imprimir na tela, por exemplo). Com os mapas numéricos simples, podemos fazer todas essas coisas simplesmente trabalhando com pares de números: os primeiros de cada texto, depois os segundos de cada texto, etc.
Nesses mapas, existe uma referência sensata que atravessa a representação dos objetos da mais pura -- os números -- para a mais abstrata -- o caractere do texto.
Essa facilidade eventualmente terminou, o que ainda parece muito traumático para programadores acostumados com essa situação tão segura.
Eventualmente a comunidade internacional decidiu dar um basta na multiplicidade dos mapas e resolveu produzir o super-mapa Unicode. Este mapa é um catálogo de praticamente todos os caracteres usados na galáxia, associados cada um deles a um número inteiro positivo. Infelizmente, são muitos caracteres, que não podem ser representados com números pequenos.
A princípio, os indivíduos decidiram usar números grandes e manter o esquema de mapa com objetos de tamanho fixo. Assim, o processamento par-a-par continuaria possível. Mas os objetos texto explodiram de tamanho e essa esquema se mostrou inviável.
Então um compromisso foi firmado: um novo mapa foi produzido para o Unicode onde quase 90% dos textos continuaria com o mesmo tamanho, e apenas 10% seria maior. Este mapa às vezes usa um número por caracteres, às vezes dois, às vezes três e às vezes quatro. Este simples fato é o pesadelo dos programadores novatos de processamento de texto.
Por que este mapa UTF-8 possui uma representação tão estranha com objetos caractere de tamanho variável, deixou de ser sensata a referência direta número-a-caractere. Um sistema que recebe 1234 3456 5678 e deve interpretar esses números como texto deve não mais assumir que o primeiro número é um caractere, e o segundo um caractere etc. É possível que na realidade os dois primeros números sejam um caractere juntos.
Uma sequência de números que deve ser interpretada como UTF-8 não pode mais ser percorrida ingenuamente número a número, e os algoritmos de processamento baseados em comparações par-a-par estão quebrados. Isso, novamente, se deve ao fato de que UTF-8 viola propositalmente premissas simples de significação dos números que compõe um texto.
Isso foi um problema grave porque programas antigos despreocupadamente tratavam seu texto de forma crua, diretamente com os números, confortados pelas premissas do processamento de texto -- ao invés de fazer isso com funções especiais em módulos de processamento de texto.
Quando o significado dos números foi alterado nos processos de substituição de mapa por mapa, consertar esses programas foi tarefa infernal. Os programas com funções especiais de tratamento de texto modificaram apenas estas funções e foram livrados deste mal.
Esta vitória do encapsulamento pode ser compreendida pelo encapsulamento de uma função sígnica -- a compreensão dos signos-número como signos-letra encapsulada em certos entes responsáveis, e uma transformação cultural pôde ser efetivada apenas instruindo estes entes responsáveis, e não todos os entes.
No final das contas o problema se tornou tão bem resolvido que surgiu um componente tão reusável que surge por toda parte, a libiconv.
Escrito por
P.
às
14:17
0
comentários
Links para este post
Tópicos: software
Entender o texto de um programa sob a ótica da semiótica é um pouco mais fácil do que entender outros tipos de texto porque o limiar de realidade do programa está bem delineado e bem próximo: a máquina.
Por essa razão, não é preciso uma poderosa metafísica para entender o que é um objeto, mesmo que este esteja, para o programa escrito, totalmente oculto.
Bolei o seguinte diagrama para descrever as três propriedades fundamentais de um objeto segundo as regras da máquina.
Escrito por
P.
às
13:37
0
comentários
Links para este post
Tópicos: software
Agora, para um pensamento menos entediante.
Considere que autenticação é o processo pelo qual um sujeito se convence que um certo signo de fato significa um certo objeto -- uma certa credencial de fato significa um certo indivíduo, por exemplo.
Quando você ouve a campainha e alguém dizer "Olá" e pensa "Deve ser fulano" você autentica o signo vocal para se convencer ainda mais usando o olho mágico.
O método de autenticação em sistemas de informação com a interação mais simples é a checagem de um segredo compartilhado. O sistema conhece um segredo para um username e assume que se alguém apresentar o username e o segredo, então deve ser o significado daquele username.
O programa em execução, após executar essa interação com sucesso, construirá um objeto na memória, e manterá uma referência para ele cujo significado ulterior é username-do-usuário. Já que a autenticação foi bem sucedida, o programa confiará até terminar que esta referência é adequada, e poderá usá-la para julgar se deve ou deve não permitir o usuário a abrir certos arquivos etc.
Esta confiança no significado daquela referência é perfeitamente adequada para programas convencionais: a memória de um programa convencional em um sistema convencional é exclusiva, de modo que ele pode facilmente se convencer de que o objeto referenciado é íntegro.
Às vezes programadores movem para sistemas diferentes onde as regras são diferentes, e esse tipo de expectativa implícita é violada com consequências drásticas.
O jovem programador que move sua atividade para a web pode escrever um site em script que autentica o usuário e guarda o username em um objeto da sessão. O programa subjacente então continuamente fará certa referência a este objeto para tomar decisões de segurança, afinal, esta referência está para o objeto certo, não é?
Porém, neste ambiente, o programador não pode assumir a integridade do objeto -- não ingenuamente, como eu assumi acima. Como a web é um sistema bem distribuído e como o browser acessa o site um arquivo por vez, sem qualquer continuidade, este objeto ao qual o script faz referência não está sob seu controle. Ele existe em uma memória distante, fora do seu controle.
Fora do seu controle significa sob controle de um outro agente: o cliente. Suponha então que eu faça um acesso a uma página restrita e posicione arbitrariamente um objeto com o username de outra pessoa justamente no local onde a referência do programa assume que ele esteja. Assim, eu posso mentir ao programa sobre quem eu sou, me valendo de uma ingenuidade no significado do programa.
Perceber esse furo de segurança no site pode ser difícil porque o texto do programa do site pode adequadamente obter o username e compará-lo com regras de autorização em todos os lugares. O problema aqui é semanticamente anterior a esta comparação: o problema está na premissa de que uma certa referência está de fato para um objeto com o significado esperado.
Assim, os defeitos nos processos de autenticação em sistemas de informação são compreensíveis sob a ótica de uma função sígnica com "defeito" -- uma oportunidade através da qual o par em uma conversação tem condições de mentir. Concretamente, esse defeito existe no programa na forma de uma confiança indevida sobre o objeto de uma referência.
Escrito por
P.
às
10:51
0
comentários
Links para este post
Tópicos: software
O padrão Proxy ocorre sempre que um objeto no sistema existe como substituto de outro objeto, por alguma razão. Em um sistema distribuído entre muitos computadores físicos, um objeto local pode ser substituto de um objeto que está em outro computador, ocultando o mecanismo de comunicação entre computadores.
O objeto proxy, de um modo ou de outro, possuirá uma referência ao objeto proxied; e o programa que possui uma referência ao objeto proxy possuirá uma referência ao objeto proxied.
Esses múltiplos níveis de indireção trazem problema para a expressão e compreensão do programa devido a frequente ausência de interpretantes para humanos -- também conhecidos como documentação.
Considere um objeto whatever que é um proxy para um objeto em um computador central, e uma rotina com essa aparência:
get_name (whatever) -> (s1)
; s1 is the name of whatever
Um programa chama get_name e obtém uma referência ao objeto "nome" de um outro objeto qualquer.
Agora, resta a pergunta: se o programa que eu estou rodando modificar o valor de s1, o que acontece com whatever? Se Fulana rodar o mesmo programa depois que eu, que valor de s1 ela vai obter? s1 é uma referência para uma cópia ou é uma referência para o original?
Essa diferença é importante por razões que não apenas as consequências de modificar o objeto. A memória do computador é finita e portanto os programas devem cuidar de destruir os objetos que já acabaram de usar. Mas o que o programa que usa get_name deve fazer com o objeto referenciado por s1? Ele deve destruí-lo? Ele pode destruí-lo? Com certeza ele não pode destruir um objeto que está referenciado por diversos outros programas.
Por que (alguns) programas devem cuidar da presença dos objetos na memória, e dar manutenção nessa memória, existe sempre o problema de dispor de espaço para objetos ocuparem e por quanto tempo. Quando um programa faz algo como:
string s4 = "Marcelinho"
a expressão de que "existe um s4 que é um texto" é interpretada implicitamente como "precisamos arranjar espaço para um texto pelo tempo necessário".
Quando o programa lida com objetos que foram criados por ele mesmo e são locais, o uso do espaço e do tempo é óbvio porque explícito; referências a objetos ocultos demandam maiores explicações.
As referências indiretas como os objetos proxies levam o problema além quando tornam possível que uma referência seja absurda -- uma referência a nenhum-objeto. Há programas onde faz sentido uma referência a nenhum-objeto e há programas onde isso não faz sentido. O programador deve deixar isso sempre claro sob pena de não ser compreendido.
Documentação é a única solução geral na medida em que linguagens de programação em geral não oferecem mecanismos sintáticos para se especificar esses atributos de uma referência.
Nem mesmo C++, que possui duas notações para referências com diversos graus de rigor sintático, consegue expressar tudo o que se deseja expressar, e a confusão sobre a especificação de "rvalue references" indica que ainda não está firmada a sintaxe do futuro.
Linguagens como Java, onde a quase totalidade dos objetos são criados por um gestor central em memória desconhecida, permitem ao programa ignorar a manutenção da memória mas ainda sofrem do problema de compreensão das referências.
Quando começamos a considerar as referências polimórficas a situação fica ainda mais punk.
Escrito por
P.
às
11:29
0
comentários
Links para este post
Tópicos: software
(TODO: Será que estou usando os termos certos? Suponho que "significante" seja o mesmo que "interpretante" mas a nomenclatura da Semiótica não está bem firme na minha memória.)
Existe bastante semiose na comunicação entre programas de computador, mesmo que seja uma semiose extremamente simples, com um universo de possibilidades bastante limitado.
O serumano ao acessar uma página na Web digita no browser: http://www.twitter.com/pedrolamarao -- uma URI.
Existe algo de muito interessante acontecendo entre o serumano, o browser e um servidor perdido na rede; algo descrito em grande pompa teórica na especificação das URIs.
Em primeiro lugar, esse texto é bastante opaco para a maioria das pessoas; muitas delas compreendem que "twitter" é o nome de um "site" e que estão querendo ver as paradas de "pedrolamarao".
Alguns mais acostumados com a Web sabem que "http" é o nome das coisas que são da Web, e que existem outros nomes próprios de outros programas, como "ftp".
Realmente esse texto, ou esse símbolo, se divide em duas partes, e deve ser interpretado em dois estágios, ou como composto de dois símbolos distintos.
O primeiro símbolo é "http" que deve ser interpretado de acordo com um esquema bem simples -- a pura comparação textual. "http" vai para cá, "ftp" vai para lá e assim por diante. O nome desse símbolo é schema e esse símbolo será o interpretante do símbolo seguinte: deve-se interpretar o resto do texto de acordo com este princípio do texto.
Existe uma infinitude de possíveis schemas, já que um schema é apenas e tão somente um monte de letras em sequência. Além disso, o acordo entre todos nós sobre o que um schema significa pode ou pode não ser bem definido; é claro que a Internet inteira concorda sobre o que é "http", mas duvido que algum de vocês saiba como interpretar "astrotv" da mesma forma que eu.
Quando o schema é "http" o sistema sabe que deve usar o browser Web. Ao menos, assim esperamos que seja, quando clicamos em "http://www.twitter.com/pedrolamarao" sublinhado em azul naquele email que recebemos. O browser Web, por sua vez, sabe que o segundo símbolo -- "www.twitter.com/pedrolamarao" -- é composto também por diversos símbolos, quando a URI é "http".
O primeiro deste último conjunto é chamado authority e possui um entre poucos interpretantes aceitáveis. Neste caso, o domain name system ou DNS é o nome do sistema responsável. Este sistema dirá ao browser Web onde está o servidor responsável. Mais detalhes são irrelevantes. Restam poucos outros interpretantes aceitáveis, e seus sistemas são cheios de números.
O segundo deste último conjunto é chamado path. Este path possui um interpretante básico: o sistema de arquivos do servidor significado pelo authority. É o mesmo que os arquivos na máquina de qualquer pessoa. É claro que, como é da natureza do mundo, existem diversos outros interpretantes possíveis, como por exemplo algum outro programa dentro do servidor Web que mapeia "pedrolamarao" para um negócio em um banco de dados.
Porém, tudo o que o browser Web precisa saber, parte do seu acordo com o servidor Web, é que para qualquer path o servidor Web enviará uma porção de dados. Na maioria das vezes, esses dados estão de acordo com a norma HTML ou CSS e devem ser interpretados através destas -- seus interpretantes. É claro que nem sempre é assim, já que vêm também scripts Javascript, fotos JPEG, música MP3 etc. etc.
Como o browser sabe qual será o interpretante mais adequado para cada um desses símbolos bizarros de 0s e 1s que vêm pela rede? A semiose durante um simples abrir de página é complexa e cheia de elementos, e será finita apenas até o ponto em que o engenheiro perder o interesse nos detalhes do sistema.
A cada passagem de símbolo a símbolo por um interpretante escolhido por qualquer agente nessa confusão toda há chance para algum problema. Administradores de servidor Web vivem às voltas com "página não encontrada" e arrancam os cabelos para entender porque um determinado path não foi encontrado. Volta e meia um browser Web resolve imprimir um monte de lixo na tela quando o usuário tem certeza que está baixando um filme. Às vezes um sujeito digita o nome de um site e o browser Web diz "nome não encontrado". O que acontece quando a configuração do DNS está com defeito!? E alguns infelizes usam sistemas que não tem muita certeza sobre o que fazer com nomes começando com "http".
Toda vez que surge um novo sistema de componentes na indústria há bravatas sobre o desenvolvimento de um novo tipo de "nome globalmente único". É o grande sonho da humanidade, ser capaz de nomear os entes sem ambiguidade. Todo um conjunto de sociedades esotéricas existe em desespero para aprender o Idioma de Adão, que soube nomear todas as coisas sem hesitação. Os humanos com senso prático compreendem que nomes são acordos entre as partes e estabelecem tais acordos entre si. O schema "http" por exemplo possui um significado em acordo estabelecido sob a autoridade do IANA. Mas você sabe o que IANA significa?..
Escrito por
P.
às
17:15
0
comentários
Links para este post
Tópicos: software
Do ponto de vista do Java e do C#, C++ é uma linguagem fracamente tipada. Apesar de dizer isso abusar dos termos, existe um fundo de verdade ali.
C++, ao contrário de Java e C#, permite a formação de referências arbitrárias a qualquer objeto -- mesmo objetos hipotéticos.
Programas como este são aceitáveis, para o compilador:
list<string>* l = (list<string>*)0x12345;
l->sort();
Esta propriedade é inútil para a maioria dos programas, o que torna C++ excessivamente complicada aos olhos da maioria dos programadores. Se o programa está dizendo que naquele lugar ocorre um list<string> então isso deve ser verdade, certo? Boa sorte!
Existem programas que fazem uso dessa possibilidade, como programas para máquinas onde certos endereços são especiais e têm significado pré-definido.
Programas como este também são aceitáveis:
Escrito por
P.
às
15:50
0
comentários
Links para este post
Tópicos: software
