Friday, March 17, 2017

Large Scale C++ Projects II

In the previous post, we discussed Levelization to help reduce link-time dependencies in Large Scale C++ Projects. Now let's build here to discuss Insulation techniques to help reduce compile-time dependencies.

Insulation
Insulation is the process of avoiding or removing unnecessary compile-time coupling.
Insulation is a physical design issue whereas encapsulation refers to logical design.

If a component can be modified without forcing clients to recompile is said to be insulated.
The following sections list techniques to minimize excessive compile-time dependencies:

Remove Private Inheritance
Private Inheritance exposes some but not all functions in private base class to clients of derived class.
 // base.h
 #ifndef _INCLUDED_BASE
 #define _INCLUDED_BASE





 class Base
 {
 public:
     Base()  {}
     ~Base() {}

     void f1(int);
     int f1() const;
 };
 #endif//_INCLUDED_BASE
 // myclass.h
 #ifndef _INCLUDED_MYCLASS
 #define _INCLUDED_MYCLASS

 #ifndef _INCLUDED_BASE
 #include "base.h"
 #endif//_INCLUDED_BASE

 class MyClass : private Base
 {
 public:
     MyClass() {}
     Base::f1; // access declaration



 };
 #endif//_INCLUDED_MYCLASS

However, the same logical interface can be achieved without exposing clients to details of the class.
 // myclass.h
 #ifndef _INCLUDED_MYCLASS
 #define _INCLUDED_MYCLASS

 class Base;

 class MyClass
 {
 public:
     MyClass();
     MyClass(const MyClass& c);
     ~MyClass();

     MyClass& operator=(const MyClass& c);
     void f1(int i);
     int f1() const;

 private:
     Base* p_base;
 };
 #endif//_INCLUDED_MYCLASS

Instead of privately deriving from Base, an implementation now holds an opaque pointer to Base;
New member functions of MyClass are defined (out-of-line) to forward calls to functions in Base.
 // my_class.c
 #include "myclass.h"
 #include "base.h"

 MyClass::MyClass()                 : p_base(new Base) {}
 MyClass::MyClass(const MyClass& c) : p_base(new Base(*c.p_base))  {}

 MyClass::~MyClass()
 {
     delete p_base;
 }

 MyClass& MyClass::operator=(const MyClass& c)
 {
     if (this != &c)
     {
         delete p_base;
         p_base = new Base(*c.p_base);
     }

     return *this;
 }
 void MyClass::f1(int i)
 {
     p_base->f1(i);
 }
 int MyClass::f1() const
 {
     return p_base->f1();
 }

Remove Embedded Data Members
Insulate clients from an individual implementation class:
  • Convert all embedded instances of that implementation class to pointers (or references)
  • Manage those pointers explicitly in constructors, destructors and assignment operators

That is, convert HasA relationship to HoldsA to improve insulation.
Here, compare before insulating clients of class to after insulation.
 // myclass_before.h
 #ifndef _INCLUDED_MYCLASS_BEFORE
 #define _INCLUDED_MYCLASS_BEFORE

 #ifndef _INCLUDED_YOURCLASS
 #include "yourclass.h"
 #endif//_INCLUDED_YOURCLASS

 class MyClass
 {
 public:
     MyClass();
     ~MyClass();
     int getValue() const;
     int getCount() const
     {
         return count;
     }

 private:
     YourClass yours;
     int count;
 };
 #endif//_INCLUDED_MYCLASS_BEFORE

 // my_class_before.c
 #include "myclass_before.h"


 MyClass::MyClass()
 {

 }
 MyClass::~MyClass()
 {

 }
 int MyClass::getValue() const
 {
     return yours.getValue();
 }
 // myclass_after.h
 #ifndef _INCLUDED_MYCLASS_AFTER
 #define _INCLUDED_MYCLASS_AFTER


 class YourClass;


 class MyClass
 {
 public:
     MyClass();
     ~MyClass();
     int getValue() const;
     int getCount() const
     {
         return count;
     }

 private:
     YourClass* p_yours;
     int count;
 };
 #endif//_INCLUDED_MYCLASS_AFTER

 // my_class_after.c
 #include "myclass_after.h"
 #include "yourclass.h"

 MyClass::MyClass()
 {
     p_yours = new YourClass;
 }
 MyClass::~MyClass()
 {
     delete p_yours;
 }
 int MyClass::getValue() const
 {
     return p_yours->getValue();
 }

Remove Private Member Functions
Private member functions, although encapsulated, are part of the component's physical interface.
Instead of making functions private, make them static free (non-member) declared at file scope.

Compare an original class, modified with only private static functions then with static free functions:
 // myclass_before.h
 #ifndef _INCLUDED_MYCLASS_BEFORE
 #define _INCLUDED_MYCLASS_BEFORE

 class MyClass
 {
 public:
     int getValue() const;
 
 private:
     int value() const;
 };
 #endif//_INCLUDED_MYCLASS_BEFORE

Step One: convert each private member function to a private static member:
 // myclass_after1.h
 #ifndef _INCLUDED_MYCLASS_AFTER1
 #define _INCLUDED_MYCLASS_AFTER1

 class MyClass
 {
 public:
     int getValue() const;

 private:
     static int value(const MyClass&);
 };
 #endif//_INCLUDED_MYCLASS_AFTER1

 // myclass_after1.c
 #include "myclass_after1.h"
 int MyClass::getValue() const
 {
     return value(*this);
 }
 int MyClass::value(const MyClass& myclass)
 {
     return 0;
 }

Step Two: remove function declaration from header file and member notation from definition file:
 // myclass_after2.h
 #ifndef _INCLUDED_MYCLASS_AFTER2
 #define _INCLUDED_MYCLASS_AFTER2

 class MyClass
 {
 public:
     int getValue() const;
 };
 #endif//_INCLUDED_MYCLASS_AFTER2

 // myclass_after2.c
 #include "myclass_after2.h"
 int MyClass::getValue() const
 {
     return value(*this);
 }
 static int value(const MyClass& myClass)
 {
     return 0;
 }

Remove Private Member Data
Removing private static data is easy for inline member functions that do not require direct access:
Move static member data into a static variable defined at file scope in the component's .c file.

Compare original class with private static member data and modified class with static file-scope data:
 // myclass_before.h
 #ifndef _INCLUDED_MYCLASS_BEFORE
 #define _INCLUDED_MYCLASS_BEFORE

 class MyClass
 {
 public:

 private:
     static int s_count;
 };
 #endif//_INCLUDED_MYCLASS_BEFORE

 // my_class_before.c
 #include "myclass_before.h"
 int MyClass::s_count;
 // myclass_after.h
 #ifndef _INCLUDED_MYCLASS_AFTER
 #define _INCLUDED_MYCLASS_AFTER

 class MyClass
 {
 public:

 private:

 };
 #endif//_INCLUDED_MYCLASS_AFTER

 // my_class_after.c
 #include "myclass_after.h"
 static int s_count;

Remove Compiler-Generated Functions
The compiler will auto-generate the following functions if not found: constructor, copy constructor, assignment operator and/or destructor. However, truly insulating class must define these explicitly.

Remove Include Directives
Unnecessary #include directives can cause compile-time coupling where none would otherwise exist: Move all unnecessary #include directives from a header file to .c file with forward class declarations.
 // bank.h
 class USD;    // class declaration instead of #include
 class CAD;    // class declaration instead of #include
 class NZD;    // class declaration instead of #include
 
 class Bank
 {
 public:
     USD getUSD() const;
     CAD getCAD() const;
     NZD getNZD() const;
 };

An alternative is to place redundant guards around each #include directive in every header file.
Although unpleasant, this may significantly reduce compile times in much larger C++ projects.
 // bank.h
 #ifndef _INCLUDED_BANK
 #define _INCLUDED_BANK
 
 #ifndef _INCLUDED_USD
 #include "usd.h"
 #endif//_INCLUDED_USD
 
 #ifndef _INCLUDED_CAD
 #include "cad.h"
 #endif//_INCLUDED_CAD
 
 #ifndef _INCLUDED_NZD
 #include "nzd.h"
 #endif//_INCLUDED_NZD
 
 class Bank {};
 #endif//_INCLUDED_BANK

Remove Enumerations
Judicious use of enumerations, typedefs, + other constructs with internal linkage achieve good insulation: Move enumerations and typedefs to .c file and replace them as private static const member of the class.

Summary
Generally if a component is used widely throughout the system, its interface should be insulated.
However, insulated interfaces are not always practical, e.g. lightweight, reusuable components.

Techniques
 Remove Private Inheritance  Convert WasA relationship to HoldsA
 Remove Embedded Data Members  Convert HasA relationship to HoldsA
 Remove Private Member Functions  Make them static at file scope and move into .c file
 Remove Private Member Data  Extract a protocol and/or move static data to .c file
 Remove Compiler Functions  Explicitly define these functions
 Remove Include Directives  Remove include directives or replace with class declarations
 Remove Enumerations  Relocate to .c file and replace as const static class member data

Conclusion
In conclusion, two important techniques can be used to mitigate cyclic dependencies in C++: Levelization can reduce link-time dependencies and Insulation can minimize compile-time dependencies. Awesome J

Tuesday, February 14, 2017

Large Scale C++ Projects

C++ continues to be one of the preferred programming languages to develop professional applications and there is much information that documents C++ coding standards and how to write Effective C++.

However, it seems rare to find information that documents how to use the C++ language effectively;
That is: write C++ in such a way that minimizes cyclic, link and compile-time dependencies in C++.

Objective
The objective of this post is to gain insight into the design of large, high-quality C++ software systems:
Create highly maintainable + testable software that uses increasing number of classes and lines of code.

Reference
The majority of information here can be found in Large-Scale C++ Software Design book by John Lakos.

Definitions
 Declaration  Introduces a name into a program
 Definition  Provides a unique description of an entity within a program
 Translation Unit  Single implementation file that includes all header files
 Internal Linkage  Name local to translation unit and cannot collide with identical name at link time
 External Linkage  In a multi-file program a name can interact with other translation units at link time

Issues
Poorly written C++ is difficult to understand + maintain. As programs get large the following issues occur:

Cyclic Dependencies
C++ components have tendency to get tangled up in each other which results in tightly physical coupling;
e.g. 2x components Rectangle and Window: Rectangle uses the Window and Window uses the Rectangle.
 // rectangle.h
 #ifndef _INCLUDED_RECTANGLE
 #define _INCLUDED_RECTANGLE

 class Window;

 class Rectangle
 {
 public:
     Rectangle(const Window& w);
 };
 #endif//_INCLUDED_RECTANGLE
 // window.h
 #ifndef _INCLUDED_WINDOW
 #define _INCLUDED_WINDOW

 class Rectangle;

 class Window
 {
 public:
     Window(const Rectangle& r);
 };
 #endif//_INCLUDED_WINDOW
Now, both objects in the system must know about each other and #include the other object's header file.
Therefore, it is now not possible to compile, link, test and use one component without the using other!

Excessive Link-Time
Cyclic dependencies make it necessary to link most dependent objects in order to test any of them at all.
Not only does this increase the executable size but can make the linking process unduly slow and painful!

Excessive Compile-Time
When developing C++ programs, changes to a single header file can sometimes cause many translation units to recompile. Why? Because the unnecessary inclusion of one header file by another is a common source of excessive coupling in C++.

Ignoring compile-time dependencies can cause translation units to unnecessarily include header files.
This results in excessive compile-time dependencies which can reduce compilation speeds to a crawl!

Poor Physical Design
This addresses design issues surrounding the physical entities of a system e.g. files, directories, libraries as well as organizational issues e.g. compile-time and link-time dependencies between physical entities.

Good physical design implications often dictate the outcome of logical design decisions;
Therefore avoid logical design choices that would imply cyclic physical dependencies.

Testing Challenges
Complex, well-designed software systems are built from layered parts that should have been tested thoroughly in isolation, then within a sequence partial subsystems, and as a fully integrated product.

Therefore, it must be possible to decompose the entire system into its single units of functionality.

Summary
Cyclic link-time dependencies among translation units can undermine understanding, testing, reusability. Unnecessary or excessive compile-time dependencies increase compilation cost + destroy maintainability.

Most C++ design books address only the logical design issues of project (classes, functions, inheritance).
However, quality of physical design often dictates improved outcome of many logical design decisions!

Techniques
Two important techniques are discussed to mitigate cyclic dependencies in C++:
 Levelization  Techniques used to help reduce link-time dependencies
 Insulation  Techniques used to minimize compile-time dependencies


Levelization
Levelization refers to the technique for reducing the link-time dependencies within a system.
Therefore, a system is levelizable when there are no cyclic dependencies, that is, acyclic.

Link-time dependencies within a system establish the overall physical quality of a system;
e.g. understandability, maintainability, testability and reusability tied to a physical design.

The following sections list techniques to help reduce link-time dependencies:

Escalation
Refer back to the original example of 2x mutually dependent objects: Rectangle and Window.
Move the cyclic functionality into a higher level component; a technique called escalation.

If peer components are dependent then it may be possible to escalate interdependent functionality;
Each component becomes static members in a higher-level component that depends on the original.
 // boxutil.h
 class Rectangle;
 class Window;
 
 class BoxUtil
 {
 public:
     static Rectangle toRectangle(const Window& w);
     static Window toWindow(const Rectangle& r);
 };

