Thursday, 14 June 2018

Coupling



In a nutshell coupling is about how strongly connected are different program elements to one another.

In this article we will talk about the different types of coupling found in our classes and reason about them.


  • Note that not all forms of coupling are problematic as it is a natural part of software development. 
  • Reasoning about coupling can improve the overall quality of our code and make our code easier to test, evolve and to reuse.



Types of coupling

 

  • Data coupling              [usually harmless]
  • Stamp coupling           [usually harmless]
  • Control coupling         [kind of disturbing]
  • Global coupling           [disturbing]
  • Content coupling         [insidious]
In the above list we have the types of coupling ordered from harmless to insidious.

Note that Data and Stamp coupling are usually harmless and can be a part of a healthy software . 

If the code is too coupled even simple changes are made challenging, imagine fixing one bug in class X and after you change code in the class alone you realize that classes A and B as well need to modified even if there is no logical connection between the classes.

Reusing coupled code is problematic as well : If you try to reuse class X and to make it work you spend hours to realize that is so coupled that you need to get a ridiculous amount of dependencies as well.

Having classes with too much baggage is not cool for your day to day activities as well.


Coupling is EVERYWHERE!


Lets talk about them

 





Data coupling

 

Classes share data through primitive parameters.

checkInClass(name:string,classId:number){
// interesting stuff going on here
}

 

Stamp coupling

 

 The classes are sharing data structures.

addHobby(hobby:Hobby){
// interesting stuff going on here
}


 

Control coupling

 

The caller controls the flow within another unit and needs implementation details.

addHobby(hobby:Hobby, schoolActivity:boolean){
// if statement is checking the boolean 
// but needs to know the internals of Hobby!
}

Here you can see that the addHobby method requires to know implementation details about Hobby in order to do it's task.

Global coupling

 

This Coupling is introduced due the usage of a global variable and that makes it hard to reason about the data flow and makes the code harder to reuse and test.

Global variables might change during the code's execution resulting to unpredictable and faulty behaviours.



Content coupling

 

The internal state of a class is getting altered directly by another class instead of using a method, this is a sign of broken encapsulation and information hiding.

This is the pinnacle of having a messed up code and probably you have lots of headaches when trying to work with this code.

Code like that is usually the "Don't touch it , if it works" kind of code and even Senior Developers avoid it using all means necessary.


class Student {


addHobby(hobby: Hobby, schoolActivity: boolean) {
//
}
manageHobby(hobby: Hobby, newName: string) {
hobby.name = newName;
}
}

class Hobby {
name: string = '';
setHobbyName(name: string) {
this.name = name;
}
}


manageHobby is directly alters hobby instead of using the method setHobbyName!


Reason about it

 

Look at your code when identifying coupling and reason when if there is a better way to do it, usually applying design principles can help you to overcome the problem at hand.

Here are some examples:

Single Responsibility: For example if a class is doing 3 - 4 different things you need to split up the functionality to new classes or to add some of it to existing ones.

Dependency Inversion: Is it really necessary for your given class to depend on concrete types ? Or by using interfaces can help to make your code more extensible and reusable ?

Wednesday, 6 June 2018

Testable Code 101

Testability is all about making our code (and our system eventually) to be easy to test.

Why?

 Testable code is an investment that will benefit your team and project in various ways, it can even make your grumpy project manager happy.
  • Testable code is more organized and will put us in the process of splitting our code's functionality to small, manageable and reusable components leading to more robust designs.
  • Refactoring your code is easier and you can verify on the spot if something is wrong thus saving you precious time and effort.
  • Writing your tests is faster and simpler.
Testable code has the following properties:
  • Controllability : Is the extend of our ability to execute the code under test with the states and parameters we care about.
  •  Observability: The behaviors of our code that can be verified. 
  • Isolateability: Failures can be isolated from each other.
  • Automatability: How able we are to automate our tests.





Examples of code being improved


Controllabity Example:

 

Our Function checks is it is Monday: if it is Monday returns true otherwise false.
This code is not testable : we have no control over the date object.
The CONTROLABILITY attribute is missing!
This function will return true once a week and is not reliable for testing!!
function isMonday():boolean{
let date = new Date();
return date.getDay() === 1;
}
Now we have refactored our code to be more controllable : we now pass a date object.
We can create reliable test cases for this function because we have control over the date object used in the function.
function isMonday(date:Date):boolean{
    return date.getDay() === 1;
    }

Observabillity Example:

 

The setName method is not observable, so we can't verify that the name is assigned.
We have made the name field public and this is a BAD IDEA to be able to test our method
class Student{
    public name: string = "";
    
