Podstawy pisania dobrego kodu

Kornel Koszela
kornel@koszela.me

KoNaR, 27.10.2022

Ułatwiaj sobie pracę

Najpierw planuj

Nie musisz rysować UMLi, ale wiedz co chcesz osiągnąć

Najpierw planuj

Najpierw planuj

Najpierw planuj

Najpierw planuj

Miro

Najpierw planuj

Taiga

Najpierw planuj

Figma

Najpierw planuj

Draw.io (app.diagrams.net)
Miro
Taiga
Figma

Używaj IDE

Macie JetBrains za darmo

Ja nie, dlatego spędziłem wieczność konfigurując VSCode

Używaj IDE

Używaj IDE

Korystaj z gita

CTRL+Z działa tylko dopóki nie wyłączysz edytora

Korystaj z gita

Korystaj z gita

Interaktywny kurs
Wizualizacja

Nie wstydź się Google'ować

Siedzenie w internecie to większość czasu programisty, kluczem jest robić to umiejętnie.

Google'uj mądrze

  • Szukaj po angielsku
  • Rozwiązując błędy, usuń identyfikujące informacje
  • Zwracaj uwagę na datę publikacji
  • Preferuj oficjalne źródła
  • Na portalach społecznościowych ignoruj odpowiedzi/pytania z niewielkim zaangażowaniem

Zadawaj dobre pytania

  • Dokładnie i w miarę treściwie opisz problem
  • Dodaj fragment kodu, bądź diagram
  • Wspomnij co już próbowałeś/aś i czemu to rozwiązanie nie działało
  • Szanuj osoby które chcą Ci pomóc

Unikaj wymyślania koła na nowo

Ktoś już pewnie rozwiązał ten problem. Najpiewniej wielokrotnie. Znajdź najlepszy i ściągnij.

Unikaj wymyślania koła na nowo

Github to skarbiec

Automatyzuj sobie pracę

  • Pisz skrypty
  • Twórz testy

Pisz skrypty

$ docker compose --file ./docker/docker-compose.yml down && \
	 docker compose --file ./docker/docker-compose.yml up

$ cat ~/.bashrc
#!/bin/bash
alias compose="docker compose --file ./docker/docker-compose.yml"
alias compose_rebuild="compose down && compose up"

$ compose up
$ compose_rebuild
					

Twórz testy

def fizzbuzz(n: int) -> str:
	answer = ""
	if x % 3 == 0:
		answer += "fizz"
	if x % 5 == 0:
		answer += "buzz"
	if answer == "":
		answer = str(n)
	return answer


import pytest

@pytest.mark.parametrize("input", [3, 6, 9, 12])
def test_fizz(input):
	assert fizzbuzz(input) == "fizz"

@pytest.mark.parametrize("input", [5, 10, 20])
def test_buzz(input):
	assert fizzbuzz(input) == "buzz"

@pytest.mark.parametrize("input", [15, 30])
def test_fizzbuzz(input):
	assert fizzbuzz(input) == "fizzbuzz"

@pytest.mark.parametrize("input", [1, 2, 4])
def test_number(input):
	assert fizzbuzz(input) == str(input)
					

Nie utrudniaj sobie pracy

Miej na uwadze złożoność kognitywną

    Jak prosto zrozumieć to co napisałeś?

Pisz prosty kod

  • Trzymaj się lewej strony ekranu
  • Pisz jednowątkowo
  • Używaj oczywistych nazw
  • Planuj zawczasu
  • Twórz dużo małych plików
  • Scrolluj tylko w dół
  • Miej na uwadze swoją drużynę

Zbyt duzo rozgałęzień

while(theWorldTurns) {
	if(isMorning || day != "Monday" && !sesja) {
	  try {
			if (env.debugMode()) {
		  	System.out.println("Hello, world!");
			}
	  }
	  catch (BadDay e) {
			System.out.println("Yikes!");
	  }
	}
}
						  

Zbyt duzo rozgałęzień

const log_debug = (data) => {
	if (env.debugMode()) {
		System.out.println(data);
	}
}

const morning_routine = () => {
	try {
		log_debug("Hello, world!");
	} catch (BadDay e) {
		System.out.println("Yikes!");
	}
}

const isGoodMorning = () => {
	return isMorning || day != "Monday" && !sesja;
}

while(theWorldTurns) {
	if(!isGoodMorning()) {
		continue;
	}

	morning_routine();
	[...]
}
						  

Dziwne operacje

float Q_rsqrt(float y){
	long i;
	float x2, y;
	const float threehalfs = 1.5F;

	x2 = number * 0.5F;
	y  = number;
	i  = * ( long * ) &y;  // evil floating point bit level hacking
	i  = 0x5f3759df - ( i >> 1 );  	// what the fuck?
	y  = * ( float * ) &i;
	y  = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
	// 2nd iteration, this can be removed
	//	y  = y * ( threehalfs - ( x2 * y * y ) );
	return y;
}
						  

Dziwne operacje

float inverse_sqrt(float number){
	return 1.0/sqrt(number);
}
						  

Lepiej żeby kod był wolny, ale zrozumiały

Godziny czasu deva są ważniejsze niż sekundy użytkownika.

Unikaj antywzorców

Podchodź do kodu krytycznie

Cargo cult programming

Pisz raz, wołaj potem

Copypasting nakłada pracy na więcej sposobów niż się wydaje

Spaghetti zostaw na obiad

Rozszerzaj, nie wydłużaj

Scyzoryk trzymaj z dala od komputera

Jedna funkcja robi jedną rzecz, jedna klasa reprezentuje jeden typ obiektu.

Jesteś programistą, nie czarodziejem

Magiczne liczby to pomioty szatana
#include 
#include 

struct sensor{
GPIO_TypeDef sensorPort;
uint16_t sensorPin;
uint16_t sensorValue;
} sensor;

bool check_sensor(struct sensor* arr[]){
	for(int i=0;i++;i<5){
	if(arr[i]->sensorValue>50){
		return true;
	}
	else{
		return false;
	}
	}

}
					
#include 
#include 

struct sensor{
GPIO_TypeDef sensorPort;
uint16_t sensorPin;
uint16_t sensorValue;
} sensor;

bool check_sensor(struct sensor* arr[]){
	for(int i=0;i++;i<5){
	if(arr[i]->sensorValue>50){
		return true;
	}
	else{
		return false;
	}
	}

}
					

Pogłębiaj swoją wiedzę

Zrozum swój system

W jaki sposób działa Twój język?

Sprawdź teorię

Pokrótce o wzorcach projektowych
Game Programming Patterns Source Making

Matmy nie unikniesz

Programowanie to wprowadzanie algorytmów Wikipedia

Pytania?


podstawy-kodu.koszela.me
kornel@koszela.me