Demotion
Move the common functionality to lower levels of the physical hierarchy; a technique called demotion.
The new lower-level component is shared upon each of which the original component(s) depends.

Opaque Pointers
In order to compile a function, the compiler needs to know the size and layout of the object it uses.
The compiler does this by #include the header file of the component containing the class definition.

A function f uses a type T in size if compiling the body of f requires having first seen definition of T.
A function f uses a type T in name only if compiling f does not require having seen definition of T.

A pointer is opaque if the type definition to which it points is not included in current translation unit.
This technique is sometimes referred to as the Pointer to Implementation idiom or the Pimpl idiom.
 // handle.h
 class Foo;
 
 class Handle
 {
 public:
     Handle(Foo* foo) : p_opaque(foo) {}
 
     Foo* get() const { return p_opaque; }
     void set(Foo* foo) { p_opaque = foo; }
 
 private:
     Foo* p_opaque;
 };

Dumb Data
Any kind of information that an object holds but does not know how to interpret.
Such data must be used in the context of another object, at a higher level.

E.g. rather than identifying objects by opaque pointer, we may use a short integer index instead. However, an indexed approach does sacrifice type safety when compared to opaque pointers.

Redundancy
This technique deliberately repeats code or data to avoid or remove unwanted physical dependencies.
The additional coupling associated with some forms may outweigh the advantage gained from reuse.

Callbacks
A function supplied by a client to allow lower-level component to take advantage of higher-level context. Callbacks are useful in event-based programming to break dependencies between co-operating classes.

However, when used inappropriately, callbacks can blur the responsibility of the lower-level objects.
This can result in unnecessary conceptual coupling that is difficult to understand, maintain + debug.

Factoring
Extracting pockets of cohesive functionality: move them where they can be independently tested and reused; General technique for reducing the burden imposed by cyclicly dependent classes. Factoring:
  • A system into smaller components: more flexible yet more complex pieces to work
  • A concrete class into two classes containing higher and lower levels of functionality
  • An abstract base class into 2x classes: pure interface and partial implementation

Escalating Encapsulation
A common misconception is that each component must encapsulate all implementation details.
Instead we can hide a number of useful low-level classes behind single component: Wrapper.
Note: Wrapper is a component-based implementation of the Fa├žade design pattern.

Summary
By proactively engineering the system as a levelizable collection of components creates a hierarchy of modular abstractions that can be understood, tested, reused independently from the rest of the design.

Techniques
 Escalation  Move mutually dependent functionality higher in physical hierarchy
 Demotion  Move mutually dependent functionality lower in physical hierarchy
 Opaque Pointers  Having an object use another in name only [Pimpl idiom]
 Dumb Data  Use data that indicates dependency on peer object in higher object context
 Redundancy  Deliberately avoid reuse: repeat small amounts of code to avoid coupling
 Callbacks  Client-supplied functions enable lower-level subsystems to perform tasks
 Factoring  Move independent testable behaviour from implementation avoids coupling
 Escalating Encapsulation  Implementation hidden from clients to higher level in physical hierarchy

Conclusion
In conclusion, this post discussed Levelization techniques to help reduce link-time dependencies in Large Scale C++ Projects. Next we will discuss Insulation techniques to help reduce compile-time dependencies.

This will be the topic in the next post.

Friday, January 20, 2017

Candy Kid WiX Installer

Candy Kid is a simple maze chase video game written in XNA using C#/.NET. All development was done on Windows therefore it made sense to build a PC version of the game to be published available for sale.

In order to build all binary files plus game content into a single deployable package, the Windows Installer XML [WiX] toolset was used. WiX is free software that builds Windows Installer packages from XML code.

Let's check it out!

Pre Requisites
First, obtain Candy Kid release build complete with game executable, managed assemblies and content:
 Folder  Content  All game content
 File  log4net.dll  log4net logging
 File  Ninject.dll  IoC Container
 File  WindowsGame.exe.config  Game configuration
 File  WindowsGame.exe  Game executable
Next, download WiX Installer here. Note: post is based heavily on the XNA Installer published by Cygon!

Implementation
Launch Visual Studio. File | New Project... | Windows Installer XML | Setup Project | CandyKidInstaller. Uncheck Create directory for solution. Delete Product.wxs and copy the following folders as per Cygon:
 Folder  Description
 Content  Candy Kid release build (as above)
 Documents  Includes license.rtf document only
 References  Includes the 2x Nuclex.Setup DLLs
 Resources  Includes all bmp, ico, and png files
 Source  Installer (wxs) + Include (wxi) files
Note: C:\Program Files (x86)\SharpDevelop\5.1\data\resources\InstallerBitmaps required in Resources.

Actions
Right click project name | Properties | Output name: RetroCandyKid. Next, action these following tasks: Note: anytime you need a GUID choose Tools menu | Create GUID | 2. DEFINE_GUID | New GUID | Copy
  • Add the Program Menu
  • Add Desktop Shortcut
  • Add the Program Files
  • Harvest content folder

Program Menu
Add this change to Files.wxs. This blob of XML is responsible to set Program Menu entry once installed. Important: make note of the Component Id as this will be used in Setup.wxs for Feature ComponentRef.
<Directory Id='ProgramMenuFolder' Name='Programs'>
<Directory Id='MyGameProgramMenuFolder' Name='Retro Candy Kid'>
        <Component Id="StartMenuEntriesComponent" Guid="{GUID}" DiskId="1">
                <RemoveFolder Id='MyGameProgramMenuFolder' On='uninstall' />
                <RegistryValue
                        Root='HKCU'
                        Key='SOFTWARE\SteveProStudios\RetroCandyKid'
                        Name="ProgramMenuFolder"
                        Type='string'
                        Value='Installed'
                        KeyPath='yes' />
        </Component>
</Directory>
</Directory>

Desktop Shortcut
Add this change to Files.wxs. This blob of XML is responsible to set the Desktop shortcut once installed. Important: make note of the Component Id as this will be used in Setup.wxs for Feature ComponentRef.
<Directory Id="DesktopFolder" Name="Desktop">
        <Component Id="ApplicationShortcutDesktop" Guid="{GUID}">
                <Shortcut
                        Id="ApplicationDesktopShortcut"
                        Name="Retro Candy Kid"
                        WorkingDirectory="INSTALLDIR"
                        Icon="ProductIcon.ico"
                        Target="[INSTALLDIR]WindowsGame.exe" />
                <RemoveFolder Id="DesktopFolder" On="uninstall" />
                <RegistryValue
                        Root="HKCU"
                        Key='SOFTWARE\SteveProStudios\RetroCandyKid'
                        Name="DesktopFolder"
                        Type="integer"
                        Value="1"
                        KeyPath="yes" />
        </Component>
</Directory>

