segunda-feira, 17 de março de 2014

E se as empresas fossem países

Vendo as constantes brigas judiciais entre as empresas de tecnologia e as aquisições de empresas menores, tive a impressão que essas mega corporações se assemelham muito a países na época das grandes conquistas. Cada um tentando aumentar sua dominação e tentando expandir território. Mas isso é assunto para outro post.

Se fossemos comparar as grandes empresas (ou produtos) com países, qual país se assemelha a cada empresa? Acho que as principais seriam:

Facebook é a China. Chegou quietinho, todos riam dela e agora está se transformando em um gigante. Tem várias regras e restrições impostas ao seu povo e a privacidade é a menor de suas preocupações;

Apple é o Japão. Pequeno, focado, com uma receita muito maior que o seu tamanho e com uma cultura admirada por muitos e ridicularizada por outros;

Samsung é o Paraguai, está cheia de cópias e os brasileiros adoram;

Yahoo é a Rússia. Já foi uma potência, mas atualmente causa mais risos do que medo;

Google são os Estados Unidos. É um gigante que espiona todos, está metido em tudo que acontece no mundo, tem muitos adoradores e alguns poucos que odeiam;

Linux é o Brasil. Assim como o Brasil é o país do futuro, o próximo ano é o ano do Linux no desktop.


* Sim, todos os fatos foram deturpados para deixar a comparação mais interessante :)

segunda-feira, 13 de janeiro de 2014

Rust, a linguagem do futuro

Você gostaria de ter uma linguagem que permite controle em baixo nível da memória, com alto desempenho e sem os problemas do C++? Então, Rust provavelmente é a linguagem que você procura.

No início de 2013 li o excelente tutorial Rust for Rubyists do Steve Klabnik. Na época gostei bastante da linguagem mas acabei não procurando mais informações. Desde então, ela vem evoluindo bastante e está se tornando bastante popular. Se você ainda não conhece, vou falar rapidamente de algumas coisas que me chamaram a atenção.

Quem deve usar Rust

Antes de mais nada é importante deixar claro qual o objetivo da linguagem e quem deve usá-la.

A linguagem Rust está sendo desenvolvida pela Mozilla para ser usada no lugar do C++. Os principais objetivos dela são segurança, concorrência e praticidade. A Mozilla usará a linguagem especialmente no Servo, um novo browser que estão desenvolvendo.

Pelo fato dela ser usada onde normalmente o C++ é adotado, ela precisa fornecer controles em baixo nível, especialmente no gerenciamento de memória, mas ela faz isso sem comprometer a estabilidade e segurança, ao contrário do C++.

Ainda não está totalmente claro em que áreas a linguagem será adotada, mas eu imagino que as principais serão:
  • Quem atualmente desenvolve em C ou C++ - para essas pessoas o Rust permitirá o mesmo controle que o C permite, porém, com muito mais segurança. Para essas pessoas a adoção do Rust será uma ótima escolha;
  • Aplicações web que fornecem APIs - no momento a linguagem Go está sendo bastante utilizada nesses casos. Eu não sou grande fã de Go (também não usei muito para poder opinar), imagino que o Rust acabará sendo adotado nesses casos também;
  • Otimizações - em Ruby é comum desenvolver em C partes do código que precisam de alta performance. Rust poderá vir a tomar esse lugar, por ser bem mais legível (coisa que rubistas valorizam bastante) e ser mais segura.

Variáveis

Ao definir as variáveis não é necessário especificar o tipo, na maioria dos casos o compilador consegue inferir o tipo a ser usado.

Por padrão as variáveis são imutáveis (por questões de performance e concorrência). Para que a variável seja mutável é necessário definí-la usando o "mut".
let hi = "hi";
let mut count = 0;

while count < 10 {
    println!("count is {}", count);
    count += 1;
}

Gerenciamento da memória

