Take what you can, spread more

Как НЕ се прави Save операция в уеб (#WordPress #fail)

Днес след доста време неактивност бях решил да публикувам нещо, като действията, които предприех ме принудиха да публикувам друго нещо. Правя го както с чисто хейтърска цел, така и за да ви предупредя да не изпаднете в същата ситуация.

Предговор

Аз съм от хората, които, когато пишат статия за WordPress, предпочитат да го правят във вградения редактор на системата. Имам си причини за това, като да речем че е най-вече защото по този начин съм сигурен какво точно ще произведа и няма да се занимавам с “натъмъняване” на форматирането. Може много да се спори по тази тема, но не е в това въпросът.

А в какво е въпросът?

Редакторът на WordPress просто не работи коректно при запазването на публикацията. Какво се случва всъщност:

Please don't save me

Редакторът кара браузърът да направи POST заявка към post.php в съответния сайт (обикновено това е [адресът на сайта]/wp-admin/post.php, като се подават и разни параметри). Тя е тази, която се грижи за запазването на публикацията. По принцип това е съвсем стандартен начин да се направи пращане на информация към някакъв сървър.

Тук обаче има една особеност – при тази POST заявка, редакторът кара браузърът да зареди нова страница, тоест операцията която се случва всъщност “затваря” текущата страница и взема отново съдържанието на поста от post.php. Без да съм се ровил много, предполагам, че просто уеб услугата, която post.php осигурява, връща като резултат от успешното си изпълнение съдържанието на публикацията. После редакторът взема този резултат и отново го визуализира.

Тоест, в цялата Save операция има един момент, в който на клиентската машина липсва публикацията, която потребителят пише. Това е моментът от натискането на бутонът “Save”, до моментът на пристигане на резултатът от запазването (който, както казахме, е самият изпратен текст).

Защо липсата на публикацията върху потребителската машина е проблем, след като тя се съхранява на сървъра?

Ако разчитаме, че Интернет връзката на потребителя е постоянна, без загуби в качеството, без прекъсвания и т.н. (т.е. идеална), всичко ще бъде наред. Това обаче не е така за 99.9% от хората по света – Интернет връзката винаги може да спре, винаги може да стане бавна, дори и уеб сървъра, който приема заявката, може да е временно паднал. И всичко това е нормално и няма как WordPress да отговаря за това. Това обаче не е оправдание за некоректно справяне с такива ситуации. Едно приложение, което ползва мрежата, задължително трябва да предполага, че нещо по нея може да се провали.

Щяхме да говорим защо е проблем публикацията за момент да изчезне от потребителската машина. Ако мрежата е наред, това не е проблем, защото публикацията се изтегля наново. Дори и връзката да прекъсне след изпращане на публикацията, тя ще е стигнала до сървъра и когато връзката се възобнови, публикацията пак ще се изтегли.

Проблемът идва тогава, когато връзката е спряла преди изпращането на публикацията. По никакъв начин редакторът не проверява дали съобщението е било получено от сървъра, преди да презареди страницата.

Съответно ако връзката прекъсне, редакторът се опитва да прати публикацията и тръгва да презарежда страницата, при което не успява да направи нито едно от двете и браузърът зарежда “не мога да отворя страницата”, затривайки всичкият текст, който сте написали в публикацията си на миналата страница.

Както сами разбирате, това е много лошо поведение на един редактор – той губи абсолютно всичкият ви изписан текст, само защото е нямало Интернет, когато сте натиснали Save бутонът. Още по-лош е фактът, че бутонът се казва Save – след като е по-безопасно да не го натискате, а да си останете на същата страница (и да си копирате в някоя друга програма текста). ОК е бутонът да се казва “Delete local copy and try to send it to the server optimistically” – защото този бутон прави точно това. Но това в никакъв случай не е Save.

Как кодерите на WordPress редакторът си МИСЛЯТ че са оправили проблема?

Всъщност създателите на редактора са помислили за подобни ситуации, както и за такива, в които потребителя е затворил без да иска браузърът си. Решението им е много просто – през определени интервали от време и при определени събития (не съм сигурен за точния алгоритъм) правят Auto Save. Разбира се този Auto Save се изпълнява умно – AJAX заявка, която проверява дали е успяла да прати информацията успешно, съобщава чрез текст в редактора.

Защо това не е достатъчно? Просто – какво се случва, ако няма връзка, откакто потребителят е почнал да пише? Редакторът по никакъв начин не съобщава, за неуспешен Auto Save – поне това ако имаше, щеше да е по-добре (едни големи червени букви “не мога да Auto Save – на” биха ме накарали да се замисля дали няма проблем с връзката). Тоест, ако връзката е спряла в началото, аз мога да продължа да пиша още много, и в момента когато кажа “Save”, ще изгубя всичко (яко, а?). Отново – това е много, много, много грешно поведение.

А как трябва да бъде имплементиран Save бутонът?

Отговорът всъщност е сравнително прост – по почти същия начин, както Auto Save функционалността. Вместо да се пренасочва браузърът, редакторът на WordPress трябва просто да прави една AJAX заявка за запазване, в която да праща съдържанието на поста към сървъра. При грешка (т.е. липса на връзка или друг проблем), на потребителя се показва по някакъв начин, че операцията не е била успешна, като текущата страница заедно с всичко което е изписал си остава на компютъра на потребителя – така потребителя може да реагира, да си back-up-не текста, да пробва по-късно и така нататък.

Не мога да дам добра причина, поради която създателите на редактора на WordPress не са имплементирали правилно тази функционалност, предвид, че почти не нужно да се пише нов код, за да се случи това – просто трябва да се ползва кодът на Auto Save функционалността. Ще се радвам в коментарите да се заформи дискусия по въпроса :)