Program Files
Add this change to Files.wxs. This blob of XML is responsible to install the executable and all assemblies. Important: make note of the Component Id as this will be used in Setup.wxs for Feature ComponentRef.
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="INSTALLDIR" Name="RetroCandyKid">
<Component Id="MyComponent" Guid="{GUID}" DiskId="1">

<File Id="WindowsGameExe" Name="WindowsGame.exe.config"
          Source="$(sys.SOURCEFILEDIR)/../Content/WindowsGame.exe.config" />
<File Id="log4netdll" Name="log4net.dll"
          Source="$(sys.SOURCEFILEDIR)/../Content/log4net.dll" />
<File Id="NinjectDll" Name="Ninject.dll"
          Source="$(sys.SOURCEFILEDIR)/../Content/Ninject.dll" />

<File Id="GameExecutable" Name="WindowsGame.exe" KeyPath="yes"
          Source="$(sys.SOURCEFILEDIR)/../Content/WindowsGame.exe">
         <Shortcut
                Id="MyGameShortcut"
                Name="Retro Candy Kid shortcut"
                Directory="MyGameProgramMenuFolder"
                Advertise="yes"
                WorkingDirectory="INSTALLDIR"
                Icon="ProductIcon.ico" />   
</File>
</Component>
</Directory>
</Directory>

Harvest Content
In order to copy the Content directory to the install folder, use the Wix "Heat" application to harvest the directory. The Wix Harvest Tool (Heat) generates the required fragment into its own Installer (wxs) file.

First, ensure that Wix Toolset is included in Environment PATH. Control Panel | Advanced system settings. Environment Variables | Path | Edit | Add install directory: C:\Program Files (x86)\WiX Toolset v3.10\bin

Next, launch Command Prompt and harvest content from Game executable level beneath Content folder: heat dir . -o MyHarvestedStuff.wxs -scom -frag -srd -sreg -gg -cg MyComponentGroupId -dr INSTALLDIR

Find and replace in wxs file Source="SourceDir\ to Source="$(sys.SOURCEFILEDIR)\..\Content\
Finally, remove all top entries with Directory="INSTALLDIR". Make note of the ComponentGroupRef Id.


Setup.wxs
Main entry point: update Product XML blob and complete the Feature list as per the components (above). Ensure you have ProductIcon value set as Icon for shortcut and Icon displayed in Add/Remove programs!
<Product Id="{GUID}"
         Name="Retro Candy Kid"
         Language="1033"
         Version="1.0.0"
         Manufacturer="StevePro Studios"
         UpgradeCode="{GUID}">

<Property Id="ALLUSERS" Value="1" />
<Property Id='ARPPRODUCTICON' Value='ProductIcon' />

<Feature Id="MyFeature" Title="Required Files" Level="1">
        <ComponentRef Id="StartMenuEntriesComponent" />
        <ComponentRef Id="ApplicationShortcutDesktop" />
        <ComponentRef Id="MyComponent" />
        <ComponentGroupRef Id="MyComponentGroupId" />
</Feature>

<!-- Includes the user interface definition defined in another file -->
<UIRef Id="UserInterface"/>
<Icon Id="ProductIcon" SourceFile="$(sys.SOURCEFILEDIR)/../Resources/Game.ico" />
<Icon Id="ProductIcon.ico" SourceFile="$(sys.SOURCEFILEDIR)/../Resources/Game.ico" />
</Product>

UserInterface.wxs
Update the relative location for "Default dialog resources for the setup" bitmap files e.g. banner and info:
 Binary  Source
 dialog.bmp  $(sys.SOURCEFILEDIR)/../Resources/InstallerBitmaps/default-dialog.bmp
 banner.bmp  $(sys.SOURCEFILEDIR)/../Resources/InstallerBitmaps/default-banner.bmp
 info.bmp  $(sys.SOURCEFILEDIR)/../Resources/InstallerBitmaps/info.bmp
 up.bmp  $(sys.SOURCEFILEDIR)/../Resources/InstallerBitmaps/up.bmp
 new.bmp  $(sys.SOURCEFILEDIR)/../Resources/InstallerBitmaps/new.bmp

Build
Finally, build WiX Installer from within Visual Studio to generate the MSI package RetroCandyKid.MSI.
Download source code here.

Summary
Double click to RetroCandyKid.MSI to install. Ensure there is a Program Menu entry + Desktop shortcut!
Retro Candy Kid is also in Programs and Features and could be uninstalled; not that you would want to J

Sunday, January 1, 2017

Retrospective VIII

Last year, I conducted a simple retrospective for 2015. Therefore, here is a retrospective for 2016.

2016 Achievements
  • Complete first Sega Master System video game 3D City using C/Z80 assembler
  • Enter 3D City into Sega Master System annual coding competition for this year
  • Complete Retro Candy Kid blog topics such as Press Release and WiX Installer
  • Integrate IPv6-only Networking into Unity3D code base using the Lidgren API
  • Document SVN Externals to scale out single game code library across clients
  • Create repositories on GitHub and publish source code from various projects
  • Scale Push Notifications application across iOS / Android improved efficiency
  • Transition existing C++ OpenGL tutorial studies to new Vulkan graphics API
Note: reviewed game project in C / Z80 assembler for Sega Master System is an achievement!

2017 Objectives
  • Complete another Sega Master System video game that can run on real hardware
  • Integrate Git Submodules similar to SVN Externals to scale out code across clients
  • Evaluate monetization plugins for MonoGame / XNA game projects e.g. Purchases
  • Check out opportunity to incorporate Virtual Reality in Unity3D game engine code

2016, as every Virtual Reality evangelist will tell you, was the year of VR. Game Engines such as Unity5 attempt to ease development transition to VR by adding Virtual Reality Supported checkbox to Settings. However, repairing breakages from Unity4 to Unity5 game project upgrade is often challenging enough.

Homebrew
Outside commercial game development, homebrew projects continue to be very popular: SMS Power hosted its annual Sega Master System coding competition and attracted more than two dozen entries.

This provided great opportunity to complete first Sega Master System video game 3D City using z88dk. Unfortunately, the game runs only in emulator. R+D has begun to ensure games run on real hardware.

Summary
Another busy year coding from Z80 assembler to C/C++ to C#/.NET certainly does keep life interesting!

Tuesday, November 15, 2016

Unity3D and IPv6 Networking

At WWDC 2015, Apple announced the transition to IPv6-only network services in iOS 9. Starting June 1st 2016 all apps submitted to the App Store must support IPv6-only networking. Therefore, Unity3D posted Unity and IPv6 Support in response to this since many developers publish Unity games to the App Store.
Let's check it out!

IPv6
IPv6 (Internet Protocol version 6) is the most recent version of the Internet Protocol communications protocol that provides identification for computers on networks and routes traffic across the Internet.

