7

私はアーケード サイトを運営していますが、ここ数年の間に多くの機能が追加されました。手続き型プログラミングが複雑すぎるように見え、新しい機能を追加したり、単純なデザインの変更を加えたりするのは非常に難しい場合があります。

したがって、同じ機能を備えた OOP 形式でサイトをゼロから再コーディングすることにしました。

私が抱えている問題は、クラスを選択することです.OOPとそれがどのように機能するかを理解していますが、常に開始するのに問題があるようです. ログインユーザー関数を持つユーザークラスなどのクラスの関数を作成しようとする必要があるのか​​ 、それともユーザークラスがユーザーの詳細を追加/更新/表示するだけで、ログイン部分がシステムでより優れているかはわかりませんクラス?

現時点では、次のクラスと関数から始めましたが、このカテゴリに収まりますか?

<?
class User {

    var $userId,
        $username,
        $userRole,
        $userEmail;

    function isLoggedIn(){

    }

    function login($postusername, $postpassword)
    {

    }

    function increaseLoginCount(){

    }

    function logout(){

    }
}
?>

次に、page.php .. (接続クラスは表示されません) に次のようなものを含めることができます。

<?
$db = new Connect;
$db->connect();

$user = new User;

if(!$user->isLoggedIn())
{
    echo "Please Log In.";

    if($_POST['user'])
    {
        $user->login($_POST['username'], $_POST['password']);
    }
}
else
{
    if($_POST['logout'])
    {
        $user->logout();
        exit;   
    }

    echo $user->username." Logged In.<br />";
}
?>

しかし、サイトにはゲームのカテゴリを表示するページがあり、単一のゲームではないため、displayGames() 関数がどこに収まるかわかりません。

「現実世界」の例を見つけようとしましたが、象の色を変えたり踊ったりする方法を示すphpコードはあまり役に立ちません...

4

4 に答える 4

9

いくつかのテキスト分析から始めましょう、私によるハイライト:

私はアーケードサイトを運営おり過去数年間

あなたがどれだけ対処できるか、そしてあなたが何を扱っているかを考えてください。また、何年にもわたって、アーケードサイトの運営について特定の知識を身に付けてきたことを理解してください。あなたはあなたの地域で職業を得ました。自分の立場や資産を過小評価しないでください。それはあなたが運営している基盤であり、変更を導入します。これには、サイトのユーザーベースが含まれます。

多くの機能が追加されており、手続き型プログラミングが非常に複雑に見え、新しい機能を追加したり、単純な設計変更を行ったりするのは非常に難しい場合があります

システムが成長すると、システムはますます複雑になります。これは手続き型プログラミングだけに固有のものではなく、事実の問題です。あなたは今何年もの間サイトを運営しているので、特にユーザーがあなたのサイトとどのようにインターフェースするかという分野で、物事がどのように変化したかを知っています。

したがって、同じ機能を使用して、OOP形式でサイトをゼロから再コーディングすることにしました。

OOP技術を使用して再利用可能なソフトウェアを作成することは可能であると言われていますが、これを証明するものはありません(できません)。

しかし、アプリケーション全体を最初から書き直すことが成功した商用ソフトウェア開発の例はごくわずかです。非常に少ない。商用ソフトウェア開発のルールは、特定のケースでは適用されない場合があるので、言ってみてください。

サイトを再コーディングする前によく考えてください。同じことを達成するためだけに多くの仕事をすることは、いくぶん無益であり、失望する可能性があります。代わりに、おそらく、現在の設計のどれが、変更したい最大の問題を引き起こしているのかをより具体的に見てください。

PHPを使用すると、手続き型とオブジェクト指向のスタイルを組み合わせることができます。これは、レガシーコードがある場合に特に役立ちます(レガシーコード一般的な定義は、自動テストなしのコードです)。

私が抱えている問題は、クラスを選ぶことです

私はそれを言い換えようとします:何のためのクラスを書くのですか?

はOOPとそれがどのように機能するかを理解していますが、始めるのにいつも問題があるようです。

最初は常に最も難しいステップです。あなたは今、決断を下す準備ができていますが、将来を見据えることはできません。最も危険な部分を排除することにより、リスクを軽減します。あなたはおそらくここであなたの決定の基礎となるフィードバックを得るために質問をし始めましたが、それはおそらく負担を軽減せず、混乱につながる可能性があります。しかし、教育を受けることはほとんどの場合良いことです。

