(7)From Nurse to C# Developer -- Basics of Object-Oriented Programming

(7)From Nurse to C# Developer -- Basics of Object-Oriented Programming

As a programmer who switched from the nursing industry, I will share how to understand the concepts of object-oriented programming through experience in medical work. This article introduces core OOP concepts such as classes, objects, properties, and methods, and uses examples from the healthcare field to deepen understanding.

Last updated 3/18/2025 9:15 PM
勇敢的天使
19 min read
Category
Sharing Course .NET
Topic
From Nurse to C# Developer
Tags
.NET C# Career Change to Development Programming Object-Oriented

Introduction

As a newcomer transitioning from nursing to programming, I discovered that object-oriented programming (OOP) concepts have many similarities with medical practice. In this article, I will share how I used my healthcare work experience to understand the basic concepts of OOP, hoping to help other healthcare professionals who are learning to code.

Procedural vs Object-Oriented

Procedural Thinking

Procedural programming focuses on the process and steps to accomplish a task, emphasizing actions and workflows. This is like the standard operating procedures (SOPs) we follow in hospitals.

For example, measuring a patient's blood sugar with procedural thinking:

// Procedural thinking: different nurses execute the same blood sugar measurement process
void NurseLiMeasureBloodSugar()  // Nurse Li (less experienced)
{
    PrepareEquipment();     // Prepare equipment
    CallForHelp();          // Call for help
    ExplainToPatient();     // Explain to patient
    DisinfectFinger();      // Disinfect finger
    PrickFinger();          // Prick finger
    ApplyBloodToStrip();    // Apply blood to strip
    ReadResult();           // Read result
    RecordData();           // Record data
    DisposeMaterials();     // Dispose of medical waste
}

void NurseZhangMeasureBloodSugar()  // Nurse Zhang (experienced)
{
    PrepareEquipment();     // Prepare equipment
    ExplainToPatient();     // Explain to patient
    DisinfectFinger();      // Disinfect finger
    PrickFingerExpertly();  // Prick finger expertly
    ApplyBloodToStrip();    // Apply blood to strip
    ReadResultAccurately(); // Read result accurately
    RecordDataInDetail();   // Record data in detail
    DisposeMaterials();     // Dispose of medical waste
}

As you can see, the procedural approach requires us to write different code for different executors; each nurse needs their own complete set of procedures, leading to code duplication and difficulty in maintenance.

Object-Oriented Thinking

Object-oriented programming is about finding an object to do the job for you. For the same blood sugar measurement task, we shift our focus from "who does what" to "what device is used," encapsulating the operations within the appropriate objects.

/// <summary>
/// GlucoseMeter class - medical device responsible for measuring and recording blood glucose values
/// </summary>
public class GlucoseMeter
{
    // Properties - represent the status of the glucose meter
    /// <summary>
    /// Indicates whether the glucose meter is calibrated
    /// </summary>
    public bool IsCalibrated { get; private set; }

    /// <summary>
    /// Indicates the current battery level of the glucose meter
    /// </summary>
    public double BatteryLevel { get; private set; }

    // Methods - represent operations the glucose meter can perform
    /// <summary>
    /// Calibrate the glucose meter to ensure accurate measurement
    /// </summary>
    public void Calibrate()
    {
        IsCalibrated = true;
        Console.WriteLine("Glucose meter calibrated");
    }

    /// <summary>
    /// Perform blood sugar measurement
    /// </summary>
    /// <returns>The measured blood sugar value, returns -1 if device is not calibrated</returns>
    public double MeasureBloodSugar()
    {
        if(!IsCalibrated)
        {
            Console.WriteLine("Error: Glucose meter not calibrated");
            return -1; // Error value
        }

        Console.WriteLine("Measuring blood sugar...");
        // Perform measurement logic
        return 5.6; // Return blood sugar value (example)
    }
}

