Kanda SDK 0.6.0
Loading...
Searching...
No Matches
Quality Standards

Code contributions should adhere to the following quality standards to maintain the consistency, reliability, and maintainability of the Kanda SDK. These standards ensure that all code is tested, backward compatible, and supports cross-platform functionality.

Conventions and Patterns

Follow the Kanda SDK style and structure conventions. Detailed guidelines are available in:

Premature Complexity

Code is not an asset, but a “debt”. The asset is the value that the code brings.

Strive to reduce the amount of dead code and unused features in the codebase. These bring complexity and make it harder to understand the code.

Some rules-of-thumb:

  • If something might be needed in the future, implement it in the future, not now.
  • If something is not used, delete it (be aware of backwards compatibility when relevant).

Predictable code makes future improvements and features simpler to add.

Example:

// Bad: Implementing unused feature with complex logic
public class UserDataManager {
public void SaveUserData(string data) {
// Complex logic for future encryption feature
string encryptedData = EncryptData(data);
SaveToFile(encryptedData);
}
private string EncryptData(string data) {
// Placeholder for future encryption logic
return data;
}
private void SaveToFile(string data) {
// Logic to save data to file
}
}
// Good: Implementing only the needed functionality
public class UserDataManager {
public void SaveUserData(string data) {
SaveToFile(data);
}
private void SaveToFile(string data) {
// Logic to save data to file
}
}

Manual Testing

Manual testing in the Unity editor is essential during development. For larger changes, ensure to test in actual builds, including login and lobby, for all target platforms.

Example:

// Manual testing script to check feature in Unity editor and builds
public class FeatureTester : MonoBehaviour {
void Start() {
// Simulate user interactions and validate results
SimulateLogin();
TestLobbyConnection();
}
private void SimulateLogin() {
// Simulate login process
Debug.Log("Simulating login...");
}
private void TestLobbyConnection() {
// Test connection to lobby
Debug.Log("Testing lobby connection...");
}
}

Automated Testing

Automated testing is crucial for long-term quality assurance. Tests help reveal bugs in your code and ensure that refactoring or related changes by other developers do not break existing functionality.

When adding or changing functionality in the Kanda SDK, cover critical cases with unit tests to ensure logic integrity.

Example:

// Unit test to verify user preference saving and loading
[Test]
public void UserPreferenceManager_ShouldSaveAndLoadPreferences() {
UserPreferenceManager manager = new UserPreferenceManager();
manager.SavePreference("theme", "dark");
string value = manager.LoadPreference("theme");
Assert.AreEqual("dark", value);
}

Error Handling

Consider how your code might fail due to external reasons and handle these scenarios appropriately.

Use Unity Assertions for upfront validation of data passed to your code. Surround risky logic with "try blocks" to handle errors gracefully.

Example:

// Error handling with assertions and try-catch blocks
public class DataLoader {
public void LoadData(string path) {
Assert.IsFalse(string.IsNullOrEmpty(path), "Path should not be null or empty");
try {
string data = File.ReadAllText(path);
ProcessData(data);
} catch (FileNotFoundException ex) {
Debug.LogError("File not found: " + ex.Message);
} catch (Exception ex) {
Debug.LogError("Error loading data: " + ex.Message);
}
}
private void ProcessData(string data) {
// Data processing logic
}
}
Note
Assertions and exceptions might not work as expected in Burst-compiled code

Boy Scout Principle

When working with legacy code, strive to leave it in a better state than you found it.

If cleaning up a class requires significant rework, perform it first and submit as a separate pull request to simplify reviews.

While complete coverage of legacy code with tests is not required, try make sure critical paths are covered.

Example:

