Migracja struktury bazy danych oraz rekorów

0

Witam,

Chcę napisać w jednym ze starszych projektów DB migracje. Głównie chodzi mi o testy jednostkowe oraz generalnie jak dodam nowa kolumne czy tabele. Znacie cos sprawdzonego?

1

chcesz testować to czy migracja przeszła?
Dobrym toolem to migracji jest doctrine migrations albo phinx.

0

Chce miec migracje dwa dwoch powodow.

  1. Do pisania testow jednostkowych na modele. Czyli klasy, ktora maja zapytania SQL.
  2. Do migracji danych oraz struktury na serwer produkcyjny oraz testowy.
1

jeśli chesz testować jednostkowo modele, to obawiam się, że próbujesz zrobić coś brzydkiego. Takie moje przeczucie :)
Jeśli masz jakąś logikę w modelach - to wynieś ją z nich tak, abyś mógł logikę biznesową przetestować bez użycia jakiejkowiek bazy danych. Wtedy same zapytanie do bazy danych zrobią się prostsze. Poczytaj proszę o czymś takim jak https://www.codeguru.com/csharp/csharp/cs_misc/designtechniques/understanding-onion-architecture.html

Może na początku wydać Ci się to jako overkill, ale z czasem się spłaci :)

0

@no_solution_found Masz może jakiś gotowy przykład onion architecture? Chyba kiedyć coś takiego pisałem już. Było kilka króków w architekturze. Coś jak MVC, ale miał dodatkowe kroki i troche inaczej się nazywało zbiory klas tj repositories, models, entities, interfaces, services. Ale dokladnie tego nie pamietam. I fakt byl taki, ze bylo w ciul interfejsów. I tych kroków bybło masakrycznie duzo. Odwołanie klasy do klasy. Taki łańcówch. Niby spoko w testowaniu i łatwy w podmienianiów modelów. Ale kroków bardzo dużo. Szybko rośnie kod, obientość bardzo puchnie. I powiem Wam, ze niestety ale projekt upadł po 6 miesiącach. Ale to nie oznacza, ze sama architektura jest zła.

0

@no_solution_found Co masz na mysli dokladnie jezeli chodzi o modele bazy danych? Taki proste zapytania w ogole nie testowac? Np tj SELECT * FROM users;? Dopiero klasy wyzej testowac z logika biznesowa? W sumie ja jak kiedys pisalem testy jednostkowe do zapytan SQL to tylko takich, gdzie byly bardzo skomplikowane te zaputani, ze np obliczaly jakas sume czy cos, ale nigdy nie pisalem to zwyklych, prostych zapytan SQL. Tylko zauwazylem, ze u mnie team tesuje kazde, nawet najprostsze zapytanie to sam tez zaczalem pisac. Ale nie wiem czy to jest popawnie czy nie. W zasadzie wszystko powinno miec testy jednostkowe. A tak moge pominac blad np jak nie dodam nowej kolumny na produkcje etc.

1

To może na przykładzie. Trochę odchodzimy od tematu posta, ale co mi tam :)

(wszystko w pseudo php)

namespace model;

class OrderTable implements OrderTableInterface {
    private $db;
    function getOrderById($id) {
        return $this->db->getOne("order", $id);
    }
}

Tu mamy bezpośredni dostęp do bazy danych. Ten model powinien zostać tak prosty jak tylko możliwe. Praktycznie tylko zapytania do bazy danych (SELECT, UPDATE etc).

W klasie poniżej masz logikę Twojej aplikacji.

namespace shop;

class Order {
    private OrderTableInterface $orderTable;

    function cancel($id, $user) {
        $order = $this->orderTable->getOrderById($id);

        if (!$this->isAllowed($order, $user, 'cancel') {
                throw new UnathorizedException();
        }

        $order->setStatus("canceled");
        $this->orderTable-save($order);
    }
}

Oczywiście sytuacja jest bardzo uproszczona, bo powinieneś też może zwrócić produkty do koszyka, magazyn zaktualizować itp. Ale teraz możesz przetestować to tak iż po prostu wstrzykujesz zmockowany orderTable i testujesz logikę biznesową. Jeśli w Twoim teamie zależy na tym, by przetestować również zapytania. to robisz prościutkie testy (z już prawdziwą bazą danych), ale już tylko na te proste INSERT, UPDATE, SELECT.

Z punktu onion architecture, to mode.OrderTable to warstwa infrastruktury, natomiast shop.Order to już warstwa domenowa (biznesowa) i ideą jest taka, by wyraźnie oddzielać jedno od drugiego.

0

Ma to sense. Czyli nic innego tj Mapper, Model i Contruktor + View.

0

@no_solution_found: Wracajac do glownego pytania. Jezeli chodzi o aplikacje na ktorej teraz pracuje to jest to wlasnie Onion Architecture. Napisales cos wczesniej, ze jezeli zamierzam pisac testy dla klas bazy danych to nie bedzie mialo zbytnio sensu. Ale w sumie dlaczego? Czytalem, ze ludzie tez pisza testy jednostkowe na proste zapytania SQL. Nawet jak to jest SELECT username, password FROM users; to i tak dalej pisza testy. Nie wiem czy to jest dobre czy zle podejsci. Po prostu chce dowiedziec sie Twojej opini i opinii reszty programistow :)

