Pages

Tuesday, February 2, 2016

Evil Traits or Poor Programming Skills

So I came across this nice little article about how evil Traits are, and I thought to my self, here is yet another developer who thinks we should all work in Assembly. Are traits evil? Of cause not. Can they be used in a wrong way? Sure they can. So can functions, classes, interfaces and so on. But you cannot blame traits for peoples bad choices. Now there is a lot of reference in this article to people with C++ background saying how wrong traits are, as these references should some how prove a point? I am positive that I have seen the same points being made against OOP by people with C background.

Let's take an example of trait usage. Let's say that we want to build an OOP database abstraction layer so that we can easily adopt code for other databases. Here is what we need for basic features.
  • Select Query class
  • Delete Query class
  • Insert Query class
  • Update Query class
Also we want some shared tools such as 'compile', so let's make an abstract class that the above mentioned can extend from, let's call this 'QueryBuilder'.

abstract class QueryBuilder {}

class SelectQuery extends QueryBuilder {}
class UpdateQuery extends QueryBuilder {}
class InsertQuery extends QueryBuilder {}
class DeleteQuery extends QueryBuilder {}

What does all 4 classes needs for starters, well the options of choosing one or more tables. No mater the query type, you will need to define at least one table. So this one is best put in 'QuryBuilder'. In the above mentioned article he wrote that one problem with traits was that you could change the access level of methods when adding them to a class. Let's get an example of why this is useful. Most databases, if not all, does not really need multiple tables for an insert operation. If we add table features to the 'QueryBuilder', then this would be possible. Let's go another way. Let's create a trait instead and see where this takes us. We will call this `QueryBuilder_Table` where we use underscore as naming convention since it's a cut of part of 'QueryBuilder'.

trait QueryBuilder_Table {
    protected function table(string $name, string $alias=null) {
        // ...
    }
}

Now that we have the table feature in a trait we can add it in different ways to each class. All 4 classes excepts a table name and an alias in their constructor. But since we have made the 'table' method protected in the trait, we can extend the features in some of the classes by simply changing the access level.

class SelectQuery extends QueryBuilder {
    use QueryBuilder_Table { table as public; }

    public function __construct(string $table, string $alias) {
        $this->table($table, $alias);
    }
}

class UpdateQuery extends QueryBuilder {
    use QueryBuilder_Table { table as public; }

    public function __construct(string $table, string $alias) {
        $this->table($table, $alias);
    }
}

class DeleteQuery extends QueryBuilder {
    use QueryBuilder_Table { table as public; }

    public function __construct(string $table, string $alias) {
        $this->table($table, $alias);
    }
}

class InsertQuery extends QueryBuilder {
    use QueryBuilder_Table;

    public function __construct(string $table, string $alias) {
        $this->table($table, $alias);
    }
}

Now your able to define multiple tables in classes such as 'Select', but not in 'Insert' while using the same trait. Could this be done with normal inheritance, sure it could, but we are not done yet. Also I might add that extending a class with normal inheritance also allows you to change the access level. So if this is something that makes traits evil, then maybe someone should read a little more about the options with class inheritance.

Fields is another great thing to add to a query, but we have two different scenarios. 'Select' for example defines fields/columns that should be returned while 'Insert' and 'Update' defines fields to insert/update with a value. So for this we make two traits 'QueryBuilder_Field_Selectable' and 'QueryBuilder_Field_Updatable'.

trait QueryBuilder_Field_Selectable {
    public function field(string $name, string $alias=null) {
        // ...
    }

    public function fields(string ...$name) {
        // ...
    }
}

trait QueryBuilder_Field_Updatable {
    public function field(string $name, $value) {
        // ...
    }
}

Of cause we exclude 'Delete' as it does not need either of these options. Let's move on to conditions, something needed for 'Select', 'Update' and 'Delete'. Again we create a trait 'QueryBuilder_Conditional'.

trait QueryBuilder_Conditional {
    public function condition(string $field, $value, string $operator="=") {
        // ...
    }
}

We could go on from here and add more, like join features etc. But let's move along to something else. We have 3 classes that share one thing, 'Delete', 'Update' and 'Insert' does not need to return a result set. Instead they would be better of returning a number of affected rows. This is a feature that is actually worth checking for, so it would not be well placed in a trait. Instead we create another abstract class named `QueryExecuter` that extends from `QueryBuilder` with a method called `execute()`. At the same time we add a similar `enquire()` method to 'Select' that returns a result set. This leaves us with 5 actual data types 'QueryBuilder', 'QueryExecuter', 'Delete', 'Insert', 'Update' and 'Select'.

abstract class QueryExecuter extends QueryBuilder {
    public function execute(): int {
        // ...
    }
}

The great thing about using traits in this way, is that we get a proper separation of the different functionality. Sure 'Update' and 'Select' could have a shared class with conditional options like a `QueryConditional` for example. But that would actually be wrong and provide a very poor design. You would be better of implementing the features separately in each class. Even though they share some similar methods, the functionality they use those methods to provide is completely different. One updates a set of rows/columns while the other fetches and returns a set of rows. So when would it ever make sense to check for 'QueryConditional'. Using traits they can share these tools without having any relation with one another. Sharing 'QueryExecuter' does make sense, because it provides the exact same functionality. It executes the query and return the number of rows affected by it.

In the above mentioned article, one of the claims for traits being so evil was that classes does not inherit the data type of a trait. Well thats sort of the point, and when used correctly it's actually a good thing. You are not meant to check for options provided by traits. You are meant to check for options provided by a specific class. How that class obtains those options is beside the point.

Let's take a last look at the first example. We could have added the 'table()' feature to 'QueryBuilder' as with a protected access level and then overwrite 'table' as public and call `parent`. But there are two things that traits does better in this scenario. Firstly you don't need to overwrite it and make an additional call to 'parent' in order to change the access level. Secondly what if you want to use 'QueryBuilder' for something else that should not have 'table' options. Maybe create a 'Condition' class that can be used to add multi-level conditions.

In this case you could extend your 'QueryBuilder_Conditional' to except 'QueryBuilder' instances, and you could use your 'QueryBuilder_Conditional' trait within your 'Condition' class to gain the conditional features. Remember that 'QueryBuilder' is used to provide the 'compile()' feature, which is not exclusive to 'QueryExecuter' or the other classes that we have made so far.

trait QueryBuilder_Conditional {
    public function condQuery(QueryBuilder query) {
        // ...
    }

    ...
}

class ConditionQuery extends QueryBuilder {
    use QueryBuilder_Conditional
}

In conclusion Traits are in no way evil. They are a brilliant addition to PHP and will save people a lot of time. Sure they can be used wrong, but as mentioned above so can everything else.

Monday, June 15, 2015

Facebook remains in the dark ages

What is HTML5? Most people would be able to answer this question, whether they are highly educated IT professionals or a hobby programmer, but at Facebook it seams as if they are still struggling with this strange concept.

The thing that I love the most about HTML5, is the fact that we no longer need any plug-ins to be installed in browsers. It's canvas and socket features replaces the old and terrible Java Applets. Don't get me wrong, I love Java. It's a nice programming language and it's great when you want to easily port programs across multiple architectures. But the Java Applets is one of the worst thing ever created, next to Microsoft's ActiveX (Along with their Browser). It will not be missed. The HTML5 Video and EME features replaces both Flash and Silverlight. Both of which brings nothing but instability and security vulnerabilities.

For a long time now, I have not had any plug-ins installed in my browser and I have not had any reason to. It seams that the vast majority of websites has either switched to full HTML5 or at least provide this as a second option. The few sites that don't, are not very important. At least that has been my observation until today.

My brother wanted to show me a video on my laptop. He navigated to Facebook and logged into he's account. He then searched for a specific video and tried to play it, but it wouldn't start because Flash is not installed in my browser. I don't use Facebook myself, so I have never noticed this. But Facebook, one of the worlds largest websites, do not have any support for HTML5 playback. Personally I have never liked Facebook, I cannot say why as I don't really know it myself. Nevertheless I have always pictured them as technologically advanced. Properly because I could not imagine a website being able to reach this magnitude of popularity while falling behind in this area. They proved me wrong.

Why am I writing about this? I have no idea. Maybe it's just the chock getting to me. Next to Google/Youtube, this was the last place that I would ever expect to be so far behind in technology. I mean this is freaking Facebook that we are talking about, and their only video solution is Flash? A technology that should have been extinct by now. And this is just the observation I made in the 2 minutes that my brother was trying to get this video to play. This is something that I would have expected from a small personal site where the owner had not yet had the time or resources to make the switch. But even those sites are up-to-date. The only one missing is the one that should have plenty of resources and highly skilled personal to do it, although I am starting to doubt the later.

Wednesday, May 27, 2015

The world of Root and Xposed Bridge

People have a tendency to install and enable things that they do not fully understand. In this article I will try to explain just what Root and Xposed Bridge is and how dangerous it can be. Don't get me wrong, I love both of these things, but it is important to be careful and not grant just any application these types of rights.

Let's picture a small village. In the middle of this village is a large bank. It is surrounded with a lot of smaller buildings. The bank represents the core Android system while the buildings are all of the Applications. All the people within each building can communicate with one another since they are all within the same building. If a building needs to communicate with another building, it has to send someone across town to the other building. It is then up to the people in that building to decide whether or not they want to let that person inside. While inside, the person can make a request or a delivery. Maybe he wants to borrow some sugar. He then delivers the response (in this case the sugar) back to his building. The same applies for the bank which is surrounded by guards. To make a request for a specific item in the bank, a building will need a permission slip for that item in order to bypass the guard watching it.

One building however has an Xposed Module implemented. In this case it is a specific type of person, I spy if you will. The building can send this person over to the bank and make him act as a guard. The bank and it's other guards will not not sense that anything is wrong. This spy can now move around in any section of the bank without any permission slip. He can steel items, place new items or make changes to the existing once without anyone asking questions. He can also disguise himself as a member of other buildings and walk around those without an invite. This spy is essentially a god amongst men.

In Android it allows applications to provide features not normally available, like changing theme and colors in any part of the system, create security modules that can restrict other applications from gathering specific information and much more. But it also allows application to do things that you might not want it to, like gathering information and uploading it to a server. Since the module can do whatever it wants, there is no way to restrict it.

Root is similar. It is the main built-in Administrator in the Linux kernel (Which Android is built on top of). In this case it acts as the emperor of the village. It is the main authority in the system and no one would dare to tell it no. It can move, do and behave just as it feels like without no one trying to stop it. The most important thing to note here is that Xposed Modules is able to acts as root, even if the device is not rooted. It is also important to note that gaining root via Xposed Bridge will not trigger your normal Root Popup window on rooted devices. So you will not even know that this has happened.

There is no doubt that devices with Xposed Bridge and Root enabled are much more fun. This article is not meant to scare anyone from rooting their devices or install Xposed Bridge on them. It is meant to inform people about the danger of doing so to make them more aware next time they enable an Xposed module or grant root to an application asking for it. Make sure that the application in question can be trusted, which most importantly mean that you should not allow this for Closed Source applications. If the source codes are close, there is no telling what has been implemented into the application.

So the next time you think about enabling an application in Xposed Bridge or grant root to an application, do some research first. Make sure that you can find a link to the source codes, make sure that the developer is contactable, do some searches to make sure that others have not warned about this application.

In any case, do not just blindly enable whatever the application asks for.