<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rodrigo Vieira</title>
    <description>The latest articles on DEV Community by Rodrigo Vieira (@rodrigosyscop).</description>
    <link>https://dev.to/rodrigosyscop</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36157%2F6a66d80d-5856-48cf-b8ed-6c47c5c669d2.jpeg</url>
      <title>DEV Community: Rodrigo Vieira</title>
      <link>https://dev.to/rodrigosyscop</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rodrigosyscop"/>
    <language>en</language>
    <item>
      <title>SELinux and AppArmor</title>
      <dc:creator>Rodrigo Vieira</dc:creator>
      <pubDate>Fri, 19 Apr 2019 15:48:29 +0000</pubDate>
      <link>https://dev.to/rodrigosyscop/selinux-and-apparmor-4n7k</link>
      <guid>https://dev.to/rodrigosyscop/selinux-and-apparmor-4n7k</guid>
      <description>&lt;p&gt;They both are security related technologies classified as MAC - Mandatory Access Control. SELinux was created by NSA - National Security Agency, while AppArmor become popular after it has adopted by Ubuntu Linux.&lt;/p&gt;

&lt;p&gt;The main idea here is to create mechanisms to extend the basic permission schema based on &lt;code&gt;ugo&lt;/code&gt;/&lt;code&gt;rwx&lt;/code&gt;. Among other things, they offer the ability to restrict access by system process to files, directories, network ports, etc.&lt;/p&gt;

&lt;p&gt;AppArmor offers an autolearn mode, which is capable to know how a system should operate, while SELinux brings an enforcing mode by default since CentOS 6.&lt;/p&gt;

&lt;h2&gt;
  
  
  SELinux
&lt;/h2&gt;

&lt;p&gt;SELinux stands for Security Enhanced Linux and it can operate in two modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;enforcing&lt;/code&gt;: SELinux will deny access based on its policy rules, a set of guidelines that control its engine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissive&lt;/code&gt;: SELinux won't deny access, but denials will be logged for actions that would have been denied if running in enforcing mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You have the choice to completely disable SELinux, however, it is not recommended these days! It's better to learn how to take advantage of this excellent tool.&lt;/p&gt;

&lt;p&gt;You can verify the current operation mode of SELInux using &lt;code&gt;getenforce&lt;/code&gt; command, and you can change it by &lt;code&gt;setenforce 0&lt;/code&gt; - permissive mode - or &lt;code&gt;setenforce 1&lt;/code&gt; - enforcing mode. To persist this change across reboots you need to set the &lt;code&gt;SELINUX&lt;/code&gt; variable in the &lt;code&gt;/etc/selinux/config&lt;/code&gt; file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To set SELINUX from or to &lt;code&gt;disabled&lt;/code&gt; mode you will have to edit the above file and reboot your system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a common use case lets see how to change the SSH daemon port from &lt;code&gt;22&lt;/code&gt; to &lt;code&gt;2222&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make sure you have the &lt;code&gt;policycoreutils-python&lt;/code&gt; package installed:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;  yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; policycoreutils-python
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Tell SELinux that port &lt;code&gt;2222&lt;/code&gt; is allowed to be used by ssh process:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# check all ports managed by SELinux&lt;/span&gt;
  selinux port &lt;span class="nt"&gt;-l&lt;/span&gt;

  &lt;span class="c"&gt;# Customize ssh to run on port 2222/tcp&lt;/span&gt;
  semanage port &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; ssh_port_t &lt;span class="nt"&gt;-p&lt;/span&gt; tcp 2222

  &lt;span class="c"&gt;# check all customized ports managed by SELinux&lt;/span&gt;
  semanage &lt;span class="nt"&gt;-lC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Another common scenario is to change the default allowed &lt;code&gt;DocumentRoot&lt;/code&gt; folder to be used by a web server. Lets add the &lt;code&gt;/srv/www&lt;/code&gt; to the list of the allowed directories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;semanage fcontext &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; httpd_sys_content_t &lt;span class="s2"&gt;"/srv/www(/.*)?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above command will grant apache read-only access to that directory and its contents.&lt;/p&gt;