0

To też zależy od intencji. Ja dzielę testy na dwie kategorie

  • testy szybkie bez zewnętrznych zależności, aby przetestować logikę biznesowa
  • testy akceptacyjne, które mogą się łączyć do niektórych zewnętrznych zasobów. Te najbardziej problematyczne i tak mockuję

Jak sam widzisz, testy zapytań bazy danych bywają... problematyczne. To jest dodatkowy koszt, który czasami nie warto ponosić. Dlatego trzymanie warstwy infrastrukturalnej jak najcieńszą się opłaca. Więc odpowiedź brzmi - to zależy :)

Co do narzędzi, to w PHP albo doctrine albo phinx. Z reszty nie korzystałem. To co ja bym zrobił, to tak zaprojektował te modele bazodanowe, aby było tam tylko zapytanie i zwrotka z wynikiem. Nic więcej. Żadnej transformacji danych tabeli na obiekty itp. Wtedy testujesz tylko to czy składnia zapytania jest poprawna no i czy tabela + schema się zgadza. Całą resztę, tj czy te dane mają sens to bym testował jednostkowo bez użycia bazy danych.

0

Ja wlasnie mam tak rozdzielona logike. Mam klasy z sama logika biznesowa oraz klasy/modele ktore lacza sie z DB. Wiekszosc pytan sa dosc proste i zwracaja tylko zapytanie. Klasy biznesowe zawsze pisze mocki, ale jak mam zmokowac model DB? Mam zmokowac to?

public method getComanyById() 
{
    $sql     = 'SELECT id FROM company;';
    $company =  $this->db->query($sql)

    return new Company($company);
}

W sumie to moje modele DB zwracaja tablice albo obiekt. W przykadku powyzej zworic obiekt.

0

phinx to jest jakis modul z cakePHP. Kurde, nie wiem, nie wiem. Zainstalowalem, napisalem kilka migration i seeding. Niby spoko, wszytko co chce jest. Nie wiem tylko jak ogarnac ten plik phinx.yml, bo nie chce trzymac username i password w repozytorium, ale tak jest w miare ok. Widze, ze phinx tworzy tabele dla migraje ktore zostaly juz utworzone, ale nie wiedze tabeli dla seeds :D

0

@no_solution_found: Zastanawialem sie jeszcze przez moment nad laravel artisant, ale wychodzi na to, ze chyba musialbym zainstalowac caly framework. NIby to tylko miejsce na dysku (/vendor) ale jakos cos mi nie pasuje w tym podejsciu. Eloquent mozna zainstalowac osobno, szkoda, ze migration & seeding tez nie da rady podkrasc z laravel.

0

Jedna rzecz ktorej nie przemyslalem to jak to wyglada przelaczeniem pomiedzy galeziami repoozytoriumi? Czy migracja zostanie usunieta ze starej galezi i dodana nowa z obecnej galezi.

0

Kolejna sprawa do przemyslenia to zero downtime migration. Musze sprawdzic czy phinx zaklada lock na tabele w czasie migracji.

0

to jest właśnie jeden z problemów dodawania jakiegokolwiek dodatkowego serwisu przy testach. Dlatego wolę ograniczać to do minimum.
Ja w takich sytuacjach to przeważnie (jeśli nie była to zmiana coś psująca) zostawiał jak jest i odtwarzał wszystko (np docker+docker-compose) w razie potrzeby.

0

Co jeszcze mnie zastanawia to caching zapytan SQL przy migracji ;-) To wszystko to wcale nie jest taki proste jak by sie nam wydawalo.

1 użytkowników online, w tym zalogowanych: 0, gości: 1