Wednesday, 9 November 2016

PHP Interfaces

When building multiple PHP classes that are interchangeable - for instance two user classes where one reads from a MySql database and one from a JSON file - it is crucial that these classes do not diverge in functionality; If you add a 'getUserInfo' method to the one, you have to add it to the other, chances are you are using a factory to instantiate your objects and would thus expect to be able to use them in exactly the same manner. An interface solves this problem.
An interface provides a set of rules that determine the shape of the class that implements this interface. In the above example the interface will enforce the existence of a 'getUserInfo' method in both the UserMySql and UserJSON classes.

Building an interface

Let's build an interface for the example above. A user class that fetches it's data from a MySql database, and a user class reads from a JSON file. These must both contain public 'create', 'read', 'update' and 'delete' methods.
interface.account.php
<?php
interface Account {
  public function create(string $name, string $email);
  public function delete();
  public function read(int $id);
  public function update(string $name, string $email);
}
?>
class.user.json.php
<?php
class UserJSON implements Account {
  public $id;
  public $name;
  public $email;
  public function create(string $name, string $email) {
    // insert into JSON file
  }
  public function delete() {
    // delete user with {$this->id}
  }
  public function read(int $id) {
    // read user from {$id}.json
  }
  public function update(string $name, string $email) {
    // update user with {$this->id}
  }
  public function doesSomethingElse () {
    // do something else
  }
  private function doesSomethingDifferent () {
    // do something different (and private)
  }
}
?>
class.user.mysql.php
<?php
class UserJSON implements Account {
  public $id;
  public $name;
  public $email;
  public function create(string $name, string $email) {
    // insert into JSON file
  }
  public function delete() {
    // delete user with {$this->id}
  }
  public function read(int $id) {
    // read user from {$id}.json
  }
  public function update(string $name, string $email) {
    // update user with {$this->id}
  }
}
?>
The interface and two classes above will work together well and the interface will keep the classes aligned properly. If either of these classes do no conform to the shape provided in the interface PHP will throw an error thus indicating that the class does not conform.

Sunday, 6 November 2016

Nesting unit tests in karma/jasmine with a higher order function

Unit tests are incredibly important, but sometimes test suites become difficult to read because the tests are not properly nested and now you are seeing 600 tests in a single line; Nesting them can also be quite tedious; Even though karma and jasmine nests test cases together with the same name, redefining a list of 'groups' in each test can be a bit difficult to maintain. We can solve this problem with a higher-order-function that accepts the entire grouping as an array.

The higher order function

The code for the higher order function (which we will call 'hofDescribe' from now on) is nothing too large or difficult, let's take a look:
/app/test/index.js
const hofDescribe = (groups, test) => {
  groups.reverse().reduce((previousTest, group) => (
    () => describe(`.${group}`, previousTest)
  ), test)();
};

export default hofDescribe;
hofDescribe take in an array of groups and the test (a function that returns a 'describe' block). It then nests the describes from the bottom up (from the deepest nested node/describe to the top root node/describe). It starts by reversing the array to have the bottom node first and passes the test given to hofDescribe as the test for the bottom node, and then returns a new describe to each parent until it reaches the top.

Putting it to use

Using hofDescribe is simple, lets 'test' three files and create a small test hiearchy. We will be testing one React component and two redux reducers.
/app/test/reducers/layout/size.js
import hofDescribe from 'test';

hofDescribe(['REDUCERS', 'Layout', 'Size'], () => describe('{ app.layout.size }', () => {
  it('Does something', () => {});
  it('Does something else even better', () => {});
}));
/app/test/reducers/layout/color.js
import hofDescribe from 'test';

hofDescribe(['REDUCERS', 'Layout', 'Color'], () => describe('{ app.layout.color }', () => {
  it('Does something', () => {});
  it('Does something else even better', () => {});
}));
/app/test/components/layout/shared/link.jsx
import hofDescribe from 'test';

hofDescribe(['COMPONENTS', 'Account'], () => describe('<Avatar />', () => {
  it('Does something', () => {});
  it('Does something else even better', () => {});
}));
The output from a test suite like this would give you a proper structured tree that makes much more sense:
.COMPONENTS
  .Account
    <Avatar />
      ✓ Does something
      ✓ Does something else even better

.REDUCERS
  .Layout
    .Color
      { app.layout.color }
        ✓ Does something
        ✓ Does something else even better
    .Size
      { app.layout.size }
        ✓ Does something
        ✓ Does something else even better

Using react-flexbox-grid in your react application

react-flexbox-grid is a great grid component layout library built for React, based on flexbox-grid.

Installation and setup

To install react-flexbox-grid, simply install it via npm:
$ npm install --save-dev react-flexbox-grid
To set it up with your webpack config you can add the following code to your webpack configuration file:
webpack.config.js
module.exports = {
  ...
  module: {
    loaders: [
      {
        test: /\.s?css$/,
        loaders: [
          'style-loader',
          'css-loader?modules&importLoaders=1&localIdentName=[name]-[local]___[hash:base64:5]',
          'sass-loader',
        ],
        include: /node_modules\/(react-toolbox|flexboxgrid)/,
      }
    ],
  },
  ...
};
The setup above is used for react-flexbox-grid and for react-toolbox, if you are not using react-toolbox you can just remove that piece from the configuration above.

Usage

To use react-flexbox-grid in your project you need to import the components you want to use (Grid, Row or Column), and use them just like you would any other React component.
/app/my-new-component.jsx
import { Grid, Row, Col } from 'react-flexbox-grid/lib/index';

const MyNewComponent = () => (
  <Grid className="my-new-component">
    <Row>
      <Col xs={12} sm={6} md={4} lg={3}>Column content here</Col>
      <Col xs={12} sm={6} md={4} lg={3}>Column content here</Col>
      <Col xs={12} sm={6} md={4} lg={3}>Column content here</Col>
    </Row>
  </Grid>
);

export default MyNewComponent;
For the full list of settings and features, have a look at the react-flexbox-grid website and Github page:
react-flexbox-grid website: http://roylee0704.github.io/react-flexbox-grid/
react-flexbox-grid GitHub: https://github.com/roylee0704/react-flexbox-grid

Friday, 4 November 2016

Splitting React Redux reducers into multiple files

Using redux for state management of your application is a really great and light way of having a single source of truth for your application; The problem is that sometimes reducers just become too big to maintain. Luckily we have the ability to split these up into smaller, more dedicated reducers with ES6 import/export and Redux's combineReducers method. Let's have a look.

Building the store

Install redux and react-redux packages.
$ npm i -D redux react-redux
We need to create the store and create the method to configure the store. Let's have a look at the store configuration method first:
/app/store/configureStore/index.js
import { compose, createStore } from 'redux';

import reducer from 'reducer';

const configureStore = (params = {}) => {
  const { initialState } = params;
  const store = createStore(
    reducer,
    initialState,
    compose(
      window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
    ),
  );
};

export default configureStore;
/app/store/index.js
import configureStore from './configureStore';

export const store = configureStore();
Now you can add your store to the store provider provided by react-redux.
/app/root/index.jsx
import React from 'react';
import { Provider } from 'react-redux';

const App = () => (
  <Provider store="{store}">
    <h1>App content here</h1>
  </provider>
);

export default App;

State and file structure

For this example we will be working towards creating a state that looks something like the following:
{
  app: {
    account: {
      name: '',
      email: '',
    },
    products: {
      data: [
        { id: 1, name: '', favourite: false },
        { id: 2, name: '', favourite: false },
      ],
      settings: {
        layout: 'grid',
      }
    },
  },
}
The file structure will very closely resemble out state tree:
app
--account
----actions.js
----index.js
--products
----data
------index.js
------product
--------actions.js
--------index.js
----settings
------actions.js
------index.js

Creating the reducers

We will be creating a reducer for each 'node' in our state (each key in our state object). Let's start by creating the top level 'app' node in the main reducer file, which is being passed to the 'configureStore' method described above.
/app/reducers/index.js
import { combineReducers } from 'redux';

import app from './app';

const reducer = combineReducers({
  app,
});

export default reducer;
Now we will build the 'app' reducer which will add the 'account' and 'products' nodes. Because the 'app' node contains more sub-nodes ('account' and 'products') the app reducer should only be concerned with combining the reducers for each sub-node, this will look like follows:
/app/reducers/app.js
import { combineReducers } from 'redux';

import account from './account';
import products from './products';

const app = combineReducers({
  account,
  products,
});

export default app;
The next reducer - the one for the 'account' node - will contain some logic to perform actions. We will split it up into two files, the reducer, and the actions. Let's build the actions file first:
/app/reducers/account/actions.js
export const ACCOUNT_CHANGE_NAME = 'ACCOUNT_CHANGE_NAME';

export const accountChangeName = name => ({
  type: ACCOUNT_CHANGE_NAME,
  name
});
Now the reducer:
/app/reducers/account/index.js
import { ACCOUNT_CHANGE_NAME } from './actions';
export const defaultState = {
  name: '',
  email: '',
};

const account = (state = defaultState, action = {}) => {
  switch (action.type) {
    case ACCOUNT_CHANGE_NAME:
      return {
        ...state,
        name: action.name,
      };
    default:
      return state;
  };
};

export default account;
The next node - 'products' - is another reducer that combines to sub-reducers for it's two sub-nodes, 'data' and 'settings', so it looks almost identical to the 'app' node's reducer. The 'settings' node's reducer will look almost identical to the 'account' node's reducer. The 'data' node returns an array of 'product' nodes. Let's build a reducer for the 'data' node and for each 'product' sub-node:
/app/reducers/products/data/index.js
import productReducer from './product';

const defaultState = [];

const data = (state = defaultState, action = {}) => {
  return [ ...state.map(product => productReducer(product, action)) ];
};

export default data;
The product reducer would then need actions and a reducer, let's build the actions first:
/app/reducers/products/data/product/actions.js
export const PRODUCT_ADD_TO_FAVOURITES = 'PRODUCT_ADD_TO_FAVOURITES';

export const productAddToFavourites = id => ({
  type: PRODUCT_ADD_TO_FAVOURITES,
  id,
});
/app/reducers/products/data/product/index.js
import { PRODUCT_ADD_TO_FAVOURITES } from './actions';

export const defaultState = {
  id: 0,
  name: '',
  favourite: false,
};

const productReducer = (state = defaultState, action = {}) => {
  switch (action.type) {
    case PRODUCT_ADD_TO_FAVOURITES:
      return {
        ...state,
        favourite: state.id === action.id ? !state.favourite : state.favourite,
      };
  };
};

export default productReducer;
Now we have split our reducer into many smaller, more maintainable - and testable - chunks.

Thursday, 3 November 2016

Adding react-toolbox to your React project

Installing react-toolbox

install the react-toolbox package via npm:
$ npm install react-toolbox --save-dev

Setting up the (s)css loader In webpack

you will need to add loaders for the react-toolbox stylesheets. This took me quite a while to figure out, hopefully someone finds it useful :).
webpack.config.js
module.exports = {
  ...
  module: {
    loaders: [
      ...
      {
        test: /\.s?css$/,
        loaders: ['style-loader', 'css-loader', 'sass-loader'],
        exclude: /node_modules/,
      },
      {
        test: /\.s?css$/,
        loaders: [
          'style-loader',
          'css-loader?modules&importLoaders=1&localIdentName=[name]-[local]___[hash:base64:5]',
          'sass-loader',
        ],
        include: /node_modules\/(react-toolbox|flexboxgrid)/,
      },
      ...
    ],
  },
  ...
};

Customizing the style variables

The default colors/layout/typography might not be right for you but luckily they are customizable, to change any of the variables you can create your own variables file and place some custom ones for your site:
/app/variables.scss
$my-app-color-white: rgb(255, 255, 255);
$my-app-color-black: rgb(0, 0, 0);
$my-app-color-dull: rgb(120, 120, 120);
$color-background: $my-app-color-white !default;
$color-text: $my-app-color-black !default;
$color-text-secondary: $my-app-color-dull !default;
This file can now be loaded via your webpack config
webpack.config.js
module.exports = {
  ...
  sassLoader: {
    data: `@import "${path.resolve(__dirname, 'app/variables.scss')}";`,
  },
  ...
}
You can find a full list of colors and globals at the following urls:
Colors: https://github.com/react-toolbox/react-toolbox/blob/dev/lib/_colors.scss
Globals: https://github.com/react-toolbox/react-toolbox/blob/dev/lib/_globals.scss
You can also set variables for each component, have a look in the lib folder on the react-toolbox GitHub repository:
lib folder: https://github.com/react-toolbox/react-toolbox/tree/dev/lib
GitHub: https://github.com/react-toolbox/react-toolbox

Using the components

Now the components can be imported into your react project and used alongside your own custom components
/app/custom-component.jsx
...
import { Button } from 'react-toolbox/lib/button';
...
<Button
  type="submit"
  icon="person"
  label="Login"
  raised
  primary
/>

Saturday, 15 October 2016

Creating a VirtualHost in Apache 2.4

What is a VirualHost?

In apache a VirtualHost is a way to host multiple websites on a single apache instance. If you're a developer that works on more than one website this is the best way to test all those websites on one machine.
Creating a VirtualHost
Creating a VirtualHost is simple, we can achieve this in four easy steps. In the following example we will be creating a VirtualHost named "website.demo":

  1. Create the VirtualHost file
    sudo nano /etc/apache2/sites-available/website.demo.conf
    <VirtualHost *:80>
      DocumentRoot /home/username/Software/website
      ServerName website.demo
    </virtualhost>
  2. Create the hosts file entry
    $ sudo nano /etc/hosts
    127.0.0.1    website.demo
  3. Enable the new VirtualHost
    $ a2ensite website.demo
  4. Restart Apache
    $ sudo service apache2 restart
Now you can go to http://website.demo and you website (which is located at /home/username/Software/website) will be there.

The VirtualHost file

The VirtualHost file (/etc/apache2/sites-available/website.demo.conf) is loaded by apache on startup and serves website.demo on port 80 which means you can visit it via your web browser.
The DocumentRoot entry tells apache where the files for this VirtualHost are located. The ServerName entry tells apache what name to serve the website as.

a2ensite and a2dissite

a2ensite enables a VirtualHost inside your sites-available folder by creating a symbolic link to it from the sites-enabled folder (which apache loads during startup). a2dissite disables a VirtualHost by removing the symbolic link created by a2ensite.

And that's it, you should now be able to create your own VirtualHosts easily.

PHP Factory pattern

What is a Factory?

A factory is in essence a function that returns an instance of an object of the desired type when the class type that you want is unknown. For instance, let's say you have a Staff class with Teacher and Janitor sub-classes. When you fetch the list of all user's from the database and you want to loop through them and create the correct object type for each user without having to write an if-block each time you want to do this. This is where a Factory comes in.

A simple Factory

Again, assuming we have a Staff class with Teacher and Janitor sub-classes:

class Staff {
  public $staffType = 'Staff';
}

class Teacher extends Staff {
  public $staffType = 'Teacher';
}

class Janitor extends Staff {
  public $staffType = 'Janitor';
}
We now want to create a new staff-member object without writing an if block each time, let's build a Factory.
class StaffFactory {

  public static function buildStaffMemberObject (string $type) {
    if ($type === 'teacher') {
      return new Teacher();
    } elseif ($type === 'janitor') {
      return new Janitor();
    } else {
      return new Staff();
    }
  }

}
When we want to create an instance of a new staff-member object we can use:
$teacher = StaffFactory::buildStaffMemberObject('teacher');
$janitor = StaffFactory::buildStaffMemberObject('janitor');
That's it, you have a working Factory that builds objects of the correct type for you.

A more complex Factory

The above example works, but it's lacking in flexibility. Every time you want to add a new type you are going to have to add another condition inside the if/else if block. What if we had a Factory that could dynamically figure out which class type to load, let's take a look:
class StaffFactory {

  public static function buildStaffMemberObject (string $type) {
    $className = ucfirst($type);
    $className = class_exists($className) ? $className : 'Staff';
    return new $className();
  }

}
This time we are checking whether a class by the given name exists in the current namespace, otherwise we default back to 'Staff'. This way when you create a new staff member type, for example, "Management", all you have to do is create and include the class in you script and you can immediately create it via your Factory.

Monday, 10 October 2016

Creating an executable bash script

What is a bash script?

A bash script is an executable script that can be run from the command-line. It can then, in turn perform any other command-line commands. This way you can group commands and add logic around their order of execution, or pass variables to them and act upon those or pass them along to other scripts.

Creating a bash script:

To create a bash script you need to create a file with the extension ".sh".
$ nano script.sh
Now we need to add some functionality to our script, let's keep it simple at first:
clear
pwd
Our command is not quite ready to be run yet, now we need to give the file 'execute' permission, we can do this by running the command:
$ chmod +x script.sh
When we run this command the screen will be cleared and the current working directory will be printed on the screen.
$ ./script.sh
That's it, your bash script is created and you are now able to use it.

Accessing variables

In your script you can access variables passed to it and make decisions based on those variables or pass them along to other scripts. Variables are passed as number in the order that they appear in the given command. Let's build a script that check's out a certain branch in git.
branch=$1
git checkout $branch
Let's execute our command and see that the branch is checked-out:
$ ./script.sh master
Master will now be the checked out branch if we are in a git repository.

Making it more accessible

Creating scripts can be really cool and can help you in automating processes easily, but typing out ./script.sh option option ... can become quite tedious, so let's take a lesson from the bash aliases tutorial and add an alias for our script.
alias sc='~/script.sh'
And now you can execute your script easily by running:
$ sc master

Thursday, 6 October 2016

Bash aliases

What is an alias?

An alias is a bash command that runs one, or many other commands. An alias can also be created as a function and passed parameters.

How to add a new alias:

To create a new alias we want to add it in the correct bash startup file. In some instances (like the Ubuntu 16.04 LTS I am currently running) the default ~/.bashrc file already points us in the right place, it includes a ~/.bash_aliases file if one is present. This is a convenient way to seperate our aliases from the already full ~/.bashrc.

The alias:

Open the ~/.bash_aliases file with your editor of choice
--in terminal
$ nano ~/.bash_aliases

Create a new alias:
--in file ~/.bash_aliases
alias sftw='cd Software';

Close and re-open your terminal window or load the aliases with:
--in terminal
$ . ~/.bash_aliases

Now run the alias from the command line to see it in action:
--in terminal
$ sftw

You can also chain commands as you can in a normal terminal command by adding two ampersands (&&) in-between them:
--in file ~/.bash_aliases
alias startWeb1='cd Software/website1 && npm start'

If ~/.bash_aliases doesn't load

If your ~/.bashrc file does not contain a reference to the ~/.bash_aliases file you can add the reference like so:
--in terminal
$ nano ~/.bashrc

And add the following lines to the end:
--in file ~/.bashrc
if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

Creating more complex aliases with functions

A function can take arguments and make multiple calls, for example:
--in file ~/.bash_aliases
gtst () {
        clear
        git branch 
        git status 
}
gtbr () {
        from=${2:-master}
        if ! `git checkout $1 &> /dev/null`; then
                `git checkout ${FROM}`
                `git checkout -b $1`
        fi
}
In the second function above we set a default value of "master" for variable 2 if no value exists. No alias entry is necessary, the function will be available.

Getting even fancier:

Let's wrap all these into a neat command called 'gt':
gt () {
        local argument2=$2
        local argument3=$3
        st () {
                clear
                git branch
                git status
        }
        br () {
                from=${argument3:-master}
                checkout=`git checkout ${argument2} 2>&1`
                if [ $? -eq 0 ]; then
                        echo "${checkout}"
                else
                        echo "`git checkout ${from}`"
                        `git checkout -b ${argument2}`
                fi
        }

        case "$1" in
                br) br;;
                st) st;;
        esac
}
Now we can call our new gt command from the command line as follows:
$ gt st
$ gt br existing-branch
$ gt br new-branch
$ gt br new-branch from-branch