問題描述
我最近介紹服務層由 Jani Hartikainen 在關于如何最好地處理 MVC 應用程序中的表單數據的討論中提供.在 做一些閱讀之后 我真的可以看到這種方法的好處.我的問題是:
I was recently introduced to service layers by Jani Hartikainen in a discussion about how to best handle form data in a MVC app. After doing some reading I can really see the benefits of this approach. My question is this:
服務類應該如何構建?
- 首先,
user_service()
是適合我的user()
模型的類名還是其他標準? - 由于我的服務中的方法只會執行一項任務,認為這些方法始終可以是
靜態函數
是否正確?服務類不代表數據,而是一系列動作,所以這似乎很合適. - 服務方法是否應該只接受一個
argument
,也就是一個array
?
- First, is
user_service()
an appropriate class name for myuser()
model or is there another standard? - Since the methods in my service will only be doing one task, is it correct to think that these can always be a
static function
? A service class isn't representing data, but rather is a series a actions, so this seems appropriate. - Should a service method only accept one
argument
, which would be anarray
?
假設表單已將數據發布到控制器以保存用戶數據:
<?php
class form_controller extends controller
{
public function process_submit()
{
if(user_service::update_preferences($_POST))
{
echo json_encode(array('success' => true));
}
else
{
echo json_encode(array('success' => false));
}
}
}
class user_service
{
// Accepts array()
public static function update_preferences($fields)
{
// Check for required fields
if((
isset($fields['firstname']) and
isset($fields['lastname']) and
isset($fields['email'])
) == false
{
return false;
}
// Update user
try
{
$s = new user();
$s->set_firstname($fields['firstname']);
$s->set_lastname($fields['lastname']);
$s->set_email($fields['email']);
$s->update();
return true;
}
catch(Exception $e)
{
return false;
}
}
}
我覺得這是一個很好的方法,因為:
- 我可以在表單中添加另一個字段,而不必更新
controller
,只需更新service
.控制器不應該關心正在傳遞什么數據,這似乎是正確的,只要它被傳遞.這使我的控制器和模型中的邏輯保持較小. - 如果我沒有傳遞
array
,我可以設置帶有多個參數的函數.例如,我的函數可以是update_preferences($firstname, $lastname, $email)
.然而,這可能會導致具有超過 20 個參數的函數(對于大型形式),并且順序會變得很糟糕. - 我可以傳遞一個
object
,但這有意義嗎?如果我正在創建一個對象,它應該是它代表的對象(在這種情況下是用戶),對嗎?但是控制器實例化用戶對象有意義嗎?這不就是服務層的全部意義所在嗎? - 也許有些方法具有多個參數(當只有一到三個時)和一些接受數組的方法(當有很多字段時)存在爭議.這似乎是一場噩夢,因為您總是必須引用該類才能知道該特定方法要求什么.
- I can add another field to my form and I won't have to update the
controller
, just theservice
. It seems right that the controller shouldn't be concerned about what data is being passed, just that it is passed. This keeps my controller small, and the logic in my models. - If I didn't pass an
array
, I could setup functions with multiple arguments. For example my function could beupdate_preferences($firstname, $lastname, $email)
. This however could make for functions with upwards of 20 arguments (for large forms), and the order would just become terrible to work with. - I could pass an
object
, but does that make sense? If I'm creating an object, it should the be the object it represents (the user in this case) right? But does it make sense that the controller instantiates the user object? Isn't that the whole point of the service layer in the first place? - Maybe there is an argument for having some methods with multiple arguments (when there are just one to three) and some methods that accept an array (when there are lots of fields). This just seems like it could be a nightmare, as you would always have to reference the class to know what that particular method was asking for.
有人對在這里做的正確事情有意見嗎?我在正確的軌道上嗎?你過去做了什么?非常感謝!
Does anyone have an opinion on what the right thing to do here is? Am I on the right track? What have you done in the past? Thanks a lot!
推薦答案
既然你給我發了一封電子郵件,你也可以回答這個問題 ;)
Might as well answer this since you went as far as sending me an email ;)
首先,user_service() 是適合我的 user() 模型的類名還是有其他標準?
First, is user_service() an appropriate class name for my user() model or is there another standard?
這是可以接受的.但是,您應該使用已建立的 PHP 編碼約定之一,例如 PEAR 或 ZF 約定.在這兩種情況下,類名都是UpperCamelCase
,方法名是lowerCamelCase
.使用這個,類將是 User
和 UserService
That's acceptable. However, you should rather use one of the established PHP coding conventions, such as the PEAR or ZF conventions. In both cases, class names are UpperCamelCase
and method names lowerCamelCase
. Using this, the classes would be User
and UserService
由于我的服務中的方法只會執行一項任務,認為這些方法始終可以是靜態函數是否正確?服務類不代表數據,而是一系列動作,所以這似乎很合適.
Since the methods in my service will only be doing one task, is it correct to think that these can always be a static function? A service class isn't representing data, but rather is a series a actions, so this seems appropriate.
沒有.將方法設為靜態是一個糟糕的設計選擇 - 這適用于大多數代碼,而不僅僅是服務.對于服務而言,主要原因之一是您的服務通常需要與數據存儲或其他代表數據層(存儲庫、數據訪問對象等)的類進行交互.
No. It's a poor design choice to make methods static - and this applies to most code, not just services. One of the main reasons in case of a service would be that generally your service needs to interact with a data store or another class which represents the data layer (repository, data access object, whatever).
當您的服務具有靜態方法時,這意味著您需要在方法中實例化您的依賴項.這反過來意味著,除其他外,代碼變得難以測試,因為您無法輕松替換依賴項.
When your service has static methods, this means you would need to instanciate your dependencies in your methods. This in turn means that, amongst other things, the code becomes hard to test, as you can't easily replace the dependencies.
對此有一些很好的閱讀,例如 here(事實上,該博客上的幾乎所有內容都適合軟件開發人員閱讀)
There's some good reading on this for example here (In fact nearly everything on that blog is good reading for software devs)
服務方法是否應該只接受一個參數,即數組?
Should a service method only accept one argument, which would be an array?
這取決于方法的作用.假設您處理表單結果集的示例,那么是的,這可能會起作用.在其他一些情況下,這可能是一個糟糕的選擇.
This is dependent on what the method does. Assuming your example of processing a form's resultset, then yes this will probably work. In some other case it might be a poor choice.
我可以在表單中添加另一個字段,而不必更新控制器,只需更新服務.[...]
I can add another field to my form and I won't have to update the controller, just the service. [ ... ]
如果我不傳遞數組,我可以設置帶有多個參數的函數.[...]
If I didn't pass an array, I could setup functions with multiple arguments. [ ... ]
是的,在我看來,您對這兩個案例的論證非常適合這個用例.
Yep, your argumentation for these two cases is pretty much spot on for this use-case in my opinion.
我可以傳遞一個對象,但這有意義嗎?如果我正在創建一個對象,它應該是它代表的對象(在這種情況下是用戶),對嗎?但是控制器實例化用戶對象有意義嗎?這不正是服務層的全部意義所在嗎?
I could pass an object, but does that make sense? If I'm creating an object, it should the be the object it represents (the user in this case) right? But does it make sense that the controller instantiates the user object? Isn't that the whole point of the service layer in the first place?
這取決于.例如,如果您使用的框架允許您將表單表示為對象(例如 Zend 框架和 Zend_Form),您可以考慮將表單對象直接傳遞給服務.
This depends. For example, if you were using a framework which lets you represent forms as objects (such as the Zend Framework and Zend_Form), you could consider passing the form object straight to the service.
也許有些方法有多個參數(當只有一到三個時)和一些接受數組的方法(當有很多字段時).這似乎是一場噩夢,因為您總是必須引用該類才能知道該特定方法要求什么.
Maybe there is an argument for having some methods with multiple arguments (when there are just one to three) and some methods that accept an array (when there are lots of fields). This just seems like it could be a nightmare, as you would always have to reference the class to know what that particular method was asking for.
您通常應該根據方法的名稱使參數至少能猜到一半.在我從事的工作中,我們有一個模型,其中包含企業和產品等,企業可以在其中贊助產品.在 ProductService
中,我們有一個名為 sponsorProduct
的方法,它以業務和產品為參數.您幾乎可以猜到需要這兩個(如果您熟悉代碼庫)
You should usually aim to make the parameters at least half-guessable based on the method's name. In something I work on, we have a model which has for example businesses and products, where a business can sponsor a product. In a ProductService
, we have a method called sponsorProduct
which takes a business and a product as parameters. You can pretty much guess it would take these two (if you were familiar with the codebase anyway)
IDE 通常也可以幫助您解決這個問題 - 它們提供代碼輔助,顯示 params 函數采用的內容.這是我認為 IDE 在大型項目中非常有用的主要原因之一,因為您無法始終記住某個函數究竟需要什么作為參數.
IDE's generally help you with this too - they provide code-assist which displays what params functions take. This is one of the main reasons I think IDE's are very useful in larger projects where you can't always remember what exactly a certain function needs as parameters.
至于參數數量,我認為通常您應該嘗試使用單獨的參數.這使任何人都可以通過查看函數的簽名輕松了解需要哪些參數,并允許您非常輕松地定義類型提示和默認值.
As for parameter count, I think usually you should try to have separate parameters. This allows anyone to easily see what parameters are required by just looking at the function's signature, and allows you to define typehints and default values quite easily.
然而,當你得到如此多的參數時有一點是太多了.這可能在 +5 左右,這取決于它是哪種方法.在這種情況下,您可以考慮使用數組或稱為參數對象的東西,它本質上是一個包含調用所有參數的對象.更多關于參數對象的信息這里
However there is a point when you get so many parameters it's too much. This is maybe at +5 or so, depending a bit on what sort of method it is. In this case you can consider using an array, or something called a Parameter Object, which is essentially an object that contains all the parameters for the call. More on parameter objects here
這篇關于用 PHP 設計服務層類的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!