Having fun with CSS: Animated concentric circles

From time to time I follow some social numbers and specific statistics about this blog. Having to check different services to get the full picture is not a fun activity, so I decided to put them all together here in the blog and save myself some time.

And while at it, why not to have fun and do something different?

Animated circles to showcase different statistics.

If you haven't seen this in action, go to the About page of the blog. Assuming you are visiting this site from an HTML5 modern browser, you'll see the circles rotating, and you'll be able to navigate through all the numbers.

At the time of this post, all the stats are still not populated dynamically; that's still a work in progress. I have to connect to several APIs to get all the information, but I liked the circles so much that I couldn't wait to post this.

If you are curious, here is the complete HTML and CSS to create the circles. The pagination is using a little bit of JavaScript, and I'm also posting it below.

Let's start with the HTML:

<div id="rings">
    <div id="first-ring">
        <div id="second-ring">
            <div id="third-ring">
            </div>
        </div>
    </div>

    <div id="ring-content">
        <div class="container active" data-index="1">
            <div class="value">1,000</div>
            <div class="description">page 1</div>
        </div>
        <div class="container hidden" data-index="2">
            <div class="value">2,000</div>
            <div class="description">page 2</div>
        </div>
        <div class="container hidden" data-index="3">
            <div class="value">3,000</div>
            <div class="description">page 3</div>
        </div>
        <div class="container hidden" data-index="4">
            <div class="value">4,000</div>
            <div class="description">page 4</div>
        </div>
        <div class="container hidden" data-index="5">
            <div class="value">5,000</div>
            <div class="description">page 5</div>
        </div>

        <ol id="pagination">
            <li><a class="active" data-index="1"></a></li>
            <li><a data-index="2"></a></li>
            <li><a data-index="3"></a></li>
            <li><a data-index="4"></a></li>
            <li><a data-index="5"></a></li>
        </ol>
    </div>
</div>

There are two main sections: the first one defines the three rotating rings (first-ring, second-ring, and third-ring), and the second one defines the content and the pagination. Let's now see the CSS:

#rings {
    position: relative;
    text-align: center;
    width: 300px;
    height: 300px;
    margin:0 auto;
    -webkit-tap-highlight-color: transparent;
}

#first-ring {
    position: absolute;
    border: 5px solid #4698f2;
    border-top-color: #eee;
    margin: 0 auto;
    text-align: center;
    width: 280px;
    height: 280px;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    -webkit-animation: turn_clockwise 10s infinite;
    -moz-animation: turn_clockwise 10s infinite;
    animation: turn_clockwise 10s infinite;   
}

#second-ring {
    position: absolute;
    border: 10px solid #eee;
    border-top-color: #fff;
    border-bottom-color: #fff;
    width: 250px;
    height: 250px;
    margin: 5px;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    -webkit-animation: turn_counter_clockwise 8s infinite;
    -moz-animation: turn_counter_clockwise 8s infinite;
    animation: turn_counter_clockwise 8s infinite;  
}

#third-ring {
    position: absolute;
    border: 2px solid #315379;
    border-bottom-color: #eee;
    margin: 5px;
    width: 236px;
    height: 236px;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    -webkit-animation: turn_clockwise 10s infinite;
    -moz-animation: turn_clockwise 10s infinite;
    animation: turn_clockwise 10s infinite;
}		

Now to the animations:

@-webkit-keyframes turn_clockwise {
    0% {
        -webkit-transform: rotate(0deg);
    }
    100% {
        -webkit-transform: rotate(360deg);
    }
}

@-moz-keyframes turn_clockwise {
    0% {
        -moz-transform: rotate(0deg);
    }
    100% {
        -moz-transform: rotate(360deg);
    }
}

@keyframes turn_clockwise {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}

@-webkit-keyframes turn_counter_clockwise {
    0% {
        -webkit-transform: rotate(360deg);
    }
    100% {
        -webkit-transform: rotate(0deg);
    }
}

