Nomad PHPBetter and Faster: TDD-ing a Ride-Hailing Application w/ PHPUnit, Symfony and Doctrine (21.4.2018, 16:11 UTC)

July - US
Presented By

Chris Holland
July 19, 2018
20:00 CDT

The post Better and Faster: TDD-ing a Ride-Hailing Application w/ PHPUnit, Symfony and Doctrine appeared first on Nomad PHP.

Link
Christian WeiskeGrav CMS: previous is next (20.4.2018, 19:22 UTC)

I'm using Grav CMS for a new project and am building my own theme for it.

When adding links to the previous and next blog posts, I noticed something strange: When I am on the first blog post (PageCollection::isFirst($page.path) == true), $collection.nextSibling() is empty.

Also, when I'm on the last page, $collection.prevSibling() is empty.

It turns out that those two methods do the opposite as I thought:

Post number prevSibling nextSibling
5 6 4

Other people were also confused, but Grav is used too much now that changing the behavior would break many many pages.

Link
Stefan KoopmanschapMental Health First Aid (20.4.2018, 17:25 UTC)

It was TrueNorthPHP conference in 2013 that I first saw Ed Finkler speak. It was his Open Sourcing Mental Illness talk. This talk has meant so much to me on so many levels, but one of the things I took away from that talk was the existence of Mental Health First Aid. Mental Health First Aid is basically the mental illness counterpart of regular first aid. It gives you basic information about how to handle when you encounter someone with a mental illess, especially in crisis situations. This includes approaching the person, what to do and not to do when talking to them, and how to make sure people get the right help, including a hand-off to (mental health) medical professionals.

Fast forward a few years to about two years ago. Doing the MHFA course was still on my wishlist, but there still was no option in The Netherlands to do so. Just as I was looking into options of travelling to the UK for the course, I found out that one of the Dutch regional institutes for mental health (GGZ Eindhoven) was working on bringing MHFA to The Netherlands. I contacted them to see if I could be part of the trial group they were doing, but never heard back. I put my focus on some other things I wanted to do and put MHFA on hold again.

Earlier this year I decided to add a bit more structure to the training programs within my company Ingewikkeld to enable my employees a bit better to increase their knowledge and skills, but decided I definitely also should use this new structure for my own. I looked up the MHFA options in The Netherlands and found out that there were now many options for taking the course, including in my favorite city Utrecht. I signed up for the course, and over the past 4 weeks have had 4 3-hour sessions.

The goal

In the first session we were asked for our goals. My main goal was to understand more about mental illness and get handholds on how to act in case of talking to someone with a mental illness, be it a crisis situation or not. And over all sessions, this was indeed what happened. I learned a lot about depression, fear, psychosis, substance abuse and crisis such as suicidal tendencies, self-harm, panic attacks, aggression and more. About what it was and about how to handle such situations. As we were asked at the end of todays session to summarize our experience over the past 4 weeks, my answer was:

Goals achieved

It became personal

As I've got issues with depression myself, especially the first two sessions caused a lot of self-reflection as I learned more about what happens with depression. There was a lot of familiar situations in the course material, and it was very interesting to hear more background information on those situations. Our group was a very nice and diverse group, with people with lots of different backgrounds, which gave me a lot of insight into how different people experience different situations.

As the course progressed though, other mental illnesses were handled that I had no experience with. This was definitely eye opening. I now have so much more understanding of what can happen in peoples heads, and I hope that helps me in a more empathetic response to such situations, if I ever encounter them.

Why I recommend more people taking this course

Isn't it a bit weird that we find it very normal to take regular first aid courses, but we try to stay away of anything related to mental health? Somehow there is still a taboo on mental health related problems. And yet (at least here in The Netherlands) there are news items on a more regular basis about people with mental illness crises. It seems like this is a growing problem, yet nobody wants to know how to handle in such situations?

Taking this course will make you understand more clearly what happens when someone has a mental health issue. How it affects their life, and how to handle when you encounter a situation involving a mental health issue. It will help you be more empathetic, not just in crisis situations, but also when simply talking to someone with a mental illness. I also think it will look good on your resume for potential employers. It is still a rare skill to know how to handle in this situations, and employers will benefit from you having this knowledge. So Check which local organization offers the course and register. I'm pretty sure you won't regret it.

Link
Nomad PHPThe PHP Developer Stack for Building Chatbots (20.4.2018, 04:05 UTC)

July - EU
Presented By

Ashley Hutson
July 19, 2018
20:00 CEST

