java oop 测试题

tech2022-09-09  106

java oop 测试题

At a certain point of my development as a PHP programmer, I was building MVC applications by-the-book, without understanding the ins-and-outs. I did what I was told: fat model, thin controller. Don’t put logic in your views. What I didn’t understand was how to create a cohesive application structure that allowed me to express my business ideas as maintainable code, nor did I understand how to really separate my concerns into tight layers without leaking low-level logic into higher layers. I’d heard about SOLID principles, but applying them to a web app was a mystery.

在作为PHP程序员发展的某个时候,我是在不了解详细内容的情况下按书构建MVC应用程序的。 我被告知:胖模型,瘦控制器。 不要在您的观点中加入逻辑。 我不了解的是如何创建一个具有凝聚力的应用程序结构,该结构使我可以将我的业务想法表达为可维护的代码,也不了解如何将我的关注点真正分成紧密的层,而又不会将低级逻辑泄漏到高层。 我听说过SOLID原理,但是将其应用于Web应用程序是一个谜。

In this series, we’ll build a quiz application using these concepts. We’ll separate the application into layers, allowing us to substitute components: for example, it’ll be a breeze to switch from MongoDB to MySQL, or from a web interface to a command-line interface.

在本系列中,我们将使用这些概念来构建测验应用程序。 我们将应用程序分成几层,从而允许我们替换组件:例如,从MongoDB切换到MySQL,或从Web界面切换到命令行界面,都非常容易。

为什么MVC不够用: (Why MVC Isn’t Enough:)

MVC, which stands for Model-View-Controller, is a powerful design pattern for web applications. Unfortunately, with its rise to buzzword status, it has been taken out of context and used as a miracle cure. It’s become standard practice to use MVC frameworks, and many developers have succeeded in using them to seperate display logic and domain logic. The trouble is that developers stop there, building quasi-object-oriented systems at best and procedural code wrapped in classes–often controllers–at worst.

MVC代表模型-视图-控制器,是一种针对Web应用程序的强大设计模式。 不幸的是,随着它成为流行语 ,它已脱离上下文而被用作奇迹疗法。 使用MVC框架已成为标准做法,许多开发人员已成功使用它们来分离显示逻辑和域逻辑。 问题在于,开发人员会停在那里,最好是构建准面向对象的系统,而最坏的情况是将过程代码包装在类(通常是控制器)中。

In building our quiz app, we’ll be using the Domain Model pattern described in Martin Fowler’s Patterns of Enterprise Application Architecture. Domain Model is just a fancy way of saying that we’ll be using an object-oriented approach to designing the system: a web of objects with different responsibilities that as a whole, will comprise our application.

在构建测验应用程序时,我们将使用Martin Fowler的Enterprise Application Architecture模式中描述的Domain Model模式。 域模型只是一种奇特的说法,我们将使用面向对象的方法来设计系统:一个具有不同职责的对象网络,总体上将构成我们的应用程序。

The Domain Model approach uses “entity” objects to represent information in the database; but instead of having our object-oriented code mimic the database, we’ll have the database mimic our object-oriented design. Why? Because it allows us to build good object-oriented code. This mapping, called Object-Relational Mapping, is a large subject, and outside of the scope of this article. Luckily, there are several mature libraries available in PHP that solve this problem. The most mature of these, and my personal favorite, is Doctrine. We’ll be side-stepping the issue entirely by manually writing the specific mapping code we need for this article.

域模型方法使用“实体”对象来表示数据库中的信息。 但是我们不用让我们的面向对象的代码模仿数据库,而是让数据库模仿我们的面向对象的设计。 为什么? 因为它允许我们构建良好的面向对象的代码。 此映射称为对象关系映射,是一个很大的主题,不在本文讨论范围之内。 幸运的是,PHP提供了一些成熟的库来解决此问题。 其中最成熟的,也是我个人最喜欢的是教义 。 我们将通过手动编写本文所需的特定映射代码来完全避免该问题。

Even when using the Domain Model pattern, there is still the problem of performing operations that require multiple classes to work together. We’ll be solving this with the Service Layer pattern.

即使使用域模型模式,仍然存在执行需要多个类一起工作的操作的问题。 我们将使用“服务层”模式解决此问题。

服务层模式: (The Service Layer Pattern:)

Correct object-oriented design dictates that you should write decoupled code. Each class should have a single responsiblity. How, then, do we combine these independent classes to perform our business logic?

正确的面向对象设计要求您应该编写解耦的代码。 每个班级应该有一个责任。 那么,我们如何结合这些独立的类来执行业务逻辑呢?

The Service Layer pattern addresses this problem. We group all our system’s operations (signing up, purchasing a product, solving a quiz) into service classes, one service per operation or group of closely-related operations. We decouple these service classes from the classes to which they delegate. This allows us to reuse the services between different use-cases, say the web interface and the CLI interface, the front- and back-end interfaces, and so on.

服务层模式解决了这个问题。 我们将系统的所有操作(注册,购买产品,解决测验)分组为服务类,每个操作一个服务或一组紧密相关的操作。 我们将这些服务类从它们委托的类中分离出来。 这使我们能够在不同用例之间重用服务,例如Web界面和CLI界面,前端和后端界面,等等。

入门: (Getting Started:)

We’ll be using Slim as our MVC framework. Slim is a light-weight framework that’s easy to learn, and perfect for our simple app. As you’ll see in the next article, when we write controller code, it’ll be easy for you to replace Slim with any framework you prefer. We’ll install Slim with Composer. Create a directory for the project with the following composer.json file:

我们将使用Slim作为我们的MVC框架。 Slim是一个轻量级的框架,易于学习,非常适合我们的简单应用程序。 正如您将在下一篇文章中看到的那样,当我们编写控制器代码时,很容易将Slim替换为您喜欢的任何框架。 我们将在Composer中安装Slim。 使用以下composer.json文件为项目创建目录:

{ "require": { "slim/slim": "2.*" } "autoload": { "psr-O": {"QuizApp\\": "./lib/"} } }

编码服务类别: (Coding the Service Class:)

We’ll need a service for handling the quiz flow: choosing a quiz, checking the user’s answers, and so on. This service will contain the bulk of the business logic of the application. The rest of the code will solve more technical, specific problems, such as accessing the database.

我们需要一种服务来处理测验流程:选择测验,检查用户的答案等等。 该服务将包含应用程序的大部分业务逻辑。 其余代码将解决更多技术性的特定问题,例如访问数据库。

Let’s define an interface for the service. Create a file lib/QuizApp/service/QuizInterface.php with the following contents:

让我们为服务定义一个接口。 使用以下内容创建文件lib/QuizApp/service/QuizInterface.php :

<?php namespace QuizApp\Service; interface QuizInterface { /** @return Quiz[] */ public function showAllQuizes(); public function startQuiz($quizOrId); /** @return Question */ public function getQuestion(); /** @return bool */ public function checkSolution($id); /** @return bool */ public function isOver(); /** @return Result */ public function getResult(); }

Most of the operations should speak for themselves, but getQuestion() and getResult() might not be so clear. getQuestion() returns the next question for the user to answer. getResult() returns an object with information about the number of correct and incorrect answers, and whether the user passed the quiz.

大多数操作都可以说明一切,但是getQuestion()和getResult()可能不太清楚。 getQuestion()返回下一个问题供用户回答。 getResult()返回一个对象,该对象包含有关正确和不正确答案的数量以及用户是否通过了测验的信息。

Before we implement this service, we should define the mapper interface, as the service will need to use it. The service needs two operations: find() which returns a single quiz by ID, and findAll().

在实现此服务之前,我们应定义映射器接口,因为该服务将需要使用它。 该服务需要两个操作: find()通过ID返回单个测验;以及findAll() 。

<?php namespace QuizApp\Mapper; interface QuizInterface { /** @return \QuizApp\Entity\Quiz[] */ public function findAll(); /** * @param int $i * @return \QuizApp\Entity\Quiz */ public function find($i); }

These operations return objects of the class \QuizApp\Entity\Quiz, which represents a single quiz. The Quiz class, in turn, contains \QuizApp\Entity\Question objects, which represent quiz questions. Let’s implement these before returning to the service.

这些操作返回\QuizApp\Entity\Quiz类的对象,该对象表示单个测验。 反过来, Quiz类包含\QuizApp\Entity\Question对象,它们表示测验问题。 让我们在返回服务之前实现这些。

<?php namespace QuizApp\Entity; class Question { private $id; private $questions; private $solutions; private $correctIndex; /** * @param string $question * @param string[] $solutions * @param int $correctSolutionIndex */ public function __construct ($question, array $solutions, $correctSolutionIndex) { $this->question = $question; $this->solutions = $solutions; $this->correctIndex = $correctSolutionIndex; if (!isset($this->solutions[$this->correctIndex])) { throw new \InvalidArgumentException('Invalid index'); } } public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } public function getQuestion() { return $this->question; } public function getSolutions() { return $this->solutions; } public function getCorrectSolution() { return $this->solutions[$this->correctIndex]; } public function isCorrect($solutionId) { return $this->correctIndex == $solutionId; } }

Notice that, in addition to its getters and setters, \QuizApp\Entity\Question has a method isCorrect() for checking if a certain answer to the question is correct.

请注意,除了其getter和setter方法之外, \QuizApp\Entity\Question还具有isCorrect()方法,用于检查对该问题的某个答案是否正确。

And the \QuizApp\Entity\Quiz class:

和\QuizApp\Entity\Quiz类:

<?php namespace QuizApp\Entity; class Quiz { private $id; private $title; private $questions; /** * @param string $title * @param Question[] $questions */ public function __construct($title, array $questions) { $this->title = $title; $this->questions = $questions; } public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } public function getTitle() { return $this->title; } public function getQuestions() { return $this->questions; } }

And the \QuizApp\Service\Quiz\Result class:

和\QuizApp\Service\Quiz\Result类:

<?php namespace QuizApp\Service\Quiz; class Result { private $correct; private $incorrect; private $passScore; public function __construct($correct, $incorrect, $passScore) { $this->correct = $correct; $this->incorrect = $incorrect; $this->passScore = $passScore; } public function getCorrect() { return $this->correct; } public function getIncorrect() { return $this->incorrect; } public function getTotal() { return $this->correct + $this->incorrect; } public function getPassScore() { return $this->passScore; } public function hasPassed() { return $this->correct >= $this->passScore; } }

编写占位符映射器: (Writing a Placeholder Mapper:)

We need a concrete \QuizApp\MapperMapper\MapperInterface class for the service to use. Let’s define a dummy implementation for the time being, so that we can test the code, before writing a real mapper that’ll access the MongoDB database. The dummy uses hard-coded ‘\QuizApp\Entity\Question’ objects to return from the find($id) and findAll() methods.

我们需要一个具体的\QuizApp\MapperMapper\MapperInterface类供服务使用。 让我们暂时定义一个虚拟实现,以便我们可以在编写将访问MongoDB数据库的真实映射器之前测试代码。 假人使用硬编码的'\ QuizApp \ Entity \ Question'对象从find($id)和findAll()方法返回。

<?php namespace QuizApp\Mapper; class Hardcoded implements QuizInterface { private static $MAP = array(); /** @return \QuizApp\Entity\Quiz[] */ public function findAll() { return [ $this->find(0), $this->find(1) ]; } /** * @param int $id * @return \QuizApp\Entity\Quiz */ public function find($id) { if (isset (self::$MAP[$id])) { return self::$MAP[$id]; } $result = new \QuizApp\Entity\Quiz( 'Quiz' . $id, [ new \QuizApp\Entity\Question( 'What colour was George Washington\'s white horse?', [ 'White', 'Gray', 'Yellow', 'All of the above' ], 0 ), new \QuizApp\Entity\Question( 'Who\'s buried in Grant\'s tomb?', [ 'Grant', 'George Washington', 'George Washingtion\'s horse', 'All of the above' ], 0 ), ] ); $result->setId($id); self::$MAP[$id] = $result; return $result; } }

The class implements the interface by returning a couple of hard-coded Quiz objects. It uses the $MAP static property as an Identity Map to ensure the class returns the same objects each time it’s called.

该类通过返回几个硬编码的Quiz对象来实现该接口。 它使用$MAP静态属性作为Identity Map,以确保每次调用该类时都返回相同的对象。

结论: (Conclusion:)

In this first part of our Pratical OOP series we began developing our quiz application. We discussed MVC and why it is not a silver bullet; we covered the Domain Model and Service Layer design patterns; we sketched out the interface for our quiz service, which will contain the logic behind a user solving a quiz; we modeled the quizes and questions as entities; and we created a dummy mapper for looking up quizzes from the “database,” which will come in handy in part two.

在我们的实用OOP系列的第一部分中,我们开始开发测验应用程序。 我们讨论了MVC以及为什么它不是灵丹妙药。 我们介绍了域模型和服务层设计模式; 我们为测验服务草拟了界面,其中将包含用户解决测验的逻辑。 我们将测验和问题建模为实体; 我们创建了一个虚拟映射器,用于从“数据库”中查找测验,这将在第二部分中派上用场。

Stay tuned! Next time we’ll be be fleshing out our application, writing the service class, and a real database mapper that will connect to MongoDB. Once we have that in place, you’ll see how easy it is to write our controllers and views, and how our elegant design keeps the “M,” the “V,” and the “C” separate, maintainable, and extensible. You can find the full source code for this part here.

敬请关注! 下次,我们将充实我们的应用程序,编写服务类,以及将连接到MongoDB的真实数据库映射器。 一旦我们准备好了,您将看到编写我们的控制器和视图有多么容易,以及我们优雅的设计如何使“ M”,“ V”和“ C”保持独立,可维护和可扩展。 您可以在此处找到此部分的完整源代码。

翻译自: https://www.sitepoint.com/practical-oop-building-quiz-app-bootstrapping/

java oop 测试题

相关资源:javaOOP测试模拟试题
最新回复(0)