Não vou entrar em detalhes do gerenciamento da memória feita pelo Rust, mas o importante é que ele detecta durante a compilação possíveis problemas.

No exemplo abaixo, em C++, repare que é retornado um ponteiro para uma área de memória que logo ficará inválida. Esse erro é bastante comum e não é algo que a linguagem C++ previne.
{
    // A memória será liberada no final da função.
    map<int, Record> m; 

    // ...

    // Obtém uma referência para um item;
    Record &r = m[1]   
    // Retorna uma referência que logo será inválida,
    // pois a memória será liberada.
    return r;          
}
Abaixo você pode ver um código semelhante em Rust. Nesse caso, a linguagem detecta que um ponteiro inválido está sendo retornado e gera um erro de compilação. Repare bem, é um erro de compilação e não de execução.
{
    let mut m = HashMap::new();

    // ...

    let r = m.get(1);
    // Erro de compilação.
    return r; 
}

Structs

Em Rust, pode-se definir structs (que contém os dados) e adicionar funções a essas structs.
// Define a estrutura.
struct Rectangle {
    width: int,
    height: int
}

// Adiciona métodos
impl Rectangle {

    fn area(&self) -> int {
       // Não é necessário usar o "return".
       self.width * self.height
    }

}

Extension methods

Em C# "extension methods" permitem adicionar métodos a tipos existentes, sem ter que alterá-los ou criar uma sub-classe. Em Rust, a forma que a definição dos métodos funciona é igual aos "extension methods" do C#. Repare no exemplo acima que o método "area" recebe como parâmetro o "self", que representa o objeto ao qual ele está associado.

Com isso, é possível também implementar métodos para tipos já existentes, inclusive os tipos definidos pela própria biblioteca padrão.

Traits

Os traits são semelhantes a "interface" em C# ou Java. Porém, com uma diferença: não é necessário alterar a struct original para implementar uma trait (interface). Em outras palavras, você pode definir uma trait para um tipo existente.

No exemplo abaixo é definida a trait "Printable" e, a seguir, é feita a implementação dela para o "int".
trait Printable {
    fn print(&self);
}

impl Printable for int {
    fn print(&self) { 
        println!("{:?}", *self)
    }
}

Pattern matching

A funcão "match" do rust funciona como um "switch", porém bem mais avançado. O uso de pattern matching não é algo novo, linguagens como Erlang fazem uso extensivo disso, mas ao menos para mim, é uma novidade em linguagens derivadas do C.
match my_number {
    0     => println!("zero"),
    1 | 2 => println!("one or two"),
    3..10 => println!("three to ten"),
    _     => println!("something else")
}
Uma das coisas mais interessantes do match é que é obrigatório definir todos os possíveis valores para ele. Se você esquecer um valor, ocorre um erro de compilação. No exemplo abaixo o "_" significa "qualquer coisa".
enum Direction {
    North,
    East,
    South,
    West
}

match dir {
    North => println!("norte"),
    South => println!("sul"),
    _     => println!("outro")
}

Não existe NULL

Quantas vezes temos que adicionar aos métodos o famoso "if (x == null) throw ..."? Isso porquê na maioria das linguagens os objetos (ponteiros) podem ser nulos.

Até o invetor do Null, Tony Hoare diz "Esse foi meu erro de bilhões de dólares".

Em Rust, os ponteiros não podem ser nulos. Caso seja necessário definir uma variável que pode ou não ter valor pode-se usar o enum "Option"
let x: Option<int> = 10;
match x {
    Some(_) => println!("tem valor");
    None    => println!("não tem valor");
}

Onde aprender mais?

Aqui apenas destaquei alguns pontos interessantes da linguagem, não entrei em detalhes em nenhum deles. Se você deseja aprender mais, aqui vão alguns links:
  • Rust for Rubyists - é um excelente tutorial do Steve Klabnik, apesar do nome, mesmo quem não conhece Ruby consegue acompanhar bem;
  • Tutorial oficial - esse é um tutorial mais longo que vai apresentar os principais recursos da linguagem;
  • Memory Ownership and Lifetimes - vídeo explicando muito bem o gerenciamento de memória feito pelo Rust. Aqui tem o arquivo para download com qualidade melhor.

