Stateless klasa i array

Opet ja. Ne mogu nać nigdje na netu objašnjenje, pa da pokušam ovdje. Problem je sljedeći:

  1. Trebam poredati array i spremiti u drugi array (dakle, array2 = array1)
  2. Rješenje mora koristiti stateless design pattern
    Kad bih (pošteno) shvatio razliku između stateless i statefull, ne bih postao ovo.

Dakle imamo array1 = (100,40,66,2) kojeg je potrebno sortirati (većeg prema manjem ili obratno, nema veze) i array1 je ujedno i input.
Output je array2 (dakle drugi array, kopija array1)

Klasa mora koristiti stateless pattern, mora biti extendable, mora zadovoljavati SOLID.

Stateless, ne smije biti singleton, ne smije biti static?!!! :face_with_symbols_over_mouth:
Ideja?

Stateless znaci da classa nema svoje varijable tj. state. Zato se takve klase najcesce pisu sa static funkcijama, kao kolekcija funkcija.
Ukoliko po zadatku to bas mora biti klasa a ne funckija, koja ce vratiti sortirani array na poziv, onda je nemoguce to rjesiti kao stateless klasa ( mora negdje spremiti array -> imat ce state).
Jedino sto vidim kao rjesenje je pisanje obicne klase, bez state-a, samo funkcije koje koje se pozivaju iz klase…

Ali volio bih vidjeti originalni zadatak, cisto da vidim da se nesto nije izgubilo u prijevodu ili objasnjenu.

Eto. Upravo to sam i sam zaključio:

Pa rekoh da ne tumačim nešto pogrešno oko stateless/statefull. Ako prije nego koristim array, spremim array u file, pa onda tom fileu pristupim iz klase, te unutar iste klase rezultat stavim u drugi file, da li je tada ispunjen stateless uvjet?
Ali opet, i tada bih morao koristito array jer bih iz filea povukao podatke u array i taj array koristio za sortiranje podataka, pa onda taj array zapisao u file… Ne znam bi li takvo rješenje zadovoljilo stateless pattern?

To nema nikakvog smisla, to nije pattern, to je antipattern. Mozes i globalnu varijablu koristit onda da si skratis muke, ali onda krsis gro pravila bilo kojeg best practica…

Kladim se da ima neki dio koji si previdio ili krivo skuzio.

“Your application is a stateless software
that will get the content on a txt file and will output another txt file”

Slobodno mi reci ako misliš da je drugačije nego sam protumačio… Možda sam pogrešno protumačio.

A onda da, al onda cemu klasa i zasto nesmije bit static?

Nije da ne smije, može, ali ja bih izbjegavao ako je moguće (a čini mi se da nije).

A ako ne bi išlo objektno, kako onda? Samo funkcijama?

Zapravo, najviše me muči taj stateless dio…
Ne shvaćam taj stateless dio u ovom slučaju sa uzimanjem podataka, sortiranjem i spremanjem.

Kako može biti stateless kada ovisi jedno o drugome i stanju u kojem se nalaze podaci u koraku prije (nema sorta bez da su podaci u memoriji, nema spremanja ako podaci nisu sortirani)?

Totalno sam zbunjen. Gledao primjere, nigdje ne mogu nać stateless primjer sa sortiranjem arraya pa da mi bude jasno. Koncept (pattern) mi je generalno jasan, ali u ovom slučaju - ni najmanje.
Ikakva ideja? Pojašnjenje kao 6-godišnjaku? :slight_smile:

Mislim da se misli da se array ne zadrzava u memoriji aplikacije.
Nemozes bas skroz stateless funkciju napravit. Dok radis sort morat ces imati pomocni array. Ono sto je bitno je da ne mjenjas originalni array vec samo vratis novi.
Sto se tice klasa i ostalog. Ovako nesto nema smisla da bude u klasi i da ne bude static. Ako je vec PHP u pitanju, mozes koristit i samo funkciju ( za razliku od JAVE imas tu mogucnost). Ako bas hoces sve drzat u klasi, a neces imati state u klasi, mozes koristit klasu sa statickim funkcijama, pa ce to biti kao nekakav interface. Ali nema puno smisla da radis klasu sa normalnim funkcijama. Onda ces morati svaki put kad zelis pozvati tu metodu ( koja realno nema veze s klasom) morat stvarati novi objekt iz te klase. To ce ti nepotrebno punit memoriju objektima koje se koriste samo za pozivanje metode.

1 Like

To ću sad morat prožvakat.
Napravit ću jednostavno rješenje, stavit ga ovdje pa da mi onda objasniš (ili netko tko se priključi) jel ok ili nije (u smislu statelessa).
Hvala ti svakako!

