Today I Learned

Escalabilidade Vertical x Horizontal

Diferença de sistemas que escalam verticalmente e horizontalmente

Sistemas que escalam verticalmente são aqueles que crescem em capacidade adicionando mais recursos ao mesmo servidor.
Sistemas que escalam horizontalmente são aqueles que crescem em capacidade adicionando mais servidores ao sistema.

Sistemas que escalam verticalmente possuem um limite de capacidade, pois a quantidade de recursos que um único servidor pode ter é limitada. Já os sistemas que escalam horizontalmente são mais flexíveis, pois podem crescer de forma quase ilimitada, já que podemos adicionar mais servidores em paralelo para dividirem a carga de recursos.

Um exemplo de sistema que escala verticalmente é um servidor de banco de dados relacional (PostgreSQL, MySQL, MariaDB, SQL Server...), onde se quisermos aumentar a capacidade de processamento, memória ou armazenamento, precisamos adicionar mais recursos ao mesmo servidor.

Em paralelo temos os bancos NoSQL, como o Cassandra, MongoDB, Couchbase, que são sistemas que escalam horizontalmente, pois podemos adicionar mais servidores ao cluster para aumentar a capacidade de armazenamento e processamento, dividindo a carga de consumo de recursos pelo sistema entre os servidores do cluster.

Validação no construtor Java

Mantendo a validação dos setters no construtor de uma classe Java

Uma boa prática na hora de criar os construtores de uma classe, é reaproveitar os setters dos atributos para manter a validação.

Imagine que temos a classe Carro, com seus respectivos setters:

public class Carro {
	private String marca;
	private String modelo;
	private int ano;
 
	public void setMarca(String marca) {
		this.marca = marca;
	}
 
	public void setModelo(String modelo) {
		this.modelo = modelo;
	}
 
	public void setAno(int ano) {
		if (ano > 0 && ano <= 2025) {
			this.ano = ano;
		}
	}
}

Perceba que temos uma validação no método setAno(int ano), que impede que o usuário defina um ano menor que 0 (negativo) e maior que 2025.

Agora vamos criar o construtor para a classe:

public class Carro {
	private String marca;
	private String modelo;
	private int ano;
 
	public Carro(String marca, String modelo, int ano) {
		this.marca = marca;
		this.modelo = modelo;
		this.ano = ano;
	}
 
	public void setMarca(String marca) {
		this.marca = marca;
	}
 
	public void setModelo(String modelo) {
		this.modelo = modelo;
	}
 
	public void setAno(int ano) {
		if (ano > 0 && ano <= 2025) {
			this.ano = ano;
		}
	}
}

Criando o construtor desse jeito, podemos instanciar a classe passando os seguintes parâmetros:

Carro carro = new Carro("Ferrari", "HB20", -2024);

Perceba que podemos passar o valor negativo como parâmetro do construtor, e isso é válido, já que o construtor não possui validação, apenas o setter do ano setAno(int ano).

Parra corrigir isso, é só chamarmos os setters no construtor, para manter a validação:

public class Carro {
	private String marca;
	private String modelo;
	private int ano;
 
	public Carro(String marca, String modelo, int ano) {
		setMarca(marca);
		setModelo(modelo);
		setAno(ano);
	}
 
	public void setMarca(String marca) {
		this.marca = marca;
	}
 
	public void setModelo(String modelo) {
		this.modelo = modelo;
	}
 
	public void setAno(int ano) {
		if (ano > 0 && ano <= 2025) {
			this.ano = ano;
		}
	}
}

Edit multiple line on Vim

How to edit multiple lines at once on vim/neovim/lunarvim

For edit multiple lines, click CTRL+V for init block selection. Click J or K for select the lines, or use arrows up/down.

Now with lines selected, press SHIFT+I for insert on all lines, or SHIFT+A for insert on the end of all lines.

ref: https://vimtricks.com/p/edit-multiple-lines-at-once-in-vim/

Disable CMP on LunarVim