The post The PHP Developer Stack for Building Chatbots appeared first on Nomad PHP.

Link
blog.phpdevPreparing for Pentesting (@ Longhorn PHP 2018) (17.4.2018, 13:57 UTC)

At this year’s Longhorn PHP conference I’ll be presenting two talks: an updated version of my “Securing Legacy Applications” session and something new and a bit different for a conference primarily aimed at development topics. I’ll be giving a tutorial on the first day (April 19th) about penetration testing. For those not familiar with the topic, penetration testing is a common security practice where you make attempts to locate the flaws in an application, usually without knowledge of the code running underneath.

For a group that’s primarily focused on “building” rather than “breaking” it might be a bit of a mind shift but I hope to at least provide my attendees with the basic concepts and tools to try it out on their own applications. There have been several sessions recently that focus on securing the code but that’s only half of the equation.

So, if you’re going to be attending my tutorial, here are a few things that can help you hit the ground running when we start. There’ll be a brief introduction to some of the basic application security concepts but we’re not going to dive too deep into those. Instead, you’ll be attacking a series of challenges I’ve created to teach the basics.

Here’s how to prepare:

– Go over the OWASP Top 10 to be familiar with the common vulnerability types (hint: several are in the challenges)
– Grab the Community Edition of the PortSwigger Burp Suite tool. We’ll be using this to help solve some of the challenges
– Check out the PHP security cheat sheet, some of the top PHP security issues and this guide to building secure PHP applications

Don’t worry if you’re not a PHP security pro – that kind of knowledge isn’t required here. The topics we’ll cover are more from the security testing side and, as an added bonus can be used on any kind of web-based application – not just PHP ones!

I hope to see you on Thursday morning – we’re going to have some fun!

Link
Matthias NobackCombing legacy code string by string (17.4.2018, 07:00 UTC)

I find it very curious that legacy (PHP) code often has the following characteristics:

  1. Classes with the name of a central domain concept have grown too large.
  2. Methods in these classes have become very generic.

Classes grow too large

I think the following happened:

The original developers tried to capture the domain logic in these classes. They implemented it based on what they knew at the time. Other developers, who worked on the code later, had to implement new features, or modify domain logic, because, well, things change. Also, because we need more things.

For instance, when a developer comes in and has to modify some of the logic related to "sales orders", they will look for classes with that name in it, like the SalesOrder entity, the SalesOrders controller, service, manager, helper, table gateway, repository, etc. Before considering the option to add more classes, most developers will first consider adding a method to one of the existing classes. Especially if the code of this class hasn't been tested.

Since this is legacy code we're talking about, it's very likely that the code hasn't been tested (if it was tested, would it be legacy code?). So most likely they will end up modifying the existing class, instead of thinking about what they really need: an object that does exactly what they need.

This is how legacy classes end up being so very large. We add more and more to it (since the new functionality is "related" to the existing code after all). It explains why legacy code has the first characteristic I mentioned at the beginning of this post ("Classes with the name of a central domain concept have grown too large."). The second characteristic still deserves some explanation though ("Methods in these classes have become very generic.").

Methods become very generic

Once we decide to take an existing class and modify it, we first analyze the code that's in the class: the method, the properties; we've all learned to take the D.R.Y. ("Don't repeat yourself") principle into account, so we're scared of redoing anything that was already done. While scanning the existing code, we may find several of the ingredients we need for the task at hand. Well, the ingredients are often somewhat useful, but not entirely what we need.

This is a crucial moment, a moment we've often experienced, a moment we've always appreciated. However, it's a moment we should fear, a moment we should fight (pardon the dramatic tone). It's the moment we change a method to fit in with our current use case.