И каква е поуката?

Очевидно, за потребителя поуката е “не разчитай на редактора и запазвай публикациите си някъде, докато ги пишеш” или направо – “ползвай външен редактор”. Бих казал, по-важната е поуката за разработчиците – ако не искате да причинявате поява на ласкателни слова за вас и вашите органи:

  • Кръщавайте бутоните си спрямо това, което наистина правят
  • Не правете Save бутон, който потенциално може да изтрие създаденото от потребителя съдържание
  • Винаги пазете back-up – особено когато имате трансфер на данни по мрежата, задължително пазете данните и при клиента в такива ситуации

Надявам се, първо че като след малко кликна “Save” бутона публикацията ще се запази, и второ – че ще бъде полезна на някои от вас, както при работата ви с WordPress, така и когато вие пишете софтуер :)

, , , , , ,

2 Responses to “Как НЕ се прави Save операция в уеб (#WordPress #fail)”

  • RadoRado says:

    Прочетох статията с очакването, да видя някакъв грандиозен бъг на Save Draft бутона, а то не се оказа т олкова фатално.

    Бърза проверка на нещата :
    1) http://en.support.wordpress.com/autosave/ се прави на всеки 2 минути. Т.е ако Save-неш и ти падне интернета шансът да си загубиш ЦЯЛАТА работа е доста малък.

    2) Тествах го при мен (На Chrome, предполагам зависи от browser-a) – написах статия, спрях си интернета и ударих Save, зареди ми страница за нямане на интернет, натиснах back button-a и целият текст си беше точно там, където съм го оставил (browser state / cache)

    Няма нищо чак толкова фатално в имплементирането на Save button-a на WordPress.

    А и може да очакваме в скоро време, да оправят редактора и наистина да минава през AJAX (тук съм съгласен с теб)

    Поздрави 😉

  • MilenG says:

    Поанзвам този проблем. Той не е свързан с имплементацията на бутона SAVE. Във всички модерни браузъри се пази кеш на попълнените форми в историята. HTTP хедъри определят дали този кеш да се поддрържа. Когато се натисне SAVE данните се изпращат, но дали да се изтрият от нея зависи от тези хедъри в HTTP протокола. Апача ги взема от конфигурацията си и тя е различна за сайтовете с SSL сертификат и без. Най-вероятно там е проблема, защото имах подобен и след като настроих правилно хедърите, браузъра започна да връща попълнена форма с бутона “назад”

Leave a Reply to RadoRado Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>