/// <summary>
/// Nurse class - represents the nursing staff performing medical operations
/// </summary>
public class Nurse
{
    /// <summary>
    /// Nurse name
    /// </summary>
    public string Name { get; private set; }

    /// <summary>
    /// Years of work experience
    /// </summary>
    public int ExperienceYears { get; private set; }

    /// <summary>
    /// Create a new nurse object
    /// </summary>
    /// <param name="name">Nurse name</param>
    /// <param name="experienceYears">Years of work experience</param>
    public Nurse(string name, int experienceYears)
    {
        Name = name;
        ExperienceYears = experienceYears;
    }

    /// <summary>
    /// Comprehensive operation to measure a patient's blood sugar
    /// </summary>
    /// <param name="patient">The patient to measure</param>
    /// <param name="meter">The glucose meter to use</param>
    public void MeasurePatientBloodSugar(Patient patient, GlucoseMeter meter)
    {
        Console.WriteLine($"Nurse {Name} is preparing to measure {patient.Name}'s blood sugar");

        // Prepare equipment
        Console.WriteLine("Prepare equipment");

        // Calibrate device (done by the glucose meter)
        meter.Calibrate();

        // Explain to patient
        Console.WriteLine($"Explain the measurement process to {patient.Name}");

        // Disinfect and prick finger (nurse's professional operation)
        Console.WriteLine("Disinfect finger and prick");

        // Measure blood sugar (done by the glucose meter)
        double bloodSugar = meter.MeasureBloodSugar();

        // Record result
        if(bloodSugar > 0)
        {
            patient.RecordBloodSugar(bloodSugar);
            Console.WriteLine($"Blood sugar value: {bloodSugar}mmol/L, recorded in patient file");
        }

        // Dispose of medical waste
        Console.WriteLine("Dispose of medical waste");
    }
}

/// <summary>
/// Patient class - represents a patient in the hospital
/// </summary>
public class Patient
{
    // Fields - private data, not directly exposed
    /// <summary>
    /// Patient name
    /// </summary>
    private string _name;

    /// <summary>
    /// Patient age
    /// </summary>
    private int _age;

    /// <summary>
    /// Patient's historical blood sugar readings
    /// </summary>
    private List<double> _bloodSugarReadings;

    /// <summary>
    /// Create a new patient object
    /// </summary>
    /// <param name="name">Patient name</param>
    /// <param name="age">Patient age</param>
    public Patient(string name, int age)
    {
        _name = name;
        _age = age;
        _bloodSugarReadings = new List<double>(); // Initialize empty list of blood sugar readings
    }

    // Properties - accessors provided to the outside
    /// <summary>
    /// Get the patient name
    /// </summary>
    public string Name
    {
        get { return _name; }
        private set { _name = value; } // Only modifiable inside the class
    }

    /// <summary>
    /// Get or set the patient age (with validation)
    /// </summary>
    public int Age
    {
        get { return _age; }
        private set { _age = value > 0 ? value : 0; } // Ensure age is positive
    }

    // Methods - operations the object can perform
    /// <summary>
    /// Record a new blood sugar measurement value
    /// </summary>
    /// <param name="value">Blood sugar value</param>
    public void RecordBloodSugar(double value)
    {
        if(value > 0)
        {
            _bloodSugarReadings.Add(value);
        }
    }

    /// <summary>
    /// Get the most recent blood sugar record
    /// </summary>
    /// <returns>The most recent blood sugar value, returns -1 if no record exists</returns>
    public double GetLatestBloodSugar()
    {
        if(_bloodSugarReadings.Count > 0)
            return _bloodSugarReadings[_bloodSugarReadings.Count - 1];
        else
            return -1; // Indicates no record
    }

    /// <summary>
    /// Get the patient's complete blood sugar history
    /// </summary>
    /// <returns>A copy of the list of blood sugar values</returns>
    public List<double> GetBloodSugarHistory()
    {
        return new List<double>(_bloodSugarReadings); // Return a copy to protect original data
    }
}

// Usage example - demonstrates collaboration between objects
/// <summary>
/// Comprehensive example of blood sugar measurement
/// </summary>
void BloodSugarMeasurementExample()
{
    // Create various objects
    Patient patient = new Patient("Wang Xiaoming", 65);
    GlucoseMeter meter = new GlucoseMeter();

    // Nurses with different experience use the same method and device
    Nurse nurseLi = new Nurse("Nurse Li", 1);  // Less experienced
    Nurse nurseZhang = new Nurse("Nurse Zhang", 10);  // Experienced

    // Both nurses perform the same operation, call the same method
    nurseLi.MeasurePatientBloodSugar(patient, meter);
    nurseZhang.MeasurePatientBloodSugar(patient, meter);

    // Check patient's blood sugar history
    List<double> history = patient.GetBloodSugarHistory();
    Console.WriteLine($"Patient {patient.Name}'s blood sugar record count: {history.Count}");
}

Through the object-oriented approach, we:

  1. Created objects representing different roles and devices (patient, nurse, glucose meter)
  2. Each object is responsible for its own functionality (glucose meter measures, nurse manages the process)
  3. Regardless of the nurse, the same method is used, reducing code duplication
  4. Responsibilities are assigned to appropriate objects, making the code more modular and easier to maintain

This is similar to real medical work: different nurses use the same medical devices and standard procedures to serve patients, rather than each nurse inventing their own process.

Understanding Classes and Objects

When working in the hospital, we have the "nursing record sheet" template, and based on it, we create specific records for each patient. In programming:

  • Class: Like the nursing record sheet template, it defines the characteristics (properties) and functions (methods) an object should have.
  • Object: Like a specific patient record filled out based on the template.

The Concept of a Class

A class is like a blueprint or a mold, similar to the nursing assessment form I used as a nurse. This form defines what needs to be recorded (properties) and the procedures (methods).

In C#, the basic syntax of a class is:

[public] class ClassName
{
    // Fields
    private string _name;

    // Properties
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    // Methods
    public void DoSomething()
    {
        // Method implementation
    }
}

Relationship Between Classes and Objects

If we compare a class to a medical record template, an object is a specific patient record created from that template. The class itself does not occupy memory (except for static members), while objects do.

Healthcare example:

// Patient class
public class Patient
{
    // Fields
    private string _name;
    private int _age;
    private string _diagnosis;

    // Properties
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public int Age
    {
        get { return _age; }
        set { _age = value > 0 ? value : 0; }  // Validate age must be positive
    }

    // Methods
    public void TakeMedicine()
    {
        Console.WriteLine($"{Name} is taking medicine...");
    }
}

// Create a Patient object
Patient patient1 = new Patient();
patient1.Name = "Zhang San";
patient1.Age = 45;
patient1.TakeMedicine();  // Output: Zhang San is taking medicine...

Understanding Properties and Fields

Difference Between Fields and Properties

In nursing work, we have a lot of data to record, but some data requires validation or special handling.

  • Field: Equivalent to raw data in medical records, usually should be protected and not directly modifiable from outside.
  • Property: Equivalent to a control mechanism for this data, can add validation logic.
public class Patient
{
    // Field (private)
    private double _temperature;

    // Property (public)
    public double Temperature
    {
        get { return _temperature; }
        set
        {
            // Add validation logic
            if(value >= 35 && value <= 42)
                _temperature = value;
            else
                throw new ArgumentException("Temperature value is unreasonable!");
        }
    }
}

Properties are essentially two methods: get() and set(). Properties can be:

  • Read-write property: has both get and set
  • Read-only property: only has get
  • Write-only property: only has set

Access Modifiers

