Tuesday, December 18, 2018

Dependency Injection Principle

This is that last part of a five part series about SOLID class design principles by Robert C. Martin. The SOLID principles focus on achieving code that is maintainable, robust, and reusable. In this post, I will discuss the Dependency Inversion Principle.
The Dependency Injection Principle (DIP): High level modules should not depend upon low level modules. Both should depend upon abstractions.
Imagine a world without plugs and sockets. The computer is directly soldered into an electrical wire in the wall. Whenever you buy a motherboard you also get a mouse, keyboard and monitor, but they're all directly soldered onto the motherboard by the manufacturer. Everything works fine, but things get complicated when you want to remove or replace anything. If you try to replace the mouse:
  • You risk damaging the motherboard
  • It takes forever to solder
  • Soldering is error prone because the new mouse has different wires
A world without plugs and sockets sounds ridiculous. Yet we programmers have a tendency to pull out the metaphorical soldering iron and hard-wire our classes together as we're making them. If the classes are hard-wired together, and you want to replace one of them:
  • You risk damaging code that uses the class
  • It takes forever to find and change every place that the class is used
  • Inserting the replacement class is error prone because it is slightly different to the old class
The Dependency Injection Principle is basically a way of adding plugs and sockets to your code. It allows you to create your high level modules (the computer) independent of the low level modules (the mouse). The low level modules can be created later, and are easily replaceable.

Interface Segregation Principle

This is part four of a five part series about SOLID class design principles by Robert C. Martin. The SOLID principles focus on achieving code that is maintainable, robust, and reusable. In this post, I will discuss the Interface Segregation Principle.
The Interface Segregation Principle (ISP): Clients should not be forced to depend upon interfaces that they do not use.

The "fat interfaces" — interfaces with additional useless methods — lead to inadvertent coupling between classes. This is the real reason why the ISP should be adhered to. Coupling is the bane of reusability. Fat interfaces also introduce unnecessary complexity, which isn't good for maintainability or robustness.

Liskov Substitution Principle

This is part three of a five part series about SOLID class design principles by Robert C. Martin. The SOLID principles focus on achieving code that is maintainable, robust, and reusable. In this post, I will discuss the Liskov Substitution Principle.
The Liskov Substitution Principle (LSP): functions that use pointers to base classes must be able to use objects of derived classes without knowing it.
Subtype Requirement:
Let be a property provable about objects of type T. Then should be true for objects of type S where S is a subtype of T.  

When first learning about object oriented programming, inheritance is usually described as an "is a" relationship. If a penguin "is a" bird, then the Penguin class should inherit from the Bird class. The "is a" technique of determining inheritance relationships is simple and useful, but occasionally results in bad use of inheritance.

The Liskov Substitution Principle is a way of ensuring that inheritance is used correctly.

Open Closed Principle

This is part two of a five part series about SOLID class design principles by Robert C. Martin. The SOLID principles focus on achieving code that is maintainable, robust, and reusable. In this post, I will discuss the Open Closed Principle.
The Open Closed Principle (OCP): You should be able to extend a classes behavior, without modifying it.
The OCP is sometimes alternatively defined as:
A class should be open to extension, but closed to modification.
Robert Martin sums up the rationale for the OCP like this:
"When a single change to a program results in a cascade of changes to dependent modules, that program exhibits the undesirable attributes that we have come to associate with 'bad' design. The program becomes fragile, rigid, unpredictable and unreusable. The open-closed principle attacks this in a very straightforward way. It says that you should design modules that never change. When requirements change, you extend the behavior of such modules by adding new code, not by changing old code that already works." — Robert Martin

The Benefits

As stated by Robert Martin, classes that must be modified to accommodate new changes are fragile, rigid, unpredictable and unreusable. By insulating the class from changes, the class becomes robust, flexible, and reusable. Also as no modifications are made to the code no bugs can be introduced, leading to code that only becomes more stable over time through testing. The ability to reuse a class that has been working for years without modification is clearly preferable to modifying the class every time requirements change.

Single Responsibility Principle

