Skip to content

Contribute

undergroundwires edited this page Feb 4, 2020 · 23 revisions

How to contribute

Join the coding process

Fork it

  1. Fork it.
  2. Create a branch (git checkout -b my_safeorbit_branch)
  3. Commit your changes (git commit -am "Added cool stuff")
  4. Push to the branch (git push origin my_safeorbit_branch)
  5. Open a Pull Request
  6. Relax and wait

Coding conventions

Constructor injection

SafeOrbit uses a constructor injection pattern for more testability and inner security.

Suggested pattern

SafeOrbit uses a very simple and easy way to achieving testability : internal constructors for dependencies/tests, parameterless constructors for production.

  1. You create your unit-testable internal constructor and inject dependencies for internal test mode:

  2. You inject the dependencies from constructors for the production mode. It allows the library user to use the simple constructors and makes the library take advantage of SafeContainer protection:

    public class SafeOrbitClass
    {
       // For internal testing
       private readonly IInjectedService _injectedService; // Consume this
       internal SafeOrbitClass(IInjectedService injectedService)
       {
          _injectedService = injectedService;
       }
       // For production mode
       public SafeOrbitClass { } : this(LibraryManagement.Factory.Get<IInjectedService>());
    }
  3. If the type is not registered in the library then you must register it in FactoryBootstrapper.cs as following :

       public class FactoryBootstrapper
       {
          public static void Bootstrap(ISafeContainer safeContainer)
          {
             ..
             safeContainer.Register<IInjectedService, InjectedService>();
             ..
             }
       }

See also : SafeContainer

Tests

It's much appreciated that you test your code. There are three kind of tests for SafeOrbit:

  1. Unit tests
    • Unit tests for the code/functionality of a single class.
    • See suggested pattern for creating unit testable classes.
    • The project is aware of internal code of SafeOrbit.
  2. Integration tests
    • Tests where you test classes with satisfied dependencies and their integration.
    • This library is not aware of internal code of SafeOrbit.IntegrationTests.
  3. Performance tests
    • These are experimental tests and the results may vary for the computers.
    • You can measure and test the performance of the classes against a target goal.
    • The project is not aware of internal code of SafeOrbit.
  4. Test apps
    • They exist in tests/apps folder and they're stand-alone app's that tests and shows data.

Naming

The naming convention for tests are: UnitOfWork_StateUnderTest_ExpectedBehavior that's suggested by Roy Oshrove. It produces names like Remove_IndexParameterHigherThanLength_ThrowsArgumentOutOfRangeException.

Arranging

The AAA (Arrange, Act, Assert) pattern is the preferred way of writing tests.

  • Arrange your objects, creating and setting them up as necessary.
  • Act on an object.
  • Assert that something is as expected.

An example is:

    [Test]
    public void Clear_OnDisposedObject_ThrowsObjectDisposedException()
    {
        // Arrange
        var sut = GetSut();
        sut.Dispose();

        // Act
        void CallOnDisposedObject() => sut.Clear();

        // Assert
        Assert.That(CallOnDisposedObject, Throws.TypeOf<ObjectDisposedException>());
    }

Strong name signing

All SafeOrbit assemblies are strong-named.

The assemblies are only signed for RELEASE builds.

The reasoning is that:

  1. Identity. To maintain type identity with previous versions of our assemblies that's been shipped as various versions. It provides the ability to consume and run libraries built against the previous identities. It allows to load two versions of the same assembly within the same process, allowing users to use two versions of the same class without collisions.

  2. Compatibility. To enable assemblies to be referenced by strong-named assemblies

The private key is checked in the repository. It's a common misconception to take signing assemblies as a security practices but they are used for identity rather than security. A strong name helps to provide a unique identity for an assembly. The purpose of strong named assemblies is to be able to differentiate among versions of the same assembly, not to determine the creator of it.

Donate

Buy me a coffee

Donate