/*=============================================================================
	ProjMan.txt: Project Management notes
	By: Tim Sweeney, Epic MegaGames, Inc.
=============================================================================*/

******************************
** Programming Requirements **
******************************

1. When you originate a piece of code, include a heading at the top of every file looking 
   like this:

	/*=============================================================================
		UnClass.cpp: Actor class functions

		Copyright 1996 Epic MegaGames, Inc. This software is a trade secret.
		Compiled with Visual C++ 4.0 using Tabs=4, Calling method=__fastcall

		Revision history:
			* Date, Created by My Name
	=============================================================================*/

2.	Whenever you revise an existing piece of code that you got some somebody else, 
	put your name, date, and summary of changes in the "Revision history".

3.	Naming conventions for internals:

	FClassName			A simple, non-resource class, for example: FVector, FMemoryCache.
	FGlobalClassName	A class for which only one instance can exist, usually a global subsystem.
	UClassName			A resource class derived from UResource, for example: UCamera, UTextBuffer.
	CClassName			An MFC-derived class, for example: CUnrealEdServer.
	IClassName			An convenience structure for a locked resource (ICamera, ILevel, IModel, IMeshMap)
	PClassName			A class used in the "void *Params" parameter along with in actor messages
	AClassName			An AActorBase-derived actor class.
	IObjectName			A COM/OLE object used by Unreal, for example: IUnrealNetwork, IUnrealGatekeeper.
	GVariableName		A global variable, for example: GMem, GBlit.
	TTemplateName		A C++ template.

	The reason is because VC++'s class browser sorts alphabetically and this
	causes classes to be grouped reasonably well.  It also keeps names consistent so that
	you can see what a particular class is all about given just its name.

4.	Wrap all of your functions in a guard block so that the function calling history can
	be displayed in case Unreal crashes in a particular routine, or in case appError is
	called:

	void MyClass::MyRoutine( int x )
	{
		guard(MyClass::MyRoutine); // A macro that encapsulates the function in a try/catch block.
		DoSomthingHere();
		unguard;
	}

    The one exception to this is when you're writing a small performance critical function.

	The guard macros expand to something like this:

	void MyClass::MyRoutine( int x )
	{
		static const char __FUNC_NAME__ = "MyClass::MyRoutine";
		try
		{
			DoSomethingHere();
		}
		catch(...)
		{
			// Write out the call stack information and trigger the next catch handler.
		}
	}

5.	Name classes and class functions in mixed upper and lower case, like FMyClass::MyFunction,
    no underscores, lowercase-only, caps-only, etc.  For non-class functions, you can either
	used a mixed name ("OpenCamera") or a mixed name prefixed with a lowercase module name
	to indicate where the function resides ("gfxOpenCamera").

6.  Use the following functions for informational and debugging output:

	debug (LOG_Info,"Some message");
	debugf(LOG_Info,"Some printf-like message, A=%i, B=%s",SomeInt,SomeString);

	They output text to the Unreal console and also write to System\Unreal.log.

7.  If an unrecoverable error occurs in your code, and you can detect it, call
    one of these functions:

	appError ("Critical error message");
	appErrorf("Critical error message, A=%i, B=%s",SomeInt,SomeString);

	This function displays the function calling history, so it allows for easy
	debugging.

8.	For portability concerns, if your code is not platform-dependent, stick with
	ANSI C/C++ conventions.  Also avoid structured exception handling with the
	one exception of using the guard/unguard macros.

	These porting concerns don't apply to code specific to a particular platform, such
	as the Windows networking code or any MFC-derived code.  These can use the full
	C++ capabilities of the target system.

9.  Whenever you use inline assembly language (or separate MASM code), include
    a conditionally-compilable C version of the routine as well, and verify that
	it works when compiled with and without ASM:

	void SomeFunction (int x)
	{
	#ifdef ASM // Fast assembly-language version.
		__asm
		{
			// Assembly code goes here.
		}
	#else // Slow C version for portability.
		// C code goes here.
	#endif
	}