ログインユーザー関数を使用してユーザークラスなどのクラスの関数を作成する必要があるのか​​、それともユーザークラスがユーザーの詳細を追加/更新/表示するだけで、システムのログイン部分が優れているのかがわかりませクラス?

これは、アプリケーションの性質とユーザーの性質に大きく依存します。おそらく、スクリプトのほとんどは、ユーザーが具体的であるか匿名であるか(匿名ユーザーがログインしていないか)、ID、名前、またはニックネームを知る必要があるだけです。

アプリケーションは、そのユーザーに消費コンポーネントを提供する必要があるため、各コマンド/スクリプトは、a)ユーザー情報の取得とユーザーの処理(ログインなど)、b)コンポーネントがユーザーに対して有効かどうかの確認(アクセス制御)を処理する必要はありません。 )。これは、別の場所、たとえばアプリケーションコントローラーPofEAAに配置する必要があります

アプリケーションコントローラオブジェクトを持つ各スクリプト/コマンドは、ユーザーを要求し、ユーザーと対話することができます。

ただし、これは技術的に言えばです。自分が確信が持てないという事実に対処し、その情報を処理します。具体的な問題をより適切に定式化し、それを解決する特定の方法の長所と短所をリストし、コーディングを開始する前に具体的なコードから離れてください。次に、長所と短所を比較します。物事をより単純で複雑でないものにするようにしてください。

おそらく、コードを書く代わりに、何が起こっているべきかを簡単な言葉で書き留めてください。

現時点では、次のクラスと関数から始めましたが、これらはこのカテゴリに当てはまりますか**?**

あなたのコードはかなり裸なので、それについて多くを語るのは難しいです-特にあなたのアーケードサイトが何であるか(そしてあなたが何について書いているのか)私は知らないので。おそらく例としてはまだ良いでしょう。クラスで見ることができるのは、すべてを互いに緊密に統合していることです。

たとえば、DBから始めます。DBはあらゆるアプリケーションの中心的なコンポーネントであるため、これは一般的なことです。アプリケーションを操作するには、DBが必要です。ただし、すべてのコマンドを他のDBで実行できるようにするか、アプリケーションの他のデータオブジェクト以外のDBに接続されている新しいユーザーオブジェクトで実行できるように、物事をゆるく結合しておく必要があります。

 $application->getDB();

ユーザーは各アプリケーションの中心的な主題であるため、非常にシンプルなインターフェイスを備えている必要があります。認証、ユーザープロパティの取得などに関するすべての栄光の詳細は、別のクラス/コンポーネントに委任する必要があります。これにより、ユーザーが保存される実装とユーザーの認証方法を変更できます。

 /**
  * @package command.modules.games
  */
 function ListGamesCommand(Request $request, Response $response)
 {
     $application = $request->getApplication();
     $user = $application->getSession()->getUser();
     $games = $application->getModels()->build('games');
     $games = $games->findByUser($user);
     $response->setProp('games', $games);
 }

この例が示すように、必要なときに機能を追加できます。たとえば、アプリケーションが実際にユーザーにログインする必要がない限り、なぜ今どのように記述されているかを気にする必要がありますか?

アプリケーションオブジェクトのユーザーを生成するファクトリを作成します-現在または将来必要になるものは何でも(クリーンコードトークのオブジェクトの2つの山-継承、ポリモーフィズム、およびテストを参照)。その後、認証が必要な場合は、それをセッションオブジェクトまたはユーザーオブジェクトインターフェイスに追加します。

認証自体は、とにかく独自のクラスで実装されAuthenticatorます。したがって、認証の呼び出しをセッションからユーザーなどに移動することで、後でインターフェイスを確認することもできます。これらの特定のタスクを処理する必要があるのはコマンドのごく一部であり、OOPを書き直して利益を得たいため、すべての新しいコードは自動テスト中であるため、すべての場所がカバーされ、適切にリファクタリングされていることを確認しました。

リクエスト変数へのアクセスについても同じことが言えます。間接参照と高度に関連している(そして間接参照の各層には価格が伴う)OOPの利点を利用したい場合は、まず、基本クラスを特定のデータで動作させ、データでは動作させないようにする必要があります(グローバルとスーパーグローバル、私は$_POSTあなたのサンプルコードで見ました)。

したがって、新しいコードがリクエストを処理してレスポンスを配信できるようにします(入力-処理-出力)。

$request  = new Request($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV);
$response = new Response;

BankAccountからの例-PHPUnitトレーニングに使用されるサンプルアプリケーション