@-moz-keyframes turn_counter_clockwise {
    0% {
        -moz-transform: rotate(360deg);
    }
    100% {
        -moz-transform: rotate(0deg);
    }
}

@keyframes turn_counter_clockwise {
    0% {
        transform: rotate(360deg);
    }
    100% {
        transform: rotate(0deg);   
    }   
}	

Finally, the styles for the content and the pagination:

#ring-content {
    position: absolute;
    width: 230px;
    height: 230px;
    background-color: #4698f2;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    margin: 30px;
    cursor: pointer;
    box-shadow: inset 0 0 0 16px rgba(255,255,255,.6),0 1px 2px rgba(0,0,0,.1);
    transition: all .4s ease-in-out;
}

#ring-content:hover {
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.1),0 1px 2px rgba(0,0,0,.1);
}

#ring-content .container {
    position: absolute;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    width: 198px;
    height: 198px;
    margin: 16px;
    background-color: #4698f2;
    transition: all .7s ease-in-out;
}

#ring-content .value {
    font-size: 50px;
    line-height: 70px;
    padding-top: 44px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 0 1px #fff,0 1px 2px rgba(0,0,0,.3);
}

#ring-content .description {
    font-size: 16px;
    line-height: 20px;
    color: #fff;
    opacity: 0;
    transition: all 1s ease-in-out .4s;
}

#ring-content .container.hidden {
    opacity: 0;
}

#ring-content .container.active,
#ring-content .container.active .description {
    opacity: 1;
}

#pagination {
    margin: 12px auto 0;
    padding: 0;
    position: absolute;
    left: 84px;
    top: 180px;
}

#pagination li {
    list-style: none;
    float: left;
    margin: 0 2px
}

#pagination li a {
    display: block;
    width: 8px;
    height: 8px;
    background: #ccc;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
}

#pagination li a.active {
    background: #fff;
}	

And that's it. To make the information change when the content is clicked, and through the pagination, here is all the JavaScript code that's needed:

function displayPage(index) {
    var element = document.getElementsByClassName("container active")[0];
    element.className = "container hidden";

    var element = document.querySelectorAll('div.container[data-index="' + index + '"]')[0];
    element.className = "container active";

    document.querySelectorAll("#pagination a.active")[0].className = "";     
    document.querySelectorAll('#pagination a[data-index="'+index+'"]')[0]
    	.className = "active";
}

(function() {
    document.getElementById("ring-content").onclick = function() {
        var element = document.getElementsByClassName("container active")[0];
        var index = parseInt(element.dataset.index) % 5 + 1;
        displayPage(index);
    }

    var elements = document.querySelectorAll("#pagination a");
    for (i = 0; i < elements.length; i++) { 
        elements[i].onclick = function(e) {
            e.preventDefault();
            e.stopPropagation();
            displayPage(this.dataset.index);
        }
    }
})();

The code is very short, but it took me all Sunday to settle with what I really wanted. I'm happy with how it turned out, and I hope it's useful for you somehow.

The madness of layered architecture

Great post by Johannes Brodwall talking about layered architectures and why they hurt so much:

I once visited a team that had fifteen layers in their code. That is: If you wanted to display some data in the database in a web page, that data passed through 15 classes in the application. What did these layers do? Oh, nothing much. They just copied data from one object to the next.

(...) enterprise applications are not like network protocols. Every layer in most enterprise application operates at the same level of abstraction.

I've seen this so many times. I've been personally responsible for doing this most of my life as a developer. But I think I already learned my lesson.

Now every time I design something, I try to be as lean as possible. Years have taught me the value of simplicity, and I stopped a long time ago adding classes and more classes just in case we need to change this or replace that.

There's value in a layered architecture, no doubt about that. But when used incorrectly they hurt your code pretty badly; they introduce unnecessary layers of indirection that are hard to understand and maintain.

Quoting Johannes again:

Every problem in computer science can be solved by adding a layer of indirection, but most problems in software engineering can be solved by removing a misplaced layer.

