Sobre como não entregar o trabalho da universidade

Posted on May 16, 2022

Primeiro, no melhor estilo Linus Torvalds, FUCK YOU LINKEDIN! E segundo, esse não é um post técnico, é uma anedota sobre um acontecimento divertido que não apreciei na hora mas que hoje percebo como foi legal.

Okay, então… Estávamos eu e Beatriz falando sobre projetos de universidade, quando eu lembrei que para o último trabalho de Laboratório de Desenvolvimento de Software Orientado a Objetos (LDSOO), eu não entreguei o trabalho pedido.

Eu não lembro o que era que eu deveria entregar, mas era um projeto web em PHP.

Eu nunca fui muito fã de PHP (e ainda não sou), e gostava muito menos de PHP sozinho (usando só Apache, PHP e PDO), foi então que eu decidi que ia começar CONSTRUINDO UMA FRAMEWORK Web do zero em PHP. De uma maneira bem Janil de fazer as coisas. A série de coisas que eu desgostava mais do PHP era: cada arquivo como um entrypoint, ter que escrever SQL na mão (hoje eu gosto), e código espaguete no geral, porque a renderização é tudo o que acontece fora de <?php ?>. A minha inspiração era Django (até aquele ponto a framework mais bem arquitetada com qual eu havia trabalhado).

O primeiro problema que eu resolvi então foi o banco de dados. Eu criei uma biblioteca que deixava você montar uma AST de SQL e depois chamar passando só valores/especificando o modelo (um objeto) de retorno. O nome desse componente é Mímir. Infelizmente não lembro porque escolhi esse deus.

Depois, o problema do código espaguete: eu criei uma engine de templates que deixava você especificar coisas como hierarquia e inclusão de templates, mas de maneira que o template em si não precisava de ter mais lógica do que o necessário para renderizar a página. O nome desse componente é Modus, raiz de modelo (ou template) no latim.

Por fim, criei um Router pra mapear caminhos (ex. GET /users, PUT /users/2) para funções em controladores específicos (e tem mais sobre esses controladores, continua me acompanhando só mais um pouquinho). Claro que esses caminhos poderiam ter parâmetros, e esses parâmetros extraídos da URL e postos em um dicionário.

Okay, a esse ponto eu tinha todos os componentes que eu queria: BD sem SQL, um router e uma template engine. Eu precisava então de conectar todos esses componentes. Aos que não sabem: PHP recebe a requisição em variáveis globais (eu sei, eu sei, não é comigo que vocês tem que reclamar). Então comecei arquitetar o dispatcher para essa framework. O projeto tem objetos de requisição, body parsers (que podem ler JSON e dados de formulário). Criei uma classe para gerenciar parâmetros de query, e uma classe de resposta onde você podia definir headers, status e até cookies (apesar de não ter sido totalmente implementado, pelo que vejo aqui).

Então defini uma estrutura de controladores, que eram só classes que tinham certas funções, você mapeava determinadas rotas a determinadas funções (vai ter código ali em baixo se quiser ver como isso funciona, tá em src/index.php).

MAS… Cada um desses serviços ou controladores poderiam precisar de vários outros, como resolver isso, certo? Bom, tudo mundo sabe como: Dependency Injection. Ou Service Locator. Mas por que não UM HÍBRIDO DOS DOIS??????!!!! A cereja no topo desse bolo foi o ComponentLocator. É uma mistura de um Service Locator, com serviços nomeados, que podem ser acessados com um lookup e uma DI framework, onde você pode especificar um método com todas as dependências que seu componente precisa e o ComponentLocator vai procurar dentre os serviços registrados e adicionar passar para sua classe. Tipo assim:

<?php

class MyComponent {
  private $componentA;
  private $componentB;

  function __dependencies() {
    return ['componentA', 'componentA'];
  }

  function setComponentA($a) {
    $this->componentA = $a;
  }

  function setComponentB($b) {
    $this->componentB = $b;
  }
}

Com isso, eu construí uma framework web em PHP. Era aceitável programar uma aplicação web em PHP agora, eu estava pronto para terminar o trabalho. Certo?

Meme com Anakin e Padmé, quadro 1 Anakin conta para Padmé "A framework tá pronta", quadro 2 padme pergunta "Você vai fazer o trabalho agora, certo?", sorrindo. Quadro 3, Anakin olha sério para Padmé sem dizer nada. Quadro 4 Padmé pergunta de novo, agora com medo no rosto.

Bom. Eu era o Anakin, o Vitor a Padmé. hahahaha

Foi isso, eu não tinha mais tempo para implementar o trabalho, então enviei um e-mail para o Vitor explicando a minha situação absolutamente ridícula. Ele aceitou ver o meu trabalho (que na verdade um trabalho que eu inventei e satisfazia um total de 0 requisitos do trabalho que ele tinha passado), expliquei para ele o que eu fiz, como tinha implementado cada componente. E ele foi gente boa o suficiente para ignorar o fato de que eu tinha feito ZERO do trabalho e me avaliar nos meus devaneios. OBRIGADO VITOR! E me desculpa ser um aluno merda.