&lt;p&gt;Finally, to apply the pilicy, making the label change effective immediately):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;restorecon &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; /srv/www
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If things are still not working as expected you can look for &lt;code&gt;AVC&lt;/code&gt; string in &lt;code&gt;/var/log/audit/audit.log&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;You can get more help at &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/index"&gt;SELinux Official Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  AppArmor
&lt;/h2&gt;

&lt;p&gt;AppArmor uses profiles defined in text files instead of policy managed by commands. There are several of them provided out of the box. These profiles are available at &lt;code&gt;/etc/apparmod.d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can check the AppArmor current status by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;apparmor_status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To switch a profile between &lt;code&gt;complain&lt;/code&gt; and &lt;code&gt;enforce&lt;/code&gt; modes, like &lt;code&gt;smbd&lt;/code&gt; profile, we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;aa-complain /etc/apparmor.d/usr.sbin.smbd
aa-enforce  /etc/apparmor.d/usr.sbin.smbd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above commands also accept bash wildcards to change multiple profiles at once.&lt;/p&gt;

&lt;p&gt;To entirely disable a profile, we just have to create a link to its file at &lt;code&gt;/etc/apparmor.d/disable/&lt;/code&gt; directory, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can get more information for AppArmor in &lt;a href="https://help.ubuntu.com/community/AppArmor"&gt;Ubuntu AppArmor Community Documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>infosec</category>
      <category>sysadmin</category>
      <category>devops</category>
    </item>
    <item>
      <title>Access Control List - ACL</title>
      <dc:creator>Rodrigo Vieira</dc:creator>
      <pubDate>Fri, 19 Apr 2019 15:45:26 +0000</pubDate>
      <link>https://dev.to/rodrigosyscop/access-control-list-acl-1im2</link>
      <guid>https://dev.to/rodrigosyscop/access-control-list-acl-1im2</guid>
      <description>&lt;p&gt;To improve the well known Linux permission schema &lt;code&gt;ugo&lt;/code&gt;/&lt;code&gt;rwx&lt;/code&gt;, allowing us to set distinct permission for different individual users or groups we can leverage the Access Control List - ACL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;The filesystem where the files you want to set ACL are stored must be mounted with ACL support. You can check that by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mount /dev/xvda1 | &lt;span class="nb"&gt;grep &lt;/span&gt;attr
/dev/xvda1 on / &lt;span class="nb"&gt;type &lt;/span&gt;xfs &lt;span class="o"&gt;(&lt;/span&gt;rw,relatime,seclabel,attr2,inode64,noquota&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can see the &lt;code&gt;attr2&lt;/code&gt; which indicates that this filesystem supports extended attributes - ACLs. If you don't see that option for your filesystem or if you see the &lt;code&gt;noacl&lt;/code&gt;, you can fix it in &lt;code&gt;/etc/fstab&lt;/code&gt; adding or removing the appropriated options, and remounting the filesystem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mount /dev/xvda1 &lt;span class="nt"&gt;-o&lt;/span&gt; remount
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can't remount the root &lt;code&gt;/&lt;/code&gt; filesystem. You have to reboot your machine to get new options enabled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using ACLs
&lt;/h2&gt;

&lt;p&gt;Imagine that we have these two groups and 5 users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;devs&lt;/code&gt;: &lt;code&gt;euler&lt;/code&gt;, &lt;code&gt;colleen&lt;/code&gt;, &lt;code&gt;eric&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ops&lt;/code&gt;: &lt;code&gt;rodrigo&lt;/code&gt;, &lt;code&gt;jonas&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we have a project folder that &lt;code&gt;devs&lt;/code&gt; have full acess to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;groupadd dev
groupadd ops
useradd euler
useradd colleen
useradd rodrigo
useradd jonas
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; devs euler
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; devs colleen
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; devs eric
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; ops rodrigo
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; ops jonas

&lt;span class="nb"&gt;mkdir&lt;/span&gt; /var/projectX
&lt;span class="nb"&gt;touch&lt;/span&gt; /var/projectX/main.py

&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; euler.devs /var/projectX
&lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 770  /var/projectX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But what if we want to grant write access to a user that is not in &lt;code&gt;devs&lt;/code&gt; group?&lt;br&gt;
We could create a new group that includes all necessary users, but it would get messy fast.&lt;/p&gt;

&lt;p&gt;With ACLs we can grant individual users access to files and directories. Hence, to add write permission for jonas to &lt;code&gt;main.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;setfacl &lt;span class="nt"&gt;-m&lt;/span&gt; u:jonas:rw /var/projectX/main.py
setfacl &lt;span class="nt"&gt;-m&lt;/span&gt; u:jonas:rx /var/projectX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok, &lt;code&gt;jonas&lt;/code&gt; now has access to read and to enter in &lt;code&gt;/var/projectX&lt;/code&gt; folder and also to write to &lt;code&gt;main.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can check for ACLs on a file by running &lt;code&gt;getfacl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;
getfacl /var/projectX/main.py

getfacl: Removing leading &lt;span class="s1"&gt;'/'&lt;/span&gt; from absolute path names
&lt;span class="c"&gt;# file: var/projectX/main.py&lt;/span&gt;
&lt;span class="c"&gt;# owner: euler&lt;/span&gt;
&lt;span class="c"&gt;# group: dev&lt;/span&gt;
user::rwx
user:jonas:rw-
group::rwx
mask::rwx
other::---
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can remove the above ACLs replacing &lt;code&gt;-m&lt;/code&gt; for &lt;code&gt;-x&lt;/code&gt;, or using &lt;code&gt;-b&lt;/code&gt; to remove all ACLs from a file or directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;setfacl &lt;span class="nt"&gt;-b&lt;/span&gt; /var/projectX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I hope you've learned a litte bit about Linux ACLs, you can learn more at &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/deployment_guide/s1-acls-setting"&gt;Setting Access ACLs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>infosec</category>
      <category>sysadmin</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why Encapsulate</title>
      <dc:creator>Rodrigo Vieira</dc:creator>
      <pubDate>Fri, 19 Apr 2019 15:27:07 +0000</pubDate>
      <link>https://dev.to/rodrigosyscop/why-encapsulate-f1g</link>
      <guid>https://dev.to/rodrigosyscop/why-encapsulate-f1g</guid>
      <description>&lt;p&gt;I'm pretty sure you can find enough material about encapsulation in the context of Object Oriented programming paradigm on the Internet. Thus, my approach here is to expose a simple PHP snippet for those are not used to encapsulation yet.&lt;/p&gt;

&lt;p&gt;Let's say you have a &lt;code&gt;wallet&lt;/code&gt; object and you want to impose some restrictions on its public interface. I mean, you want to guide how client code should use your &lt;code&gt;wallet&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Among other attributes and methods, let's keep our object as simple as we can and stay focused on encapsulation. For this reason, let's start with a &lt;code&gt;$balance&lt;/code&gt; and a &lt;code&gt;$limit&lt;/code&gt; attributes, besides two &lt;em&gt;public&lt;/em&gt; methods, &lt;code&gt;withdraw()&lt;/code&gt; and &lt;code&gt;deposit()&lt;/code&gt;, and a &lt;em&gt;private&lt;/em&gt; one, the &lt;code&gt;setLimit()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Wallet&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Balance of the wallet
     *
     * @var float
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Availabe limit for the wallet
     *
     * @var float
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Creates a Wallet with a initial balance and a certain limit.
     * @param  float  $balance
     * @param  float  $limit
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setLimit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Can't create a wallet with balance under limit."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setLimit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Increase balance
     * @param  float  $amount
     * @return float
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Decrease balance
     * @param  float $amount
     * @return float
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Insuficient funds."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * A string representation for the wallet's balance
     * @return string
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;__toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Balance: $ %.2f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First, we don't want to allow client code to create Wallets with no balance, or with a balance under a certain limit. Thus we've defined this initial rules in the constructor method.&lt;/p&gt;

&lt;p&gt;Next, we can't let the client code manipulate the balance of a wallet directly. This change must occur through one of the assessor methods, 'deposit()' or 'withdraw()'. For this reason, we've defined the &lt;code&gt;$balance&lt;/code&gt; property as private.&lt;/p&gt;

&lt;p&gt;We also want to ensure that the balance of a portfolio does not fall below the limit set in the builder. We can define this business rule in the &lt;code&gt;withdraw()&lt;/code&gt; method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Wallet class
&lt;/h2&gt;

&lt;p&gt;With our Wallet class defined, we can easily create a new wallet, specifying its initial balance and limit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$my_wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Wallet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Changes on &lt;code&gt;$balance&lt;/code&gt; property are limited through &lt;code&gt;deposit()&lt;/code&gt; and &lt;code&gt;withdraw()&lt;/code&gt; methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$my_wallet&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1450.25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$my_wallet&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;500.50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are able to see a nice string representation of a Wallet object just printing it, thanks to the &lt;code&gt;__toString()&lt;/code&gt; magic method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$my_wallet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Lastly, we are verifying for a &lt;em&gt;limit&lt;/em&gt; violation when withdrawing or when creating a new Wallet object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Will throw an Exception: "Insuficient funds"&lt;/span&gt;
&lt;span class="nv"&gt;$my_wallet&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2000.00&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;# Will throw an Exception: Can't create a wallet with balance under limit.&lt;/span&gt;
&lt;span class="nv"&gt;$other_wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Wallet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;225.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The main goal of &lt;em&gt;encapsulation&lt;/em&gt; is to protect entire object data from being accessible to its clients. Our business rule about the &lt;em&gt;limit&lt;/em&gt; is hidden from client code. We have blundled the data with the methods that operate on that data.&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>Interfaces and Abstract Classes</title>
      <dc:creator>Rodrigo Vieira</dc:creator>
      <pubDate>Fri, 19 Apr 2019 15:20:10 +0000</pubDate>
      <link>https://dev.to/rodrigosyscop/interfaces-and-abstract-classes-35oh</link>
      <guid>https://dev.to/rodrigosyscop/interfaces-and-abstract-classes-35oh</guid>
      <description>&lt;p&gt;For most people I've talked on my journey through software development, &lt;em&gt;abstraction&lt;/em&gt; always brings the idea of &lt;em&gt;code reuse&lt;/em&gt;. You might think about company and person objects, both have names, addresses, phone contacts, and so on. They both share common attributes and maybe even common behavior. You can define an abstract base class named &lt;code&gt;Entity&lt;/code&gt; and then create two concrete classes, &lt;code&gt;Person&lt;/code&gt; and &lt;code&gt;Company&lt;/code&gt;, extended from &lt;code&gt;Entity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a step back, imagine basic PHP types, boolean, integer, float, objects and all the ways you are able to work with them. Everyone knows or at least should know, the expected behavior of those types. I mean, if you create an integer variable, you know what kind of value to expect and what kind of operations you can perform with it. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every type has its own stable behavior.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A programming language cares itself about the unchangeable behavior of its essential types. The same idea applies when we are defining abstract classes and their concrete implementations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstract Classes
&lt;/h2&gt;

&lt;p&gt;When extending from other classes, we are creating new &lt;em&gt;data types&lt;/em&gt;. The code snippets below define a new child class &lt;code&gt;ArrayCache&lt;/code&gt;, which &lt;strong&gt;is a&lt;/strong&gt; &lt;code&gt;AbstractCache&lt;/code&gt; class. Thus, the child class is a specification that will inherit all of the parent's non-private properties and methods. &lt;strong&gt;The client code still expects them to behave exactly as their parent does&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractCache&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArrayCache&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;AbstractCache&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;According to Liskov Substitution Principle, we can use these sub-types, without any special knowledge, only by reading the parent class public interface.&lt;/p&gt;

&lt;p&gt;All concrete implementations from the same abstract base class should obey the abstract class interfaces. &lt;strong&gt;When using inheritance, it is our responsibility to respect the parent class interface.&lt;/strong&gt; When working with inheritance, try to keep the hierarchy short, no more than three levels. Also, remember that if there is some code in the &lt;em&gt;parent&lt;/em&gt; class that you are using from the client one as &lt;code&gt;parent::method()&lt;/code&gt;, you must care about the returned values as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When we provide public methods we are saying: "With this data type you can do this and it will behave in this particular way."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can think of abstraction as taking out unnecessary details to describe something in simpler terms in order to focus only on important aspects of the current context. Encapsulation plays the main role here, as a technique used to hide some state and behavior from the outside world. Client code can interact with it through its methods, but cannot access its state directly.&lt;/p&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A public interface is a set of rules, that defines the way in which we can interact with an object.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Interfaces
&lt;/h2&gt;

&lt;p&gt;When you are trying to enforce the same behavior for different types, you may want to take advantage of &lt;em&gt;Interfaces&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;An interface in PHP can contain methods and constants, but can't contain any variables. All methods must be public and have no implementation. Also, an interface can be inherited from another by &lt;em&gt;extends&lt;/em&gt; keyword. Even though classes can inherit from multiple interfaces, that can't implement two interfaces that share the same method names, it would cause ambiguity.&lt;/p&gt;

&lt;p&gt;Hence, we usually use abstraction for code reuse when defining a hierarchy of data types. As for interfaces, its common use is to enforce certain behavior.&lt;/p&gt;

&lt;p&gt;For instance, we want to make sure that those two types, &lt;code&gt;Company&lt;/code&gt; and &lt;code&gt;Person&lt;/code&gt; can be cached by providing its own key and its own value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Cacheable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCacheKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCacheValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We have to create the &lt;code&gt;Company&lt;/code&gt; class and the methods imposed by &lt;code&gt;Cacheable&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Cacheable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCacheKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'company_'&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCacheValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s1"&gt;'phone'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s1"&gt;'address'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s1"&gt;'foundation_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;foundation_date&lt;/span&gt;
       &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The same for &lt;code&gt;Person&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Cacheable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCacheKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'person_'&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCacheValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s1"&gt;'phone'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s1"&gt;'address'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s1"&gt;'birth_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;birth_date&lt;/span&gt;
       &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this &lt;em&gt;inverted&lt;/em&gt; approach, all caching logic is encapsulated in a &lt;em&gt;cacheable&lt;/em&gt; class. Every class must define its own rules, how it should be stored in the cache. The &lt;code&gt;Cache&lt;/code&gt; class knows nothing about these details, it trusts &lt;code&gt;Cacheable&lt;/code&gt; objects and calls their &lt;code&gt;getCacheKey&lt;/code&gt; and &lt;code&gt;getCacheData&lt;/code&gt; methods.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This blind trust is the main idea of using interfaces. We are establishing a contract that must be honored by both sides.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can now redefine our &lt;code&gt;ArrayCache&lt;/code&gt; like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractCache&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;AbstractCache&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Cacheable&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getCacheKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Cacheable&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getCacheKey&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getCacheValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Keep in mind that interfaces don't define a new type, they describe an aspect of a type.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://daylerees.com/php-pandas-interfaces/"&gt;https://daylerees.com/php-pandas-interfaces/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://daylerees.com/php-interfaces-explained/"&gt;https://daylerees.com/php-interfaces-explained/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leanpub.com/phpoopway"&gt;https://leanpub.com/phpoopway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
    </item>
  </channel>
</rss>