10.	Document all of your class functions as black boxes in your class header files,
    i.e. describe the functions inputs, outputs, and possible error conditions.
	If you need to document the module in more detail, stick all docs in a comment
	block of the class header.  This is harder to lose than separate text files.

11.	The best kind of C/C++ code is code which is well-structured and obvious enough
	that it doesn't need much commenting, like this:

		for( i=0; i<NumCameras; i++ )
			RedrawCamera( CameraList[i] );
	
	Use comments within your code to describe non-obvious tricks you're doing,
	especially in areas where other people may need to understand or modify the code.

12. To prevent multiple inclusion, all of your header files should be guarded with logic 
    like this:

	#ifndef _INC_MYMODULENAME
	#define _INC_MYMODULENAME
	//
	// All header code goes here...
	//
	#endif // _INC_MYMODULENAME

13. Use 8.3 (DOS-compatible) filenames.

14. Use Visual C++'s tabs=4 setting.  Whether you actually use tabs or not is up to you.

15. Define enumerations like this:

	enum EFruit
	{
		FRUIT_None		= 0,	// Tag zero should generally be 'none'.
		FRUIT_Apple		= 1,	// Apples are nice.
		FRUIT_Orange	= 2,	// Oranges are tangy.
		FRUIT_MAX		= 3,	// One beyond the maximum enumeration.
	};

16. Unless performance needs dictate otherwise, write all of your subsystems
	as black boxes, with a pure virtual base class (FMyClassBase) in a
	header file which defines all of the public functions, and a concrete class 
	defined either in your C++ code or in a separate header, which contains all of
	your private functions and nitty gritty implementation details.  This makes it
	much easier for others to use your subsystem without understanding how it
	works internally.

********************
** Using comments **
********************

1. Comment your code well enough that others are going to be able to browse through
   it, figure out what's happening, and be able to extend/debug it in the future,
   after a few hours of reading and learning.

2. Put a comment before the implementation of every function that describes what the function
   does, especially including any error/exception conditions:

//
// Open a new camera.  Returns a pointer to the camera structure, or NULL if the
// maximum number of cameras was exceeded.  Call with AllowEdit to enable editing
// within the camera window.
//
UCamera *OpenCamera (char *CameraName, int AllowEdit)
{
	// Do something...
	return Camera;
}

*********************
** Recommendations **
*********************

1. Indent code using the Microsoft C++ programming standards, like:

	void *FMemoryCache::Get(DWORD ID)
	{
		GUARD;

		// Try to find a matching entity.
		for (int i=0; i<HackEntities; i++)
		{
			if (EntityList[i].ID==ID)
				return HackEntityList[i].Data;
		}

		// Couldn't find a matching entity.
		return NULL;

		UNGUARD("FMemoryCache::Get");
	}

2. One statement per line.

3. Comments should be complete sentences terminated with a period.

4. Name regular variables with a pure name (i.e. PlayerDescription) rather than
   something crazy like lpszPlayerDescription, playerDescription, or player_description.

******************
** Comment tags **
******************

Use the following comments to tag code which needs work or is somehow dangerous:

	//todo: [Name] Use this tag to denote stuff that you need to do.
	//obsolete: Use this to denote obsolete code which is no longer in use.
	//warning: Use this to document dangerous but necessary coding practices, such as:
		*	A C++ structure which is mirrored elsewhere, for example in an assembly
			language .inc file.
		*	Code with complex and non-obvious interactions (such as Unreal's camera
			closing code, whose path of execution goes all over the places due to
			Windows messaging quirks).

************************
** Programming Spirit **
************************

1.	Be a minimalist.  The simpler and more concise your code, the less opportunity for
	errors.  The easier it is to read and understand, the easier it will be to debug.

2.	Make your code multi-programmer friendly.  We expect this project to evolve over
	a long period of time and be greatly extended, so make sure that others will be
	able to approach your code later on.

3.	Catch your bugs very early on in development by using asserts and by testing everything.

4.	Keep all of your code as modular as possible, and as separated from the rest of
	the codebase as possible.  This makes it much easier to make sweeping changes to
	one part of the codebase without causing havoc on the rest.

-Tim