// Before: Legacy code with unclear logic
public class LegacyUserManager {
public void UpdateUser(string id, string data) {
// Complex, unclear logic
}
}
// After: Refactored code with improved clarity
public class UserManager {
public void UpdateUser(string userId, string newData) {
ValidateUserId(userId);
SaveUserData(userId, newData);
}
private void ValidateUserId(string userId) {
if (string.IsNullOrEmpty(userId)) {
throw new ArgumentException("User ID cannot be null or empty");
}
}
private void SaveUserData(string userId, string newData) {
// Logic to save user data
}
}
// Adding tests for critical paths in legacy code
[Test]
public void UserManager_ShouldUpdateUserCorrectly() {
UserManager manager = new UserManager();
manager.UpdateUser("123", "new data");
Assert.Pass();
}

Backward Compatibility

Code changes should be backward compatible. Implement changes in a way that allows them to co-exist with previous implementations, using composition, feature flags, strategy patterns, or similar methods.

Component composition example:

// Old component
public struct Player : IComponentData {
public int health;
}
// New component to change behavior without altering the old component
public struct Regeneration : IComponentData {
public int regenerationRate;
}
// System that ensures backward compatibility by checking for the new component
public struct UpdatePlayerSystem : ISystem {
public void OnUpdate(ref SystemState state) {
// Process entities with only the Player component
foreach (var (player, entity) in SystemAPI.Query<Player>().WithNone<Regeneration>()) {
player.health += 10; // Original update logic
EntityManager.SetComponentData(entity, player);
}
// Process entities with both Player and Regeneration components
foreach (var (player, regeneration, entity) in SystemAPI.Query<Player, Regeneration>()) {
player.health += regeneration.regenerationRate; // New behavior
EntityManager.SetComponentData(entity, player);
}
}
}

Feature flag example:

// Using feature flags for backward compatibility
public class FeatureToggle {
public bool NewFeatureEnabled { get; set; }
public void ExecuteFeature() {
if (NewFeatureEnabled) {
ExecuteNewFeature();
} else {
ExecuteOldFeature();
}
}
private void ExecuteNewFeature() {
// New feature logic
}
private void ExecuteOldFeature() {
// Old feature logic
}
}

Strategy pattern example:

// Strategy interface
public interface IMovementStrategy {
void Move(Transform transform);
}
// Old movement behavior
public class WalkMovement : IMovementStrategy {
public void Move(Transform transform) {
transform.Translate(Vector3.forward * Time.deltaTime);
}
}
// New movement behavior
public class FlyMovement : IMovementStrategy {
public void Move(Transform transform) {
transform.Translate(Vector3.up * Time.deltaTime);
}
}
// Context class using the strategy pattern
public class PlayerMovement : MonoBehaviour {
private IMovementStrategy movementStrategy;
private void Start() {
// Set default strategy
movementStrategy = new WalkMovement();
}
private void Update() {
movementStrategy.Move(transform);
}
// Method to change the movement strategy
public void SetMovementStrategy(IMovementStrategy newStrategy) {
movementStrategy = newStrategy;
}
}
// Usage example
public class GameController : MonoBehaviour {
public PlayerMovement playerMovement;
private void Start() {
// Use old movement behavior
playerMovement.SetMovementStrategy(new WalkMovement());
// Later in the game, switch to new movement behavior
playerMovement.SetMovementStrategy(new FlyMovement());
}
}

Common Backward Compatibility Smells

  • Automated tests are failing.
  • Changing or adding core components.
  • Adding special cases or enabled-by-default features to widely used components.

Explicitly test for backward compatibility if you encounter these smells to ensure the old functionality remains operational or has a clear migration path.

Cross-Platform Support

The Kanda SDK supports PC and VR default. New features should ideally support all platforms. If not, specify this in your PR and ensure the feature is disabled by default on unsupported platforms.

If extending a core platform system (e.g., VR input), extend other platform systems similarly to prevent feature disparity and hard-to-debug issues.

By following these quality standards, we can maintain a high level of code quality and reliability across the Kanda SDK.

Example:

// Platform-specific feature handling
public class PlatformFeatureHandler {
public void Execute() {
#if UNITY_STANDALONE
ExecutePCFeature();
#elif UNITY_ANDROID
ExecuteVRFeature();
#endif
}
private void ExecutePCFeature() {
// PC-specific logic
}
private void ExecuteVRFeature() {
// VR-specific logic
}
}