стратегии управления длинными файлами класса в php

У меня есть набор функций, которые я хочу переместить в класс. Они в настоящее время разделяются на несколько довольно длинных файлов. Я предпочел бы не иметь одни 2 500 файлов строки, но насколько я могу сказать, Вы не можете использовать, включают для разделения класса на несколько файлов. В теории я мог сгруппировать функции в различных классах, но они достаточно тесно связаны, что я чувствую, что они принадлежат вместе, и разделение их уменьшит часть утилиты, которую я надеюсь получить от отодвигания от процедурного подхода (с общими свойствами, а не набором параметров, которые находятся почти в каждой функции).

Я знаю, что это немного неопределенно, но какие-либо предложения/указатели? Если это имеет значение, это для прототипа, таким образом, простота управления кодом имеет приоритет по безопасности и производительности.

ОБНОВЛЕНИЕ: Позвольте мне видеть, могу ли я удалить часть неопределенности:

Этот класс/набор функций производит HTML для сложной формы. Существует много различных разделов и изменений в каждом разделе, в зависимости от приблизительно 5 или 6 параметров, которые в настоящее время передаются в функции. Я надеялся определить параметры однажды как свойства класса и затем иметь доступ к ним изо всех методов создания раздела. Если я буду использовать подклассы, то значения тех свойств не будут инициализированы правильно, следовательно требование одного класса. (Хм..., если я не определяю их как статичных. Я, возможно, просто ответил на свой собственный вопрос. Я должен буду надеяться видеть, существует ли какая-либо причина, которая не работала бы.)

Я в настоящее время получал путаницу функций как:

get_section_A ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
    if ($this->type == 'foo') { }
    else ($this->type == 'foo') { }
}    

Таким образом, я первоначально воображал что-то как:

class MyForm {
    public $type;          // or maybe they'd be private or 
    public $mode;          // I'd use getters and setters 
    public $read_only;     // let's not get distracted by that :)
    public $values_array;
    // etc.

    function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
        $this->type = $type;
        // etc.
    }

    function get_sections () {
        $result = $this->get_section_A();
        $result .= $this->get_section_B();
        $result .= $this->get_section_C();        
    }      

    function get_section_A() { 
        if ($this->type == 'foo') { }
        else { }
    }
    function get_section_B() {}
    function get_section_C() {}
    // etc. for 2500 lines
}

Теперь я думаю что-то как:

// container class file
class MyForm {
    static $type 
    static $mode
    static $read_only
    static $values_array
    // etc.

    function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
        MyForm::$type = $type;
        // etc.
    }

    function get_sections () {
        $result = new SectionA();
        $result .= new SectionB();
        $result .= new SectionC();
    }      
}

// section A file
class SectionA extends MyForm {
    function __constructor() { 
        if (MyForm::$type == 'foo') { }
        else { }
    }

    function __toString() {
        // return string representation of section
    }
}

// etc.

Или вероятно мне нужен абстрактный класс FormSection, где свойства живут.

Какие-либо другие идеи/подходы?

7
задан Gordon 17 December 2009 в 20:26
поделиться

6 ответов

Я бы разделил их на столько классов, сколько вы хотите (или столько, которые имеют смысл), а затем определил автозагрузчик , чтобы избежать проблем с включением.

РЕДАКТИРОВАТЬ

Хорошо, после просмотра большего количества вашего кода - я думаю, что вы неправильно подходите к подклассам. У вас есть много if утверждений против $ type , которые сигнализируют мне, что - это то, на чем должен основываться полиморфизм.

abstract class MyForm
{
  protected
      $mode
    , $read_only
    , $values
  ;

  public function __construct( $mode, $read_only=false, array $values = array() )
  {
    $this->mode      = $mode;
    $this->read_only = (boolean)$read_only;
    $this->values    = $values;
  }

  abstract function get_section_A();

  abstract function get_section_B();

  abstract function get_section_C();

  //  final only if you don't want subclasses to override
  final public function get_sections()
  {
    return $this->get_section_A()
         . $this->get_section_B()
         . $this->get_section_C()
    ;
  }
}

class FooForm extends MyForm
{
  public function get_section_A()
  {
    // whatever
  }

  public function get_section_B()
  {
    // whatever
  }

  public function get_section_C()
  {
    // whatever
  }
}
6
ответ дан 6 December 2019 в 15:23
поделиться

Обычно я делаю что-то вроде этого:

class one
{
    public function __get($key)
    {
        // require __DIR__ / $key . php
        // instanciate the sub class
    }

    public function mainMethod()
    {
    }
}

class one_subOne extends one
{
    public function otherMethod()
    {
    }
}

class one_subTwo extends one
{
    public function anotherMethod()
    {
    }
}

$one->mainMethod();
$one->subOne->otherMethod();
$one->subTwo->anotherMethod();
4
ответ дан 6 December 2019 в 15:23
поделиться

Все они находятся в разных файлах, что означает, что они достаточно разные, чтобы сгруппировать их по файлам. Просто воспользуйтесь той же логикой при построении классов. У меня есть объект Page, который занимается построением страницы. Технически HTML для заголовка моей страницы является частью страницы, но я разделяю его на класс Page_HTML для поддержания моего рассудка, а не для создания гигантских классов.