Amen.

Back in 2010 I blogged about this. The article is in Spanish, but if you can read it you'll get the full picture about where I stand about this whole thing.

As a bonus, go and watch this video titled Layers Considered Harmful.

How to know if your Python code is running locally or in App Engine

This blog uses memcache to store almost everything. This is great for production, but really annoying for when I'm making changes or writing a new post.

I created a simple flag to turn memcache on and off, but I always forget to turn it back on before publishing, so most of the time I had to re-publish the code after fixing the mistake.

There had to be a better way, and it turns out that there is!

import os

is_running_locally = os.environ['SERVER_SOFTWARE'].startswith('Development')
is_running_on_appengine = os.environ['SERVER_SOFTWARE'].startswith('Google App Engine')

From the Google documentation:

The following environment variables are part of the WSGI and CGI standards, with special behavior in App Engine:

  • SERVER_SOFTWARE: In the development web server, this value is "Development/X.Y" where "X.Y" is the version of the runtime. When running on App Engine, this value is "Google App Engine/X.Y.Z".

So all I had to do was setting my flag to the appropriate value:

MEMCACHE_ENABLED = os.environ['SERVER_SOFTWARE'].startswith('Google App Engine')

This way memcache will be always disabled during development, and always enabled when deployed.

La informática en Cuba

(The last time I posted a Spanish article on this blog was back in 2011. Three years later, the readership of the blog has mainly switched to English speakers, so I apologize in advance for throwing this post in your face. I wanted to talk about the informatics on my home country, so I considered appropriate to use my native tongue as well).

Aunque no precisamente este modelo, computadoras como esta eran muy comunes a principios de siglo en Cuba. Fuente oldcomputers.net.

Hace ya una década que salí de la universidad. En junio de 2004, luego de 5 años estudiando Ingeniería Informática en la Universidad de Camagüey, llevaba para mi casa el flamante título de graduado y me preparaba para iniciar mi carrera profesional.

Mucho ha llovido desde entonces, sobre todo en el mundo de la tecnología, donde diez años son una eternidad. Sin embargo, aparentemente el tiempo no pasa con la misma velocidad en todas partes del mundo. La Cuba a la que regresé hace unas semanas sigue siendo la de aquella primavera de 2009 cuando me fui, la que me vió terminar mis estudios en el verano de 2004, la misma de siempre.

A pesar de que mucho ha cambiado, en el plano informático Cuba está sumida en un letargo. Las conversaciones de las que un día fui partícipe antes de salir siguen en boca de todos. Las mismas discusiones aún no han encontrado solución. Los viejos problemas son cada vez más problema, o quizás peor; posiblemente ya nadie quiera intentar resolverlos o todos hayan muerto del aburrimiento, o de desilusión, o un poco de ambos.

El mundo desarrollado habla hoy en día un idioma que mi país todavía no es capaz de comprender. Cuando la Internet en los países del primer mundo es algo tan natural como la electricidad o el agua potable, en Cuba sigue siendo un sueño para la mayoría de las personas y empresas. Más que la Internet, la informatización del país es extremadamente incipiente.

Basta con mirar alrededor y hacer unas pocas preguntas para darse cuenta de que aún todo es papel y lápiz. Las empresas que cuentan con computadoras carecen de personas que sepan operarlas correctamente y, cuando el personal existe, entonces falta el software adecuado.

Ocurre así a todos los niveles, desde las mismas instituciones de gobierno, pasando por empresas ricas y pobres, hasta llegar al ámbito de los nuevos “cuentapropistas” y las universidades. Peor aún, la misma -y única- institución dedicada a producir software en Camagüey me dicen que está en la misma situación: sin brújula, recursos o ideas. Si no ellos, ¿quién?

La solución no es mágica ni tiene mucho que ver con el embargo. No está en ninguna otra parte sino en el mismísimo patio cubano y sólo falta que exista una voluntad de poner la maquinaria en movimiento para que el país comience a acortar distancias.