How is this usually achieved? Most often we use one of the following tactics:

  1. Add an extra parameter (a.k.a. a parameter flag), using which we can influence the behavior of the method. Of course we provide a sensible default parameter, for backwards compatibility:

    // The original method:
    public function findAllSalesOrders()
    {
        // some complicated SQL, *almost* what we need
    }
    
    // The modified method, with a parameter flag
    public function findAllSalesOrders($excludeFinishedOrders = false)
    {
        // ...
    }
    
    
  2. Call another method first (a.k.a. decoration). This method may do some of the work, and maybe let the original method do its original work afterwards.

    // The original method:
    public function findAllSalesOrders()
    {
        // some complicated SQL, *almost* what we need
    }
    
    // The new method, which decorates the original one:
    public function findOpenSalesOrders()
    {
        // call the original method
        $salesOrders = $this->findAllSalesOrders();
    
        return array_filter($salesOrders, function(SalesOrder $order) {
            return $order->isOpen();
        };
    }
    
    

Sometimes we even combine the two, making one method more generic, and calling it from a more specific one:

// The original method:
public function findAllSalesOrders()
{
    // some complicated SQL, *almost* what we need
}

// The modified method:
public function findSpecificSalesOrders(array $statuses = [])
{
    // some complicated SQL, can do anything we need
}

// The new method, which decorates the modified original one
public function findOpenSalesOrders()
{
    return $this->findSpecificSalesOrders([SalesOrder::STATUS_OPEN]);
}

Over time, the original methods become more generic. That is, they can be used in many different scenarios. At the same time, the classes containing these methods keep growing. Every time we need a slightly different method, we add it, and use one of the tactics described. Slowly the class becomes too large to remain manageable (see

Truncated by Planet PHP, read more at the original (another 3906 bytes)

Link
Matthias NobackExceptions and talking back to the user (10.4.2018, 09:12 UTC)

Exceptions - for exceptional situations?

From the Domain-Driven Design movement we've learned to go somewhat back to the roots of object-oriented design. Designing domain objects is all about offering meaningful behavior and insights through a carefully designed API. We know now that domain objects with setters for every attribute will allow for the objects to be in an inconsistent state. By removing setters and replacing them with methods which only modify the object's state in valid ways, we can protect an object from violating domain invariants.

This style of modeling domain aggregates (entities and value objects) results in methods that modify state, but only after checking if the change is allowed and makes sense, given the rules dictated by actual domain knowledge. In terms of code, these methods may make some simple assertions about the arguments passed to it: the number of things, the range of a number, the format of a string. When anything is wrong about a provided argument, the domain object simply throws an exception. If everything is okay, the changes will be accepted by modifying any attribute involved.

So exceptions in your (object-oriented) domain model are not merely meant to signal an exceptional situation. They can be used to prevent invalid or unsupported usage of an object. By offering well-named methods (with sensible parameters) for changing the object's state, and by being very precise about throwing exceptions when invalid use is imminent, you make your domain objects usable in only one way: the way that makes sense. This is the exact opposite of how your domain objects end up looking if you generate getters and setters for every attribute.

Using exceptions for validation

You might say that, given that the object protects itself from ending up in an in valid state, it basically validates itself. However, it won't be good for our application's usability if we'd use these domain-level exceptions as messages to the user. The thing is:

  • Exceptions get thrown ad hoc, whenever something threatens the consistency of the domain object. You can only catch one of these exceptions and turn it into an error message for the user. If the user tries to fix the issue by making a change, sending the form again, and they manage to get past this exception, there may be another exception just around the corner. This will be very frustrating for the user, as it will feel like trial-and-error.
public function processDelivery(int $quantity, string $batchNumber): void {
    if ($quantity <= 0) {
        /*
         * If the user triggers this exception, they have to resubmit,
         * which may trigger another exception further down the line...
         */
        throw new InvalidArgument(
            'Quantity should be more than 0.'
        );
    }

    if (empty($batchNumber) {
        throw new InvalidArgument(
            'This delivery requires a batch number.'
        );
    }

    // ...
}

  • Domain exceptions aren't always about validating the data the user provides. They often signal that something is about to happen that can't logically happen, like a state change that isn't allowed or conceptually possible. E.g. once an order has been cancelled, it shouldn't be possible to change its delivery address, because that makes no sense:
public function changeDeliveryAddress(...): void {
    if ($this->wasCancelled) {
        throw new InvalidState('You cannot change ...');
    }

    // ...
}

  • Exception messages may contain more information than you'd like to share with the user.
  • Validation errors often require internationalization (i18n). They need localization in the sense that numbers should be formatted according to the user's locale. Of course, they often need translation too. Exceptions aren't naturally usable for translation, because they contain special values hard-coded into their messages.
throw new InvalidArgument(
    'Product 21 has a stock level of 100, but this delivery has a quantity of 200.'
);

Translation needs a template message which will be translated, after which the variables it contains will be replaced by their real values.

So exceptions thrown to protect domain invariants are not validation messages all by themselves. They are there to prevent bad things from happening to your domain objects. They are not useful if what you want is talk back to the user. If you're looking for a dialogue with the user about what they're trying to achieve, you should be having it in a layer of the application that's closer to the user.

There are several options there

Truncated by Planet PHP, read more at the original (another 6127 bytes)

Link
Paul M. JonesThe Conquest Code of Conduct (9.4.2018, 13:50 UTC)

If you’re tired of SJW COCs in open-source projects, try this one on for size:

Conquest’s Second Law: “Any organization not explicitly right-wing sooner or later becomes left-wing.”

tl;dr: No Socialism or Social Justice.


All contributions and communication are welcome, so long as they do not (within this project space) espouse, entertain, advocate for, or otherwise positively discuss the political ideals associated with Social Justice, Progressivism, Communism, Socialism, Fascism, Marxism, or anything else generally reminiscent of any political philosophy to the left of Classical Liberals or Libertarians.

If you suspect or are subjected to criminal behavior within this project space, first notify the appropriate authorities; then, if you wish, you may notify the project owner. The project owner makes no promises in advance regarding accusations or complaints.

The project owner is the final arbiter on all contributions and communication within this project space.

Link
Voices of the ElePHPantInterview with Chris Hartjes (8.4.2018, 16:34 UTC) Link
Matthias NobackMocking the network (3.4.2018, 07:15 UTC)

In this series, we've discussed several topics already. We talked about persistence and time, the filesystem and randomness. The conclusion for all these areas: whenever you want to "mock" these things, you may look for a solution at the level of programming tools used (use database or filesystem abstraction library, replace built-in PHP functions, etc.). But the better solution is always: add your own abstraction. Start by introducing your own interface (including custom return types), which describes exactly what you need. Then mock this interface freely in your application. But also provide an implementation for it, which uses "the real thing", and write an integration test for just this class.

The same really is true for the network. You don't want your unit tests to rely on a network connection, or a specific web service to be up and running. So, you override PHP's curl_exec() function. Or, if your code uses Guzzle, you inject its Mock Handler to by-pass part of its real-life behavior. The smarter solution again is to introduce your own interface, with its own implementation, and its own integration test. Then you can prove that this implementation is a faithful implementation of the interface (contract) you defined. And it allows you to mock at a much more meaningful level than just replacing a "real" HTTP response with a recorded one.

Though this solution would be quite far from traditional mocking I thought it would be interesting to write a bit more about it, since there's also a lot to say. It does require a proper example though. Let's say you're writing (and testing) a piece of financial calculation code where you're doing a bit of currency-conversion as well. You need a conversion rate, but your application doesn't know about actual rates, so you need to reach out to some web service that keeps track of these rates. Let's say, you make a call to "exchangerates.com":

# ...

$response = file_get_contents('https://exchangerates.com/?from=USD&to=EUR&date=2018-03-18')
$data = json_decode($response);
$exchangeRate = (float)$data->rate ?? 1;

# use the exchange rate for the actual calculation
# ...

Yes, this is horrible. Testing this code and "mocking" the network call is only one of our problems. We have to deal with broken connections and responses, and by the way, this code doesn't even take into account most of the other things that could go wrong. Code like this that connects with "the big bad world" requires a bigger safety net.

The first thing we should do is (as always) introduce an interface for fetching an exchange rate:

interface ExchangeRateService
{
    public function getFor(string $from, string $to, DateTimeImmutable $date): float
}

We could at least move all that ugly code and stick it in a class implementing this interface. Such is the merit of setting up a "facade", which "provides a simplified interface to a larger body of code". This is convenient, and it allows client code to use this interface for mocking. At the same time though, we're hiding the fact that we're making a network call, and that things can go wrong with that in numerous ways.

Implement an Anti-Corruption Layer

The first thing we can and should do is protect ourselves from the bad (data) model which the external service uses. We may have a beautiful model, with great encapsulation, and intention-revealing interfaces. If we'd have to follow the weird rules of the external service, our model risks being "corrupted".

That's what Domain-Driven Design's "Anti-Corruption Layer" (ACL - a bit of a confusing name) is meant for: we are encouraged to create our own models and use them as a layer in front of an external service's source of data. In our case, the interface we introduced was a rather simple one, one that doesn't allow for proper encapsulation. And because of the use of primitive types, there certainly isn't a place for a good and useful API. Due to a quirk in the external service I didn't mention yet, if one of the currencies is EUR, it always needs to be provided as the second ($to argument).

It'll be a perfect opportunity for an ACL. Instead of dealing with an exchange rate as a rather imprecise float type variable, we may want to define it as an integer and an explicit precision. And instead of working with DateTimeImmutable, we'd be better off modelling the date to be exactly what we need, and encode this knowledge in a

Truncated by Planet PHP, read more at the original (another 3011 bytes)

Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP