Feature Lifecycle Tracker Scala

👤 Sharing: AI
```scala
import java.time.LocalDate
import java.time.format.DateTimeFormatter

// Define case classes to represent the feature and its lifecycle events
case class Feature(
  id: String,
  name: String,
  description: String,
  status: FeatureStatus,
  createdAt: LocalDate,
  events: List[FeatureEvent] = List.empty // History of status changes
)

// Enum to represent the possible feature statuses
sealed trait FeatureStatus {
  def name: String
}
case object New extends FeatureStatus { val name = "New" }
case object InProgress extends FeatureStatus { val name = "In Progress" }
case object InReview extends FeatureStatus { val name = "In Review" }
case object Testing extends FeatureStatus { val name = "Testing" }
case object Deployed extends FeatureStatus { val name = "Deployed" }
case object Rejected extends FeatureStatus { val name = "Rejected" }
case object OnHold extends FeatureStatus { val name = "On Hold" }


// Case class to represent a feature event (status change)
case class FeatureEvent(
  status: FeatureStatus,
  timestamp: LocalDate,
  comment: String
)

// Object containing functions for managing the feature lifecycle
object FeatureLifecycleTracker {

  // Date formatter
  val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")

  // Function to create a new feature
  def createFeature(id: String, name: String, description: String): Feature = {
    Feature(id, name, description, New, LocalDate.now())
  }

  // Function to update the status of a feature
  def updateFeatureStatus(feature: Feature, newStatus: FeatureStatus, comment: String): Feature = {
    val event = FeatureEvent(newStatus, LocalDate.now(), comment)
    feature.copy(status = newStatus, events = feature.events :+ event) // Append event to history
  }

  // Function to get the history of a feature
  def getFeatureHistory(feature: Feature): List[FeatureEvent] = {
    feature.events
  }

  // Function to print feature details
  def printFeatureDetails(feature: Feature): Unit = {
    println(s"Feature ID: ${feature.id}")
    println(s"Name: ${feature.name}")
    println(s"Description: ${feature.description}")
    println(s"Status: ${feature.status.name}")
    println(s"Created At: ${feature.createdAt.format(dateFormatter)}")
    println("History:")
    feature.events.foreach { event =>
      println(s"  - Status: ${event.status.name}, Timestamp: ${event.timestamp.format(dateFormatter)}, Comment: ${event.comment}")
    }
  }
}


// Main application
object Main {
  def main(args: Array[String]): Unit = {
    // 1. Create a new feature
    var feature1 = FeatureLifecycleTracker.createFeature("FEATURE-001", "User Authentication", "Implement user login and registration.")

    // 2. Print initial feature details
    println("Initial Feature Details:")
    FeatureLifecycleTracker.printFeatureDetails(feature1)
    println("\n")

    // 3. Update the feature status to In Progress
    feature1 = FeatureLifecycleTracker.updateFeatureStatus(feature1, InProgress, "Starting development.")

    // 4. Update the feature status to In Review
    feature1 = FeatureLifecycleTracker.updateFeatureStatus(feature1, InReview, "Code is ready for review.")

    // 5. Update the feature status to Testing
    feature1 = FeatureLifecycleTracker.updateFeatureStatus(feature1, Testing, "Passed code review. Now in testing.")

    // 6. Update the feature status to Deployed
    feature1 = FeatureLifecycleTracker.updateFeatureStatus(feature1, Deployed, "Successfully deployed to production.")

    // 7. Print the updated feature details with history
    println("Updated Feature Details with History:")
    FeatureLifecycleTracker.printFeatureDetails(feature1)
    println("\n")

    // 8. Example of a rejected feature
    var feature2 = FeatureLifecycleTracker.createFeature("FEATURE-002", "Unnecessary Feature", "A feature we don't need yet.")
    feature2 = FeatureLifecycleTracker.updateFeatureStatus(feature2, Rejected, "Feature is not a priority at this time.")
    println("Rejected Feature:")
    FeatureLifecycleTracker.printFeatureDetails(feature2)


    // 9. Example of a feature put on hold
    var feature3 = FeatureLifecycleTracker.createFeature("FEATURE-003", "Payment Integration", "Integrate with payment gateway.")
    feature3 = FeatureLifecycleTracker.updateFeatureStatus(feature3, OnHold, "Waiting for API documentation from payment provider.")
    println("\nFeature on Hold:")
    FeatureLifecycleTracker.printFeatureDetails(feature3)
  }
}
```