El principal impedimento que existe en la isla hoy en día es el acceso a Internet, no sólo para los profesionales de la rama sino para todas las personas. El público crea la demanda que impulsa el desarrollo de nuevas soluciones. Sin Internet Cuba seguirá aislada y desconectada, tanto del mundo exterior como internamente, de sus mismos ciudadanos. Hay otros factores necesarios, por supuesto, y cada pieza tomará su lugar en el momento adecuado, pero lo primero es conectar al país porque la Internet es el principal motor de una revolución tecnológica.

¿Qué va a suceder una vez vencido este primer reto y luego de que la mayor parte del país tenga acceso a la red? ¿Cuánto tiempo va a tardar la informatización en alcanzar un nivel adecuado?

Los recursos humanos están, pero ¿están preparados? Me pregunto si con tantos años desconectados del mundo exterior existe hoy en día en Cuba el nivel necesario para llevar a cabo el desarrollo de la esfera tecnológica. Si nos detenemos a analizar la formación técnica de los estudiantes antes de entrar a la universidad veremos que es incipiente y en muchos lugares del país, nula. Una gran cantidad de los muchachos llegan a cursar estudios superiores sin jamás haber tocado una computadora o, peor aún, muchos se gradúan sin prestarle la más mínima atención.

El sistema de educación cubano tiene que mejorar su enfoque en ese sentido. La informática debe estudiarse desde la base para que aquellos jóvenes decididos a estudiar una de las ramas técnicas lleguen con una preparación sólida a la universidad. Si la calidad de la enseñanza aumenta en los grados inferiores veremos que se incrementará de manera exponencial a nivel profesional.

La universidad tiene, además, que adaptar sus programas al mundo actual. Es imposible mantener una carrera universitaria cambiando constantemente, pero tampoco puede estar estática por años y años sin correr el riesgo de convertirse en irrelevante. El estado del arte en materia informática cambia aceleradamente con cada año que pasa y la universidad cubana debe actualizarse y buscar vías para distribuir conocimientos relevantes a los profesionales de la rama.

Muchas asignaturas que se estudian hoy en día están desactualizadas o ya son intrascendentes para el mundo actual. Del mismo modo, temas fundamentales están siendo completamente obviados y, como consecuencia, los recién graduados tienen que enfrentarse a un universo profesional para el cual no están preparados.

La lista es larga, pero temas como el desarrollo web, las base de datos no relacionales y las metodologías ágiles deberían ser parte del programa oficial y no tópicos optativos. Asignaturas como Máquinas Computadoras, Diseño Asistido por Computadora, Gestión de Software, Automatización Industrial, Administración de Empresas e Ingeniería de Software deberían actualizar su contenido para brindar un valor superior acorde a los tiempos modernos.

Es este el momento de reformular modelos obsoletos y de impulsar a Cuba hacia el siglo XXI. La Internet será el combustible indispensable, pero la formación de profesionales jugará un papel igualmente determinante en el futuro tecnológico del país.

Es tiempo de cambios.

Mailtrap and Loggly

Here are a couple of online applications you'll appreciate if you are a developer (descriptions copied from their websites):

  • Mailtrap: A fake SMTP server for development teams to test, view and share emails sent from the development and staging environments without spamming real customers.
  • Loggly: A cloud-based log management service that helps technical teams make sense of logs that are being produced by cloud-centric applications in order to solve operational problems faster.

If you haven't heard from them before, go and check them out because changes are you already need them.

Looking back on my 10th-graduation anniversary

Last week I realized that this June represents my 10th-graduation anniversary. An entire decade since I got my college degree after 5 long years and started working as a professional software engineer. That was the summer of 2004, and I wanted to celebrate the occasion taking a quick look back.

2004 - 2008

After graduating, I started working as a software developer in ETECSA, the only telecommunications company in Cuba. Back then in my town this was one of the best gigs a developer could get. Right now with the introduction of private-owned businesses, it's probably one of the worsts.

