30/09/2018, 16:40

Refactor a big class

Em có 1 class lớn như thế này chuyên để gửi HTTP request.
Hướng nào là tốt nhất để group những hàm liên quan lại với nhau thành 1 class (số lượng endpoint có thể lên đến vài trăm)

https://github.com/daynhauhoc/sync-wiki/blob/master/app/Api/Discourse/Discourse.php

@laptrinhio

Lập Trình Sư viết 18:48 ngày 30/09/2018

Nôm na abc thì có thể làm thế này

interface CurlInterface {
	
	function get($reqString, $paramArray = null, $apiUser = 'system');

	function post($reqString, $paramArray, $apiUser = 'system'); // thêm cái param cuối xác định là PUT cũng được

	function put($reqString, $paramArray, $apiUser = 'system');
}

class Curl implements CurlInterface {
	
	// mấy hàm trong DiscourseCurl, tương ứng với CurlInteface ở trên
}

interface DiscourseApiInterface {
	
	public function group($groupname, $usernames = array());

	public function getGroups();

	public function createUser($name, $userName, $emailAddress, $password);

	public function activateUser($userId);

	public function getUsernameByEmail($email);

	public function getUserByUsername($userName);

	public function createCategory($categoryName, $color, $textColor = '000000', $userName = 'system');

	public function createTopic($topicTitle, $bodyText, $categoryId, $userName, $replyToId = 0);

	public function createPost($bodyText, $topicId, $categoryId, $userName);

	public function editPost($postId, $bodyText, $editReason = '');

	public function inviteUser($email, $topicId, $userName = 'system');

	public function changeSiteSetting($siteSetting, $value);
}

class DiscourseCurl extends Curl implements DiscourseApiInterface {
	
	// đẩy code vô 
}

sau đó nếu có service khác ko phải Discource thì cứ tương thôi

interface WhateverApiInterface {
	// interface của cái củ riêng mà Whatever nó support
}

class WhateverCurl extends Curl implements WhateverApiInterface {
	// đẩy code vô	
}

Tạo ra ServiceProvider rồi bind

$this->app->bind('\path\to\DiscourseApiInterface', function () {
	return new \path\to\DiscourseCurl; // chỗ này bind config API key rồi gì gì trong constructor luôn cũng được.
});

$this->app->bind('\path\to\DiscourseApiInterface', function () {
	return new \path\to\WhateverCurl;
});
Khoa Nguyen viết 18:52 ngày 30/09/2018

class WhateverCurl extends Curl implements WhateverApiInterface {
// đẩy code vô
}

Nhưng như vậy thì class lớn nhất là DiscourseAPI vẫn như vậy ? Chỉ có thể interface để dễ đọc hơn thôi. Cái Curl em định thay bằng Guzzle nên mới tách ra như vậy.

Có cách nào mà nó thế này:

$discourseApi->topic->create($param, $param2)

Em định dựng 1 Discourse API hoàn chỉnh theo từng route của nó rồi sau đó thêm 1 cái wrapper của App để thực hiện mấy cái riêng dành cho App

Lập Trình Sư viết 18:46 ngày 30/09/2018

Nhưng như vậy thì class lớn nhất là DiscourseAPI vẫn như vậy ? Chỉ có thể interface để dễ đọc hơn thôi. Cái Curl em định thay bằng Guzzle nên mới tách ra như vậy.

class DiscourseObject {
	protected $url;

	public function __construct($url) {
		$this->url = $url;
	}
}

interface DiscourseGroupInterface {

	public function group($groupname, $usernames = array());

	public function getGroups();
}

class DiscourseGroup extends DiscourseObject implements DiscourseGroupInterface {

	protected $curl; // ko dùng DI thì Trait cũng được

	public function __construct($curl) {
		parent::__construct('/admin/groups/');
		$this->curl = $curl;
	}

	public function group($groupname, $usernames = array()) {

		// loằng ngoằng
		$this->curl->get($reqString, $paramArray = null, $apiUser = 'system');
	}	

	// đổ nốt
}

class DiscourseApi implements DiscourseApiInterface {
	
	protected $group;

	public function __construct(DiscourseGroupInterface $group) {
		$this->group = $group;
	}

	public function group($groupname, $usernames = array()) {
		return $this->group->group($groupname, $usernames);
	}

	// tương tự các củ khác, Topic, User, Post, Category
}

Nốt lại tương ServiceProvider bind các interface.

Thay cục Curl bằng cục Guzzle, thích abstract nữa thì lại interface

Khoa Nguyen viết 18:49 ngày 30/09/2018

Thay cục Curl bằng cục Guzzle, thích abstract nữa thì lại interface

Yeah. Em đã hiểu . Mình abstract luôn cái Curl, Guzzle thành 1 cái như là DiscourseHttp rồi bind nó vào

Anh xem qua cái prototype về quy trình get link này xem có ổn ?
https://github.com/daynhauhoc/sync-wiki/blob/master/app/Http/Controllers/WelcomeController.php

Lập Trình Sư viết 18:56 ngày 30/09/2018

quy trình thì chắc ko vấn đề, còn logic trong Controller này thì đẩy vào Bus.

Khoa Nguyen viết 18:53 ngày 30/09/2018

Ok. So far so good
https://github.com/daynhauhoc/sync-wiki/tree/master/app/Api/Discourse

Đã refactor xong (còn 1 số method nhỏ để đó từ từ làm tiếp).

Em có 1 chỗ bí phải dùng facade của Laravel.
https://github.com/daynhauhoc/sync-wiki/blob/master/app/Api/Discourse/Objects/DiscourseObjects.php#L15

Nếu không dùng Facade thì phải làm sao ?

Bài liên quan
0