How to disable completitions on specific LunarVim session

You can disable cmp with inline Lua command, invoked by :lua command.

:lua require('cmp').setup({ enabled = false })

Relearning Java

How we start a Java file

Java is a 100% POO language, so to starts a Java software, our main function need to be a class method.

The filename need to be the same of the class that was declared in this file.

So the basic structure of Java file is:

class Program {
  public static void main(String[] args) {
    System.out.println("Hello World");
  }
}

Where Program is the class name of this file and main the method name, i.e., the main function that will be executed.

  • public means that our main() method can be used by all files that imports Program
  • static means that our main() method can be called without instantiate the class Program
  • void means that our main() method doesn't return anything
  • args is the argument that our main() method receives. In this case, an array of String objects. This is the way that Java receives the arguments passed by the command line.
  • System.out.println() is the way that Java print something in the console.
    • System is a class that Java provides to us native methods to interact with the system
    • out is a static object of System class that represents the output stream
    • println() is a method of out object that prints a string and a new line (Alternative: print(), that prints only the string without a new line)

And, the filename need to be Program.java because our class is named Program.

Animated text

Animated cascade text on terminal with Python

Cascade effect of texts

import string
import time
 
text = "Hello World!"
 
temp = ""
for ch in text:
  for i in string.printable:
    if i == ch or ch == " ":
      time.sleep(0.02)
      print(temp+i)
      temp += ch
      break
    else:
      time.sleep(0.02)
      print(temp+i)
 
print('\033[1;32m'+text)

Single Tenant vs Multi Tenant

Diferença do modelo Single Tenant e Multi Tenant em um SaaS

Os modelos de Single Tenant e Multi Tenant são duas abordagens diferentes para a arquitetura de um SaaS, e dizem respeito a como o serviço/infraestrutura é oferecido ao cliente.

SaaS: Software as a Service

Single = Um software que é utilizado por UMA empresa, cada cliente possui um instância do software, incluindo a infraestrutura e banco de dados.

Multi = Um software que é utilizado por VÁRIAS empresas, todos os clientes compartilham a mesma instância do software, incluindo a infraestrutura e banco de dados.

Multi Tenant NÃO QUER DIZER subdomínios.
Multi Tenant NÃO QUER DIZER um banco de dados por empresa.

ref: https://www.youtube.com/watch?v=fZeNbnMqMLM

Supress hydration warning on Next.js

Supress "Text content does not match server-rendered HTML"

Just use suppressHydrationWarning on the component that is causing the warning:

<time datetime="2016-10-25" suppressHydrationWarning />

Promise.all

Otimizando chamadas assíncronas no Javascript

Dica JavaScript: Otimize Chamadas Assíncronas com Promise.all

Executar await em chamadas assíncronas de forma sequencial, como em getProducts() seguido por getOrders(), faz com que a segunda chamada espere a conclusão da primeira, aumentando o tempo total de execução.

Optar por Promise.all nesse caso, permite que as chamadas sejam feitas em paralelo, reduzindo o tempo de espera e melhorando a performance da sua aplicação.

worse

async function getData() {
  const products = await getProducts()
  const orders = await getOrders()
}

better

async function getData() {
  const [products, orders] = await Promise.all([
    getProducts(), getOrders()
  ])
}

Mas o Promise.all deve ser usado com cuidado, porque se uma das requisições falhar, todas vão falhar.

ref: https://www.linkedin.com/feed/update/urn:li:activity:7166552833750773760/

Intentional Hover Effects

Create intentional hover effects with transition-delay

Intentional CSS :hover effects 🎈

Add a small transition-delay so you know the :hover is intentional. See the difference below 🎞️

a::after { transition: scale 0.2s ease-in-out; }

vs.

a::after { transition: scale 0.2s 0.125s ease-in-out; }

Can be useful for some designs 🤙

CodePen

ref: https://twitter.com/jh3yy/status/1756827897573089383

`iter` vs `into_iter`

Tthe difference between `iter`, `into_iter` and `iter_mut` on Rust