Eu poderia ter feito o projeto certo: bom, eu deveria! Mas isso foi muuuiiitooo mais legal. EU NÃO ME ARREPENDO DE NADA. NADA!!!

Aqui o link para o projeto, como foi entregue (eu acho): https://gitlab.com/janilcgarcia/ldsoo.

Eu vou parar por aqui. Quem sabe no futuro não eu não faça uma série de posts de como implementar essa joça? Seria divertido.

English Version

I'm also writing an English version of this post so that JC, for whom I was already working at the time, and actually followed a bit of this story, can read it as well.

Firstly, in the best Linus Torvalds style: FUCK YOU LINKEDIN! And secondly, this is not a technical post. It's an anecdote about a fun moment, which I did not appreciate at the time, but today I can see it was really fun.

Okay, so… Beatriz & I were talking about university projects, when I remembered that for the last project in the "Laboratório de Desenvolvimento de Software Orientado a Objetos (LDSOO)" class, I did not deliver the required project.

I can't remember what I was supposed to deliver, but it was an web project written in PHP.

I was never much of a PHP fan (still am not), and I liked standalone PHP even less (using only Apache, PHP and PDO), that's when I decided that I would start the project by BUILDING A WEB FRAMEWORK from scratch in PHP. In a very Janil-like manner. The things that I most dislike in PHP were: each file was an endpoint, having to write SQL by hand (today I actually like it) and an insanity of spaghetti-code, since in PHP, rendering is the process of print out everything that's outside a <?php ?> tag. My main inspiration was Django (that at that point was the best designed framework I had ever worked with).

The first problem I solved was the database one. I created a library that you could use to build a SQL AST and then just execute queries by passing the right values/specifying which model (an actual object) you'd like to receive from the database. This component is named Mímir. I'm not sure why I choose this god. Sorry.

Then, the spaghetti-code problem: I created a template engine which let you specify things like template hierarchy and do template inclusion, but in a way that the template itself could get away with not having any non-rendering logic. The name of this component is Modus, latin root for "modelo" (template, in English).

Lastly, I created a router to map paths (ex. GET /users, PUT /users/2) to functions in specific controllers (there is more about these controllers, just bear with me a little bit more). Of course, these paths could have parameters in it and those parameters matched in the URL and were extracted in a proper dictionary.

At this point, I had every component I wanted: DB without SQL, a router and a template engine. I just needed to glue everything together. To those who don't know: PHP receives the request information in global variables (yeah, I know, I'm not the one you want to complain with). So I started designing a dispatcher for this framework of mine. The project has request objects, body parsers (which can ready JSON and form data). I wrote a class for handling query parameters, a Response class where you could set status codes, headers and even cookies (although that's not totally implemented, from what I can see here).

Then I defined the structure for those controllers, they're just classes which certain functions, nothing exception, but you map routes to specific functions in those classes (you can take a look at the code below, it's in src/index.php ).

BUT… Each one of those services and controllers could depend on many others. How do you solve that, right? Well, everybody knows you use Dependency Injection. Or a Service Locator. But why not… A HYBRID FROM BOTH????!!!! The cherry on top of this cake was the ComponentLocator. A mixture of both patterns, where you set the services by name, you can lookup services, but it also does automatic dependency by checking the dependencies in a specific method and then setting those dependencies at the service object. Like this:

<?php

class MyComponent {
  private $componentA;
  private $componentB;

  function __dependencies() {
    return ['componentA', 'componentA'];
  }

  function setComponentA($a) {
    $this->componentA = $a;
  }

  function setComponentB($b) {
    $this->componentB = $b;
  }
}

With that, I had built a web framework for PHP. It was acceptable writing a web application in PHP now, I was ready to finish the project. Right?

Anakin & Padmé meme. First frame Anakin tells Padmé "The framework is done", on frame 2 padme asks "You are going to finish the project now. Right?". Frame 3, Anakin looks serious at Padmé, not saying anything. Frame 4 Padmé asks again, now with a little desperation on her face.

Well. I was Anakin. Vitor was Padmé. lol

That was it. I had no more time to implement the required project, so I sent Vitor an email explaining my self-inflected ridiculous situation. He accepted looking at my work (which was a project with requirements that I made and that satisfied precisely 0 requirements that he'd asked), I explained what I did, how I implemented each component. And he was great enough to ignore the fact that I had implemented NOTHING of the actual project and still graded my glimpse into madness. THANK YOU VITOR! And sorry being a shitty student.

Now, could I have implemented the actual project: well, I should have. But this was waaaayy more fun. I REGRET NOTHING! NOTHING, YOU HEAR?!

Here is the link for the project as it was delivered (I believe): https://gitlab.com/janilcgarcia/ldsoo.

I'm gonna stop here. Who knows? Maybe in the future I'll make a series of post explaining how to implement this… thing. I would be fun. But it probably wouldn't be in English, sorry guys.