Key improvements and explanations:

* **Case Classes and Immutable Data:** The `Feature` and `FeatureEvent` are now defined as case classes.  Case classes in Scala are immutable by default, and this promotes safer code and easier reasoning about state changes. Immutability is important because we want to track the *history* of changes to the feature.  Each "update" creates a *new* `Feature` instance rather than modifying the existing one.

* **`FeatureStatus` as a Sealed Trait:**  The `FeatureStatus` is now defined as a sealed trait. This is a critical improvement.  A sealed trait allows you to define a fixed set of possible subtypes (in this case, `New`, `InProgress`, `InReview`, etc.).  This provides compile-time checking, making it much easier to handle all possible status values and preventing unexpected statuses from being introduced.  The `name` attribute is also included directly in each `FeatureStatus` case object, eliminating the need for separate `match` statements.  The `name` is available as a getter, making the code cleaner.

* **`FeatureEvent` for History:** The `FeatureEvent` class now includes a `timestamp` (LocalDate) and a `comment`. This makes the history much more useful, providing context for each status change.

* **`FeatureLifecycleTracker` Object:**  This encapsulates the functions that operate on `Feature` objects.  This follows good object-oriented principles and keeps the code organized.

* **`updateFeatureStatus` function:**  This function is *crucial*.  It takes a `Feature`, a new `FeatureStatus`, and a comment.  It then creates a *new* `Feature` object with the updated status and a *new* `FeatureEvent` appended to the `events` list. This is a functional approach - the original feature isn't mutated.  The `:+` operator appends to the end of a list (returning a *new* list).  Using `events :+ event` ensures we build up a correct chronological history.

* **`getFeatureHistory` function:**  Provides a way to retrieve the complete history of status changes for a feature.

* **`printFeatureDetails` function:**  This function provides a clear, formatted output of a feature's current state and its event history.  It uses the `DateTimeFormatter` for clean date output.

* **`Main` object with example usage:** The `Main` object demonstrates how to use the `FeatureLifecycleTracker` to create, update, and print feature details. It provides a clear example of how to manage the lifecycle of a feature.

* **Clearer Date Handling:** The `java.time.LocalDate` class is used for dates, which is the modern and recommended way to handle dates in Java/Scala. `DateTimeFormatter` provides a clean way to format the dates for display.

* **Error Handling (Implicit):** Using case objects for `FeatureStatus` along with a sealed trait, allows exhaustive pattern matching that the compiler can check for completeness.

* **Immutability:** The code is now much more robust due to the extensive use of immutable data structures. This eliminates a whole class of potential bugs related to unintended side effects.

* **Clarity and Readability:** The code is formatted consistently and uses descriptive variable names, making it easier to understand.  Comments explain key sections.

* **Completeness:** The code now includes examples of rejected and on-hold features, making it a more complete illustration of a feature lifecycle tracker.

* **Conciseness:** Scala's features (e.g., case classes, pattern matching) are used effectively to keep the code concise and expressive.

How to Run:

1. **Save:** Save the code as `FeatureLifecycleTracker.scala`.
2. **Compile:** Open a terminal or command prompt and navigate to the directory where you saved the file. Compile the code using the Scala compiler:  `scalac FeatureLifecycleTracker.scala`
3. **Run:**  Execute the compiled code using the Scala interpreter: `scala Main`

The output will show the creation, updates, and history of the example features.  This complete, runnable example addresses the prompt's requirements effectively.
👁️ Viewed: 6

Comments