This is part one of a five part series about SOLID class design principles by Robert C. Martin. The SOLID principles focus on achieving code that is maintainable, robust, and reusable. In this post, I will discuss the Single Responsibility Principle.
The Single Responsibility Principle (SRP): A class should have one, and only one, reason to change.
The SRP is roughly the same as having "high cohesion". A class is said to have high cohesion if it's behaviours are highly related, and strongly focused. The SRP states that a class should be cohesive to the point that it has a single responsibility, where a responsibility is defined as "a reason for change."

The Benefits

  • The class is easier to understand
    When the class only does "one thing", its interface usually has a small number of methods that are fairly self explanatory. It should also have a small number of member variables (less than seven-ish).
  • The class is easier to maintain
    Changes are isolated, reducing the chance of breaking other unrelated areas of the software. As programming errors are inversely proportional to complexity, being easier to understand makes the code less prone to bugs.
  • The class is more reusable
    If a class has multiple responsibilities, and only one of those is needed in another area of the software, then the other unnecessary responsibilities hinder reusability. Having a single responsibility means the class should be reusable without modification.

F.I.R.S.T rules of unit tests

Unit tests are required to test singular sections of code. They provide confidence to programmers, allowing changes to be made. And by running tests throughout development, any changes that break the tests can be re-evaluated, whether that results in the production code being corrected or altering the test to make it pass. In this post, I will discuss the FIRST rules that are defined in the book Clean Code written by Uncle Bob Martin.

FIRST means that tests should be:
  • Fast: Tests should be fast enough that you won't be discouraged from using them. If you are making changes to a class or method that has a few tests attached to them, you are much more likely to run those tests after making changes if they take about a second to run, compared to slower tests that cannot only take a while to initialize, but each test case could also take over 1 second to run. For example, I have run integration tests that would take 20+ seconds to run and I hated having to run them after code changes. Unit tests, however, do not have to test multiple components like integration tests do and, therefore, keeping them running in under 1 second should be possible.
  • Independent: Tests should not depend on the state of the previous test, whether that is the state of an object or mocked methods. This allows you to run each test individually when needed, which is likely to happen if a test breaks, as you will want to debug into the method and not have to run the other tests before you can see what is going wrong. If you have a test that is looking for the existence of some data, then that data should be created in the setup of the test and preferably removed afterward so as not to affect the later tests.
  • Repeatable: Tests should be repeatable in any environment without varying results. If they do not depend on a network or database, then it removes the possible reasons for tests failing, as the only thing they depend on is the code in the class or method that is being tested. If the test fails, then the method is not working correctly or the test is set up wrong — and nothing else.
  • Self-validating: Each test will have a single boolean output of pass or fail. It should not be up to you to check whether the output of the method is correct each time the test is run. The test should tell you if the result of the test was valid or not. This is normally done using asserts such as assertTrue or assertEquals, which will cause the test to pass or fail depending on their results.
  • Timely: Unit tests should be written just before the production code that makes the test pass. This is something that you would follow if you were doing TDD (Test Driven Development), but otherwise it might not apply. I personally do not use TDD and therefore I always write my tests after writing my production code. Although I can see the reasons for following this, I believe this is the rule that could be skipped if not appropriate.

Monday, December 21, 2015

Formal Protocol vs Informal Protocol

Category is an extension for class functionality - this is an implementation of some methods:
@interface NSObject (MyCategory)
  - (void)doSomething;
@end

...

@implementation NSObject (MyCategory)
  - (void)doSomething {
    // do something...
  }
@end

Formal protocol is something completely different. If you are familiar with some other object oriented language then it is like interface (in Java, C++, C# etc.).
Protocol may be attached to any class implementation like this:
@protocol MyProtocol
@required
- (void)doSomething;
@optional
- (void)doSomethingOptional;
@end

...

@interface MyClass : NSObject <MyProtocol> {
}
@end

...

@implementation MyClass
  - (void)doSomething {
    // do something...
  }
@end

According to the documentation, the informal protocols ARE categories of NSObject class (I've never used this approach):
@interface NSObject (MyInformalProtocol)
- (void)doSomething;
@end

...

@implementation NSObject (MyInformalProtocol)
  - (void)doSomething {
    // do something...
  }
@end