Requestこれで、これより下のすべてがResponseオブジェクトに対して動作できるようになります。入力を処理して出力に変換します。ドメインコマンド(スクリプト/そのことを実行するコマンド)は、使用するようにHTTPリクエストから入力を抽出することを気にする必要がなくなります。$_POSTまたは$_GET、-から直接取得することも、Request独自のコマンドのクラスを作成する場合も-これはさらに調整することができます。また、一部のコマンドは、独自の要求と応答を操作できます。

次の大きなトピックはユーザーインターフェイスです。あなたはあなたがしたいことを書きます:

同じ機能を使用して、OOP形式でサイトをゼロから再コーディングすることにしました。

私はすでにそのようなことは無益である可能性があると書いた。OOPコードを利用できるということは、次にコードを変更したときに、コンポーネントを再利用できることを意味します。ソフトウェアは絶えず変化しているので、今回はもう次回です。したがって、既存のコードをすでに再利用したいとします。既存のコードの一部が出力ロジックだと思います。したがって、既存の出力ロジックは、例示以上のものとインターフェースする必要がRequestありますResponse

私はあなたがウェブサイトを愛しているに違いない。あなたはそれらをうまく機能させて見栄えを良くするのが大好きです。あなたは何年にもわたってあなたのサイトを構築してきました、そしてすべてがあなたが望むようであるとは限らなくても、あなたはそれを落としたくありません。したがって、書き直しには、すべてを破壊するのではなく、現在から将来まで機能するフォームを保持できることが重要です(機能するアプリケーションの保持;リストの最後のポイントも参照してください)。

Webアプリでは、ビューは非常に重要な部分です。ビューを失うと、サイトのアイデンティティが失われます。変更しすぎると、サイトは今日の使用に慣れているユーザーを失います。

あなたがそれを壊すならば、

  1. あなたも気づきますか?
  2. 直してもらえますか?

一方、アプリケーションコード(機能、機能)がそれほど緊密にバインドされないようにして、コードを書き直すメリットを得る必要があります。アプリケーションを書き直したいので、見てみましょう:

     .---------.                            .-------------.
     | website |  ---> [interface in ] ---> | application |
     | user    |  <--- [interface out] <--- |             |
     `---------´                            `-------------´

このスキーマが示すように、アプリケーションを相互作用のように見えるもの(Webサイト、(スマートフォン)GUI、またはチケットシステムなど)からより独立させるには、アプリケーションコードを置き換え可能にする必要があります。たとえば、新しいアプリケーションコードのすべてのタイプのユーザーインターフェイスに対してユーザーゲームを取得するロジックをコーディングする必要はありませんが、古いアプリケーションコードでコーディングしました。

Userここで例としてオブジェクトを取り上げます。それがどのように認証され、どこに保存されるかは、新しいアプリケーションコマンドコードが懸念するものであってはなりません。コマンドがそれを必要とする場合、それはただそこにあります。グローバルではありませんが、特にコマンドが要求した場合。

一方、登録とパスワードの紛失の手順は既存のアプリケーションの一部であり、引き続き存在します。

次に、古いコードと新しいコードをまとめる必要があります。

したがって、おそらくHTTP要求とHTTP応答のインターフェースから始めるでしょう。ビューは、そのInterfaceOutで始まります。そのインターフェースを介してビューに必要なすべてのデータを割り当て/渡すと、アプリケーションはビューを認識しなくなります。新しいアプリケーションコード内では、CSS、Javascript、またはHTMLコードを処理しません。これは、出力の一番上の砂糖です。アプリケーションは、プレーンテキストのコンソール/ telnetを介して、またはリモートXMLRPCサービス、AJAXエンドポイントなどとしてもインターフェースする必要があります。

したがって、おそらくビューコードを一般化して、それに変数を挿入することができます。ビューレイヤーを作成するのは、PHPファイルを含めるのと同じくらい簡単です。スコープ内で使用可能な変数を操作します。スコープ内で使用できる「ヘルパー」関数(テンプレートマクロ)を利用できます。ビューモデルオブジェクトを利用できます。ビュー用に独自の言語(テンプレート言語、ドメイン固有言語(DSL))を作成することも可能です。

ただし、これは、アプリケーションコードがそうすることを可能にするインターフェースを作成する場合にのみ可能です。

したがって、現在行うことは、HTTP / HTML / CSS/JSをアプリケーションから独自のアダプターに移動することです。そのアダプタは、のインターフェイスを介して任意のアプリケーションに渡すことができる汎用コマンドを作成できます。

アプリケーションは、コマンドを実行し、インターフェース出力を介してその応答を配信することのみに注意を払います。つまり、アプリケーションとWebサイトの2つのドメインができました。

これらの2つの新しいドメインの作成を開始してから、レガシーコード用と新しいコード用のインターフェイスを提供できます。

また、「2つの」アプリケーションが隣り合っています。それらは最終的にデータベースとバインドされ(独自のコードでは表示されません)、サイトのデータが正常であるように注意します。そして、それがデータベースの目的です。データをコードから分離して、時間の経過とともにコードを変更できるようにします。

また、再コーディングする場合は、既存のコードと新しいコードの間に境界線を引きます。

幸運を!そして、これを読んで、あなたの特定のケースのためのいくつかのオプションがあなたに示されることを願っています。また、コントローラーをデータベースの単なる別のファサードに変えないように注意してください。アプリケーションがWebサイト専用である可能性があるため、軽量のHTTP抽象化とビューレイヤーのみを使用することで、おそらく最高のメリットが得られます(具体的な最大の問題はわかりません)。

HTTP / PHPの場合と同様に:

[Interface In]  Plain Text HTTP request
[Application]   Free to go
[Interface Out] Plain Text HTTP response

通常、入力を解析して出力を構築するために必要な機能は一部だけです。

さらに、ファットモデルを使用しないことには、データにすばやく順番にアクセスできるという利点があります。たとえば、出力を一度に渡す必要がない場合(バッファリング、1ブロック)、出力をサーバ。

OOPかどうかではなく、アプリケーションのリファクタリングに重要な部分を決定する必要があります。手続き型と同様に、OOPも適切に実行する必要があります。今日、手続き型コードを記述して問題が発生した場合、OOPコードは問題に対する答えではない可能性があります。より良い手続き型コードを書く必要があるかもしれません。ただ、アプリケーションをリファクタリングするのは簡単ではないので、最初に実際の問題を特定する必要があります。

  1. あなたがそれを壊した場合、あなたも気付くでしょうか?
  2. あなたがそれを壊した場合、あなたはそれを修正できますか?

重要な部分は、あなたが気付くことができ、修正を行うためのすべてが手元にあるということです。

あなたのウェブサイトをテスト下に置いてください。そうすれば、ここでコードを変更するのか、それとも実際にうまくやっているのかを言うことができます。それが機能していないことが明らかになった場合は、変更を元に戻すことができます(より良い)。

これで、新機能を簡単に決定できます。新しい機能を導入する必要がない限り、機能の記述方法を変更する必要はありません。そしてそこまで、新機能を計画することはできません。

したがって、アプリケーションを書き直す前に、よく考えてください。書かれているように、これはプロジェクトを殺す可能性があります。


関連項目: PHP / SQL / HTML / CSSコードにMVCスタイルを実装するにはどうすればよいですか?SO Q&A

于 2012-01-03T12:03:48.623 に答える
7

OOP とは、責任のある領域を特定し、それらの領域の 1 つだけを処理することを目的とした自己完結型のコード ユニットを構築することです。一般的な経験則では、システム内の各オブジェクトは現実世界で同等のオブジェクトまたは概念を具現化する必要がありますが、システムを機能させるために必要な抽象的なものについても心配する必要があるため、常にそうであるとは限りません (ここでは抽象的なという意味です)。ビジネス ロジックの項目を表すものではないが、システムを機能させるためにはまだ必要であるという意味で (まったく別の抽象クラスを意味するわけではありません)。

たとえば、ゲーム サイトでは、おそらくゲーム、ユーザー、モデレーター、アカウント、レビュー、コメントなどを処理する必要があります。これらはそれぞれ独自のクラスである必要があり、そのクラスのすべてのインスタンスは特定のユーザー、ゲーム、コメントなどを表す必要があります。

しかし、クラスには責任の領域があり、前述のように、クラスはその責任の領域だけを処理する必要があります。ページのレンダリングは、上記のオブジェクト クラスの責任ではありません。これが、システムのエンティティを表さないクラスの出番です。おそらく、ページ用のクラス、セッション用のクラス、データベース接続用のクラスが必要になるでしょう (ただし、PHP では PDO で既にカバーされています)。および mysqli などの他の DB モジュールの一部)。

ページをレンダリングするには、ページ クラスのインスタンスを使用します。ログインしたユーザー オブジェクトへの参照、表示したいゲーム オブジェクトへの参照などを渡します。次に、実際の HTML をレンダリングします。Page クラスは、渡されたオブジェクトの内部動作について何も知る必要はありません。ただし、それらのオブジェクトが公開する API (OOP サークルではオブジェクトのプロトコル、つまりパブリック メソッドとプロパティとして知られています) 以外は何も知る必要はありません。(非常に基本的な) Page クラスは次のようになります。

class Page
{
    private $user = NULL;
    private $games = array ();

    public function setUser (User $user)
    {
        $this -> user = $user;
    }

    public function getUser ()
    {
        return ($this -> user);
    }

    public function addGame (Game $game)
    {
        $this -> games [] = $game;
    }

    public function getGames ()
    {
        return ($this -> games);
    }

    public function generate ()
    {
        $user = $this -> getUser ();
        $games = $this -> getGames ();

        $pageFile = '/path/to/a/php/script/representing/the/page/markup.php';
        require ($pageFile);
    }

    public function __construct (User $user, array $games)
    {
        $this -> setUser ($user);
        foreach ($games as $game)
        {
            $this -> addGame ($game);
        }
    }
}

実際の markup.php スクリプトは、おそらく次のようになります。

<html>
    <head>
        <title>Games page for <?php echo ($this -> user -> getName ()); ?>
    </head>
    <body>
    <p>Hello, <?php echo ($this -> user -> getName ()), here are your games.</p>
    <?php if (count ($this -> games)) { ?>
    <ul>
        <?php foreach ($this -> games as $game) { ?>
        <li><?php echo ($game -> getName ()); ?>: your best score is <?php echo ($game -> getHighScore ($this -> user)); ?></li>
        <?php } ?>
    </ul>
    <?php } ?>
    </body>
</html>

お気づきかもしれませんが、このアプローチを使用すると、アプリケーションのモジュールは 3 つのカテゴリのいずれかに分類される傾向があります。User や Game などのビジネス ロジック オブジェクト、markup.php ファイルなどの表示ロジック、および Page クラスなどのグルー ロジックと調整のフォームとして機能する 3 番目のグループです。

この特定のケースではサイトに固有のものですが、このアプローチをさらに一般化すると、Model、View、Controller の略である MVC として知られるデザイン パターンに分類されます (実際には、プレゼンテーション用の PAC と呼ばれるパターンに近いものです)。 、Abstraction、Controller ですが、何らかの理由で PHP コミュニティではほぼ常に MVC と呼ばれているため、ここでは MVC とだけ呼びます)。パターンとは、プログラマーが定期的に遭遇する問題のクラスを一般化したものであり、事前に作成されたソリューションのツールキットが便利です。

ゲーム アプリケーションの場合、User と Game はモデル、Page はコントローラー、markup.php はビューです。別の markup.php スクリプトをこのコードに代入すると、それを使用してまったく同じデータをまったく別の方法 (たとえば XML ファイルなど) で表示できます。同じモデルを別のコントローラーで使用して、別のことをさせることもできます。ここで心に留めておくべき重要なことは、モデルがどのように使用されているかを気にする必要はなく、コントローラーが何を達成する必要があるかに応じて、さまざまな方法でモデルを使用できるということです。

MVC はパターンであるため、PHP で MVC (実際には MVC ではありませんが ;)) アプリケーションを構築するためのツールキットが既に存在します。これらはフレームワークと呼ばれます。Symfony、CodeIgnitor、Zend Framework など、選択肢はたくさんあります。個人的には好きというわけではありませんが、最近最も人気のあるフレームワークは Zend です。(ただし、Zend Framework 2 のベータ版は、フレームワークの現在のバージョンよりもはるかに優れていると言えます)。

これがお役に立てば幸いです。OOP は最初は気が遠くなるかもしれません。プログラマーとしての考え方を変える必要がありますが、十分な練習が必要です。

于 2011-12-31T07:54:17.267 に答える
0

ユーザー クラスのすべてのメンバーは、そこに属しているように見えます。gui コードを他のコードから分離することが重要です。私は、displayGames() を何らかの gui クラスに入れます。

于 2011-12-31T04:15:00.633 に答える
0

GordonM の投稿は、始めるのに適した投稿です。確立されたフレームワークを使用して作業を開始することをお勧めします。フレームワークは多くの面倒な作業を行い、PHP 内の OOP に慣れるのに役立ちます。個人的には、PHP5.3 を使用している場合は Symfomy2 をお勧めしますが、それは純粋に個人的な好みです。また、「ギャング・オブ・フォー」の本を手に入れることをお勧めします。これは非常に重要な読み物であり、主に非要求駆動型環境のバックグラウンドから来ていますが、多くのパターンは依然として PHP に関連しています。

于 2011-12-31T11:04:17.073 に答える