TL;DR

  • The iterator returned by into_iter may yield any of T, &T or &mut T, depending on the context.
  • The iterator returned by iter will yield &T, by convention.
  • The iterator returned by iter_mut will yield &mut T, by convention.

The first question is: "What is into_iter?"

into_iter comes from the IntoIterator trait:

pub trait IntoIterator 
where
    <Self::IntoIter as Iterator>::Item == Self::Item, 
{
    type Item;
    type IntoIter: Iterator;
    fn into_iter(self) -> Self::IntoIter;
}

You implement this trait when you want to specify how a particular type is to be converted into an iterator. Most notably, if a type implements IntoIterator it can be used in a for loop.

For example, Vec implements IntoIterator... thrice!

impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>

Each variant is slightly different.

This one consumes the Vec and its iterator yields values (T directly):

impl<T> IntoIterator for Vec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;
 
    fn into_iter(mut self) -> IntoIter<T> { /* ... */ }
}

The other two take the vector by reference (don't be fooled by the signature of into_iter(self) because self is a reference in both cases) and their iterators will produce references to the elements inside Vec.

This one yields immutable references:

impl<'a, T> IntoIterator for &'a Vec<T> {
    type Item = &'a T;
    type IntoIter = slice::Iter<'a, T>;
 
    fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ }
}

While this one yields mutable references:

impl<'a, T> IntoIterator for &'a mut Vec<T> {
    type Item = &'a mut T;
    type IntoIter = slice::IterMut<'a, T>;
 
    fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ }
}

So:

What is the difference between iter and into_iter?

into_iter is a generic method to obtain an iterator, whether this iterator yields values, immutable references or mutable references is context dependent and can sometimes be surprising.

iter and iter_mut are ad-hoc methods. Their return type is therefore independent of the context, and will conventionally be iterators yielding immutable references and mutable references, respectively.

ref: https://stackoverflow.com/a/34745885

Subslice Pattern Rust

Use pattern matching on Rust slices/vectors

This is a usefull pattern on Rust match when you want to match slices of a vector.

Imagine this problem: We want to implement a function which takes an vector containing the names of people that like an item. It must return the display text as shown in the examples:

[]                                -->  "no one likes this"
["Peter"]                         -->  "Peter likes this"
["Jacob", "Alex"]                 -->  "Jacob and Alex like this"
["Max", "John", "Mark"]           -->  "Max, John and Mark like this"
["Alex", "Jacob", "Mark", "Max"]  -->  "Alex, Jacob and 2 others like this"
For 4 or more names, the number in 'and 2 others' simply increases.

We can solve this with:

fn likes(names: &[&str]) -> String {
  match names {
    [] => format!("no one likes this"),
    [a] => format!("{} likes this", a),
    [a, b] => format!("{} and {} like this", a, b),
    [a, b, c] => format!("{}, {} and {} like this", a, b, c),
    [a, b, rest @ ..] => format!("{}, {} and {} others like this", a, b, rest.len()),
  }
}

Where rest @ .. will catch all the rest of the vector items.


Another examples:

Fixed size
let arr = [1, 2, 3];
match arr {
  [1, _, _] => "starts with one",
  [a, b, c] => "starts with something else",
};

Dynamic size
let v = vec![1, 2, 3];
match v[..] {
  [a, b] => { /* this arm will not apply because the length doesn't match */ }
  [a, b, c] => { /* this arm will apply */ }
  _ => { /* this wildcard is required, since the length is not known statically */ }
};

fn foo(words: &[&str]) {
  match words {
    [] => println!("empty slice!"),
    [one] => println!("one element: {:?}", one),
    [one, two] => println!("two elements: {:?} {:?}", one, two),
    _ => println!("I'm not sure how many elements!"),
  }
}

fn foo(words: &[&str]) {
  match words {
    ["Hello", "World", "!", ..] => println!("Hello World!"),
    ["Foo", "Bar", ..] => println!("Baz"),
    rest => println!("{:?}", rest),
  }
}