Pošto se puno priča o array-u, ti koristiš input i output u obliku txt fajla. Gdje se tu uklapa array koji je svojstven php fajlovima?
Ali neka je to i neki plain text 5,1,6,2,4 i output treba da bude 6,5,4,2,1 to je neka fizika koju treba uraditi unutar jednog metoda.
Stateless bi bilo da je klasa nezavisan dio koda same aplikacije. Takoreći servis koji aplikacija koristi.
Obilježja tog servisa su da:

  1. prima string file path za input
  2. vrši neku akciju nad sadržajem
  3. pravi novi fajl u izlazu koristeći novodobijene podatke

Može to sve u jednu funkciju da se natrpa ali što bi?
Meni je to ovako nekako:

<?php

namespace App\Service;

class StoreInput
{
    /**
     * Directory path for output files
     */
    const OUTPUT_PATH_DIR = '/var/www/html/';

    /**
     * @var string|null $inputData
     */
    private $inputData = null;

    /**
     * @var string|null $outputData
     */
    private $outputData = null;

    public function __construct(string $inputPath = null)
    {
        if (null === $inputPath) {
            $classname = get_class($this);
            if ($pos = strrpos($classname, '\\')) {
                $classname = substr($classname, $pos + 1);
            }
            $error = $classname . ' class requires file path on instantiation.';
            throw  new \Exception($error);
        }

        try {
            true === is_file($inputPath);
            $this->setInputData($inputPath);
            $this->setOutputData();
            $this->outputFile($this->outputData);
        } catch (\Exception $e) {
            throw $e;
        }
    }

    private function setInputData($path): void
    {
        $this->inputData = file_get_contents($path);
    }

    private function getInputData()
    {
        return $this->inputData;
    }

    /**
     * Set value for outputData
     *
     * @return void
     */
    private function setOutputData(): void
    {
        // what ever action you need to do on $this->inputData
        // and after that set $this->outputData value
        //
        // $this->outputData = value_we_have_got_one_line_above

        //i.e.
        $this->outputData = strrev($this->getInputData());
    }

    private function getOutputData()
    {
        return $this->outputData;
    }

    /**
     * Store file
     *
     * @param $outputData
     * @throws \Exception
     */
    private function outputFile($outputData = null)
    {
        if (null === $outputData) {
            $outputData = $this->getOutputData();
        }

        if (false === is_string($outputData)) {
            throw new \Exception('Wrong data format.');
        }

        $file = self::OUTPUT_PATH_DIR . 'output_' . time() . '.txt';

        if (false === file_put_contents($file, $outputData)) {
            throw new \Exception("Can't write to file.");
        }
    }

    public function __destruct()
    {
        $this->inputData = null;
        $this->outputData = null;
    }
}

I sada možeš da koristiš servis nezavisno otkud ti fajl dolazi.

try {
    (new \App\Service\StoreInput('/some/path.txt'));
    $outputMessage = "Output file set.";
} catch (\Exception $e) {
    $outputMessage = $e->getMessage();
}

Ako je to file upload, pri upload-u ćeš upotrijebiti ovo nad tmp fajlom.
Ako treba da obradiš neke fajlove u nekom dir-u opet možeš da ga iskoristiš.
Valjda je to stateless, gdje klasa ne gleda koji je izvor već samo očekuje neki fajl čija struktura setOutputData metoda mora da bude zadovoljena. S tim da sve treba u jednom ciklusu da se završi i pozove destruktor koji će da deinicijalizuje vrijednosti.
Možeš da imaš i neku parent klasu koja će da zove ovu klasu u svom metodu a kakvih će imati više:

public function concreteMethodOne(string $filePath): bool
{
    try {
        (new \App\Service\StoreInput($filePath));
        return true;
    } catch (\Exception $e) {
        log($e->getMessage());
        return false;
    }
}

I onda u paketu možeš imati parent klasu od koje svaki metod zove svoju klasu. Mislim, što da ne? :slight_smile:

Od kuda ti sve to čupaš, slobode ti?! :smiley:

Ne želim kompletan “problem” iznijet van jer bi se moglo desit da dobijem kompletno rješenje od vas, pa onda neću ništa naučit niti shvatit. Osobno moram doć do rješenja,samo mi je potrebna pomoć oko razumijevanja.

Ovo sa txt fileom, te zašto spominjem array…
U txt fileu su spremljeni podaci u formatu:
xxxx, 1111, zzzz, yyyyy
u nekoliko stotina redova.
Poredani su u txt-u po “zzzz”, moram ih sortirati po “1111” polju. Ne vidim drugo rješenje nego da txt “prebacim” u array, napravim sort i onda zapišem u novi txt (zato spominjem array).
I da bude stateless (goXno) ispoštovan.

Ono, objasni k’o malom djetetu je dvosmjerno.
Je l’ ovakva struktura fajla?

oooo, 7777, zzzz, ccccc
ssss, 2222, tttt, aaaaa
nnnn, 6666, pppp, mmmmm
jjjj, 3333, kkkk, lllll
gggg, 4444, ffff, ddddd

