Thrift PHP singleton without locks? - php

I come from the C++ world.
And recently, I started using Apache Thrift, the RPC framework. I am writing PHP client code and Python server code.
When I am reading the PHP implementation, I find the following:
class TStringFuncFactory {
private static $_instance;
/**
* Get the Singleton instance of TStringFunc implementation that is
* compatible with the current system's mbstring.func_overload settings.
*
* #return TStringFunc
*/
public static function create() {
if(!self::$_instance) {
self::_setInstance();
}
return self::$_instance;
}
....
}
It is the singleton WITHOUT locks.
Question
What is the processing pattern of PHP? Does it guarantee that this won't happen risk condition.

+1 #N.B.
PHP (cli or http) exists as a single thread on a single cpu core unless you do some real work to make your application multithreaded.
How can one use multi threading in PHP applications
For the HTTP side, each PHP execution lives and dies with the request cycle. The server may process several requests concurrently, which would result in several concurrent PHP executions, but each is entirely independent from the next.
So basically this is a non-issue. For all intents and purposes checking the static data member satisfies the singleton pattern.

Related

I can't figure out how to PHPUnit test Ratchet/Sockets

Let me first confess that I absolutely am a novice in the field of TDD and unit tests. Currently, I am learning to work with TDD to advance myself in my career.
I am reprogramming a program I wrote a year ago using TDD. The program is not that complex. It listens to a websocket (Ratchet), receives information, parses the information, and sends messages through a message bus (RabbitMQ).
I am trying to approach this via TDD so I am starting to write my test first.
My listener class has 4 methods.
Connect (connects to the stream via Ratchet)
Listen (starts listening)
Parse (parses received information)
SendMessage (send a message to the RabbitMQ bus)
The problems I encounter while writing the test first.
How can I mock a Ratchet connection and assert that my function can "connect"
How can I assert that the information received matches my expectations
I find it really hard to find information on this specific subject and I understand that my question is broad. I do not expect a complete solution or answer but hopefully, the terminology to further investigate this subject and lectures/tutorials about writing tests for methods of this kind.
It's hard to argue without having seen any code. From your description it sounds like you have one class that does all the things. This may already be a reason that makes testing harder than it has to be.
When it comes to unit tests, I like to stick with Michael Feathers definition:
A test is not a unit test if:
it talks to the database.
it communicates across the network.
it touches the file system.
it can't run at the same time as any of your other unit tests.
you have to do special things to your environment (such as editing config files) to run it.
Mocking the Ratchet and RabbitMQ connections may seem like a way to make a test fit the above definition, but there is also this other phrase: "Don't mock what you don't own". Although it's not a hard rule, I think it's a pretty good guideline. There are a lot of articles on that topic. This should give you a good overview
Ratchet is a bit special with the server and event loop part, though. But it's well tested, so you don't have to do it. My suggestion: Keep the integration with Ratchet so thin, that there isn't much left to test anyway and just skip the test.
final class MyRatchetApp implements MessageComponentInterface
{
private MessageProcessor $processor;
public function __construct(MessageProcessor $processor)
{
$this->processor = $processor;
}
public function onMessage(ConnectionInterface $from, $msg)
{
$this->processor->handle($msg);
}
// ...
}
This leaves you with a MessageProcessor that you can test in isolation. All of its dependencies are types you own, so you can use mocks, stubs or fake implementations to test their interaction. This implementation is overly simplified and misses stuff like error handling that you certainly want to do and of course want to test.
final class MessageProcessor
{
private MessageParser $parser;
private MessageBroadcaster $broadcaster;
public function __construct(MessageParser $parser, MessageBroadcaster $broadcaster)
{
$this->parser = $parser;
$this->broadcaster = $broadcaster;
}
public function handle(string $rawMessage): void
{
$this->broadcaster->send($this->parser->parse($rawMessage));
}
}
interface MessageParser
{
/**
* #throws BadMessageException
*/
public function parse(string $message): Message;
}
interface MessageBroadcaster
{
/**
* #throws UnsupportedMessageException
* #throws UnroutableMessageException
*/
public function send(Message $message): void;
}
Creating an implementation of the MessageParser should be straightforward and easily unit testable. The RabbitMQ implementation of the MessageBroadcaster would be a perfect candidate for an integration test.
Finally, plug all the concrete implementations together for the real application.
$server = IoServer::factory(
new MyRatchetApp(
new MessageProcessor(
new CommandMessageParser(),
new RabbitMqMessageBroadcaster()
)
),
8080
);
To make sure all parts work together, you can create some end-to-end tests that perform full roundtrips and verify the results. Creating these tests first, allows you to do Double Loop TDD

Multithreading in PHP?

I am coming from java background which has rich threading framework. In the past , I kept hearing that PHP does not support threading.
But below code from this site creates the thread in PHP in almost same way as java does.
So what's the difference ?
<?php
class ChildThread extends Thread {
public $data;
public function run() {
/* Do some work */
$this->data = 'result';
}
}
$thread = new ChildThread();
Also I read below statements on google
Avoid the idea of running paralell tasks (threads or processes) in
PHP. It has some modules for this purpose, but they are not available
on every platform and are not part of the PHP core, so the chances for
you to be able to use them are very low.
This way wil not will work in every single environment
So My question above way of creating thread thread does not work on every platform(which platform for example) ? Does it mean there is no true
way of creating thread that works on all environment ?

Function Structure vs Unit Testing Private Function

