admin管理员组文章数量:1391947
I am working on a web application that will make extensive use of AJAX techniques for client/server munication...JSON-RPC specifically. Zend Framework is being used server-side, and it offers a nice JSON-RPC server that I would like to use.
My goal is to architect a maintainable system that exposes a large subset of server-side functionality to the client-side (javascript), without unnecessary code duplication. I've seen numerous blog posts and tutorials on how to use ZF's JSON-RPC server (see here and here), but they all seemed geared towards exposing a small, publicly consumable API. Code duplication is mon, for example one blog post has the following method exposed:
public static function setTitle($bookId, $title) {
$book = new Nickel_Model_Book($bookId);
$book->setTitle($title);
$book->update();
return true;
}
I don't like the fact that there are two setTitle
methods. If the method signature for one changes, the other has to be kept in sync...seems like a maintainability nightmare if your API is extensive. It seems to me that there should be one Book
class, with one setTitle
method.
My initial thought is add a docblock annotation @export
to methods/classes that I want exposed. When I decide to expose the setTitle
method, I just add the annotation rather than a new method.
One potential problem I see involves object persistence. Server-side, it makes sense for setTitle
to set the object's title property...but not persist it in the database until update()
is called. Client-side, calling setTitle
should immediately affect the database. One potential solution is to modify all accessors such that they take a optional second parameter signifying the modification should update the database immediately:
function setTitle($title, $persist = false) {
$this->title = $title;
if ($persist) $this->update();
}
Some sort of proxy class could ensure that the $persist
flag is set for all client-side RPC invocations.
Another problem is the serialization of PHP objects. Server-side, it makes sense to do a OO-style $book->setTitle("foo")
call, but client-side book.setTitle(1234, "foo")
makes sense (where 1234 is the book's ID) due to the lack of state. My solution for this would be to have the aforementioned proxy class be responsible for somehow turning book.setTitle(1234, "foo")
into:
$book = new Book();
$book->load(1234);
return $book->setTitle($title);
I feel like this problem must have been tackled or discussed before...but I'm not finding many resources online. Does this seem like a sane solution?
I am working on a web application that will make extensive use of AJAX techniques for client/server munication...JSON-RPC specifically. Zend Framework is being used server-side, and it offers a nice JSON-RPC server that I would like to use.
My goal is to architect a maintainable system that exposes a large subset of server-side functionality to the client-side (javascript), without unnecessary code duplication. I've seen numerous blog posts and tutorials on how to use ZF's JSON-RPC server (see here and here), but they all seemed geared towards exposing a small, publicly consumable API. Code duplication is mon, for example one blog post has the following method exposed:
public static function setTitle($bookId, $title) {
$book = new Nickel_Model_Book($bookId);
$book->setTitle($title);
$book->update();
return true;
}
I don't like the fact that there are two setTitle
methods. If the method signature for one changes, the other has to be kept in sync...seems like a maintainability nightmare if your API is extensive. It seems to me that there should be one Book
class, with one setTitle
method.
My initial thought is add a docblock annotation @export
to methods/classes that I want exposed. When I decide to expose the setTitle
method, I just add the annotation rather than a new method.
One potential problem I see involves object persistence. Server-side, it makes sense for setTitle
to set the object's title property...but not persist it in the database until update()
is called. Client-side, calling setTitle
should immediately affect the database. One potential solution is to modify all accessors such that they take a optional second parameter signifying the modification should update the database immediately:
function setTitle($title, $persist = false) {
$this->title = $title;
if ($persist) $this->update();
}
Some sort of proxy class could ensure that the $persist
flag is set for all client-side RPC invocations.
Another problem is the serialization of PHP objects. Server-side, it makes sense to do a OO-style $book->setTitle("foo")
call, but client-side book.setTitle(1234, "foo")
makes sense (where 1234 is the book's ID) due to the lack of state. My solution for this would be to have the aforementioned proxy class be responsible for somehow turning book.setTitle(1234, "foo")
into:
$book = new Book();
$book->load(1234);
return $book->setTitle($title);
I feel like this problem must have been tackled or discussed before...but I'm not finding many resources online. Does this seem like a sane solution?
Share Improve this question asked Nov 22, 2010 at 18:40 Josh JohnsonJosh Johnson 9,4424 gold badges26 silver badges32 bronze badges 4- 1 Did you solve this problem or does it still exist? Could you post your solution or delete the question or tell us to start thinking! – markus Commented Mar 20, 2011 at 14:49
- 4 Sometimes when a pattern for something you think should exist doesn't, it is because you are envisioning an incorrect solution. The reason you don't want to just expose large amounts of methods as a webservice is because the client should get as course grained methods as possible. Your service design should emerge from client-side needs. A client should have access to an ideally simple interface. Create course grained services, and make them finer grained as positions require. A separation from a public api and your library is worth the extra effort. – JeremyWeir Commented Jun 7, 2011 at 5:52
- I am tackling this exact problem with nowjs. and expressjs. – James Andino Commented Aug 23, 2011 at 6:22
- If I understand well : you want to get rid of the controller , and instead call your model directly with your view. no ? – remi bourgarel Commented Sep 14, 2011 at 9:23
3 Answers
Reset to default 3What you're looking for is called Service Layer.
Their entities should be purely data containers (unless you're using Active Record), you should only expose your service layer, and this in turn accesses their entities and their respective methods.
Your class of service would be something like this:
class BookService extends Service {
//...
public function changeBookTitle( $title, Book $book )
{
//verify if the $title is correct and valid
$book->setTitle( $title );
$this->methodToGetThePersistenceManager()->save( $book );
//fire events, create a result object, etc...
}
}
I was mulling over your question for a few minutes. If you want to try, and it's in PHP, you could make some magic methods of the form
set{Property}of{Object}.
You can do this through the magic __call method.
That way you wouldn't have to explicitly define the methods but the properties would still get set.
The magic method would identify which type of object it has to instantiate and which property to set on it and then persist.
You'd have to find some way of differentiating between remote calls and local calls though so you don't persist by mistake if you're making local library calls and that you do persist on remote calls.
I feel like I misunderstood your question somehow but I tried.
Well,
What you are wanting to do sounds really good on paper, and you want code to be maintainable, and depending on your actual system, what you ask may even be somewhat safe, however it's getting close to being dangerous and error prone.
Anyway, you would probably have to do most of this yourself, or just insert some sort of interceptor to all method calls, here's a quick example:
class Book {
public $title = '';
public $id = 0;
public function setTitle($string) {
$this->title = $string;
echo "title called with $string\n";
}
public function twoArgs($arg1,$arg2) {
echo "Multi-call: $arg1,$arg2\n";
}
}
class Api {
public function parse($json) {
$jsonobj = json_decode($json,true);
foreach ($jsonobj as $key=>$value) {
$class_name = $key;
$obj = new $class_name();
foreach ($value as $vkey=>$vvalue) {
if (method_exists($obj,$vkey)) {
call_user_func_array(array($obj,$vkey),$vvalue);
} else if (isset($obj->$vkey)) {
echo "Setting $vkey\n";
$obj->$vkey = $vvalue;
}
}
}
}
}
$json = json_encode(array('Book' => array('id' => 1234, 'setTitle' => array('The new title'))));
$api = new Api();
$api->parse($json);
$json = json_encode(array('Book' => array('id' => 1234, 'twoArgs' => array('arg1 :) ', 'arg2 :]'))));
$api->parse($json);
Obviously you'd want to add in logic to handle persist flagging, and loading or allow them to pass in a constructor: [args] and handle that. etc. When it es to exposing functions, you expose them in documentation, they are all accessible as long as they are public functions from that point on etc.
本文标签: javascriptdeveloping a maintainable RPC systemStack Overflow
版权声明:本文标题:javascript - developing a maintainable RPC system - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744675678a2619093.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论