I worked there for four years, give or take, mainly developing on .NET, specifically with ASP.NET Web Forms (I think I first used ASP.NET MVC after leaving ETECSA, although I'm not totally sure). I spent some time during my last year there working on a big-flop project with Java and Eclipse RCP (of course, this app didn't go anywhere).

I specifically remember a couple of web applications I created and were used in several offices across the country, and a set of integration tools to streamline the onboarding process for new employees. The tools connected our Human Resource database (a Microsoft Access DB) with our Windows Domain (LDAP) server. These were fun and tricky to develop, and taught me to hate Microsoft Access and everything related to it.

Here is a quick summary of all the important things I remember that happened during these 4 years:

  • For the first time I had the opportunity to work in real applications used by real people. More important, I had the opportunity to deal with changes on already-deployed applications.
  • I spent the majority of my time on events and forums presenting over and over again the applications I once created. This was a lot of fun because I traveled a lot, but more importantly gave me tons of free time that I used to work on freelance projects.
  • I learned that Cuba gives a shit about its economy and it's all about politics.
  • I learned that the only way to advance your career in Cuba is by moving to Havana and become another cog in "The Process". Outside Havana, people are just invisible. Outside "The Process", there's nothing worth looking at.
  • For a software developer living in Cuba, the only way to do something meaningful is by doing it yourself and forgetting about any support from your company. They are going to promise a lot, but it will never come. Trust me.
  • In Cuba nobody cares.

2008 - 2009

By the end of my time in ETECSA, I had already given up trying to move forward the technical state of the company. I became another frustrated professional pursuing an impossible cause, so I decided to go with a 24/7 freelancer life. There was way more money, and way more opportunities to learn.

I had done some freelancing work before, but at this point I was ready to take it more seriously. I moved full time to a room at home and started working with another 3 friends. A crappy Internet connection (modem at ~56kbps) was enough for us, so we started working on several projects for a north american company.

It's hard to remember on how many projects I participated during this time, but I'd guess they were about a couple dozen. I started as a developer, but soon enough I took more of a lead role. My job was basically communicating with our client, organizing/distributing all the work, and putting fires out whenever needed.

This was my real introduction to the web. Almost all applications we worked on during this period were web applications, although I remember a couple of desktop apps here and there.

Around winter of 2008, when money stopped to be a problem, I decided to leave Cuba and move to United States. My boss at the time promised me a job, and the uncertainty of leaving the country added that extra adrenaline that I needed. I touched American soil on May 2009, and then a total new chapter started on my career.

Some of the highlights for these years:

  • It was the first time I took JavaScript, CSS, and HTML seriously. In the middle of my ignorance I honestly believed those were for amateurs.
  • Learned a lot about how important is to be on time, up-front with clients, proactive, and how to solve problems.
  • Learned a ton about managing software projects and spliting and assigning work to different developers.
  • Learned a lot about writing and reading English. (If you are reading this and you consider it bad, try to picture it 5 years ago).
  • Learned how to appreciate small things, like my slow-as-crap 56kbps modem, or a microwaved lunch.

2009 - 2010

Days after coming to U.S. I started working with/for my boss. I did it by creating my own company, and although most of the work came from my boss's company, I scored a few new clients that helped me pay the bills.

This was the time when I started learning how to live on a capitalist country. The change was brutal on every aspect of my life, but it was totally worth it.

Professionally, it was the first time I used a decent Internet connection, so all of the sudden I had infinite opportunities right opened before my eyes. I learned a lot working on all the projects I had (a few dozen I'd guess). I had to code like crazy, but I spent most of my time on a management role.

The most important career-related highlights:

  • Learned a lot of English. Heck, I had to living among Americans.
  • The Internet opened for me a sea of possibilities and life-changing opportunities: For the first time I started following blogs, reading career-relevant stories, tweeting, using different online tools, etc.
  • Worked on my first Android application after buying my first Android phone.
  • Learned that getting somebody to sign a check for you is a difficult task. You have to work hard to get money out of people's pockets.
  • Learned that businesses love to pay your invoices after they are overdue. (And sometimes a little later than that).
  • Realized that freelancing is just not for me. I love the entrepreneurial mindset, but I'd rather work in a different environment.
  • Started blogging.
  • Started hating Adobe Flash. And right to its death (at least on the mobile side), I hated it.
  • Worked a lot. A whole lot more that I had ever worked before in my life.

2010 - 2014

By the end of 2010, a small digital agency located in South Florida contacted me looking for help on a project with one of their biggest clients. It was Java, so I decided to go. They brought me on-site to work from their office.

Small company I remember. I think there were around 10 employees at the time. I worked on the thing, helped the team release it, and when I was done, the company asked me to come on board as a full time employee.

Hell, why not? I was a little bit tired chasing clients around, so I gave it a shot and took the offer.

The rest is history. Levatas is close to a hundred employees right now, and I'm very proud to be part of that growth. From a Senior Software Engineer position I found my way to an Engineer Manager role, and I couldn't be happier doing it (well, not true, humans can always be happier!).

During all these years I have touched literally hundreds of projects, mostly small ones, although you can throw a handful of multi-year engagements on that list. Working for big names like IBM, Cisco, HP, Dell, Avaya, Emerson, Fujitsu, and HSBC is something that you can't get everyday, and I'm very grateful to my company for that opportunity.

The most interesting events:

  • Got my first paycheck as a full time employee.
  • For the first time I started speaking the HTML5 lingo.
  • Had the opportunity to work for several Fortune 500 companies.
  • Worked on my first iOS application. (I liked Android way more but Java probably biased this assessment).
  • Released on GitHub my first open source project, an Android application to check the stock market.
  • Started working with Scrum, leaving behind years of Waterfall experience.
  • Started working with NoSQL databases, scalable technologies, and cloud applications.
  • Participated on Google I/O 2013. It was a blast and I don't remember any other time when I was able to absorb so much knowledge in just a few days.
  • Participated on Google Chrome Summit 2013. It was good, although Google I/O had already spoiled the event for me.
  • Was introduced to managing people (not projects). A little bit different to what I expected, and 100 times harder.

Another set of important events

Here are some other important events that happened during this time, but are hard for me to time-box under specific years:

  • Became a phone-aholic.
  • Learned to appreciate soft-skills on professionals, like self-organization, motivation, passion, perseverance, among others.
  • Became really passionate about performance on websites.
  • Realized that email can be a time-sucking machine.
  • Realized that there's a lot to do for me in the next 10 years.

Looking forward to the next 10 years

Luckily for me, this is just the beginning. I feel like I've never been so much excited before about what's about to come. Hopefully, I'll be able to look back in 2024 to do the 20-year summary just like this one.

Here I come!

Building the blog - Episode 10 - Related Posts

A great way to increase the visibility of your posts is by adding a "Related posts" section at the end of each article. There are several services out there that channel your content and create this list for you, but I'm all about free and fast, so I decided to build my own engine.

And it turned out to be a very simple and clean implementation.

I started by adding the ability to tag my posts. This way I can add keywords to each post that will later serve as the indicator for the related posts engine. (The not-so-fun part was going back and updating several old posts with tags. I didn't update all of them though, so I'll have to at some point). ​​

When a post is about to be served, the engine finds related posts using a weighted list where tag coincidence and post date are the two important pieces. If there are no matchings the section is not displayed.

Since everything on the blog is heavily cached, the engine will have to run only the first time a post is visited, but will serve results from memcache after that.

The engine is implemented on the Mapping class (you can see the complete source code here) and it's less than 40 lines of code.

And while at it, I decided to make some tweaks to the design of the blog to add a little bit of color. Very subtle but I'm happy with how it turned out (basically links are now blue, making them easy to spot).