Доброго времени суток. Пушу это сообщение тут, так как считаю вас наиболее профессиональной публикой. Мой вопрос имеет концептуальный характер и он требует наличие опыта. Собственно вопрос: Какой метод программирования самый лучший. Сразу две оговорки, первая – метод не совсем верное определение (а какое верное? Вы поймете это в контексте сообщения), второе – «саамы лучший», я имею ввиду самый лучший с вашей точки зрения. Вот смотрите, пример моего кода: Код (Text): <?php include ('../classes/db-class.php'); include ('../classes/picture-class.php'); $picture = new picture(); switch ($_REQUEST['action']){ case 'addCatalog': $all->htmlHead("Visual CMS 2009 | Папка добавлена"); $picture->addCatalog(); $picture->uploadPictureForm(); $picture->newCatalogForm(); break; case 'delCategory': $picture->delCategory(); $all->htmlHead("Visual CMS 2009 | Папка удалена"); $picture->uploadPictureForm(); $picture->newCatalogForm(); break; …………. …………. …………. default: $all->htmlHead("Visual CMS 2009 | Работа с изображениями"); $picture->uploadPictureForm(); $picture->newCatalogForm(); break; } $all->htmlFoot(); ?> - это как вы поняли файл в котором вся логика, построена она очень просто. На странице передаются переменные $_REQUEST[‘action’] и на основе этих переменных вызываются ф-ии. Вот второй файл: Код (Text): <?php class picture{ #Начало класса, конструкт function __construct (){ $this->db = new db(); $this->db->connect(); $this->all = new all(); echo ' <script> //////////////////////////////////////////////////////////////////////////////// public function addCatalog(){ $config = parse_ini_file('../elements/config/cms_config.ini', true); $root_document = $config['main']['root_document']; $catalog_name = $this->all->in_var($_REQUEST['catalog_name']); $catalog_real_name = $this->all->in_var($_REQUEST['catalog_real_name']); $root_document = $config['main']['root_document']; $link = $root_document."elements/i/cms_folders/$catalog_real_name/"; if(!@mkdir($root_document."elements/i/cms_folders/$catalog_real_name/", 0777)){ echo '<H2><font color="red"><div align="center">Папка не создана!</div></font></H2>'; }else{ $this->db->query('INSERT INTO pictures_catalog (picture_catalog_name, picture_catalog_real_name) VALUES ( "'.mysql_real_escape_string($catalog_name).'", "'.mysql_real_escape_string($catalog_real_name).'")'); } } //////////////////////////////////////////////////////////////////////////////// public function delCategory(){ $config = parse_ini_file('../elements/config/cms_config.ini', true); $root_document = $config['main']['root_document']; $this->db->query('SELECT * FROM pictures_catalog WHERE ID = '.$_REQUEST['id_cat']); $mysql_array = $this->db->return_obj_array(); $id = $mysql_array[0]['ID']; $catalog_real_name = $this->all->out_var($mysql_array[0]['picture_catalog_real_name']); $path = $root_document."elements/i/cms_folders/$catalog_real_name/"; rmdir_recurse($path); $this->db->query('DELETE FROM pictures_catalog WHERE ID = '.$_REQUEST['id_cat']); rmdir($path); } //////////////////////////////////////////////////////////////////////////////// public function saveCatalog(){ $config = parse_ini_file('../elements/config/cms_config.ini', true); $root_document = $config['main']['root_document']; $new_catalog_name = $_REQUEST['new_catalog_name']; $new_catalog_real_name = $_REQUEST['new_catalog_real_name']; $idDir = $_REQUEST['idDir']; $oldName = $_REQUEST['oldName']; $u = 'elements/i/cms_folders/'; @rename($root_document.$u.$oldName, $root_document.$u.$new_catalog_real_name); $this->db->query('UPDATE pictures_catalog SET picture_catalog_name = "'.$this->all->in_var($new_catalog_name).'", picture_catalog_real_name = "'.$this->all->in_var($new_catalog_real_name).'" WHERE `ID` = '.$idDir); } //////////////////////////////////////////////////////////////////////////////// } ?> -тут соответственно хранятся функции. Файл db-class.php я во внимание не беру, т.к. это простейший класс. Я считаю эту методику достаточно эффективной но я хочу развиваться… Так вот что вы думаете о моем методе и какой метод применяете вы.[/code]
А в чем методика?) switch лучше переделать: когда у вас будет пара десятков пунктов - долго будете листать до нужного места. $_REQUEST['catalog_name'] и т.п. лучше передавать как параметры конструктора (метода). если такой тип сообщения будет использовать более 1 раза и вы захотите потом добавить к нему скажем жирное начертание, будете долго по коду искать всё ли вы поправили.
Сколько раз, за время выполнения скрипта, создаются экземпляры классов db и all? Оформите методы этих классов как статическимие. Намного удобнее писать: DB::query чем $this->db->query. Кроме того, хорошо бы лобавить методы в db_class типа select, insert, update, delete, чтобы не писать каждый раз SQL для простых запросов, и зставить эти методы автоматически ескейпить строки. Используйте массивы $_POST и $_GET, хотя бы потому, что они короче =) Подавление ошибок - дурной тон. Проверяйте директорию на возможность записи.
Мой ответ: ООП причем для веб или не для веб, не важно, интерфейс должен быть отделен от логики. Так что если хочешь развиваться читай Объектно ориентированный анализ и проектирование, а потом, когда большие программы станет тяжело сопровождать и развивать вспомни про МВЦ и акуеешь, как акуел в свое время я. А второй совет о том чего не надо делать: не надо сразу хвататься за сложные фреймворки, только потеряешь время.
Не согласен, ибо, бывает, что переменная можетт прийти и через Гет, и через Пост. Тоже не совсем согласен с таким подходом, хотя он и используется в большинстве случаев. Иногда надо заескепить переменную, а иногда - проверить ctype_digit, ctype_xdigit и не делать запроса вообще, если данные неподходящие. С остальным согласен
Экземпляры создаются один раз, в конструкторе. Насчет статических методов, согласен. Насчет массива реквест, переменная приходит как из гет так из пост.
"читай Объектно ориентированный анализ и проектирование" - буду благодарен за ссылку на хорошую книгу или статьи
Г. Буч. ИМХО, хоть и не новая, лучше все равно никто не смог написать. А все остальное- все эти рефакторинги с умными названиями, и темплейты и МВЦ-ы, ORM-ы разные уже из нее вытекают. Все это не какие-то отдельные методики, а проверенные временем наработки ООП. Чего я бы не советовал делать, так это начинать с конца, то есть сначала хвататься за МВЦ-фреймворки и др. шаблоны и через них приходить к пониманию ООП. Еще из моего опыта это что UML слишком уж возвеличивают. Пока все это читается в книжке- все очень красиво. Но на практике почти неприменимо. Из всего UML самое полезное- диаграмма классов. Но и то, если только она генерируется автоматически из исходников. Если говорить про ПХП, то такое умеют только PDT и его преемники как Zend Studio и Aptana PHP еще вроде. Еще очень пригодятся МВЦ и Юнит тесты и PHPDoc-и. Это то, про что мне никто не рассказывал и чему меня никто не учил, но жизнь как говорится заставила. Еще откажись от местных кодировок и перейди сразу на UTF и пока вообще не обращай внимания на потребляемые ресурсы железа. UML, юнит тесты и МВЦ становятся нужны только на больших проектах. Это где- то начиная от 200-300 завязанных между собой собственных классов, то есть ни считая классов в библиотеках. Так что пока можно про них не думать. К PHPDoc-ам привыкай сразу. Они нужны как воздух. Если Буча не читал, я тебе советую умри но достань. так что вот. Ну а про ссылки, ссылки я тебе не дам, у меня их нет.
на форуме имеется в достаточном количестве. код твой тоже смотрел. раз уж ты сам напросился, чтобы тебя покритиковали, то скажу честно есть притензии Во- первых сразу бросилось в глаза отсутствие PHPDoc-ов а вместо них #Начало класса, конструкт и какие-то полоски ///////////////////////////////// Это полная лажа. Но к счастью легко лечится. Я когда впервые сел на PHP после языков со строгой типизацией тоже так писал, но долго это не могло продолжаться, потому что без PHPDoc вообще не работает автокомплит! Во- вторых, первый файл- это у тебя чистый контроллер. Его осталось только оформить в виде класса. И в- третьих, про второй файл. Там у тебя получилось почти чистая модель, с небольшой примесью не пойми чего. Но это легко исправить. Поменяй все экхи '<H2><font color="red"><div align="center">Папка не создана!</div></font>' на throw new Exception("Папка не создана") и вуа ля ты получил чистую модель. В остальном очень даже чистый класс не смешанный с контроллером и вьюшкой. про @rename согласен, про $_GET и $_POST вместо $_REQUEST нет
Модуль авторизации в текущем проекте. Класс: PHP: <?php /** * @name authintefication.inc * @copyright Vasilii B. Shpilchin (2009) * @package ****** (: * * Авторизация пользователя на сайте. * Используйет memcached-сессии (класс memsess) */ class auth { public static $logged = false; /** * Попытка авторизации * * @param string $login * @param string $password * @return boolean */ public static function try_login($login, $password) { if (strlen($login) < 4) { return false; } if (strlen($password) < 4) { return false; } $where = array('name='=>$login, 'password='=>$password); $user = array(); $res = DB::select('`id`', 'users', $where); $user = mysqli_fetch_array($res, MYSQLI_ASSOC); $success = isset($user['id']); if (!$success) { return false; } else { memses::set('__logged', 1); memses::set('__uagent', md5($_SERVER['HTTP_USER_AGENT'])); memses::set('__id', $user['id']); memses::update(); self::$logged = true; return true; } } /** * Проверка авторизации * * @return boolean */ public static function check() { if (!memses::check()) { return false; } else { if (memses::get('__logged') === 1) { $ip = memses::get('__ip'); $uagent = memses::get('__uagent'); $id = memses::get('__id'); if ($ip == $_SERVER['REMOTE_ADDR'] && $uagent == md5($_SERVER['HTTP_USER_AGENT'])) { return $id; } } return false; } } /** * Логаут */ public static function logout() { if (!memses::check()) { self::$logged = false; } else { memses::set('__logged', 0); memses::del('__uagent'); memses::del('__id'); self::$logged = false; } } } ?> Логика: PHP: <?php /** * @name module.php * @copyright Vasilii B. Shpilchin (2009) * @package ****** (: * * Модуль авторизации (login) */ require('./login/authintefication.inc'); if (isset($_POST['name']) && isset($_POST['password'])) { $_POST = SYS::escape($_POST); if (auth::try_login($_POST['name'], $_POST['password'])) { SYS::go_to('home'); die(); } else { include('./login/templates/incorrect_login.tpl'); } } include('./login/templates/form.tpl'); ?>
Судить код я не могу, вроде хорошо написанно. Единственное стиль мне не нравиться Код (Text): if (strlen($login) < 4) { return false; } if (strlen($password) < 4) { return false; } но, на вкус и цвет товарища нет[/code]
Всё уже придумано, вспомним Зенд PHP: <? set_include_path($_SERVER['DOCUMENT_ROOT']); function __autoload($name){ $name=strtolower($name); if(!is_file($file="classes/{$name}.class.php")){ if(!is_file($file=str_replace("_","/",$name).'.class.php'){ trigger_error("Немогу загрузить $name",E_USER_ERROR); } } incldue_once $file; } if($_GET['module_name']){ if(is_file("moduls/".basename($_GET['module_name']).".class.php")){ $module_name="Moduls_".$_GET['module_name']; $class=new $module_name(); $_GET['module_name']=strtolwoer($_GET['module_name']); if($_GET['action'] && method_exists($class,$act="Action".$_GET['action'])){ $_GET['action']=strtolower($_GET['action']); $result=$class->$act(); $tplname=$_GET['module_name']."_".$_GET['action'].".tpl"; }else{ $result=$class->ActionIndex(); $tplname=$_GET['module_name']."_index.tpl"; } }else print "Error Module Not Found"; }else{ $class=new Moduls_Index(); $result=$class->ActionIndex(); $tplname="index_index.tpl"; } if($result){ $tpl=new Tpl(); if(is_array($result) && !empty($result)) { $tpl->Set($result); } print $tpl->Load($tplname); } ?> Module Example PHP: <? class Module_Name { function ActionIndex(){ // return array если хотим чтобы в шаблончик добавило переменные, return true чтобы просто показало шаблончик, return false; чтобы ничего не показало } function ActionSome(){ /* .... */ } } ?> Ps/ Код писал налету
При выполнении этого кода используются методы из четырех пользовательских классов, но не создается ни одного экземпляра - всё в статике. Эти классы - интерфейс, API, здесь не нужны объекты (экземпляры). С другой стороны, в модуле home для пользователя создается экземпляр класса user с соответствующими конкретному пользователю свойствами.
Раз так много людей хочет попонтоваться своим кодом, приходит в голову идея. Может отдельную тему создать, куда можно будет выложить свой код, чтобы другие могли сделать замечания. у?