Кроме того, я предпочитаю делать подклассы, такие как Page_HTML в данном случае, статическими, вместо того, чтобы создавать их экземпляры. Таким образом, я могу получить доступ к переменным $ this в классе Page, но все же сгруппировать их в другой класс.

class Page
{
    function buildPage($content)
    {
        $content = Page_HTML::getHeader() . $content;
    }
}

class Page_HTML
{
    function getHeader()
    {
    }
}
0
ответ дан 6 December 2019 в 15:23
поделиться

Этот класс / набор функций выводит html для сложной формы.

Почему бы не удалить PHP из уравнения? Кажется, вы используете PHP для организации представлений, что можно легко сделать с файловой системой. Просто напишите представления в HTML, используя как можно меньше PHP. Затем используйте PHP для сопоставления запросов с представлениями. Я предполагаю, что вы обрабатываете формы с помощью PHP и можете продолжать это делать. Однако ваши классы станут намного меньше, потому что они только принимают, проверяют и предположительно сохраняют ввод.

0
ответ дан 6 December 2019 в 15:23
поделиться

Что касается построения представления, вы можете попробовать шаблон CompositeView .

Вот небольшой пример того, как это может выглядеть в PHP. Для этого примера представьте, что View :: $ html инкапсулирован в класс Template, который может загружать html с диска и позволяет вводить переменные, обрабатывать экранирование вывода и т. Д.

interface IView {
    public function display();
}

class View implements IView {
    public $html = ''; 

    public function display() {
        echo $this->html;
    }   
}

class CompositeView implements IView {
    private $views;
    public function addPartial(IView $view) {
        $this->views[] = $view;
    }   
    public function display() {
        foreach ($this->views as $view) {
            $view->display();
        }   
    }   
}

Причина, по которой интерфейс IView состоит в том, чтобы позволить вам создавать составные представления с другими составными представлениями.

Итак, теперь рассмотрим форму, состоящую из трех частей: заголовок, тело и нижний колонтитул.

class HeaderView extends View {
    public function __construct() {
        $this->html .= "<h1>Hi</h1>\n";
    }   
}

class BodyView extends View {
    public function __construct() {
        $this->html .= "<p>Hi there.</p>\n";
    }   
}

class FooterView extends View {
    public function __construct() {
        $this->html .= "<h3>&copy; 2012</h3>\n";
    }   
}

(Опять же, вы не будете просто писать HTML в эта общедоступная переменная и обработать вывод, экранируясь самостоятельно. Скорее всего, вы укажете имя файла шаблона и зарегистрируете свои данные через интерфейс шаблона.)

Затем, чтобы собрать все вместе, вы должны:

$view = new CompositeView();
// here you would make decisions about which pieces to include, based
// on your business logic.  see note below.
$view->addPartial(new HeaderView());
$view->addPartial(new BodyView());
$view->addPartial(new FooterView());
$view->display();

Итак, теперь ваши представления могут быть составлены, а фрагменты повторно использованы, но вы можете легко испортить код, который их строит, особенно если у вас много условий и много различных возможных результатов (что, похоже, так и есть. ) В этом случае шаблон Стратегия, вероятно, поможет.

Если вы еще не читали статью Дядя Боба о SOLID , сделайте это прежде всего! По крайней мере, принцип единой ответственности. Я также порекомендовал бы когда-нибудь прочитать книгу Джошуа Кериевского «Рефакторинг под шаблоны».

Если вы еще не читали статью Дядюшки Боба о SOLID , сделайте это прежде всего! По крайней мере, принцип единой ответственности. Я также порекомендовал бы когда-нибудь прочитать книгу Джошуа Кериевского «Рефакторинг под шаблоны».

Если вы еще не читали статью Дядюшки Боба о SOLID , сделайте это прежде всего! По крайней мере, принцип единой ответственности. Я также порекомендовал бы когда-нибудь прочитать книгу Джошуа Кериевского «Рефакторинг под шаблоны».

3
ответ дан 6 December 2019 в 15:23
поделиться

Если вы хотите сделать операцию ООП, разделите проблемы и инкапсулируйте их в соответствующие классы. Комбинируйте их либо по расширению, либо по составу, либо по лучшей группировке. Удалите любой дублирующий код. Не повторяйтесь.

В вашем случае, отделите вещи, относящиеся к любой форме, от вещей, относящихся к вашей конкретной форме. Код, который может быть использован для любой формы - это код, который вы хотите поместить в общий класс формы. Вы можете повторно использовать его в более поздних проектах. Для примера очень сложного класса формы посмотрите Zend_Form.

Все в вашем коде, что связано со специфической формой, попадает в собственный класс, который расширяет общую форму. Предположив, что из свойства type, данного в вашем коде, вы можете получить несколько классов специальной формы (вместо одного типа-fits-all-form), что, скорее всего, устранит сложность методов getSection и сделает ваш код намного проще в обслуживании, потому что вы можете сконцентрироваться на том, как должен выглядеть и что должен делать конкретный тип формы.

Наконец, если у вас есть код, который получает данные для формы изнутри формы или иным образом не имеет прямого отношения к построению формы, удалите его и сделайте из него отдельный класс. Помните, что вы хотите отделить заботы и ваши классы формы заботятся о том, чтобы построить форму, а не получать ее данные или что-то в этом роде. Данные - это то, что вы захотите передать форме через конструктор или специальный сеттер

.
1
ответ дан 6 December 2019 в 15:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: