- Modular Programming with PHP 7
- Branko Ajzele
- 442字
- 2021-07-14 10:06:00
Single responsibility principle
The single responsibility principle deals with classes that try to do too much. The responsibility in this context refers to reason to change. As per the Robert C. Martin definition:
"A class should have only one reason to change."
The following is an example of a class that violates the SRP:
class Ticket { const SEVERITY_LOW = 'low'; const SEVERITY_HIGH = 'high'; // ... protected $title; protected $severity; protected $status; protected $conn; public function __construct(\PDO $conn) { $this->conn = $conn; } public function setTitle($title) { $this->title = $title; } public function setSeverity($severity) { $this->severity = $severity; } public function setStatus($status) { $this->status = $status; } private function validate() { // Implementation... } public function save() { if ($this->validate()) { // Implementation... } } } // Client $conn = new PDO(/* ... */); $ticket = new Ticket($conn); $ticket->setTitle('Checkout not working!'); $ticket->setStatus(Ticket::STATUS_OPEN); $ticket->setSeverity(Ticket::SEVERITY_HIGH); $ticket->save();
The Ticket
class deals with validation and saving of the ticket
entity to the database. These two responsibilities are its two reasons to change. Whenever the requirements change regarding the ticket validation, or regarding the saving of the ticket, the Ticket
class will have to be modified. To address the SRP violation here, we can use the assisting classes and interfaces to split the responsibilities.
The following is an example of refactored implementation, which complies with SRP:
interface KeyValuePersistentMembers { public function toArray(); } class Ticket implements KeyValuePersistentMembers { const STATUS_OPEN = 'open'; const SEVERITY_HIGH = 'high'; //... protected $title; protected $severity; protected $status; public function setTitle($title) { $this->title = $title; } public function setSeverity($severity) { $this->severity = $severity; } public function setStatus($status) { $this->status = $status; } public function toArray() { // Implementation... } } class EntityManager { protected $conn; public function __construct(\PDO $conn) { $this->conn = $conn; } public function save(KeyValuePersistentMembers $entity) { // Implementation... } } class Validator { public function validate(KeyValuePersistentMembers $entity) { // Implementation... } } // Client $conn = new PDO(/* ... */); $ticket = new Ticket(); $ticket->setTitle('Payment not working!'); $ticket->setStatus(Ticket::STATUS_OPEN); $ticket->setSeverity(Ticket::SEVERITY_HIGH); $validator = new Validator(); if ($validator->validate($ticket)) { $entityManager = new EntityManager($conn); $entityManager->save($ticket); }
Here we introduced a simple KeyValuePersistentMembers
interface with a single toArray
method, which is then used with both EntityManager
and Validator
classes, both of which take on a single responsibility now. The Ticket
class became a simple data holding model, whereas client now controls instantiation, validation, and save as three different steps. While this is certainly no universal formula of how to separate responsibilities, it does provide a simple and clear example of how to approach it.
Designing with the single responsibilities principle in mind yields smaller classes with greater readability and easier to test code.
- Extending Jenkins
- Node.js 10實戰(zhàn)
- 機器學習系統(tǒng):設(shè)計和實現(xiàn)
- ASP.NET Core 5.0開發(fā)入門與實戰(zhàn)
- Java入門很輕松(微課超值版)
- JavaScript 網(wǎng)頁編程從入門到精通 (清華社"視頻大講堂"大系·網(wǎng)絡(luò)開發(fā)視頻大講堂)
- Python GUI Programming Cookbook
- Java持續(xù)交付
- AutoCAD VBA參數(shù)化繪圖程序開發(fā)與實戰(zhàn)編碼
- 深入分布式緩存:從原理到實踐
- Mastering Android Game Development
- 算法設(shè)計與分析:基于C++編程語言的描述
- 進入IT企業(yè)必讀的324個Java面試題
- Java Web開發(fā)教程:基于Struts2+Hibernate+Spring
- Visual C++網(wǎng)絡(luò)編程教程(Visual Studio 2010平臺)