Pedoman pengkodian — MRTK2
Dokumen ini menguraikan prinsip dan konvensi pengkodian yang harus diikuti saat berkontribusi pada MRTK.
Filsafat
Ringkas dan berusahalah untuk kesederhanaan
Solusi paling sederhana sering kali yang terbaik. Ini adalah tujuan utama dari pedoman ini dan harus menjadi tujuan dari semua aktivitas pengkodian. Bagian dari menjadi sederhana adalah ringkas, dan konsisten dengan kode yang ada. Cobalah untuk menjaga kode Anda tetap sederhana.
Pembaca hanya boleh menemukan artefak yang memberikan informasi yang berguna. Misalnya, komentar yang mengembalikan apa yang jelas tidak memberikan informasi tambahan dan meningkatkan kebisingan terhadap rasio sinyal.
Jaga agar logika kode tetap sederhana. Perhatikan bahwa ini bukan pernyataan tentang menggunakan jumlah baris terkecil, meminimalkan ukuran nama pengidentifikasi atau gaya kurung kurawal, tetapi tentang mengurangi jumlah konsep dan memaksimalkan visibilitas baris tersebut melalui pola yang sudah dikenal.
Menghasilkan kode yang konsisten dan dapat dibaca
Keterbacaan kode berkorelasi dengan tingkat cacat yang rendah. Berusahalah untuk membuat kode yang mudah dibaca. Berusahalah untuk membuat kode yang memiliki logika sederhana dan menggunakan kembali komponen yang ada karena juga akan membantu memastikan kebenaran.
Semua detail kode yang Anda hasilkan penting, dari detail paling mendasar tentang kebenaran hingga gaya dan pemformatan yang konsisten. Jaga agar gaya pengkodian Anda tetap konsisten dengan apa yang sudah ada, meskipun gaya tersebut tidak cocok dengan preferensi Anda. Ini meningkatkan keterbacaan basis kode secara keseluruhan.
Mendukung konfigurasi komponen baik di editor maupun pada run-time
MRTK mendukung beragam pengguna - orang yang lebih suka mengonfigurasi komponen di editor Unity dan memuat prefab, dan orang-orang yang perlu membuat dan mengonfigurasi objek pada run-time.
Semua kode Anda harus berfungsi dengan KEDUANYA menambahkan komponen ke GameObject dalam adegan yang disimpan, dan dengan membuat instans komponen tersebut dalam kode. Pengujian harus mencakup kasus pengujian baik untuk membuat contoh prefab dan membuat instans, mengonfigurasi komponen saat runtime.
Play-in-editor adalah platform target pertama dan utama Anda
Play-In-Editor adalah cara tercepat untuk melakukan iterasi di Unity. Menyediakan cara bagi pelanggan kami untuk iterasi dengan cepat memungkinkan mereka untuk mengembangkan solusi dengan lebih cepat dan mencoba lebih banyak ide. Dengan kata lain, memaksimalkan kecepatan iterasi memberdayakan pelanggan kami untuk mencapai lebih banyak hal.
Buat semuanya berfungsi secara editor, lalu membuatnya berfungsi di platform lain. Tetap bekerja di editor. Sangat mudah untuk menambahkan platform baru ke Play-In-Editor. Sangat sulit untuk membuat Play-In-Editor berfungsi jika aplikasi Anda hanya berfungsi di perangkat.
Tambahkan bidang publik baru, properti, metode, dan bidang privat berseri dengan hati-hati
Setiap kali Anda menambahkan metode publik, bidang, properti, metode tersebut menjadi bagian dari permukaan API publik MRTK. Bidang privat yang ditandai dengan [SerializeField]
juga mengekspos bidang ke editor dan merupakan bagian dari permukaan API publik. Orang lain mungkin menggunakan metode publik tersebut, mengonfigurasi prefab kustom dengan bidang publik Anda, dan mengambil dependensi pada metode tersebut.
Anggota publik baru harus diperiksa dengan hati-hati. Setiap bidang publik perlu dipertahankan di masa depan. Ingat bahwa jika jenis bidang publik (atau bidang privat berseri) berubah atau dihapus dari MonoBehaviour, yang dapat merusak orang lain. Bidang harus terlebih dahulu ditolak untuk rilis, dan kode untuk memigrasikan perubahan bagi orang-orang yang telah mengambil dependensi perlu disediakan.
Memprioritaskan pengujian penulisan
MRTK adalah proyek komunitas, yang dimodifikasi oleh beragam kontributor. Kontributor ini mungkin tidak mengetahui detail perbaikan/fitur bug Anda, dan secara tidak sengaja merusak fitur Anda. MRTK menjalankan pengujian integrasi berkelanjutan sebelum menyelesaikan setiap permintaan pull. Perubahan yang menghentikan pengujian tidak dapat dicek masuk. Oleh karena itu, pengujian adalah cara terbaik untuk memastikan bahwa orang lain tidak merusak fitur Anda.
Ketika Anda memperbaiki bug, tulis pengujian untuk memastikannya tidak mengalami kemunculan di masa mendatang. Jika menambahkan fitur, tulis pengujian yang memverifikasi bahwa fitur Anda berfungsi. Ini diperlukan untuk semua fitur UX kecuali fitur eksperimental.
Konvensi C# Coding
Header informasi lisensi skrip
Semua karyawan Microsoft yang berkontribusi file baru harus menambahkan header Lisensi standar berikut di bagian atas file baru apa pun, persis seperti yang ditunjukkan di bawah ini:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Header ringkasan fungsi /metode
Semua kelas publik, struktur, enum, fungsi, properti, bidang yang diposting ke MRTK harus digambarkan dengan tujuan dan penggunaannya, persis seperti yang ditunjukkan di bawah ini:
/// <summary>
/// The Controller definition defines the Controller as defined by the SDK / Unity.
/// </summary>
public struct Controller
{
/// <summary>
/// The ID assigned to the Controller
/// </summary>
public string ID;
}
Ini memastikan dokumentasi dihasilkan dan disebarluaskan dengan benar untuk semua kelas, metode, dan properti.
File skrip apa pun yang dikirimkan tanpa tag ringkasan yang tepat akan ditolak.
Aturan namespace MRTK
Mixed Reality Toolkit menggunakan model namespace layanan berbasis fitur, di mana semua namespace dasar dimulai dengan "Microsoft.MixedReality.Toolkit". Secara umum, Anda tidak perlu menentukan lapisan toolkit (misalnya: Core, Providers, Services) di namespace Anda.
Namespace yang ditentukan saat ini adalah:
- Microsoft.MixedReality.Toolkit
- Microsoft.MixedReality.Toolkit.Boundary
- Microsoft.MixedReality.Toolkit.Diagnostics
- Microsoft.MixedReality.Toolkit.Editor
- Microsoft.MixedReality.Toolkit.Input
- Microsoft.MixedReality.Toolkit.SpatialAwareness
- Microsoft.MixedReality.Toolkit.Teleport
- Microsoft.MixedReality.Toolkit.Utilities
Untuk namespace dengan sejumlah besar jenis, dapat diterima untuk membuat sejumlah terbatas sub-namespace untuk membantu dalam cakupan penggunaan.
Menghilangkan namespace layanan untuk antarmuka, kelas, atau jenis data akan menyebabkan perubahan Anda diblokir.
Menambahkan skrip MonoBehaviour baru
Saat menambahkan skrip MonoBehaviour baru dengan permintaan pull, pastikan AddComponentMenu
atribut diterapkan ke semua file yang berlaku. Ini memastikan komponen mudah ditemukan di editor di bawah tombol Tambahkan Komponen . Bendera atribut tidak diperlukan jika komponen tidak dapat muncul di editor seperti kelas abstrak.
Dalam contoh di bawah ini, Paket di sini harus diisi dengan lokasi paket komponen. Jika menempatkan item di folder MRTK/SDK , maka paket akan menjadi SDK.
[AddComponentMenu("Scripts/MRTK/{Package here}/MyNewComponent")]
public class MyNewComponent : MonoBehaviour
Menambahkan skrip inspektur Unity baru
Secara umum, cobalah untuk menghindari pembuatan skrip inspektur kustom untuk komponen MRTK. Ini menambahkan overhead tambahan dan manajemen basis kode yang dapat ditangani oleh mesin Unity.
Jika kelas inspektur diperlukan, coba gunakan Unity DrawDefaultInspector()
. Ini lagi-lagi menyederhanakan kelas inspektur dan meninggalkan banyak pekerjaan untuk Unity.
public override void OnInspectorGUI()
{
// Do some custom calculations or checks
// ....
DrawDefaultInspector();
}
Jika penyajian kustom diperlukan di kelas inspektur, coba gunakan SerializedProperty
dan EditorGUILayout.PropertyField
. Ini akan memastikan Unity menangani render prefab berlapis dan nilai yang dimodifikasi dengan benar.
Jika EditorGUILayout.PropertyField
tidak dapat digunakan karena persyaratan dalam logika kustom, pastikan semua penggunaan dibungkus di sekitar EditorGUI.PropertyScope
. Ini akan memastikan Unity merender inspektur dengan benar untuk prefab berlapis dan nilai yang dimodifikasi dengan properti yang diberikan.
Selain itu, cobalah untuk menghias kelas pemeriksa kustom dengan CanEditMultipleObjects
. Tag ini memastikan beberapa objek dengan komponen ini dalam adegan dapat dipilih dan dimodifikasi bersama-sama. Setiap kelas inspektur baru harus menguji bahwa kode mereka berfungsi dalam situasi ini di tempat kejadian.
// Example inspector class demonstrating usage of SerializedProperty & EditorGUILayout.PropertyField
// as well as use of EditorGUI.PropertyScope for custom property logic
[CustomEditor(typeof(MyComponent))]
public class MyComponentInspector : UnityEditor.Editor
{
private SerializedProperty myProperty;
private SerializedProperty handedness;
protected virtual void OnEnable()
{
myProperty = serializedObject.FindProperty("myProperty");
handedness = serializedObject.FindProperty("handedness");
}
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField(destroyOnSourceLost);
Rect position = EditorGUILayout.GetControlRect();
var label = new GUIContent(handedness.displayName);
using (new EditorGUI.PropertyScope(position, label, handedness))
{
var currentHandedness = (Handedness)handedness.enumValueIndex;
handedness.enumValueIndex = (int)(Handedness)EditorGUI.EnumPopup(
position,
label,
currentHandedness,
(value) => {
// This function is executed by Unity to determine if a possible enum value
// is valid for selection in the editor view
// In this case, only Handedness.Left and Handedness.Right can be selected
return (Handedness)value == Handedness.Left
|| (Handedness)value == Handedness.Right;
});
}
}
}
Menambahkan ScriptableObjects baru
Saat menambahkan skrip ScriptableObject baru, pastikan CreateAssetMenu
atribut diterapkan ke semua file yang berlaku. Ini memastikan komponen mudah ditemukan di editor melalui menu pembuatan aset. Bendera atribut tidak diperlukan jika komponen tidak dapat muncul di editor seperti kelas abstrak.
Dalam contoh di bawah ini, Subfolder harus diisi dengan subfolder MRTK, jika berlaku. Jika menempatkan item di folder MRTK/Providers , maka paket akan menjadi Penyedia. Jika menempatkan item di folder MRTK/Core , atur ini ke "Profil".
Dalam contoh di bawah ini, myNewService | MyNewProvider harus diisi dengan nama kelas baru Anda, jika berlaku. Jika menempatkan item di folder MixedRealityToolkit , biarkan string ini keluar.
[CreateAssetMenu(fileName = "MyNewProfile", menuName = "Mixed Reality Toolkit/{Subfolder}/{MyNewService | MyNewProvider}/MyNewProfile")]
public class MyNewProfile : ScriptableObject
Pengelogan
Saat menambahkan fitur baru atau memperbarui fitur yang ada, pertimbangkan untuk menambahkan log DebugUtilities.LogVerbose ke kode menarik yang mungkin berguna untuk penelusuran kesalahan di masa mendatang. Ada tradeoff di sini antara menambahkan pengelogan dan kebisingan tambahan dan pengelogan tidak cukup (yang membuat diagnosis sulit).
Contoh menarik di mana pengelogan berguna (bersama dengan payload yang menarik):
DebugUtilities.LogVerboseFormat("RaiseSourceDetected: Source ID: {0}, Source Type: {1}", source.SourceId, source.SourceType);
Jenis pengelogan ini dapat membantu menangkap masalah seperti https://github.com/microsoft/MixedRealityToolkit-Unity/issues/8016, yang disebabkan oleh sumber yang tidak cocok yang terdeteksi dan peristiwa sumber hilang.
Hindari menambahkan log untuk data dan peristiwa yang terjadi pada setiap bingkai - idealnya pengelogan harus mencakup peristiwa "menarik" yang didorong oleh input pengguna yang berbeda (yaitu "klik" oleh pengguna dan serangkaian perubahan dan peristiwa yang berasal dari yang menarik untuk dicatat). Status yang sedang berlangsung dari "pengguna masih memegang gerakan" yang dicatat setiap bingkai tidak menarik dan akan membanjiri log.
Perhatikan bahwa pengelogan verbose ini tidak diaktifkan secara default (harus diaktifkan dalam pengaturan Sistem Diagnostik)
Spasi vs tab
Pastikan untuk menggunakan 4 spasi alih-alih tab saat berkontribusi pada proyek ini.
Jarak
Jangan tambahkan spasi tambahan antara tanda kurung siku dan tanda kurung:
Jangan
private Foo()
{
int[ ] var = new int [ 9 ];
Vector2 vector = new Vector2 ( 0f, 10f );
}
Lakukan
private Foo()
{
int[] var = new int[9];
Vector2 vector = new Vector2(0f, 10f);
}
Konvensi penamaan
Selalu gunakan PascalCase
untuk properti. Gunakan camelCase
untuk sebagian besar bidang, kecuali gunakan PascalCase
untuk static readonly
bidang dan const
. Satu-satunya pengecualian untuk ini adalah untuk struktur data yang mengharuskan bidang diserialisasikan oleh JsonUtility
.
Jangan
public string myProperty; // <- Starts with a lowercase letter
private string MyField; // <- Starts with an uppercase letter
Lakukan
public string MyProperty;
protected string MyProperty;
private static readonly string MyField;
private string myField;
Pengubah akses
Selalu nyatakan pengubah akses untuk semua bidang, properti, dan metode.
Semua Metode UNITY API harus
private
secara default, kecuali Anda perlu mengambil alihnya di kelas turunan. Dalam halprotected
ini harus digunakan.Bidang harus
private
selalu , denganpublic
atauprotected
pengaktor properti.Gunakan anggota bertubuh ekspresi dan properti otomatis jika memungkinkan
Jangan
// protected field should be private
protected int myVariable = 0;
// property should have protected setter
public int MyVariable => myVariable;
// No public / private access modifiers
void Foo() { }
void Bar() { }
Lakukan
public int MyVariable { get; protected set; } = 0;
private void Foo() { }
public void Bar() { }
protected virtual void FooBar() { }
Gunakan kurung kurawal
Selalu gunakan kurung kurawal setelah setiap blok pernyataan, dan letakkan di baris berikutnya.
Jangan
private Foo()
{
if (Bar==null) // <- missing braces surrounding if action
DoThing();
else
DoTheOtherThing();
}
Jangan
private Foo() { // <- Open bracket on same line
if (Bar==null) DoThing(); <- if action on same line with no surrounding brackets
else DoTheOtherThing();
}
Lakukan
private Foo()
{
if (Bar==true)
{
DoThing();
}
else
{
DoTheOtherThing();
}
}
Kelas publik, struktur, dan enum semuanya harus masuk ke dalam file mereka sendiri
Jika kelas, struct, atau enum dapat dibuat privat maka tidak apa-apa untuk disertakan dalam file yang sama. Ini menghindari masalah kompilasi dengan Unity dan memastikan bahwa abstraksi kode yang tepat terjadi, itu juga mengurangi konflik dan melanggar perubahan ketika kode perlu berubah.
Jangan
public class MyClass
{
public struct MyStruct() { }
public enum MyEnumType() { }
public class MyNestedClass() { }
}
Lakukan
// Private references for use inside the class only
public class MyClass
{
private struct MyStruct() { }
private enum MyEnumType() { }
private class MyNestedClass() { }
}
Lakukan
MyStruct.cs
// Public Struct / Enum definitions for use in your class. Try to make them generic for reuse.
public struct MyStruct
{
public string Var1;
public string Var2;
}
MyEnumType.cs
public enum MuEnumType
{
Value1,
Value2 // <- note, no "," on last value to denote end of list.
}
MyClass.cs
public class MyClass
{
private MyStruct myStructReference;
private MyEnumType myEnumReference;
}
Menginisialisasi enum
Untuk memastikan semua enum diinisialisasi dengan benar mulai dari 0, .NET memberi Anda pintasan rapi untuk menginisialisasi enum secara otomatis hanya dengan menambahkan nilai (starter) pertama. (misalnya Nilai 1 = 0 Nilai yang tersisa tidak diperlukan)
Jangan
public enum Value
{
Value1, <- no initializer
Value2,
Value3
}
Lakukan
public enum ValueType
{
Value1 = 0,
Value2,
Value3
}
Enum pesanan untuk ekstensi yang sesuai
Sangat penting bahwa jika Enum kemungkinan akan diperpanjang di masa depan, untuk memesan default di bagian atas Enum, ini memastikan indeks Enum tidak terpengaruh dengan penambahan baru.
Jangan
public enum SDKType
{
WindowsMR,
OpenVR,
OpenXR,
None, <- default value not at start
Other <- anonymous value left to end of enum
}
Lakukan
/// <summary>
/// The SDKType lists the VR SDKs that are supported by the MRTK
/// Initially, this lists proposed SDKs, not all may be implemented at this time (please see ReleaseNotes for more details)
/// </summary>
public enum SDKType
{
/// <summary>
/// No specified type or Standalone / non-VR type
/// </summary>
None = 0,
/// <summary>
/// Undefined SDK.
/// </summary>
Other,
/// <summary>
/// The Windows 10 Mixed reality SDK provided by the Universal Windows Platform (UWP), for Immersive MR headsets and HoloLens.
/// </summary>
WindowsMR,
/// <summary>
/// The OpenVR platform provided by Unity (does not support the downloadable SteamVR SDK).
/// </summary>
OpenVR,
/// <summary>
/// The OpenXR platform. SDK to be determined once released.
/// </summary>
OpenXR
}
Meninjau penggunaan enum untuk bitfields
Jika ada kemungkinan bagi enum untuk memerlukan beberapa status sebagai nilai, misalnya Handedness = Kiri & Kanan. Maka Enum perlu didekorasi dengan benar dengan BitFlags untuk memungkinkannya digunakan dengan benar
File Handedness.cs memiliki implementasi konkret untuk ini
Jangan
public enum Handedness
{
None,
Left,
Right
}
Lakukan
[Flags]
public enum Handedness
{
None = 0 << 0,
Left = 1 << 0,
Right = 1 << 1,
Both = Left | Right
}
Jalur file yang dikodekan secara permanen
Saat membuat jalur file string, dan secara khusus menulis jalur string yang dikodekan secara permanen, lakukan hal berikut:
- Gunakan API C#jika
Path
memungkinkan sepertiPath.Combine
atauPath.GetFullPath
. - Gunakan / atau
Path.DirectorySeparatorChar
alih-alih \ atau \\.
Langkah-langkah ini memastikan bahwa MRTK berfungsi pada sistem berbasis Windows dan Unix.
Jangan
private const string FilePath = "MyPath\\to\\a\\file.txt";
private const string OtherFilePath = "MyPath\to\a\file.txt";
string filePath = myVarRootPath + myRelativePath;
Lakukan
private const string FilePath = "MyPath/to/a/file.txt";
private const string OtherFilePath = "folder{Path.DirectorySeparatorChar}file.txt";
string filePath = Path.Combine(myVarRootPath,myRelativePath);
// Path.GetFullPath() will return the full length path of provided with correct system directory separators
string cleanedFilePath = Path.GetFullPath(unknownSourceFilePath);
Praktik terbaik, termasuk rekomendasi Unity
Beberapa platform target proyek ini perlu mempertimbangkan performa. Dengan mengingat hal ini, selalu berhati-hatilah saat mengalokasikan memori dalam kode yang sering disebut dalam perulangan atau algoritma pembaruan yang ketat.
Enkapsulasi
Selalu gunakan bidang privat dan properti publik jika akses ke bidang diperlukan dari luar kelas atau struktur. Pastikan untuk menemukan bersama bidang privat dan properti publik. Ini membuatnya lebih mudah dilihat, sekilas, apa yang mendukung properti dan bahwa bidang dapat dimodifikasi oleh skrip.
Catatan
Satu-satunya pengecualian untuk ini adalah untuk struktur data yang mengharuskan bidang diserialisasikan oleh JsonUtility
, di mana kelas data diperlukan untuk memiliki semua bidang publik agar serialisasi berfungsi.
Jangan
private float myValue1;
private float myValue2;
public float MyValue1
{
get{ return myValue1; }
set{ myValue1 = value }
}
public float MyValue2
{
get{ return myValue2; }
set{ myValue2 = value }
}
Lakukan
// Enable field to be configurable in the editor and available externally to other scripts (field is correctly serialized in Unity)
[SerializeField]
[ToolTip("If using a tooltip, the text should match the public property's summary documentation, if appropriate.")]
private float myValue; // <- Notice we co-located the backing field above our corresponding property.
/// <summary>
/// If using a tooltip, the text should match the public property's summary documentation, if appropriate.
/// </summary>
public float MyValue
{
get => myValue;
set => myValue = value;
}
/// <summary>
/// Getter/Setters not wrapping a value directly should contain documentation comments just as public functions would
/// </summary>
public float AbsMyValue
{
get
{
if (MyValue < 0)
{
return -MyValue;
}
return MyValue
}
}
Nilai cache dan serialisasikan di adegan/prefab jika memungkinkan
Dengan mengingat HoloLens, yang terbaik adalah mengoptimalkan referensi performa dan cache dalam adegan atau prefab untuk membatasi alokasi memori runtime.
Jangan
void Update()
{
gameObject.GetComponent<Renderer>().Foo(Bar);
}
Lakukan
[SerializeField] // To enable setting the reference in the inspector.
private Renderer myRenderer;
private void Awake()
{
// If you didn't set it in the inspector, then we cache it on awake.
if (myRenderer == null)
{
myRenderer = gameObject.GetComponent<Renderer>();
}
}
private void Update()
{
myRenderer.Foo(Bar);
}
Referensi cache ke bahan, jangan panggil ".material" setiap kali
Unity akan membuat bahan baru setiap kali Anda menggunakan ".material", yang akan menyebabkan kebocoran memori jika tidak dibersihkan dengan benar.
Jangan
public class MyClass
{
void Update()
{
Material myMaterial = GetComponent<Renderer>().material;
myMaterial.SetColor("_Color", Color.White);
}
}
Lakukan
// Private references for use inside the class only
public class MyClass
{
private Material cachedMaterial;
private void Awake()
{
cachedMaterial = GetComponent<Renderer>().material;
}
void Update()
{
cachedMaterial.SetColor("_Color", Color.White);
}
private void OnDestroy()
{
Destroy(cachedMaterial);
}
}
Catatan
Atau, gunakan properti "SharedMaterial" Unity yang tidak membuat materi baru setiap kali dirujuk.
Gunakan kompilasi dependen platform untuk memastikan Toolkit tidak akan merusak build di platform lain
- Gunakan
WINDOWS_UWP
untuk menggunakan API khusus UWP, non-Unity. Ini akan mencegah mereka mencoba menjalankan di Editor atau pada platform yang tidak didukung. Ini setara denganUNITY_WSA && !UNITY_EDITOR
dan harus digunakan untuk mendukung. - Gunakan
UNITY_WSA
untuk menggunakan API Unity khusus UWP, sepertiUnityEngine.XR.WSA
namespace layanan. Ini akan berjalan di Editor ketika platform diatur ke UWP, serta di aplikasi UWP bawaan.
Bagan ini dapat membantu Anda memutuskan mana yang #if
akan digunakan, tergantung pada kasus penggunaan Anda dan pengaturan build yang Anda harapkan.
Platform | UWP IL2CPP | UWP .NET | Editor |
---|---|---|---|
UNITY_EDITOR |
FALSE | FALSE | True |
UNITY_WSA |
True | True | True |
WINDOWS_UWP |
True | True | Salah |
UNITY_WSA && !UNITY_EDITOR |
True | True | Salah |
ENABLE_WINMD_SUPPORT |
True | True | FALSE |
NETFX_CORE |
FALSE | True | FALSE |
Pilih DateTime.UtcNow daripada DateTime.Now
DateTime.UtcNow lebih cepat daripada DateTime.Now. Dalam penyelidikan performa sebelumnya, kami telah menemukan bahwa menggunakan DateTime.Now menambahkan overhead yang signifikan terutama saat digunakan dalam perulangan Update(). Yang lain mengalami masalah yang sama.
Lebih suka menggunakan DateTime.UtcNow kecuali Anda benar-benar memerlukan waktu yang dilokalkan (alasan yang sah mungkin Anda ingin menunjukkan waktu saat ini di zona waktu pengguna). Jika Anda berurusan dengan waktu relatif (yaitu delta antara beberapa pembaruan terakhir dan sekarang), yang terbaik adalah menggunakan DateTime.UtcNow untuk menghindari overhead melakukan konversi zona waktu.
Konvensi pengkodean PowerShell
Subset basis kode MRTK menggunakan PowerShell untuk infrastruktur alur dan berbagai skrip dan utilitas. Kode PowerShell baru harus mengikuti gaya PoshCode.