In hospital information systems, personnel at different levels can access different information. This is similar to the concept of access modifiers in C#:

  • public: Public, like basic patient information viewable by all medical staff.
  • private: Private, accessible only within the current class, like certain sensitive test results viewable only by the attending physician.
  • protected: Protected, accessible by derived classes, like certain treatment plans viewable only by members of the medical team.

Object Initialization

When a new patient is admitted, we need to fill out a series of forms to record their basic information. In programming, we accomplish object initialization through constructors.

Constructor

A constructor is a special method that automatically executes when an object is created, used to initialize the object.

public class Patient
{
    // Fields
    private string _name;
    private int _age;

    // Constructor
    public Patient(string name, int age)
    {
        _name = name;
        _age = age;
        Console.WriteLine($"Created a new patient: {name}, {age} years old");
    }

    // Properties
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public int Age
    {
        get { return _age; }
        set { _age = value; }
    }
}

// Use constructor to create an object
Patient newPatient = new Patient("Li Si", 50);

Characteristics of constructors:

  1. No return value, not even void.
  2. Name must match the class name.
  3. Can have multiple overloaded versions.
  4. A class has a default parameterless constructor, but if you define a custom constructor, the default parameterless constructor disappears.

The Role of the new Keyword

When we use new to create an object, it does three things:

  1. Allocates space in memory.
  2. Creates the object in that space.
  3. Calls the constructor to initialize the object.

Just like a hospital assigning a new patient a bed, preparing medical records, and entering basic information.

Static vs Non-Static

In a hospital, some information is unique to each patient (e.g., name, age), while some information is shared among all patients (e.g., hospital name, department doctors).

Static Members and Instance Members

  • Instance member: Properties or methods unique to each object, like each patient having their own temperature, blood pressure, etc.
  • Static member: Properties or methods belonging to the class itself rather than objects, shared by all objects, like the hospital name, treatment protocols, etc.
/// <summary>
/// Hospital class (static) - contains hospital-level information shared by all departments
/// </summary>
public static class Hospital
{
    // Static properties - shared by all departments

    /// <summary>
    /// Hospital name - shared by all departments
    /// </summary>
    public static string Name { get; } = "Peace Hospital";

    /// <summary>
    /// Total number of beds - shared by all departments
    /// </summary>
    public static int TotalBeds { get; private set; } = 500;

    /// <summary>
    /// Hospital address - shared by all departments
    /// </summary>
    public static string Address { get; } = "123 Peace Road";

    /// <summary>
    /// Emergency number - shared by all departments
    /// </summary>
    public static string EmergencyNumber { get; } = "120";

    // Static methods - hospital-level operations
    /// <summary>
    /// Patient admission process - assign to a specific department
    /// </summary>
    /// <param name="patient">Admitted patient</param>
    /// <param name="department">Target department</param>
    public static void AdmitPatient(Patient patient, Department department)
    {
        if(TotalBeds > 0)
        {
            department.AssignBed(patient);
            TotalBeds--;
            Console.WriteLine($"{patient.Name} has been admitted to the {department.Name} department");
        }
        else
        {
            Console.WriteLine("Hospital beds are full, cannot admit");
        }
    }

    /// <summary>
    /// Patient discharge process - discharge from a specific department
    /// </summary>
    /// <param name="patient">Discharged patient</param>
    /// <param name="department">Source department</param>
    public static void DischargePatient(Patient patient, Department department)
    {
        department.ReleaseBed(patient);
        TotalBeds++;
        Console.WriteLine($"{patient.Name} has been discharged from the {department.Name} department");
    }

}

/// <summary>
/// Department class - represents a specific department in the hospital, each with its own characteristics
/// </summary>
public class Department
{
    // Fields - department-specific data
    /// <summary>
    /// Department name
    /// </summary>
    private string _name;

    /// <summary>
    /// Total number of beds in the department
    /// </summary>
    private int _totalBeds;

    /// <summary>
    /// Number of available beds in the department
    /// </summary>
    private int _availableBeds;