I have a function, which someone else wrote, that creates a cURL wrapper object inside the function. Simplified version below
public function getCodes()
{
//do some stufff
$communicator = new Communicator();
$result = $communicator->call($this->API_KEY);
//do some stuff with $result
}
I was tasked with learning PHPUnit and writing tests for this type of code. In doing so I found that it's really hard to test a function like this when the object is created inside of the function and also that tests shouldn't require any outside communication to work.
We wanted to push our tests to git as many projects do but we didn't want to accidentally or intentionally push our API credentials to git.
So my solution was to keep getCodes() public but make it a wrapper for a private function that accepts a Communicator object as a parameter. Then I could test the private method with a mock Communicator object.
But this would mean that getCodes is never tested (my boss wants 100% code coverage) and I also read that you shouldn't be writing tests for private functions in most circumstances.
So my question is basically, how do I write a test for a function like this with an API call.
I would really suggest rewriting the code to inject the Communicator object via constructor.
If you already see there is a big issue with writing tests for something it is a very strong signal to re-thing the current implementation.
Another thing is that you shouldn't test your privates. Sebastian Bergmann wrote a post on his blog about this some time ago and the conclusion is - it is possible just not good (https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html).
Completely different thing is that I think your tests shouldn't go outside of the boundaries of your system. That is - mock everything that connects to outside systems. Such tests may fail for various of reasons non of witch are valid from the sole perspective of running tests.
You also mentioned coverage. Unfortunately this is something where, I hope, everyone will agree - you cannot have it the moment you start using native PHP resources (with some small exception like FS). You have to understand that things like curl, ssh, ftp and so on cannot be unit tested.

PHP - static classes and caching classes

The code below is how I used to cache objects in Java.
class Account{
private static ArrayList<Account> accounts = new ArrayList<Account>(); //Array that holds Account objects
private String username; //Unique Name or Username
public Account(String username) { // constructor
this.username = username;
Account.accounts.add(this); //Add object to accounts Array
}
public String getUsername() {
return this.username; // Return username
}
public Account getAccount(String username) { //Get object "Account" with username
for (Account acc: Account.accounts) { //Foreach loop that loop over all accounts from the Array
if (acc.getUsername() == username) return acc; // Return Account object if given username == object's username
}
return null;
}
}
I commented it so it will make sense if you don't understand Java but Java OOP is similar to PHP OOP.
From the Java code above I can hold all objects on an Array, So it doesn't query the Database all the time.
1) I'm wondering if I can do something similar with PHP to speed up code and cache classes. If this is possible can you please show me an example. If not what would be the best way to achieve this?
2) What are some good practices to use when object oriented programming to keep memory usage low?
Thanks in advance
The biggest difference between a Java app and a PHP app is that Java is typically a constantly running program handling several incoming connections at once, while PHP instances are started and torn down by the hosting web server for every single individual request. That means any class you load or object you instantiate or variable you assign only has a lifetime of a number of milliseconds (in a decently fast application). Static class properties work the same as in Java, however, the entire application is torn down after a few milliseconds, so this doesn't work as a long-term cache. And more importantly, each individual HTTP request is its own independent thread, so assigning something in one thread doesn't make it visible in any other simultaneous or subsequent threads.
To cache something cross-request, you need an external data store. For this you have many options, depending on what suites you best:
serialize to a file
APC
memcached
Redis
sessions (for per-user data storage)
many more

One time initialization for Application

I have a Java background. So please bear with me.
In a Java application, one way to perform one time initialization is to have an "Initializer Servlet" whose init() method can have one time initialization code. Another more general purpose mechanism is to have a Singleton that initializes on first use - and this mechanism will work in various languages / platforms. What I need to know is how to do it for my PHP webapp.
Should I use the Singleton Pattern? Is there another / better / PHP specific way? Essentially I want have a "Registry" - a single instance of it - which I can then use to create instances of other objects (themselves Singleton or not depends on situation at hand).
The ultimate goal is - I need certain things initialized BEFORE any web request is served by my PHP web application - something an "Initializer Servlet" in Java guarantees me. Maybe there is an "Initializer PHP Page" or something like that?
Thanks in advance
The source PHP, in the regular sense, does not generate an executable program. It is a scripting language. However, you are able to create a singleton.
PHP's nature will not allow you to have a initialization like servlets. In PHP everything will be inside a web request.
As you mentioned, the Registry design pattern can help you to have a place to put your objects, however, they will be recreated on every request.
I do not have a Java background, but a singleton that on construction initiates and returns (or holds as static) other singletons/factories is a common pattern. Because the only defined "entry point" of a PHP application is the file that gets passed to the parser, many PHP applications go to great lengths to redirect to a "bootstrap" script, which prepares the environment and instantiates any singleton and static objects needed by the application. This is then included at the entry point to assure it is available to the entire application.
<?php // this file is bootstrap.php
// ...
class MySingleton {
private static $instance;
private function __construct() {
$this->myFactory1 = new MyFactory1();
$this->myFactory2 = new MyFactory2();
$this->myOtherSingleton = MyOtherSingleton::get();
}
public static function get() {
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
// Before we leave, we'll get an instance!
$myBootstrapUtility = MySingleton::get();
// end of bootstrap.php ?>
one would then make sure to require_once('bootstrap.php'); before the rest of application logic.
Of course the actual details are entirely up to you, but this is certainly not an uncommon way of doing what you're after.

Categories