a ti bi da dobiješ ovo

oooo, 7777, zzzz, ccccc
nnnn, 6666, pppp, mmmmm
gggg, 4444, ffff, ddddd
jjjj, 3333, kkkk, lllll
ssss, 2222, tttt, aaaaa

Mislim, solidne si odgovore i dobio ako si na početku rek’o da imaš array. :smiley:
Ako sam u pravu za ovu gore strukturu i željeni rezultat, na kojem koraku je zapelo (ostavi zasad sateless priču)?

Od kuda čupa, e, :smile: tako razmišljaju programeri; 300 na sat. :fast_forward:
Još rješavamo jedan PHP problem Tpojka i ja na private. :+1: Big Tpojka. :blush: :o:

1 Like

Pa stateless sxranje je zapelo! :smiley:
Ovo gore što si napisao, to trebam i nije problem to dobit. Problem je to dobit poštujući stateless.
To me muči, ne sortiranje i spremanje, sve su to priče koje radim godinama, stateless me muči jer ga NE SHVAĆAM da ga jexes u ovom slučaju.

Sad nisam siguran da li je ovo gore dobro.
Stateless klasa bi trebalo da bude trigger-ovana spolja ali tako da taj spoljni faktor ne očekuje ništa zauzvrat.
Tj. dalja egzekucija koda u spoljnom faktoru ne zavisi od return-a “stateless” klase.
Radio sam nešto slično sa webhook rutom.
Pravio sam aplikaciju za Shopify i pri deinstalaciji Shopify će da pošalje signal tvom serveru na adresu koju si naveo ne očekujući ništa osim response koda 200.
Služi da tvoja aplikacija na serveru primi informaciju da je mušterija deinstalisala aplikaciju iz svog shop-a i da se na serveru upotpuni šta bi trebalo u odnosu na tu informaciju (tipa da promijeniš mu status, obrišeš iz baze ili bilo šta treće).
Dakle Shopify samo pošalje signal da se mušterija skinula sa aplikacije i ne zanima ga šta ćeš ti sa tim saznanjem - ne utiče na dalji rad ni Shopify kompanije ni mušterije nezadovoljne (?) tvojom aplikacijom. Ako mu (Shopify-ju) ne vratiš status 200 slaće opet nekad u toku dana ali to je to, mušterija nema više veze sa tvojom aplikacijom bez obzira dao ti do znanja da ti je jasno (status code 200) ili ne.
To bi bio stateless.
A sa druge strane ni ovaj kod gore ne zavisi od session-a ili čega drugog već samo očekuje fajl.

Ajmo ovako, obzirom na ovo što si napisao, i na osnovu mog razmišljanja kako to napraviti (opet govoreći o tom famoznom patternu čije ime neću više spominjati):

$t = new  SortirajFajl("in-file.txt", "out-file.txt")

Klasa SortirajFajl{
__construct ($inputfile, $outfile)
{
    $this->fileUArray();
    $this->sortirajArray();
    $this->spremiFile($outfile);
}
}

bi bilo neispravno?

Imaš syntax error :stuck_out_tongue: ali to je otprilike šta sam stavio gore osim naziva output fajla kojeg sam ostavio auto generatoru.
Mislim da je to to i samo proslijediš out file kome treba (u slučaju da nije trigerovan error/exception).

Syntax error… :smiley:
Pišem preko moba, ideju črčkam, ne kod.
Dakle, to bi zapravo bilo ispravno, bez obzira što se array sortira u “memoriji” unutar klase?
To je taj s. dio koji ne shvaćam. Dozvoljeno je vrtiti array unutar klase a da se poštuje? Stateless klasa zapravo ne smije “vraćati” nikakvo stanje objekta? Odnosno, ta klasa ne ni smjela imati svoje stanje, ali unutar sebe može baratati podacima kako želi, uključujući i čitanje datoteke, držanja arraya (koji ne smije biti dostupan van klase) i pisanje po disku? Jel to?

Pa ti definitivno moraš da trošiš neku memoriju unutra da čitaš sadržaj fajla.
Šta s’ se stis’o za memoriju? :joy:
I nemoj ostavljati u varijabli $t već samo izvrši egzekuciju.
I to u try catch bloku a u klasi idi sa throw new \Exception kad god ti nešto ne odgovara.
Ja sam tako nešto ostavio gore a ovaj dodatak sa davanjem imena output fajla je odličan.

Gdje god da pozivaš ovu funckcionalnost:

try {
    (new \namespace\to\SortirajFajl("string1", "string2"));
} catch (\Exception $e) {
    // not executed
}

Ma nije što sam škrt na memoriji, nego mi je taj shitless pattern misterija.
Jesam li dobro shvatio s pattern? (prethodni odgovor)?