Ładowanie plików - wszystko na raz czy lepiej osobno?

0

Cześć!
Mam do napisania dość dużą aplikację i zaczęła zastanawiać mnie jedna rzecz. Mianowicie ładowanie plików. Jakie według was jest lepsze wyjście:

  1. Ładowanie wszystkiego od razu
  2. Ładowanie tylko core i użycie autoloadu
  3. Jeśli autoload to czy ma skanować wszystkie podfoldery
  4. czy lepiej generować (automatycznie) plik (ini lub cokolwiek szybszego) w którym będzie nazwa klasy i ścieżka do niej
  5. Wrzucić wszystko do pamięci aby tam cały czas było (od razu mówię że nie wiem jak, i nie wiem czy nie było by problemu przy używaniu self::)

Według mnie najlepsze będzie rozwiązanie 4 ponieważ w pamięci będzie tylko co jest potrzebne. A jakie jest wasze zdanie?

2

Użyć frameworka? Np: Symfony 2/3 http://symfony.com/

Sorry, ale jeśli zadajesz takie pytania, lepiej nie pisz dużej aplikacji bez większej wiedzy na temat programowania i PHP.
Chociaż pytanie brzmi czym jest duża aplikacja, ale to już inny temat. Użyj frameworka który ogarnie Ci wszystko a ty sam:

  1. Nauczysz się go
  2. Inny programista wchodząc do projektu będzie wiedział co i jak
  3. Jak niczego nie zepsujesz będzie działać dość wydajnie lub bardzo łatwo będzie można znaleźć punkty krytyczne (profilery itp)
1

Poniższe podejście opiera się wyłącznie na położeniu plików, nie używa się żadnych przestrzeni nazw.

 define('DOCROOT', realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR);

function autoload($class, $directory = 'classes')
{
    $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';

    if ($path = DOCROOT . $directory . DIRECTORY_SEPARATOR . $file)
    {
        require $path;
	return TRUE;
    }

    return FALSE;
}

spl_autoload_register('autoload');

$model   = new Model_User();
$view    = new View();

$controller = new Controller_User($model, $view);
echo $controller->action_show();

Opiera się również o następujące założenia:

1 Przy założeniu że jest projekt w katalogu o jakiejś tam nazwie testmvc, ten właśnie index.php będzie w tym katalogu, natomiast wszystkie klasy będą w podkatalogu classes który to jest z małych liter
2. Wszystkie klasy w tym podkatalogu classes mogą być w podkatalogach, natomiast przy tym podejściu rozróżniane są duże i małe litery w nazwach plików klas i podkatalogów, więc trzeba się pilnować
3. Klasy kontrolerów muszą się znajdować w katalogu classes/Controller, modele w katalogu classes/Model, zaś wszystkie helpery np. DB.php, View.php które to mają klasy o nazwach DB, View muszą być w katalogu classes

Czyli zasada jest taka:

Klasa o nazwie Controller_User musi być w pliku classes/Controller/User.php
Klasa o nazwie Model_User w położeniu** classes/Model/User.php**
Klasa View w położeniu classes/View.php

Czyli widać jak na dłoni, że nazwy klas mają w sobie nazwy katalogów, w których się znajdują a ostatnia część nazwy to nazwa plików w których jest ich kod i tutaj jako separator nazw klas jest znak podkreślenia, katalogi Controller oraz Model i odpowiednio pliki User.php i User.php zaczynają się z dużych liter to i w nazwach klas ma też tak być. Na bazie nazwy klasy szukane jest położenie pliku php, znaki podkreślenia są zamieniane na ukośnik, co też jest w tej funkcji autoload.

To jest jedno z możliwych podejść, niektóre framreworki właśnie na takim podejściu się opierają, tzn. nie używa się przestrzeni nazw jak w Symfony czy Laravelu ale to już inna sprawa. Czy to jest bonusem czy też nie to już nie mnie to oceniać.