    /// <summary>
    /// List of medical staff IDs in the department
    /// </summary>
    private List<string> _staffIds;

    /// <summary>
    /// List of current patients in the department
    /// </summary>
    private List<Patient> _patients;

    /// <summary>
    /// Create a new department
    /// </summary>
    /// <param name="name">Department name</param>
    /// <param name="totalBeds">Total number of beds</param>
    public Department(string name, int totalBeds)
    {
        _name = name;
        _totalBeds = totalBeds;
        _availableBeds = totalBeds;
        _staffIds = new List<string>();
        _patients = new List<Patient>();
    }

    // Properties - information exposed by the department to the outside
    /// <summary>
    /// Get the department name
    /// </summary>
    public string Name { get { return _name; } }

    /// <summary>
    /// Get the number of available beds in the department
    /// </summary>
    public int AvailableBeds { get { return _availableBeds; } }

    // Methods - operations the department can perform
    
    /// <summary>
    /// Assign a bed to a patient
    /// </summary>
    /// <param name="patient">Patient needing a bed</param>
    public void AssignBed(Patient patient)
    {
        if(_availableBeds > 0)
        {
            _patients.Add(patient);
            _availableBeds--;
            Console.WriteLine($"{patient.Name} has been assigned a bed in the {_name} department");
        }
        else
        {
            Console.WriteLine($"{_name} department has no available beds");
        }
    }

    /// <summary>
    /// Release a bed when a patient is discharged
    /// </summary>
    /// <param name="patient">Discharged patient</param>
    public void ReleaseBed(Patient patient)
    {
        if(_patients.Contains(patient))
        {
            _patients.Remove(patient);
            _availableBeds++;
            Console.WriteLine($"{patient.Name} has released a bed in the {_name} department");
        }
    }

    /// <summary>
    /// Add a medical staff member to the department
    /// </summary>
    /// <param name="staffId">Medical staff ID</param>
    public void AddStaff(string staffId)
    {
        _staffIds.Add(staffId);
    }

    /// <summary>
    /// Display the current status of the department
    /// </summary>
    public void DisplayDepartmentStatus()
    {
        // Here we access both static members (hospital name) and instance members (department info)
        Console.WriteLine($"{Hospital.Name} - {_name} Department");
        Console.WriteLine($"Total beds: {_totalBeds}, Available beds: {_availableBeds}");
        Console.WriteLine($"Current number of patients: {_patients.Count}");
    }

}

The this Keyword

The this keyword represents the current instance of the class. In healthcare work, it can be understood as "the current patient being handled."

Uses of this:

  1. Differentiate between local variables and member variables.
  2. Call other constructors within a constructor.
public class Patient
{
    private string name;
    private int age;

    // Use this to distinguish between variables with the same name
    public Patient(string name, int age)
    {
        this.name = name;  // this.name is the field, name is the parameter
        this.age = age;
    }

    // Use this to call another constructor
    public Patient(string name) : this(name, 0)
    {
        // This constructor will first call the above constructor
    }
}

Medication Record Example

Below is a complete example of a medication record class, demonstrating the application of object-oriented programming in a medical scenario:

/// <summary>
/// MedicationRecord class - records detailed medication administration information for a patient
/// </summary>
public class MedicationRecord
{
    // Fields - internal data of the record

    /// <summary>
    /// Medication name
    /// </summary>
    private string _medicationName;

    /// <summary>
    /// Dosage (numeric part)
    /// </summary>
    private double _dosage;
    
    /// <summary>
    /// Dosage unit (e.g., mg, ml)
    /// </summary>
    private string _unit;
    
    /// <summary>
    /// Administration time
    /// </summary>
    private DateTime _administrationTime;
    
    /// <summary>
    /// Nurse ID who administered the medication
    /// </summary>
    private string _nurseId;
    
    /// <summary>
    /// Patient ID who received the medication
    /// </summary>
    private string _patientId;
    