     setName(name:string){
         this.name = name;
     }

}
So in our test suite we have something like:
let student = new Student().setName('Patrick');
expect(student.name).to.equal('Patrick');
we use the name field. There has to be a better way!

We refactored our code and now we can verify that the name is assigned while our name field remains private!
class Student{
    private name: string = "";
    
     setName(name:string):string{
         this.name = name;
         return this.name;
     }
}
Now we can test the method:
let student = new Student();

expect(student.setName('Patrick')).to.equal('Patrick');

 

Isoletabillity

 

Isoletabillity can be achieved by splitting large methods to smaller components enabling us to better trace where a fault is located.
If you have a method of 80+ lines of code there are various things that are going on in there. So it's not easy to find where the fault is located.
If we split the functionality inside the method using helper methods we can better test and understand where things gone bad.
Note here our enrollStudent method: if something fails in there can be a fault in setting the school functionallity , setName or Both. This method has no isoletabillity!
class Student{
    private name: string = "";
    
     setName(name:string):string{
         this.name = name;
         // 20 lines of functionallity

          return this.name;
     }




     enrollStudent(name:string,schoolID:number){
         this.setName(name);
        // set the school functionallity
        // lots of things here
        // like 30 lines of code
     }
}
Refactoring our code now our method is using helper methods to achieve the same functionality but now we can better test the method and it's helpers to be able to effectively trace the fault.
class Student{
    private name: string = "";
    
     setName(name:string):string{
         this.name = name;
         // 20 lines of functionallity
         return this.name;
     }


     setSchool(id:number){
         // lots of things here
          // like 30 lines of code
        
     }


     enrollStudent(name:string,schoolID:number){
         this.setName(name);
         this.setSchool(schoolID);
     }
}

 

Automatabillity

 

The goal is to be able to automate testing our functionality, to strive for code that can be tested and verified programmatically.
Assume we are developing a weather application , instead of relying on the actual api and having delays , network errors and other things out of our control, we can build our own mock api to simulate the functionality and to be able to better automate the testing process.

Friday, 1 June 2018

Software Requirements 101



The requirements should: Define what the system is doing but Not how is done!


Functional :


The Functional Requirements capture what the system should do
Examples :
"We want our users to be able to log in using a single click"
"User should be able to view his/her purchase history on history tab"
Those would be great functional requirements.

Non Functional :

 

The Non Functional Requirements are about the qualities our system should have
  • Usability
  • Performance
  • Security
  • Complexity
  • Reliability
  • Test-ability
Different stakeholders will care about different qualities for example: The customer will care more about Usability, Performance and Security but the Development team will care more for Test-ability and Complexity .

It's important that all the stakeholders involved are to weigh the pros and cons of each of these requirements. Because these decisions that you make will often be at the expense of one or another.

And make sure that each quality is testable : How can you measure Performance ? Is it about the response time, the throughput, the memory size in the disk or in RAM ? Some or all of them?
Capture them using means that are measurable : the size, the time etc.. so you can actually know what the customer means and you can actually verify that you deliver what agreed.

Each quality should be defined

Examples :

Performance is :
  • Response time to be less than 100ms
  • System should not consume more than 256MB of RAM

Usability is :
  • User can navigate anywhere using at most 3 clicks
  • User can order products with 2 clicks

 

Design Constraints :


Constraints that will affect your design
  • Regulatory
  • Internal Processes
  • Budgetary Constraints

 

Environmental Constraints :

 
  • Is the system required to work with other systems (internal or external) ?
  • Where our system is deployed (OS, Customer premises, Third Party Service provider,etc..)?

 

Preferences :


Preferences are about customer priorities or anything that can change the order of the system implementation.
Example:
Order of feature implementation as instructed by the customer : most important features to be implemented first.

 

Requirements Properties


Important properties that well defined requirements must have
  • Complete
  • Consistent
  • Precise
  • Concise

Wednesday, 9 May 2018

Typescript boilerplate

A simple boilerplate for Typescript projects with Mocha, Chai and coverage report using nyc


As part of learning Typescript i came across of finding my self a hard time to setup all the tools to practice my coding skills. After a lot of trial and error i found the way to setup a simple yet usable environment for my projects.
Use this boilerplate and get coding asap instead of wasting your time!



What is included ?

 

  • Testing : Test your app with Mocha and Chai... directly in Typescript!
  • Coverage report : Take your testing to the next level and get coverage reports to improve your codes quality
  • Build your files : Build your typescript files with a single command

How to use

 

Setup the boilerplate

git clone https://github.com/Cyb3rN4u7/typescript-mocha-chai-nyc-boilerplate.git
cd typescript-mocha-chai-nyc-boilerplate
npm install
 

Useful scripts included

 

Build Typescript project

npm run build

Run Tests

npm run test

Run Coverage report

npm run coverage
After open the index.html in the coverage folder with your favourite browser to see the report!

Friday, 13 April 2018

Google play ratings are broken

Google play is undoubtedly the largest market for android apps , while Google has made relatively easy for anyone to publish their app the rating system is kind of broken.


Publishing your app

 


After you publish the app and is available in the store nobody is installing it because is not visible as play store has a ranking system based on different variables like : size, SEO, Ratings and others... those are important but the most important is the rating the app is receiving by the users.

The impact of rating

 

"The quest of 5 star ratings begins"

Users avoid apps with poor or no rating , plus the number of installs an app has makes it more likely to be installed : the more the merrier. You might think : "Why is this a problem?" well think that an app when published has no ratings or installs that makes getting users very difficult as the store puts the app way below other apps with better ratings and installs.
So you get to the point where your app is "available" but almost nobody installs it, you can get friends and family to install it and give ratings and the app becomes more visible and more people start to use it.
But the process is SLOW and as a dev probably you do it for a living , so you use adwords to get more users : people start to install the app and the visibility is improved to the point you have a fair number of organic installs, Things got well till now.
Till one day you start getting 1 star ratings with NO FEEDBACK and all your effort is wasted... This can happen for 3 reasons :
  • Users are not happy with the app
  • User expected the app to be something else
  • Sabotage

Enter the world of PAYED RATINGS

 

"You can pay for ratings , it happens a lot!"

While Google can remove ratings of 4 and 5 stars coming from countries that provide payed ratings services , they DON'T REMOVE the bad ones! That makes you vulnerable to get bad ratings and kind of makes devs to pay for ratings to have their app being available to more users.

"Bad ratings are staying there forever to haunt you"


Google should make some changes to the app rating system :

 

  • Feedback should be mandatory
  • Bad ratings should be reviewed like the good ones
  • Instead of a "submit" in the rating form should have a "liked" if given 4 or 5 stars and "disliked" in all other cases.
  • When a bad rating is given the user should be provided with the option of contacting the developer about the issue instead of rating the app

"The 1 star rating bullying is real"


There are solutions and i hope that one day the rating bullying will stop and all devs will have equal opportunities in the play store.
What do you think about the play store rating system?

Monday, 5 March 2018

Lost key-store or key pair?

If you had this experience , it's frustrating ...
Without your key-store and key-pair you can't even update your application, publishing a new app is out of the question.
 
While it's not possible to recover your lost key-store or key pair there is a solution for this problem.

What you will need to do


If you didn't lost the key-store skip step 1
Step 1 : Create a new key-store 
Step 2:  Generate a new key-pair 
Step 3:  Extract the certificate of the key-pair to pem format 
In command line type :
keytool -exportcert -rfc -alias <upload> -file <upload_certificate.pem> -keystore <keystore.jks>

 
Step 4:  Contact Support Team by filling this form 

You should attach the exported certificate you created on step 3 and describe the problem in the form.
The support team responds usually in 2 working days

Step 5:  Avoiding future headaches

Always keep a copy of your key-store and your passwords in a safe location , i personally use google drive. 

More info:

https://support.google.com/googleplay/android-developer/answer/7384423

Saturday, 24 February 2018

Pick an Image for Android


In this simple tutorial you will learn how to  create an image picker for android !
Creating an image picker for your app is simpler that you might have expected, by using a real working app you can see how you can implement it for your own projects.






Todo list

  •  Add permission WRITE_EXTERNAL_STORAGE
  •  create a button and an imageView
  •  launch an intent on button click
  •  get the result and update the imageView



Implementation


Permissions : Add this permission to your AndroidManifest.xml :

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

In our Main Activity we have a button and an image view , when we click our button we will prompt our user to select an image :


Intent intent = new Intent(Intent.ACTION_PICK,
        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

startActivityForResult(intent, IMG_RESULT);

because we care about the image our user selected we will retrieve it using onActivityResult :

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 try {

    if (requestCode == IMG_RESULT && resultCode == RESULT_OK && null != data) {
  
// get the selected image

Uri imageUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
 
// display the image

imageView.setImageBitmap(bitmap);

} catch (Exception e) {
    Toast.makeText(this,"oops something went wrong", Toast.LENGTH_LONG)
            .show();
       }
} 
 


Now our users can select images from their devices using our cool app... Well done!


Get the code on Github

You can see the applications code for reference here :

Happy coding!