Jakiś czas temu tworzyłem anglojęzyczną prezentację o tytule "How to create a good enough website?". Rzecz jasna starałem się tam przedstawić przede wszystkim kwestie teoretyczne i przygotowawcze do kreowania stron internetowych, bo jakakolwiek próba praktycznego przedstawienia tak szerokiego zagadnienia w formie ustnej zakończyłaby się za pewnie wielogodzinną przemową bez konkretnych wniosków. Nie mniej jednak zmotywowało mnie to do napisania "kilku" słów szerszego poradnika na temat "jak zacząć i o czym należy pamiętać tworząc strony internetowe..." - w formie głównie teoretycznej z aspektami praktycznymi...
2. Czy na pewno tego chcesz?
Jest to chyba podstawowe pytanie które powinien zadać sobie każdy przyszły, bądź początkujący programista. "Czy naprawdę masz na tyle czasu i motywacji, aby utworzyć swój pierwszy serwis?". Pytanie jest o tyle ważne, że tworzenie jakichkolwiek mniej lub bardziej zawiłych, czy to programów, czy w naszym przypadku aplikacji internetowych jest procesem najczęściej skomplikowanym i długim. Przede wszystkim musisz myśleć abstrakcyjnie, co powoduje, że w wielu przypadkach niektóre aspekty codziennej logiki odchodzą w zapomnienie. Nie licz na to, że każdy z Twoich problemów rozwiążą inni. Z tym wiąże się fakt, że musisz posiadać choć małą nutkę umiejętności szukania i analizowania gotowych rozwiązań bądź porad. Jeśli spełniasz powyższe zasady, masz szansę że twoja zabawa z kodem nie zakończy się klęską.
3. Rozpocznij projektowanie tradycjonalnie...
No właśnie. Pomimo różnych zawiłości które już po części wymieniłem początek jakiejkolwiek większej pracy należy rozpoczynać tradycjonalnie, najlepiej podług uogólnionych zasad. Musisz wiedzieć, że:
- tradycjonalnie nie znaczy zawsze tak samo,
- pamiętaj, że rola projektanta wiążę się z rolą programisty z podstawowych powodów:
- kreowanie strony której nie da się zaimplementować lub implementacja nie będzie działać poprawnie jest co najmniej niemądre,
- w drugą stronę - zmieniane struktury projektu za każdym razem kiedy chcemy zmienić sposób działania strony będzie na pewno czasochłonne, a niekiedy nawet kosztowne.
- jeśli stronę miałoby tworzyć kilka osób należy zabrać pod uwagę przy projektowaniu możliwości każdego z programistów w celu jak najoptymalniejszej implementacji przyszłego kodu.
[/list]4. Co z tym projektowaniem samym w sobie?
I doszliśmy do pierwszego punktu nie stricte teoretycznego. Przed praktycznym pisaniem musisz wiedzieć czego chcesz i czego oczekujesz po swojej stronie. Można to nazwać "architekturą informacji" twojej strony. Po fazie informacyjnej przedstawionej wyżej musisz stworzyć, przetestować i zweryfikować strukturę i możliwości swojej przyszłej strony. Mówiąc dokładniej, czy to na kartce, czy we własnej głowie przeanalizuj:
- jaki serwis chcesz tworzyć?
- jaki ma być cel tego serwisu?
- co chcesz wykorzystać przy jego tworzeniu i w jaki sposób chcesz to zaimplementować?
- i co najważniejsze - do jakiej grupy osób ma być on kierowany i czy chcesz rozwijać jego możliwości poprzez np. wielojęzykowość?
Jest to o tyle ważny punkt całego kreowania, że wybór którego dokonasz przy planowaniu będzie obowiązywał twoją stronę praktycznie do końca jej istnienia. Pamiętaj także, aby dokładnie testować wszystkie możliwe skutki swoich ewentualnych wyborów. W wypadku większych projektów pomocne będą tu znane od wielu lat... kartka i długopis :]
Kiedy już dojdziesz dokładnie do tego czego oczekujesz po swoim przyszłym tworze pora poznać kilka informacji o projektowaniu samym w sobie. Wiele osób nie mających zbytnio nic wspólnego z technologiami internetowymi może uważać, że tworzenie rozwiązań tego typu to rodzaj tajemniczej sztuki. Nic mylnego moim zdaniem. To po prostu pewne predyspozycje do bycia kreatywnym. Dokładniej zbiór umownych reguł do rozwiązywania problemów w celu zrozumienia zapotrzebowań użytkowników i tworzenia efektywnych rozwiązań internetowych. Oczywiście definicja ta ma tylko zobrazować pojęcie i naginanie jej wg. indywidualnych potrzeb jest jak najbardziej zrozumiałe. Niekiedy z angielskiego "design" jest mylnie kojarzony tylko i wyłącznie z tworzeniem wizualnej części stron, a związane jest to z dominacją grafików internetowych (z angielskiego "graphic designers").
Reasumując paragraf:
- nie należy zapominać o kooperacji z użytkownikami, którzy często są bardzo ważnym źródłem informacji i zapotrzebowań wśród ludzi,
- należy zapoznać się z podstawowymi zasadami użyteczności stron i projektowania stron internetowych - wymienionych po części powyżej,
- należy projektować jak już zostało wyżej podane abstrakcyjnie, ale nie "na ślepo", w jednym kierunku. Tłumacząc bardziej: kreuj swój serwis tak, jak sam chciałbyś go widzieć będąc swoim własnym klientem.
5. Mam ułożony w głowie dokładny plan, ale za co mam się "chwycić" żeby go zaimplementować?
Po pierwsze języki programowania, bądź związane z nimi technologię. Bez tego - to lepiej odpalić nowe CoD i czekać, aż osoby które się znają na tego typu sprawach zrobią coś za nas i dla nas. Prawda jest taka, że informatyka nie jest łatwą dziedziną, bo pomimo, że jest młoda daje ogromne pole do popisu i manewru, a to za sprawą ogromu na jaki się rozwinęła. I tak jest i przy tworzeniu aplikacji internetowych. HTML lub bardziej rygorystyczny xHTML i do tego CSS (Kaskadowe arkusze stylów) w celu implementacji strony wizualnej i jej modyfikacji, a także PHP i najbardziej znany tego typu system MySQL w celu utworzenia zdatnych do działania algorytmów, rozwiązań i przechowania danych to niestety w dzisiejszych czasach niezbędne minimum.
Nie będę omawiał tu każdego z tych języków. Bo w zasobach internetu można znaleźć wiele dobrych kursów, opracowań i przykładów. Wystarczy spojrzeć tutaj. Dodam tylko, że postaram się zawrzeć kilka informacji o pewnych aspektach tych języków. Jeśli ktoś już na początku chce mieć swobodną możliwość wyboru to przedstawiam poniżej kilka języków wraz z ich alternatywami (oczywiście są to tylko przykłady, względem własnych potrzeb można konfiguracje ułożyć inaczej):
Osobiście będę starał się opierać na podanej wyżej konfiguracji podstawowej.
Do programowania w czymkolwiek przydałby się też jakiś edytor/program przeznaczony do tego typu zadań. A mianowicie:
- PHP, HTML, xHTML, MySQL w Notepad++, ZendStudio (dla bardziej zaawansowanych - posiada kolorowanie składni, podpowiedzi, klienta ftp, cvs, debuger kodu, zarządzanie projektami, przeglądanie funkcji, klas, metod i wiele innych). Dodam tylko, że nie polecam np. Notatnika z racji dla przykładu problemów z kodowaniem, o czym później,
- CSS w Top Style Pro, Visual Studio .NET, itp.,
- JS/AJAX w ZendStudio, Visual Studio .NET.
Oczywiście to nieliczne przykłady, najlepiej zacząć od testowania ich, albo ewentualnie innych tego typu programów w celu odnalezienia najbardziej przyjaznego samemu sobie.
6. Czym jest te wspomniane kodowanie?
Nieszczęsna rzecz. I w gotowych serwisach i w czasie pisania swoich skryptów. Sprawa jest jasna - najlepiej jeśli kodowanie plików, charset dokumentu i kodowanie wraz z porównywanie znaków bazy danych są tego samego typu. Dzięki temu powinniście uniknąć problemów z "krzakami" przy imporcie starej bazy, czy pisania dodatkowego kodu odpowiadającego za dynamiczne zmiany kodowania.
Jako polscy użytkownicy dla których domyślnie grupami odbiorców są właśnie także Polacy macie do wyboru dwa kodowania:
Jest jeszcze trzecie - Microsoftowskie windows-1250, ale stanowczo odradzam używanie go. Do podanych powyżej pierwsze odnosić się będzie stricte tylko do polskich użytkowników. Drugie jest uniwersalne i doradzam używanie go, jeśli masz świadomość, że w pewnym momencie będą twoją stronę przeglądać użytkownicy z zagranicy. W nawiasie podałem odpowiedni w MySQL-u.
Teraz ciut praktyki. Czyli jak to wygląda kolejno w xHTML-u / HTML-u, kodowaniu plików (na podstawie ZendStudio) i MySQL-u (via phpMyAdmin).
W pierwszym i drugim języku każda strona i podstrona musi posiadać nadany odpowiedni charset. My będziemy chcieli uzyskać dla przykładu utf-8. xHTML:
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
A także w postaci deklaracji języka dokumentu, dla przykładu w tagu html:
<html lang="pl" xml:lang="pl" xmlns="http://www.w3.org/1999/xhtml"> // xhtml 1.0
<html xml:lang="pl" xmlns="http://www.w3.org/1999/xhtml"> // xhtml 1.1
Jeśli wewnątrz strony zmienia się język to w tagu nadrzędnym regionu ze zmienionym językiem możemy zadeklarować inny język:
Witaj użytkowniku!
<div lang="en" xml:lang="en">Welcome user!</div>
// xhtml 1.0
Witaj użytkowniku!
<div xml:lang="en">Welcome user!</div>
// xhtml 1.1
Dla czystego HTML-a powyższe elementy będą wyglądać następująco:
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<html lang="pl">
Witaj użytkowniku!
<div lang="en">Welcome user!</div>
To nie wszystko. Taki plik należy odpowiednio otwierać i odpowiednio zapisywać. Rzecz jasna piszę tu o kodowaniu. Dla przykładu - zapis w ZendStudio w kodowaniu proporcjonalnym do charset-u powinien wyglądać tak:
No i ostatnia sprawa. Aspekt bazy danych. Jeśli już z niej korzystasz w celu składowania danych należy ustawić porównywanie znaków i kodowanie pól w phpMyAdmin na w naszym przypadku utf8_unicode_ci.
7. Ponad zakresowy aspekt numer jeden: bezpieczeństwo!
Kolejny praktyczny aspekt, który za pewnie można znaleźć w sieci, ale czymże byłby ten tekst bez niego. Dla laików - kilka porad co może czychać na niezabezpieczony skrypt i jak można się przed tym uchronić.
Cross-Site scripting (XSS)
Opis: - sposób ataku możliwy do przeprowadzenia przy braku odpowiedniego filtrowania danych pozwalający na wstrzyknięcie niepowołanego kodu najczęściej w postaci JavaScript.
Przykład kodu niezabezpieczonego:
$nick = $_GET['nick']; print 'Zalogowany jako: ' . $nick;Przykład użycia luki:
http://serwer.pl/index.php?nick="><script>alert(document.cookie);</script>Sposób zabezpieczenia: należy przefiltrować dane poprzez funkcje htmlspecialchars(), strip_tags() lub/i htmlenties(), a także dodatkowo można via np. str_replace() usuwać ze zmiennych takie ciągi jak <script>.
$nick = strip_tags(htmlspecialchars($_GET['nick']));SQL Injection
Opis: - atak spowodowany nieodpowiednim typowaniem lub brakiem filtrowania pozwalający na modyfikację zapytania do SQL-a.
Przykład kodu niezabezpieczonego:
$nick = $_GET['nick']; mysql_query('SELECT id FROM users WHERE nick = ' . $nick);Przykład użycia luki:
http://serwer.pl/index.php?nick=-1%20union%20select%201,2,3,4,5,6,7/*Sposób zabezpieczenia: należy przefiltrować dane poprzez mysql_real_escape_string() wraz z sprawdzeniem, czy magic_quotes na serwerze jest włączony.
$nick = $_GET['nick']; if ( ini_get('magic_quotes_gpc') ) { $nick = stripslashes($nick); } $nick = mysql_real_escape_string($nick);Cross-site request forgery (XSRF)
Opis: - polega na wykorzystaniu uprawnień osoby administrującej w celu wykonania zadanego kodu.
Przykład użycia luki:
[url]http://serwer.pl/index.php?mode=delete&u=2[/url]Sposób zabezpieczenia: należy przede wszystkim dokładnie sprawdzać co się otwiera. Nie zawsze, czy to grafiki, czy to odnośniki są tym czym mogą się wydawać. Po za tym należy przesyłać ważne dane np. w PA poprzez $_POST, a nie $_GET. Można ograniczyć przesyłanie linków w BBCode związanych z najważniejszymi funkcjami danego serwisu. Ostatecznie można też uniemożliwić używanie BBCode w serwisie.
Session fixation
Opis: - polega na przejęciu konta użytkownika poprzez poznanie jego id sesji.
Przykład użycia luki: - najczęściej poprzez przekazywanie id sesji poprzez adres i nieodpowiednie sprawdzanie go w czasie ładowania strony.
http://www.mojadomena.pl/index.php?PHPSESSID=987654321Sposób zabezpieczenia: należy regenerować id sesji w taki sposób, aby użytkownik nie mógł nadać sobie samemu jej id. Dodatkowo powinno się sprawdzać nadane id sesji, wraz z danymi użytkownika z tymi które istnieją w bazie danych.
session_start(); if (!isset($_SESSION['nick'])) { session_destroy(); } session_regenerate_id(); $_SESSION['nick'] = true;Local File Include / Remote File Include
Opis: - pozwala na załączenie (via np. include, require, readfile, fopen) niepożądanego pliku na serwerze lub zdalnie z poza serwera skryptu.
Przykład niezabezpieczonego kodu:
require 'include/' . $_GET['id'];Przykład użycia luki: - %00 na końcu to tzw. atak z użyciem zerowego bajtu (Poison Null Byte) przez co po zaincludeowaniu ścieżki wszystko co po za zmienną zostanie usunięte (pozbywamy się np. rozszerzenia html z include wpisanego na stałe).
http://serwer.pl/index.php?id=./../../../../../../../../../etc/passwd%00Sposób zabezpieczenia: można filtrować dane podług danych znaków i te wejściowe, ale także niektóre z $_SERVER. Po za tym należy wyłączyć możliwość zdalnego odwoływania się do plików z poza serwera przez readfile, include czy fopen.
Pamiętaj także, że w każdym z wyżej wymienionych przypadków jeśli masz pewność, że przekazywane dane będą wartością np. całkowitą najlepiej jest wykonać rzutowanie lub przefiltrować odpowiednią funkcją je. Dla przykładu:
$id = intval($_GET['id']); // funkcja
$id = (int)$_GET['id']; // rzutowanie
8. Ponad zakresowy aspekt numer dwa: podstawy optymalizacji!
Punkt ten możesz brać z malutkim przymrużeniem oka Optymalizacja jest ważna, ale bardziej w formie zaprojektowania serwisu i bazy danych (szczególnie korelacji pół i tabel, a także optymalizacji zapytań) niż aspektów stricte semantycznych które podam. O to kilka testów wraz z wynikami w komentarzach (w postaci prędkości):
// długość zmiennej if ( strlen($try) < 5000000 ) { echo 0; } // kontra if ( !isset($try{5000000}) ) { echo 0; } // wynik: // 1: 0.000046 // 2: 0.000012 // powodem jest fakt, że isset() jest konstrukcją językową, a strlen() funkcją
// pre / post-inkrementacja for ( $i = 0; $i < 150000; ++$i ) { print null; } // kontra for ( $j = 0; $j < 150000; $j++ ) { print null; } // wynik: // 1: 0.0441 // 2: 0.0489 // wszędzie po za parametrami warunków należy używać pre-inkrementacji, gdyż nie jest wtedy tworzona dodatkowa przejściowa zmienna przez co czas użycia jest krótszy.
// przeliczanie funkcji w pętlach for ( $i = 0; $i < sizeof($tablica); ++$i ) { print null; } // kontra $size = sizeof($tablica); for ( $j = 0; $j < $size; ++$j ) { print null; } // wynik: // 1: 0.00066 // 2: 0.00031 // w pierwszym przypadku przy każdej iteracji pętli zostaje obliczany wynik funkcji sizeof co wydłuża działanie skryptu
// wyrażenia regularne i funkcje wbudowane if (preg_match("!^foo_!i", "FoO_")) { } // kontra if (!strncasecmp("foo_", "FoO_", 4)) { } // wynik: // 1: 0.0000791 // 2: 0.0000119 // wyrażenia regularne w wypadku prostych zastosowań są o wiele wolniejsze niż przeznaczone do tego funkcje wbudowaneTo tylko niektóre proste testy, ukazujące z pozoru nieznaczne, ale przy nagromadzeniu i większych projektach uciążliwe różnice w wydajności. Więcej informacji już niedługo będzie można uzyskać na moim blogu.
9. A może kilka słów jak projektować bazy?
Nie, nie uzyskasz krok po kroku porad jak utworzyć uniwersalną bazę. Nie ma chyba takich poradników. To zależy od tego czego potrzebujesz. Mogę jednak wypunktować główne założenia:
- jeśli masz zamiar wykonywać bardzo dużo operacji w jednoczesnym czasie to proponuje wybrać typ InnoDB. Jest on ciut wolniejszy, ale za to posiada takie dodatkowe aspekty jak transakcje co lepiej organizuje i zabezpiecza działanie na bazie (w przeciwieństwie do MyISAM),
- każda tabela powinna posiadać indeks, a w wypadku kiedy istnieje możliwość, że tabela rozrośnie się do dużych rozmiarów korzystaj z unikalnych indeksów na danych kolumnach co zwiększy wydajność przeszukiwania tabeli. Musisz pamiętać jednak, że przed umieszczeniem wpisu w tabeli musisz sprawdzić, czy nie istnieje już czasami wartość tego typu w kolumnie o nadanym unikalnym indeksie. W przeciwnym razie wystąpi błąd przy wykonaniu zapytania.
ALTER TABLE nazwa_tabeli ADD UNIQUE INDEX (nazwa_kolumny);
- spróbuj przewidywać długość typów pól. Jeśli zapisujesz w czystej postaci IP to nie twórz typu VARCHAR większego niż 15ście znaków. Jeśli zapisujesz zahashowane w md5 hasło to ustaw pole na 32 znaki. Nadmiary wielkości nie są potrzebne w bazie i odbijają się na wydajności.
- konstruuj tabelę tak, abyś mógł bez problemu przeszukiwać ją po ID. Kardynalnym błędem w zautomatyzowanych serwisach jest działanie np. na nickach użytkowników. Wyjątkiem są specyficzne serwisy, gdzie jedno pole danej tabeli nie oddziałuje na drugie. W przeciwnym wypadku działanie na ID jest bardzo dobrą metodą na łączenie danych z kilku tabel.
SELECT u.username, g.groups FROM groups g LEFT JOIN users u ON g.user_id = u.user_id WHERE g.group_id = 1;
- jeśli masz możliwość używaj modułu mysqli - jest wydajniejszy już z samej konstrukcji.
10. Co, gdy mój serwis już stoi?
Teraz możesz się przygotować na kilka tygodni, miesięcy bardziej równomiernej pracy nad promocją serwisu. O ile naprawdę chcesz go promować. Twój kod za pewnie standardowo nie jest przystosowany dla wyszukiwarek. Więc pierwsze co możesz zrobić to pomajsterkować z mod_rewrite i przepisywaniem linków na bardziej przyjazne wyszukiwarką.
RewriteEngine on RewriteRule ^([a-z0-9]+)$ /index.php?action=$1 [L,QSA,NE,NC]Po za tym zainteresuj się systemami linkującymi i pozycyjnymi - szczególnie tymi o wysokim PageRank-u. Po jakimś czasie pomoże się wybić to twojej stronie na wyższe pozycje pod danymi frazami. Możesz wspomóc się automatycznymi skryptami do dodawania, ale one najczęściej dodają przede wszystkim do stron o niskim pożytku dla nas samych.
Ważnym i przyciągającym najwięcej klientów, czy użytkowników (a co zarazem idzie rozwijającym serwis i zwiększającym PR) są systemy typu AdWords. Płatnie wyświetlają one reklamy w google po wpisaniu zadanych fraz przez użytkownika w wyszukiwarce. Przewidywalnie za około 100 złotych może twoją stronę odwiedzić kilkadziesiąt tysięcy użytkowników (praktycznie jest to tyle kliknięć).
No i ostatecznie najważniejszym aspektem jest twoja opieka nad stroną. Jej rozwój, zmiana treści, zachowanie poprawności (sprawdzanej np. tutaj), udoskonalanie pod oczekiwania użytkowników czemu pomóc może np. system analityczny Google Analytics - to wszystko pozwoli Ci maksymalnie rozwinąć twój serwis internetowy.
© m1chu aka Kai, 2008