    /// <summary>
    /// Route of administration (oral, intravenous, etc.)
    /// </summary>
    private string _route;
    
    /// <summary>
    /// Create a new medication record
    /// </summary>
    /// <param name="patientId">Patient ID</param>
    /// <param name="medicationName">Medication name</param>
    /// <param name="dosage">Dosage</param>
    /// <param name="unit">Dosage unit</param>
    /// <param name="route">Route of administration</param>
    /// <param name="nurseId">Nurse ID</param>
    public MedicationRecord(string patientId, string medicationName,
                           double dosage, string unit, string route, string nurseId)
    {
        _patientId = patientId;
        _medicationName = medicationName;
        _dosage = dosage;
        _unit = unit;
        _route = route;
        _nurseId = nurseId;
        _administrationTime = DateTime.Now; // Record current time as administration time
    }
    
    // Properties - data access interfaces exposed to the outside
    
    /// <summary>
    /// Get medication name (read-only)
    /// </summary>
    public string MedicationName { get { return _medicationName; } }
    
    /// <summary>
    /// Get dosage (read-only)
    /// </summary>
    public double Dosage { get { return _dosage; } }
    
    /// <summary>
    /// Get dosage unit (read-only)
    /// </summary>
    public string Unit { get { return _unit; } }
    
    /// <summary>
    /// Get administration time (read-only)
    /// </summary>
    public DateTime AdministrationTime { get { return _administrationTime; } }
    
    // Methods - operations related to the record
    
    /// <summary>
    /// Get complete dosage information
    /// </summary>
    /// <returns>Formatted dosage and route information</returns>
    public string GetFullDosageInfo()
    {
        return $"{_dosage} {_unit} {_medicationName} administered via {_route}";
    }
    
    /// <summary>
    /// Get the complete administration record
    /// </summary>
    /// <returns>Formatted complete administration record</returns>
    public string GetAdministrationRecord()
    {
        return $"Patient ID: {_patientId}, Medication: {_medicationName}, " +
               $"Dosage: {_dosage}{_unit}, Route: {_route}, " +
               $"Time: {_administrationTime.ToString("yyyy-MM-dd HH:mm:ss")}, " +
               $"Nurse: {_nurseId}";
    }
    
    /// <summary>
    /// Check if the medication was administered within the specified time threshold
    /// </summary>
    /// <param name="hoursThreshold">Threshold in hours</param>
    /// <returns>True if within threshold, otherwise false</returns>
    public bool IsAdministeredRecently(int hoursThreshold)
    {
        return (DateTime.Now - _administrationTime).TotalHours < hoursThreshold;
    }

}

// Usage example
public class MedicationExample
{
    public static void Main()
    {
        // Create a medication record
        MedicationRecord record = new MedicationRecord(
        "P001", "Aspirin", 100, "mg", "Oral", "N007");

        // Get the complete record
        string fullRecord = record.GetAdministrationRecord();
        Console.WriteLine(fullRecord);
    
        // Check if administered recently (within 6 hours)
        bool isRecent = record.IsAdministeredRecently(6);
        Console.WriteLine($"Administered within 6 hours: {isRecent}");
    }

}

Summary

As a newcomer transitioning from nursing to programming, I find that object-oriented programming concepts have many similarities with medical practice:

  • Class is like a medical record template.
  • Object is like a specific patient's medical record.
  • Properties are like the patient's various indicators, some requiring data validation.
  • Methods are like the various medical operations performed on the patient.
  • Constructor is like the patient admission registration.
  • Static members are like the hospital's shared resources and regulations.

Through these analogies, I can more easily understand and memorize the concepts of object-oriented programming. In the next article, I will continue to explore advanced OOP concepts such as inheritance, polymorphism, and interfaces.

Looking forward to sharing more learning insights from healthcare to programming with everyone!

Keep Exploring

Related Reading

More Articles