Therefore, Apple's new requirement means that apps must be able to operate on an IPv6-only network!

Example
As an example, suppose that you have a typical client / server networked game that uses the Lidgren library as the networking layer to communicate messages from the client to the server and vice versa.

Lidgren
Initially, the Lidgren library uses IPv4-only specific APIs to communicate messages from the client to the server. Therefore, here is a short list of tasks to transition the code to support IPv6-only networking now:
  • Look for IPv4 addresses (e.g. 127.0.0.1, 8.8.4.4). Any hardcoded addresses should be removed. Prefer host names: use to look up IPv4 or IPv6 address of device for the proper type of network.

  • Look for the use of the IPAddress.AddressFamily property. Any code that branches based on the value of the AddressFamily must ensure the code handles IPv6-only networking option properly.

  • Look for the use of IPAddress.Any and IPAddress.Loopback fields. These fields work with IPv4 addresses not IPv6. Use IPAddress.IPv6Any and IPAddress.IPv6Loopback for IPv6 compatibility.

Fortunately, a Lidgren pull request has been submitted by jens-nolte to implement IPv6 Dual Mode, that is, upgrade Lidgren library to support both IPv4 and IPv6 network connections in client and server code.

However, all C#/.NET code in pull request is based on .NET Framework 4.5 whereas Unity uses Mono 3.5! Therefore, implement the server as Dual Mode but the client must detect at runtime either IPv4 or IPv6.

Server
Let's implement the server first [Dual Mode] as is easier + simply requires .NET Framework 4.5 (above). Channel all network connectivity through IPv6. If IPv6 then leave otherwise map IPv4 address to IPv6.

NetPeer.cs
public NetPeer(NetPeerConfiguration config)
{
  m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.IPv6Any, 0);
}
public virtual NetConnection Connect(IPEndPoint remoteEndPoint, NetOutgoingMessage hailMessage)
{
  remoteEndPoint = NetUtility.MapToIPv6(remoteEndPoint);
}
NetPeer.Internal.cs
private void BindSocket(bool reBind)
{
  m_socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
  m_socket.DualMode = true;

  var addr = m_configuration.LocalAddress.MapToIPv6();
  var port = reBind ? m_listenPort : m_configuration.Port;

  var ep = (EndPoint)new IPEndPoint(addr, port);
  m_socket.Bind(ep);
}
NetPeer.LatencySimulation.cs
internal bool ActuallySendPacket(byte[] data, int numBytes, IPEndPoint target, out bool connectionReset)
{
  target = NetUtility.MapToIPv6(target);
}
NetPeerConfiguration.cs
public NetPeerConfiguration(string appIdentifier)
{
  m_localAddress = IPAddress.IPv6Any;
}
NetUtility.cs
public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback)
{
  if (ipAddress.AddressFamily == AddressFamily.InterNetwork || 
      ipAddress.AddressFamily == AddressFamily.InterNetworkV6) {}
}
internal static IPEndPoint MapToIPv6(IPEndPoint endPoint)
{
  if (endPoint.AddressFamily == AddressFamily.InterNetwork)
  {
    return new IPEndPoint(endPoint.Address.MapToIPv6(), endPoint.Port);
  }
  return endPoint;
}

Client
Let's implement the client: detect network connectivity from IPv4 or IPv6 at runtime and inject either AddressFamily.InterNetwork | IPAddress.Any into Lidgren for IPv4 or AddressFamily.InterNetworkV6 | IPAddress.IPv6Any for IPv6.

Create custom class to store the IPAddress and AddressFamily from IPv4 or IPv6 and inject at runtime.
public struct NetGameConfig
{
  public NetGameConfig(IPAddress netIPAddress, AddressFamily netAddressFamily)
    : this()
  {
    NetIPAddress = netIPAddress;
    NetAddressFamily = netAddressFamily;
  }

  public IPAddress NetIPAddress { get; private set; }
  public AddressFamily NetAddressFamily { get; private set; }
}

public enum IPProtocol { IPv4, IPv6 }

Unity4
Note: if you are on an older version of Unity e.g. Unity4 then you must upgrade to Unity 4.7.2f1. If you use .NET / IL2CPP libraries, e.g. to support 64-bit architecture on iOS, then upgrade to Unity 4.7.2p1; Especially if ReceiveFrom() method is used on the Socket otherwise sender remote becomes corrupt!

Finally, remove any code referencing the LocalEndPoint property on the Socket otherwise an exception will be thrown. Again this is if you use IL2CPP scripting backend to support 64-bit architecture on iOS.

IMPORTANT
The corresponding code will not work on Android platform with Unity4: a SocketException will occur as Unity Technologies explicitly decided not to back port these changes. More information is available here.

NetClient.cs
public NetClient(NetPeerConfiguration config, NetGameConfig netGameConfig)
  : base(config, netGameConfig) {}
NetPeer.cs
public NetGameConfig NetGameConfig { get; protected set; }

public NetPeer(NetPeerConfiguration config, NetGameConfig netGameConfig)
{
  NetGameConfig = netGameConfig;
  m_senderRemote = (EndPoint)new IPEndPoint(netGameConfig.NetIPAddress, 0);
}
public NetConnection Connect(string host, int port)
{
  var addr = NetUtility.Resolve(host, NetGameConfiguration.NetAddressFamily);
  return Connect(new IPEndPoint(addr, port), null);
}
NetPeer.Discovery.cs
public bool DiscoverKnownPeer(string host, int serverPort)
{
  IPAddress address = NetUtility.Resolve(host, NetGameConfig.NetAddressFamily);
}
NetPeer.Internal.cs
private void BindSocket(bool reBind)
{
  m_socket = new Socket(NetGameConfig.NetAddressFamily, SocketType.Dgram, ProtocolType.Udp);
}
NetPeer.Send.cs
public void SendUnconnectedMessage(NetOutgoingMessage msg, string host, int port)
{
  IPAddress adr = NetUtility.Resolve(host, NetGameConfig.NetAddressFamily);
}
NetPeerConfiguration.cs
private NetGameConfig m_NetGameConfig;

public NetPeerConfiguration(string appIdentifier, NetGameConfig netGameConfig)
{
  m_NetGameConfig = netGameConfig;
  m_localAddress = m_NetGameConfig.NetIPAddress;
}
NetServer.cs
public NetServer(NetPeerConfiguration config, NetGameConfig netGameConfig)
  : base(config, netGameConfig) {}
NetUtility.cs
public static void ResolveAsync(string ipOrHost, AddressFamily addressFamily, ResolveAddressCallback callback)
{
  if (ipAddress.AddressFamily == addressFamily) {}
}
Finally, create an IPNetworkManager to get the host address for the IPProtocol type and resolve the DNS.