2

Powinieneś użyć composera i w nim skonfigurować autoloading:

https://getcomposer.org/doc/01-basic-usage.md#autoloading

Dwie pieczenie na jednym ogniu zarządzanie zależnościami w projekcie i wydajne ładowanie klas.

0

Tak jak napisał @gaUa69, lepiej użyć composera, bo jest to pewien standard. Takie Zendowe ładowanie jak pokazał @drorat1, mimo że prawidłowe, jest troche upierdliwe, szczególnie jak chcesz sie odwołać do jakiegoś const'a i masz nazwe klasy na 10 km.

0

@drorat1: Według mnie takie rozwiązanie jest średnie. W moim wypadku nazwa pliku nie mieściła by się na monitorze :D
@gaUa69: W sumie racja. Nawet nie pomyślałem aby użyć composera. To mi w sumie załatwi wszystko problemy. Muszę tylko zagłębić się w źródła composera bo nie ukrywam że ładowanie wszystkich plików będzie bardzo bez sensu (wiele bibliotek, do nich providery, a do nich dodatkowe klasy które odpowiadają za np. konkretny silnik bazodanowy).

0

A po co chcesz się zakłębiać? Takie mikro-optymalizacje są bez sensu.

0

Wrzuciłem na Pastebin żeby nie zaśmiecać:

https://4programmers.net/Pastebin/6445
https://4programmers.net/Pastebin/6446
https://4programmers.net/Pastebin/6447

Dotyczy tego co jest w vendor/composer w jednym z projektów, akurat L4.2

Tragedia.

Co do tego co przedstawiłem.

  • żadnego dump autoload po dodaniu, modyfikacji czy usuwaniu plików, od razu wszystko działa (pomijam cache-owanie tych ścieżek plików)
  • żadnego wpisywania potrzebnych przestrzeni nazw na początku pliku php przed kodem klasy
  • można łatwo też obsłużyć Cascading Filesystem
  • mam nadzieję że łatwe do zrozumienia co się w tym kodzie dzieje

Ale fakt, klasy mogą się np. nazywać:

Repository_ORM_User_Bookeeping_Account
Repository_ORM_User_Bookeeping_Transaction

i trochę lipa.

0

Przy małej skali projektu są bez sensu, ale przy dużej już nie są. ponieważ jeśli wszystko dzięki temu miałoby działać 1/50 sekundy szybciej realnie zrobi się różnica sekundy na request. A to już jest sporo.

0
NickOver napisał(a):

Przy małej skali projektu są bez sensu, ale przy dużej już nie są. ponieważ jeśli wszystko dzięki temu miałoby działać 1/50 sekundy szybciej realnie zrobi się różnica sekundy na request. A to już jest sporo.

Miałem styczność z wielkimi projektami, nie spotkałem się żeby ktoś optymalizował ładowanie klas. Do optymalizacji masz to:

https://getcomposer.org/doc/articles/autoloader-optimization.md

Do tego PHP ma coś takiego jak opcache:

http://php.net/manual/en/intro.opcache.php

Nie testowałem tego ale na logike zalezności tez cachuje i trzyma w pamieci. Tak więc nie bawiłbym się w nic więcej :P

0

@gaUa69: Nie chodzi o optymalizowanie ładowania klas (chociaż jest to jedna z najwolniejszych operacji bo czyta z dysku) a o optymalizacje np. zapytań do bazy danych. O opcache muszę poczytać, może się sprawdzi.

0

Wcześniej nic nie wspominałeś o bazie danych. Według mnie optymalizacja bazy danych nie ma już nic wspólnego z samym PHP (no chyba, że używasz ORMa, to wtedy przestań go używać ;) ). Jeżeli zapytania działają za wolno to ustaw poprawne indexy, sprawdź schemat bazy, jeśli nadal jest za wolno pomyśl nad denormalizacją, jeśli nadal jest wolno to możesz wrzucić jakiś in memory cache typu mecached lub redis itp itd.

0

@gaUa69: Chyba znów się nie zrozumieliśmy. Chodziło mi o sytuację w której:
Mam DatabaseProvider'a który to odpowiada za operacje na bazie dla np. jakiejś biblioteki. Teraz na serwerze może być np. postgres albo mysql. Niby język sql ten sam, ale oby dwie bazy mają inne dialekty, inne typy danych. Dzięki czemu nie muszę pisać 10 providerów gdzie 90% kodu będzie kopią poprzedniego tylko nazwijmy to "sterowniki" dla konkretnej bazy.
Może najlepszym przykładem będzie zliczenie ilości rekordów:
MySQL dobrze radzi sobie z:

SELECT COUNT(*) FROM database;

Natomiast w postgreSQL count działa wolno, i lepiej zrobić:

 SELECT id FROM database;

i po stronie aplikacji zliczyć wyniki.

0

Trochę nie rozumiem Twoich problemów, coś chyba za bardzo komplikujesz. Na bank będziesz używał jednego silnika bazy danych i pewnie nigdy go nie zmienisz :). Najlepiej to użyj gotowej abstrakcji bazy danych np: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/, a jeżeli nie chcesz to możesz poczytać np o wzorcu adapter i jak za jego pomocą zrobić prostą abstrakcje ;)

Na szybko i nie działające rozwiązanie ale idee powinieneś załapać (bazowałem na twoich potrzebach ;)):

interface DbAdapter
{
    public function count();

    public function fetchAll();

    public function getConnection();
}

abstract class SQLAdapter implements DbAdapter
{
    public function count()
    {
        return $this->getConnection()->query("SELECT COUNT(*) FROM table_name");
    }

    public function fetchAll()
    {
        return $this->getConnection()->query("SELECT * FROM table_name");
    }

    abstract public function getConnection();
}

class MySQLAdapter extends SQLAdapter
{
    private $connection;

    public function __construct()
    {
        $this->connection = new \PDO('mysql');
    }

    public function getConnection()
    {
        return $this->connection;
    }
}

class PostgresAdapter extends SQLAdapter
{
    private $connection;

    public function __construct()
    {
        $this->connection = new \PDO('postgres');
    }

    public function count()
    {
        return $this->connection->query("SELECT id FROM table_name");
    }

    public function getConnection()
    {
        return $this->connection;
    }
}

class Database implements DbAdapter
{
    private $db;

    public function __construct(DbAdapter $db)
    {
        $this->db = $db;
    }

    public function count()
    {
       return $this->db->count();
    }

    public function fetchAll()
    {
        return $this->db->fetchAll();
    }

    public function getConnection()
    {
        return $this->db->getConnection();
    }
}
0

Do testów będę zmieniać. I nie mam wpływu na to co ma klient. Nie traktuj mnie jak idiotę, który nie zna praktycznie podstaw każdego języka obiektowego. Mam nadzieję że to co napisałeś wyżej to tylko bardzo duży przykład i nie wpadłeś na pomysł abym wszystko pakował do jednego pliku? W ogóle wytłumacz mi sens tej dyskusji. Pytam co wybrać. A Ty usilnie próbujesz mi wmówić że:
-optymalizacje ładowania plików są bez sensu
-optymalizacje kwerend do bazy danych są bez sensu

0

Optymalizacje ładowania plików jest bez sensu.

Nie chodzi o optymalizowanie ładowania klas (chociaż jest to jedna z najwolniejszych operacji bo czyta z dysku) a o optymalizacje np. zapytań do bazy danych.

Co ma jedno do drugiego? Zakładasz temat o ładowaniu klas, a nagle dochodzimy do optymalizacji zapytań.

@gaUa69 Nie mozesz hardkodować w adapterze zapytań. Adaptery zajmują się czymś takim jak auto increment vs sequence.

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