segunda-feira, 6 de janeiro de 2014

Evitando a renderização de áreas ocultas em layouts responsivos

Atualmente é bastante comum o uso de layouts responsivos, ou seja, layouts que se adaptam ao navegador do usuário.

Se um usuário acessa o site usando um smartphone, o site provavelmente irá exibir apenas o conteúdo essencial, deixando invisível boa parte do HTML.

Agora, por que devemos renderizar as áreas que não são visíveis? Evitando a renderização de áreas que sabemos estarem ocultas podemos melhorar o desempenho e economizar bateria dos dispositivos.

Ember Responsive Area

Para o Ember.js criei um componente bastante simples que resolve esse problema. Toda a área dentro do componente será renderizada apenas se estiver visível. O componente se chama Ember Responsive Area.

O uso dele é bastante simples:
<div class="hidden-phone">
  {{#responsive-area}}
    Aqui vem o conteúdo.
  {{/responsive-area}}
</div>

Como funciona

Quando o componente é carregado, ele verifica se o elemento está visível. Se estiver visível, renderiza a área. Caso contrário, não renderiza e monitora o redimensionamento do navegador.

Se o usuário redimensionar o navegador ou girar o dispositivo (tablet/smartphone) o componente irá verificar novamente se deve renderizar a área.

Note que isso só funciona se a visibilidade da região depende do tamanho da janela do navegador, isso não funcionará se você está ocultando e exibindo manualmente a área.

sábado, 21 de julho de 2012

Como acentuar palavras rapidamente no iPad

Quem usa o iPad ou iPhone por algum tempo, logo descobre como funciona a acentuação no sistema. Basta segurar a tecla por 1 segundo que aparecem as variantes para aquela letra. Se você não está familiarizado com isso, veja essa dica do Blog do iPhone.

Esse modo de acentuar é bastante intuitivo (logo o usuário descobre como funciona), mas nem sempre é prático. Ao digitar textos mais longos irrita ter que ficar esperando 1 segundo para o acento aparecer. Pois bem, existe uma forma mais rápida de se fazer isso: basta clicar na letra e deslizar rapidamente pra cima.

Ao clicar em uma letra e deslizar rapidamente pra cima aparecem as variações mais comuns dela. Por exemplo, ao apertar a letra "a", e deslizar pra cima ela fica "á". Deslizando pra cima e pro lado pode-se escolher "ã", "à" e "â".

Infelizmente isso só funciona no iPad, mas faz sentido, é onde mais digitamos. Depois que descobri isso a digitação ficou bem mais rápida.

sábado, 14 de julho de 2012

Como adaptar seu site para telas retina

Telas com alta densidade de pixels, chamadas pela Apple de "telas Retina", já são uma realidade. Temos smartphones, tablets e notebooks com essa incrível resolução.

Se considerarmos a porcentagem de visitantes utilizando essas telas, pode parecer pouco, mas esse é um número que só vai crescer a cada dia. Como diz o Marco Arment, esses visitantes representam o futuro. Não é como a porcentagem de pessoas utilizando o Internet Explorer 6, que só tende a diminuir, nesse caso o número só vai aumentar.

Agora, como adequar seu site para essas telas? Como primeiro passo, siga esse guia. A biblioteca Retina.js pode lhe ajudar a prover imagens de alta resolução apenas em dispositivos compatíveis, economizando largura de banda para os outros dispositivos.

Alterar as imagens do site é apenas o primeiro passo. Com isso feito, cabe a você identificar as áreas que não estão com boa aparência. Talvez trocar a fonte utilizada, ajustar outros elementos do site... mas isso só vendo o site em uma tela Retina pra poder dizer.