Testing
Apple recommend the easiest way to test for IPv6 DNS64 / NAT64 compatibility, which is the type of network most cellular carriers deploy, is to set up a local IPv6 DNS64 / NAT64 network with your Mac.

Hosts
If you would like to setup hosts files then assume example has 1x Game Server and 2x Game Clients:
 Environment  Platform  Mode  Address  Host
 Game Server  Windows PC  Dual  fc00:992b:a::1  GameServer.v6net
 Game Client  Windows PC  IPv4  fc00:992b:a::4  StevePro-PC.v6net
 Game Client  Mac OS/X  IPv6  fc00:992b:a::6  SteveProIMac.v6net

Game Server
Edit the hosts file located at C:\Windows\System32\drivers\etc
# localhost name resolution is handled within DNS itself.
127.0.0.1        localhost 
::1              localhost
fc00:992b:a::1   GameServer.v6net
fc00:992b:a::4   StevePro-PC.v6net
fc00:992b:a::6   SteveProIMac.v6net

Game Client [PC]
Edit the hosts file located at C:\Windows\System32\drivers\etc
# localhost name resolution is handled within DNS itself.
127.0.0.1        localhost 
::1              localhost
fc00:992b:a::1   GameServer.v6net
fc00:992b:a::4   StevePro-PC.v6net
Disable IPv4 networking to ensure IPv6-only connection. Local Area Connection | Double click (TCP/IPv6)

Game Client [Mac]
Launch terminal as root. Edit the hosts file located at /etc/hosts
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
127.0.0.1        localhost
255.255.255.255  broadcasthost
::1              localhost 
fc00:992b:a::1   GameServer.v6net
fc00:992b:a::6   SteveProIMac.v6net
Disable IPv4 networking to ensure IPv6-only connection. System Preferences | Network. Click Advanced
Download code sample here.

Summary
At the time of this writing, Lidgren uses IPv4-only specific APIs to communicate all networked messages. These APIs are built into .NET Framework 3.5 and therefore can currently be accessed from within Unity.

However, to access IPv6-only specific APIs from within Unity [Dual Mode] requires .NET Framework 4.5. The .NET Profile Upgrade is currently on the Unity roadmap for this functionality although there's no ETA!

Thursday, September 15, 2016

Candy Kid Press Release

A Press Release is an official statement issued to give information on particular matters e.g. Video Games! Here is the official Press Release for Retro Candy Kid and its full implementation with the assistance from @PhilipGHarris [writer, developer, designer] using MailChimp to distribute the Press Release accordingly.

Let's check it out!

MailChimp
MailChimp is an email marketing service used to directly send commercial messages, typically to a group of people, using email. MailChimp offers these main features: Campaigns | Templates | Lists | Reports:
 Campaigns   Campaigns are how you send template emails to the contacts in your MailChimp list.
 Templates   A template is an HTML file used to create the layout and basic design for a campaign.
 Lists   A MailChimp list is a powerful and flexible tool that helps you manage your contacts.
 Reports   MailChimp reports analyze clicks, opens, subscribers’ social activity, e-commerce data.

Therefore, let's use MailChimp to complete Press Release for Retro Candy Kid. Action the following tasks:
  • Get Promo Codes
  • Build Email List
  • Build Template
  • Send Campaign
Promo Codes
Generate iOS promo codes: Log in iTunes Connect. Select My Apps | Candy Kid | Features | Promo Codes.
Enter a number of Promo Codes required for Press Release (e.g. max 100) | Click Generate Codes button. Check "I have read and agree to the terms presented above". Generate Codes and download as a txt file.

Lists
MailChimp | Lists | Create List | Create List | Enter the following details to complete the list information:
 List name  CandyKidList
 Default From email address  steven_boland@hotmail.com
 Default From name  StevePro Studios
 Remind people how they signed up to your list  Enter reminder information
 Contact information for this list  Enter contact information

Next page: View subscribers | Import subscribers | CSV or tab-delimited text file | Next | Upload CSV file. Browse to CSV file and Check "I understand that my billing plan may be automatically upgraded" | Next. Match any unmatched columns: "Make a Selection" | New column name | e.g. COUPON | Save | Import.

Finally, ensure columns can be used as placeholders in Template: Settings | List fields and *|MERGE|* tags. Ensure the "Field label and type" values are aligned to the "Put this tag in your content" values!
 FULLNAME  FNAME  LNAME  COMPANY  EMAIL  COUPON
 Steven Boland  Steven  Boland  StevePro Studios  steve@stevepro.com  YY3FR7L7NNY3
 Suzanne Boland  Suzanne  Boland  FN Days Ltd  suzanne@stevepro.com  7YHALRJ39FJX
 Adriana Boland  Adriana  Boland  Stinky Inky Co.  adriana@stevepro.com  N6X4L79KKLNK
IMPORTANT: tags have maximum 10x characters thus better use "COMPANY" instead of ORGANIZATION.

Templates
MailChimp | Templates | Create Template | Code your own | Paste in code | Select | Edit code | ENTER:

Retro Candy Kid is a top-down maze chase video game inspired by the 8-bit title "Candy Kid".

Candy Mama enemies are always out to get you as you try and eat all the candy to complete the level. Simple!

Try it for yourself with this free iOS Promo Code: *|COUPON|*

Retro Candy Kid is available on mobile platforms (iOS / Android / Kindle) and PC.

You Tube http://www.youtube.com/watch?v=rEWGOwq4yAI
Facebook http://www.facebook.com/CandyKidVideoGame



Retro Candy Kid includes the following key features that were not available in the original 8-bit title:
 - All 100x levels are unlocked.
 - Double bonus pts available.
 - Giant candy for extra lives.
 - Free man every 20,000 pts.
 - Open tunnels or closed exits.
 - Avoid trees or Death trees.
 - God mode for invincibility.
 - Unlimited game continues.

Company Bio
StevePro Studios is an independent game developer that builds and publishes 80s retro arcade video games! The studio was founded by Steven Boland "SteveProXNA" in January 2007 as a "one man team of one" and is currently based in Dublin, Ireland.

Fact Sheet
The original 8-bit title Candy Kid was a "type-in" video game published by New Zealand's Sega Computer Magazine in the September 1984 issue, pages 17-18. Inspired by the Sega Retro Gaming scene, "Candy Kid" was re-written as "Retro Candy Kid" by StevePro Studios in September 2015.

Price point
 USD   0.99
 GBP   0.79
 EUR   0.99
 JPY     120
 AUD   1.49
 CAD   1.19
 NZD   1.29
 CNY   6.00

Contact
 Blog
 Email
 Phone
 StevePro Studios
 steven_boland@hotmail.com
 +353 877 541 327
 Linked In
 Twitter
 Skype
 StevePro Studios
 @SteveProXNA
 SteveProXNA

Best,
Steven Boland.
Note: *|COUPON|* placeholder in the Press Release text will be substituted with promo code from list.

Campaigns
Although you can create campaigns directly from Campaigns tab, a simpler method is through Templates:

MailChimp | Templates | Click "Edit" dropdown to right of Template saved | Create Campaign. Choose a list to get started e.g. CandyKidList. Send to entire list | Next [bottom]. Enter following Campaign Info:
 Campaign name  RetroCandyKidCampaign
 Email subject  Retro Candy Kid – Awesome Arcade Action
 From name  StevePro Studios
 From email address  steven_boland@hotmail.com

Note: leave all checkboxes unchecked except the Personalize the "To" field. Set *|FNAME|* for recipient. Next Template | Next Confirm | Review summary all correct. Finally, Prepare for launch and Send Now!
Note re-send: MailChimp | Campaigns | Click "View Report" dropdown to right of Campaign | Replicate.

Summary
After campaign is successfully sent, the main Dashboard will report all activity; which includes: 24-hour performance, Top links clicked, Subscribers with most opens, Top locations by opens and much more...!

Wednesday, August 31, 2016

GitHub Cheat Sheet

Subversion (SVN) client–server model makes it easy to checkout source code from server-side centralized repository [repo], make local changes to working copy on client, and commit changes back to the server.

Whereas Git: a distributed version control system, unlike most client-server systems, every Git directory is full-fledged repository [repo] complete with history + independent of network access or central server.

Differences like these may be challenging at first. Therefore, let's smooth the transition from SVN to Git:

Let's check it out!

Pre Requisites
Here are the Atlassian Git tutorials this post makes reference to. Attached is basic diagram for Newbies: Note: in the simplest terms, git pull [not pictured] does a git fetch followed by a git merge.

Download Git distributed version control system for Windows or Mac. Setup Git global configuration here:
 Windows  C:\Users\<username>\.gitconfig
 Mac OS/X  /Users/<username>/.gitconfig

Here are basic commands to get and set Git global user name and user email throughout all repositories:
 User name  git config --global --get user.name
 git config --global user.name "SteveProXNA"
 User email  git config --global --get user.email
 git config --global user.email "steven_boland@hotmail.com"

Git Clients
There are free Git clients available for Windows and Mac such as GitHub Desktop and SourceTree however these show complex branched code which can be overwhelming for Newbies. Let's focus on simpler tools:
   SVN  GIT
 Windows  TortoiseSVN  TortoiseGit
 Mac OS/X  svnx  Gitbox
Note: Gitbox non-commercial version only allows one repository at a time but often that can be sufficient.

IMPORTANT:
If you have Cygwin installed on Windows then ensure TortoiseGit settings do NOT use Unix Git.exe Path:

GitHub
Create an account on github.com if you have not already done so. Read the guide is another good start. Choose Start a Project | Enter the name of your new repo e.g. "MyCoolRepo" and initialize with README: Launch command prompt. Type 3x variants of following git clone command to checkout local repository:
git clone https://github.com/SteveProXNA/MyCoolRepo.git MyCoolRepo
git clone https://<username>@github.com/SteveProXNA/MyCoolRepo.git MyCoolRepo
git clone https://<username>:<password>@github.com/SteveProXNA/MyCoolRepo.git MyCoolRepo
As a convenience, cloning automatically creates a remote connection called origin pointing back to the original repository. This makes it easier to interact with the repository. Also, default branch is master.
repo   local    master
repo   remote   origin/master
When you push to origin/master [remote] you will be prompted with whatever credentials are required. Note: here all git clone repos are done via https protocol. Checkout here for SSH git clone repo setup.

Configure current user name and email for repo activity, especially if you have multiple Github accounts:
 User name  git config --get user.name  git config user.name "SteveProXNA"
 User email  git config --get user.email  git config user.email "steven_boland@hotmail.com"

Note: local Git repo information can be found in hidden .git folder at root level where repository is cloned:
 Windows  C:\Users\<username>\GitHub\SteveProXNA\MyCoolRepo\.git\config
 Mac OS/X  /Users/<username>/GitHub/SteveProXNA/MyCoolRepo/.git/config

IMPORTANT:
If you push code changes using TortoiseGit then you may need to change Global User Info name + email; especially if you git clone repository using credentials that are different from the global GitHub account.

Windows Explorer | Right click MyCoolRepo directory | TortoiseGit | Settings | Git [OK] Configure source:

Before making any changes to the repo, prepare working environment to detect changes via Git tools:
 Windows  Explorer | Right click MyCoolRepo directory | TortoiseGit | Check for modifications
 Mac OS/X  Finder | Navigate to MyCoolRepo directory | Drag MyCoolRepo into Gitbox application

Command Prompt
Developers will add changes from the working directory to staging area and commit changes to local repo. When they push from local repo [master] to remote repo [origin/master] changes are available on server.

TortoiseGit + Gitbox can co-ordinate this activity, however, here are some command prompt equivalents:
 git status  List which files are staged, unstaged, and untracked.
 git add file  Stages file from working directory to staging area.
 git reset file  Unstages file from staging area to working directory.
 git commit file  Commits file from staging area to the local repo.
 git push  Push files from local repo to remote [origin] repo. [SVN Commit]
 git clean -df  Remove untracked directories and untracked files from current directory.
 git reset --hard  Reset staging area and working directory to match most recent commit.
 Obliterates all uncommitted changes so be careful using this command!
IMPORTANT: you cannot seem to commit an empty directory; add dummy README file here as needed.

Commit Comparison
One of the more challenging aspects found during the SVN to Git transition is difference between commit.

SVN commits working copy changes from client to server whereas Git commits from staging area to local repo only; git status shows staged + unstaged files thus how do you list all local commits for next push?

Windows right click MyCoolRepo directory | Git Sync... | Click "Out ChangeList" tab | lists local commits.
Mac OS/X in Gitbox each commit listed but not yet pushed is displayed with a dot on the left hand side.

Logging
Whereas git status lets you inspect the working directory and staging area the git log command lets you list the project history, filter and search for specific changes and only operates on the committed history.
 git status
 git log
 git log --grep="SteveProXNA"
 git log --author="SteveProXNA"
 git log --grep="commit"
 git log --merges
 git log -S"today"
 git log --oneline
 git log --graph --decorate --oneline
 git log --oneline master..MyNewBranch
 git log --pretty=format:"%cn committed %h on %cd"
 git log --after="2016-4-1"

Command Prompt II
After developers (eventually) push changes from local repo to remote, here are some more commands:
 git branch  Lets you create, list, rename, and delete branches.
 git checkout  Lets you navigate between branches created by git branch.
 git merge  Lets you integrate independent lines of development into a single branch.
 git rebase  Process of moving branch to new base commit to maintain linear history.
 git fetch  Imports remote changes but does not integrate changes into local repo.
 git pull  Equivalent to a git fetch followed by a git merge. [SVN Update]