fn foo(words: &[&str]) {
  match words {
    // Ignore everything but the last element, which must be "!".
    [.., "!"] => println!("!!!"),
 
    // `start` is a slice of everything except the last element, which must be "z".
    [start @ .., "z"] => println!("starts with: {:?}", start),
 
    // `end` is a slice of everything but the first element, which must be "a".
    ["a", end @ ..] => println!("ends with: {:?}", end),
 
    rest => println!("{:?}", rest),
  }
}

refs:

Find-And-Replace Vim

How to fast replace all mathing strings on vim

For basic find-and-replace on vim, we can use the :substitute (:s) command.

The general form of the substitute command is as follow:

:[range]s/{pattern}/{string}/[flags] [count]

The command search each line in [range] for a {pattern}, and replaces it with a {string}.
[count] is a positive integer that multiplies the command.

If no [range] and [count] are given, only the pattern found in the current line is replaced.
The current line is the line where the cursor is placed.

For example, to search for the first occurrences of the string "foo" in the current line, and replace it with "bar", you should use:

:s/foo/bar

To replace all occurrences of the search pattern in the current line, add the g flag:

:s/foo/bar/g

If you want to search and replace the pattern in the intire file, use the percentage character % as a range.
This caracter indicates a range from the first to the last line of the file:

:%s/foo/bar/g

We can also use | as parameter separator:

:s|foo|bar

To show confirmation for each substituition, use c flag:

:s/foo/bar/gc

To ignore case sensitivity, use i flag:

:s/foo/bar/gi

There is much more options, look at the ref link for more...

ref: https://linuxize.com/post/vim-find-replace/

Application-Only Volume on MOCP

How to use a "application-only" volume on MOCP for change volume on mocp without affect system

I was using MOCP on linux for a while to listenning some musics that I have downloaded on my machine, but the only defect of MOCP is the volume controll... until now...

The default volume controll of MOCP controlls the volume from ALSA hardware mixer setting, which change the volume from all system. That is a pain when you want to listennig musics as background music, while listenning another sounds too (like noisekun.com).

Today I discovered that there is a way to make mocp volume controll independent from system volume.

You may see that on volume bar (lower left corner) was writen "Master":
screenshot of mocp volume bar (https://i.imgur.com/9YpA3DE.png)

This mean that the volume controll reflect the system volume, so we need to change this with the key X. Now our bar is:
screenshot of mocp volume bar (https://i.imgur.com/jaAFNpo.png)

And the volume is independent of system volume.

If your volume bar is writen "S.Off", you can type W to change to "Soft"

ref: https://moc.daper.net/node/1512

Rust Box

What is the "Box" in Rust Lang

Reading some Rust code examples in documentation and blogs, I can see the use of Box<T> declaration. Like:

struct Schema {
    commands: Vec<Box<dyn Migration>>,
}

According to the official Rust documentation: "All values in Rust are stack allocated by default. Values can be boxed (allocated on the heap) by creating a Box<T>. A box is a smart pointer to a heap allocated value of type T. When a box goes out of scope, its destructor is called, the inner object is destroyed, and the memory on the heap is freed."

ref: https://doc.rust-lang.org

Random Strings in Rust

How to generate a random fixed size string in Rust

For generate a random string with fixed size in Rust, we can use Alphanumeric trait from rand crate:

use rand::{distributions::Alphanumeric, Rng}; // 0.8
 
fn main() {
  let s: String = rand::thread_rng()
    .sample_iter(&Alphanumeric)
    .take(7)
    .map(char::from)
    .collect();
  println!("{}", s);
}
 

ref: https://stackoverflow.com/questions/54275459/how-do-i-create-a-random-string-by-sampling-from-alphanumeric-characters

Rust + SQLite

Connect SQLite in a Rust app

For run SQL queries on SQLite database from Rust, we can use the sqlite3 crate:

let connection = sqlite::open(":memory:").unwrap();
 
connection
  .execute(
    "
    CREATE TABLE users (name TEXT, age INTEGER);
    INSERT INTO users (name, age) VALUES ('Alice', 42);
    INSERT INTO users (name, age) VALUES ('Bob', 69);
    ",
  )
  .unwrap();
Open a connection, create a table, and insert some rows.

connection
  .iterate("SELECT * FROM users WHERE age > 50", |pairs| {
    for &(column, value) in pairs.iter() {
      println!("{} = {}", column, value.unwrap());
    }
    true
  })
  .unwrap();
Select some rows and process them one by one as plain text:

And more...

ref: https://docs.rs/sqlite3/latest/sqlite3/

Handshake Combinations

Math behind the calculation of the number of handshakes from N persons

Given nn people, how many handshakes will be given by all the people greeting each other?

We can determine this using the formula:

n(n1)2\frac{n(n-1)}{2}

Where nn is the number of people that will handshake.

ref: solution for https://www.hackerrank.com/challenges/handshake/problem

Disable Node Warnings

How to disable node warnings with env variable

When we run a node script, we can see incovenie warnings like:

https://i.imgur.com/1yHZHf9.png

(node:3174) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)

For disable this warnings, just pass NODE_NO_WARNINGS=1 as environment variable before node command or script, e.g.:

NODE_NO_WARNINGS=1 node index.js

On package.json script:

// ...
  "script": {
    "test": "NODE_NO_WARNINGS=1 jest --watch"
  }
// ...

Position Sticky

Use position sticky with tailwindcss

We can use sticky class when using tailwind to make an element fixed on screen while the parent element is visible.

Code:

<div class="relative">
  <h1 class="sticky top-0">Element</h1>
</div>

CSS Equivalent:

.parent-element {
  position: relative;
}
.element {
  position: sticky;
  top: 0;
}

Visual example: https://www.w3schools.com/howto/howto_css_sticky_element.asp

Mock module inside test

How to mock module implementation inside a test with jest

Sometimes you are testing a component and need to mock a module (in this case I needed to mock a zustand store), but with the exemple of "next/navigation" mock, you are mocking the module for entire test suit on the file that you declare the jest.mock(). But, if you want to mock a specific implementation for each test? So first, with need to declare the module mock, without pass the implementation function:

jest.mock('../../stores/sounds-state-store')

In this case we are mocking "../../stores/sounds-state-store" module

And, inside each test, we will use the jest.Mock.mockImplementation() function to mock the implementation of module inside it/test scope:

the store we want to mock is useSoundsStateStore, from '../../stores/sounds-state-store'

useSoundsStateStore.mockImplementation(
  () =>
    [{ active: true, id: 'd4ad48e', loaded: true, volume: 1 }] as SoundState[]
)

Full code:

// other imports...
import { SoundState, useSoundsStateStore } from '../../stores/sounds-state-store'
 
jest.mock('../../stores/sounds-state-store')
 
describe('Clear Button', () => {
  // tests...
 
  it('should not be disabled', async () => {
    ;(useSoundsStateStore as unknown as jest.Mock).mockImplementation(
      () =>
        [
          { active: true, id: 'd4ad48e', loaded: true, volume: 1 }
        ] as SoundState[]
    )
 
    render(<ClearButton />)
 
    const button = await screen.findByRole('button', { name: /clear/i })
 
    expect(button.getAttribute('disabled')).toBeNull()
  })
 
  // tests...
})

Note that we use:

;(useSoundsStateStore as unknown as jest.Mock).mockImplementation()

instead of:

useSoundsStateStore.mockImplementation()

Because it's a typescript project, and we need to tell the ts compiler that useSoundsStateStore have jest.Mock functions on this scope.

references:

Mock "next/navigation" with Jest

How to fix error "invariant expected app router to be mounted" when test Next.js hooks/components

Next.js: 14.0.3

When you try to test a component or hook that uses some function from "next/navigation" module (like useRouter, useSearchParams, useSearchParams, etc.), you may come across the error:

● Test suite failed to run
 
  invariant expected app router to be mounted
 
    5 |
    6 | export default function useQueryState(key: string, defaultValue: string = '') {
  > 7 |   const router = useRouter()
      |                           ^
    8 |   const searchParams = useSearchParams()
    9 |   const pathname = usePathname()
   10 |

This happening because the "next/navigation" just works when app router was monted, to solve this, you need to mock the entire module. Put this before all your describes and it/tests:

jest.mock('next/navigation', () => ({
  useRouter: jest.fn(() => ({
    replace: jest.fn()
  })),
  useSearchParams: jest.fn(() => ({
    get: jest.fn()
  })),
  usePathname: jest.fn()
}))

references: https://github.com/vercel/next.js/discussions/48937

Enable Locales on GNOME

Enable some locales to use when they not appear on "Region & Language" menu

When we go to Region & Language menu to change locale (language and units) of a newly installed system with GNOME, may not have the language you are looking for. For the most cases is a question of enable it on /etc/locale.gen.

For this, just edit the file /etc/locale.gen with root privileges:

$ sudo vim /etc/locale.gen

And uncomment the language that you looking for, e.g:

for

#pt_BR.UTF-8 UTF-8

remove the #, and save

pt_BR.UTF-8 UTF-8

After edit the locale file, regenerate locales with command:

sudo locale-gen

That's it! Just go to Region & Language and select your language.

referencies:

Gnome (Debian 11): How to install en*DK formats (date, numbers, units)?: https://unix.stackexchange.com/questions/679315/gnome-debian-11-how-to-install-en-dk-formats-date-numbers-units [_archive*]

Black Wallpaper Bug on XFCE4

Black wallpaper on xfce4 when restart the computer

This problem consists of black background insted the wallpaper on xfce4, apparently is the xfdesktop daemon that was not starting on login. To fix it, wee just need to setup this daemon to auto start on login:

  1. Go to Session and Startup > Application Autostart
  2. Then click on Add
  3. Will appear a window, enter some name, like "Wallpaper Daemon" and the description, "Daemon to load the xfce4 wallpaper", on the command field, add the command xfdesktop --replace.
  4. After save the config, restart the computer.

references:

Desktop background appears black when using XFCE: https://unix.stackexchange.com/questions/151471/desktop-background-appears-black-when-using-xfce [archive]

Oak Over Https

Integrando Oak com certificados SSL

Dependências

Primeiro devemos certificar que temos o programa openssl

dpkg -l |grep openssl

deve aparecer algo como isto

ii libgnutls-openssl27:amd64   2.12.23-12ubuntu2.4   amd64   GNU TLS library - OpenSSL wrapper
 
ii openssl   1.0.1f-1ubuntu2.16   amd64   Secure Sockets Layer toolkit - cryptographic utility

senão tiver o openssl instalado, instale com o comando:

(debian based)

apt-get install openssl

Gerar Chaves

Para gerar a chave privada e o certificado rode o comando:

openssl req -x509 -newkey rsa:2048 -keyout keytmp.pem -out cert.pem -days 365

Depois gere a chave descriptografada:

openssl rsa -in keytmp.pem -out key.pem

ja pode excluir o arquivo keytmp.pem, ele não será mais necessário.

Usar Oak com a chave e o certificado

Para usar Oak com HTTPS devemos passar os atributos secure, certFile e keyFile.
como o exemplo a seguir:

await App.listen({
  port: 8000,
  secure: true,
  certFile: './cert.pem',
  keyFile: './key.pem',
})

Referências

How To Create an HTTPS Server on Localhost using Express: https://medium.com/@nitinpatel_20236/how-to-create-an-https-server-on-localhost-using-express-366435d61f28 [archive]

oak docs: https://github.com/oakserver/oak [archive]

OpenSSL Tutorial: How Do SSL Certificates, Private Keys, & CSRs Work?: https://phoenixnap.com/kb/openssl-tutorial-ssl-certificates-private-keys-csrs [archive]