Branching
Unlike SVN, Git differentiates between local and remote branches: local branches exist only on the local machine for local user whereas remote branches are branches pushed to origin and are accessible to all.
git branch                              ; list local  branches
git branch -r                           ; list remote branches
git branch -a                           ; list all    branches [local + remote]
Create branches:
git branch MyNewBranch                  ; create local  branch
git push origin MyNewBranch             ; pushes remote branch
Delete branches:
git branch -d MyNewBranch               ; delete local branch if merged changes
git branch -D MyNewBranch               ; delete local branch unconditionally
git push origin --delete MyNewBranch    ; delete remote branch
General update commands to synch github remote and local repository:
git remote update               ; if remote stale then update to synch latest
git fetch --all --prune         ; if delete on one computer and replicate to other
Detached HEAD
HEAD points to specified branch. When you checkout a commit, it switches into "detached HEAD" state from rest of project. If you were to develop in this state then there would be no branch to get back to.

Tagging
Similar to SVN, Git tags are symbolic names for a given revision: code snapshot implemented by git tag.
 Windows  Explorer | Right click MyCoolRepo directory | TortoiseGit | Create Tag... | Enter Tag
 Mac OS/X  Gitbox application | Click dropdown list next to "pull" button | New tag... | Enter Tag

  Here are some command prompt equivalents:
 git tag  ; show tag on local
 git push origin --tags ; push tag to remote
  Also synchronize Git tags with remote:
 git tag -l | xargs git tag -d
 git fetch
Finally, if remote stale then git remote update and replicate to another computer git fetch --prune --tags.

Merging
Merging integrates changes from one source branch into a destination branch and combines histories of both branches. Merging is non-destructive: neither branch is changed in any way, however, the merged branch may have an extraneous merge commit every time you need to incorporate upstream changes.

Fast-Forward Merge
When there is linear path from current branch tip to target branch, instead of actually merging branches, all Git has to do to integrate the histories is move ["fast forward"] current branch tip up to target branch.
git checkout -b MyNewBranch master      ; create branch and switch
                                        ; add and commit to branch
git checkout master                     ; switch to the trunk node
git merge MyNewBranch                   ; merge branch up to trunk
git branch -d MyNewBranch               ; delete local branch
3-Way Merge
Occurs when it is impossible for Git to perform a fast-forward merge as there is no way to move current branch tip to target branch without backtracking. Very common when branch takes long time to develop.
git checkout -b MyNewBranch master      ; create branch and switch
                                        ; add and commit to branch
git checkout master                     ; switch to the trunk node
                                        ; add and commit to master
git merge MyNewBranch                   ; merge branch up to trunk
git branch -d MyNewBranch               ; delete local branch

Rebasing
Rebasing is an alternative to merging and moves the entire source branch to the tip of destination branch by incorporating all new commits. Rebasing re-writes project history by eliminating unnecessary commits.
git checkout -b MyNewBranch master      ; create branch and switch
                                        ; add and commit to branch
git checkout master                     ; switch to the trunk node
git rebase MyNewBranch                  ; rebase branch upto trunk
git branch -d MyNewBranch               ; delete local branch

Merging vs. Rebasing
The benefit of rebasing is a much cleaner project history. Rebasing eliminates all the unnecessary merge commits required by git merge resulting in a perfectly linear project history followed up to the feature tip.
IMPORTANT: the Golden Rule of Rebasing stipulates never to use git rebase command on public branches!

Pull Request
GitHub fosters a fast, flexible, collaborative development process where you work with or without others. Here, you can sign into GitHub and fork an existing repository and create pull request to merge changes.
Choose repository to actively collaborate e.g. MonoGame. Click "Fork" button top right. Choose location. There should now be repository forked under your username ready to git clone and commit changes to:
git clone https://<username>:<password>@github.com/SteveProXNA/MonoGame.git MonoGame
git config user.name "SteveProXNA"
git config user.email "steven_boland@hotmail.com"
Commit changes to local repo and push from local repo [master] to remote repo [origin/master] as usual. However, create pull request to integrate changes from your forked remote repository to the source repo.

Click "New pull request". This prompts "Comparing changes" dialog for the source repository + your fork.
https://github.com/MonoGame/MonoGame/compare/master...SteveProXNA:master
   User  Repo
 Source  MonoGame  https://github.com/MonoGame/MonoGame
 Fork  SteveProXNA  https://github.com/SteveProXNA/MonoGame

Click "Create Pull Request". Owner receives email notification to view proposed changes to integrate. Click "Merge pull request" to merge changes back into source repository and automatically close Pull Request.
IMPORTANT: if you would like to keep up to date with the source repository then follow these short steps:
git clone git@github.com:SteveProXNA/MonoGame.git
cd C:\Users\<username>\GitHub\SteveProXNA\MonoGame
git remote add upstream git://github.com/MonoGame/MonoGame.git
git fetch upstream
git pull upstream master

Imperatives
Here is a short list of git commands that is imperative that you should not do; especially to public history:

Don’t Reset Public History
You should never reset commits pushed to a public repository. Reset a commit poses serious problems for collaboration: when developers sync up with your repo, it'll look like project history abruptly disappeared.

Don’t Rebase Public History
Similar to git reset, you should never rebase commits that have been pushed to a public repository. The rebase would replace old commits with new ones and look like part of project history abruptly vanished.

Jenkins
Integrate all GitHub Plugins with Jenkins. Assume MSBuild setup in Manage Jenkins | Configure System:
 Name  JenkinsMSbuild
 Path to MSBuild  C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
Next, install plugins: Manage Jenkins | Manage Plugins | GitHub Plugin. You may need to install Git plugin.

Navigate to Jenkins | New Item | Create Freestyle project. Ensure the following build configurations set:
 Source Code Management => Git Repositories
 Repository URL  https://github.com/SteveProXNA/MyCoolRepo
 Credentials  <username>:<password>
 Branches to build  Branch Specifier (blank for 'any') */master



 Build a Visual Studio project or solution using MSBuild
 MSBuild Version  JenkinsMSbuild
 MSBuild Build File  MyCoolRepo.sln
 Command Line Arguments  /p:Configuration=Debug
 /p:Configuration=Release

 Execute Windows batch command
 Command  "C:\Program Files (x86)\NUnit 2.5.7\bin\net-2.0\nunit-console-x86.exe"  MyCoolRepo.UnitTests/UnitTests.nunit

Summary
Additional topics that could explored include git stash to push unfinished changes onto a stack that can be popped off later and git submodule to keep another Git repo in subdirectory very similar to SVN Externals.