From cada4238ed3bd6c28b9d948c1cc7b4d010f553e1 Mon Sep 17 00:00:00 2001 From: Yucongkoo Date: Thu, 9 Nov 2023 16:40:49 +0800 Subject: [PATCH 1/5] Update planned enhancements Updated planned enhancements --- docs/DeveloperGuide.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 82cdc610562..59b472a1b0f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -945,7 +945,7 @@ Priorities: High - `* * *`, Medium - `* *`, Low - `*` This section covers the enhancements we plan to implement in the future. -#### Enhancement 1 : Deletion of all tags(and insurances) in a single command +#### Enhancement 1 : Deletion of all tags in a single command **Feature flaw:**
As a customer might have many tags, and they could potentially want to remove all the @@ -978,12 +978,6 @@ Expected: Error, an error message showing the usage of tag command is shown to t Expected: Error, an error message informing the user that they should input `deleteall` to confirm the deletion of all tags is shown to the user. -**Additional notes:**
-As the behaviour of the `insurance` command is nearly identical to `tag` command, this planned enhancement applies to -the `insurance` command too, the proposed enhancements and behaviours will be identical. The following is the updated -command format for `insurance` command:
-`insurance [ai/]... [di/]... [dai/deleteall]` - --------------------------------------------------------------------------------------------------------------------
From 01c2c7c5293ca782a644a1e64d03785469dfc31c Mon Sep 17 00:00:00 2001 From: Yucongkoo Date: Sat, 11 Nov 2023 12:05:26 +0800 Subject: [PATCH 2/5] Merge conflicts Merged conflicts --- docs/DeveloperGuide.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 47c6fe5d259..c05c9f082fe 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -985,14 +985,7 @@ Priorities: High - `* * *`, Medium - `* *`, Low - `*` This section covers the enhancements we plan to implement in the future. -<<<<<<< HEAD #### Enhancement 1 : Deletion of all tags in a single command -======= -###### **Aspect: Searching for Multiple Insurances or Tags:** - - -#### Enhancement 1 : Deletion of all tags(and insurances) in a single command ->>>>>>> master **Feature flaw:**
As a customer might have many tags, and they could potentially want to remove all the From 9d5f4714faf6a42e61657198fe5966434154ecaf Mon Sep 17 00:00:00 2001 From: Yucongkoo Date: Sat, 11 Nov 2023 14:54:55 +0800 Subject: [PATCH 3/5] Modify tag feature implementation description in DG Modified tag feature implementation description in DG --- docs/DeveloperGuide.md | 88 ++++++++----------- docs/diagrams/DeleteSequenceDiagram.puml | 6 +- .../tag-feature/ExecuteActivityDiagram.puml | 24 +++-- .../tag-feature/ExecuteSequenceDiagram.puml | 2 +- .../tag-feature/ParseSequenceDiagram.puml | 16 +++- .../tag-feature/PersonClassDiagram.puml | 1 + .../tag-feature/TagCommandClassDiagram.puml | 4 +- .../tag-feature/TagSequenceDiagram.puml | 2 +- .../logic/parser/TagCommandParser.java | 60 ++++++------- 9 files changed, 107 insertions(+), 96 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c05c9f082fe..597cec2c62e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -117,7 +117,7 @@ The sequence diagram below illustrates the interactions within the `Logic` compo -**Note:**
The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. +**Note:**
The lifeline for `DeleteCommandParser` and `DeleteCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
How the `Logic` component works: @@ -181,11 +181,14 @@ This section describes some noteworthy details on how certain features are imple This feature allows users to assign tags to / remove tags from customers in EzContact, increasing the recognizability of customers to users. -The activity diagram below shows the action sequence of updating the tags of a customer. +###### **Overview** + +The activity diagram below shows the action sequence of updating the tags of a customer. Note that definition of not +valid indexes/tags/tag set will be defined later in following sections. -### Implementation +
###### **Implementing `Tag`** @@ -195,13 +198,14 @@ Hence, a `Person` will now also be associated to any number of `Tag`s. -###### **Integrating a command for handling tag features into the execution logic** +###### **Integrating a command for handling tag features into the overall execution logic** In order to integrate the command for handling tag features into the execution logic as described in [LogicComponent](#logic-component), -we first update the `AddressBookParser` to recognise the `tag` _command word_ and will create a `TagCommandParser` subsequently. -The `TagCommandParser` will then parse the _command arguments_ to create a `TagCommand` that can be executed. - -
+there are 3 main steps we need to implement: +1. Modify `AddressBookParser` to recognise the **tag** _command word_ and will create a `TagCommandParser` subsequently. +(Modification required is trivial and hence not described in detail) +2. Implement a `TagCommandParser` class that will parse the _command arguments_ and construct a `TagCommand` accordingly. +3. Implement a `TagCommand` class that will handle the main execution logic of the tag features and return a `CommandResult` accordingly. The sequence diagram below illustrates the interactions within the `Logic` component when executing a tag command, taking `execute("tag 1 at/tall dt/short at/handsome")` API call to `LogicManager` as an example. @@ -209,49 +213,36 @@ taking `execute("tag 1 at/tall dt/short at/handsome")` API call to `LogicManager -**Note:**
The lifeline for `TagCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. +**Note:**
The lifeline for `TagCommandParser` and `TagCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
###### **Implementing `TagCommandParser`** `TagCommandParser` plays the role of parsing _command arguments_ into two information:
-* `index` indicating the index of the targeted customer in the displayed customer list, and
-* `descriptor` encapsulating tags to add to/delete from the targeted customer.
+* **index** indicating the index of the targeted customer in the displayed customer list, and
+* **descriptor** encapsulating tags to add to and/or delete from the targeted customer.
-Both `index` and `updatePersonTagsDescriptor` will be used to create the `TagCommand` to be executed.
-The parsing steps are as follows: -1. Parse the command arguments into `index`, `tagsToAdd` and `tagsToDelete`(throws ParseException if there are format errors). -1. Create the `UpdatePersonTagsDescriptor` using `tagsToAdd` and `tagsToDelete`. -1. Verify that there is at least one tag to add/delete(throws ParseException if no tag to update is provided). -1. Construct and return the `TagCommand`. +Both **index** and **descriptor** will then be used to construct a `TagCommand`.
Note that **duplicate tags will be ignored** (see [Design Considerations](#design-considerations) for more information). The sequence diagram below illustrates the interactions of `TagCommandParser#parse(String arguments)`, -taking `parse(1 at/tall dt/short at/handsome)` call to the `TagCommandParser` as an example. Note that the -**reference frames have been omitted** as the operations performed are trivial. +taking `parse(1 at/tall dt/short at/handsome)` call to the `TagCommandParser` as an example. ###### **Implementing `TagCommand`** -The following class diagram illustrates how a `TagCommand` hold information required for its execution. +The following class diagram illustrates how a `TagCommand` holds information required for its execution. -`TagCommand` plays the role of executing the tag command on a `Model`, it will update the `Model` accordingly to -reflect the changes after the tag command completes its execution. Note that if there are conflicting tags(i.e. there -is a common tag to add and delete), the command execution will fail.
-The execution steps are as follows:
-1. Verify that the `TagCommand` is executable(i.e. there is no conflicting tag in the `updatePersonDescriptor`). -1. Retrieve `personToUpdate` from the model using `index`. -1. Retrieve `tagsToAdd` and `tagsToDelete` from `updatePersonTagsDescriptor`. -1. Create the `updatedPerson` from the above information. -1. Verify that the `updatedPerson` has a different tag set from `personToUpdate` (i.e. the command execution will change the person). -1. Verify that the `updatedPerson` has a valid number of tags (i.e. not exceeding the maximum allowed tag count). -1. Set the `personToUpdate` to `updatedPerson` in the `Model`. -1. Returns the `CommandResult` of the execution. +`TagCommand` plays the role of executing the main logic of the tag feature, it will: +* Use information encapsulated in it to create the updated `Person` object accordingly. +* Update the `Model` accordingly to reflect the changes. + +Note that a `TagCommand` is **non-executable** if there are **conflicting tags** (i.e. there are common tags to add and delete). The sequence diagram below illustrates the interations of `TagCommand#execute(Model model)`, taking `execute(m)` call to the `TagCommand` as an example. Note that the **reference frames have been omitted** @@ -261,15 +252,12 @@ as the operations performed are trivial. ###### **Wrapping up the tag feature** -As reaching this point, we have completed the implementation of the tag feature, where users are allowed to add and delete -tags of a person in the same command. The following section will discuss certain design considerations when implementing -this feature. +As reaching this point, we have completed the implementation of the tag feature. +The following section will discuss certain design considerations when implementing this feature.

-
- ### Design considerations: ###### **Aspect: Data structure to store tags in a Person object:** @@ -299,8 +287,6 @@ Alternative 1 was chosen over alternative 2 based on the following reasons: * Repeated action signals the users' strong intention of performing that action(e.g. wanting to add the same tag twice shows the importance of that tag). * The target audience is forgetful and careless, it is common for the users to enter duplicate tags without realising it, blocking such actions brings no value to the product. -
- ###### **Aspect: Deletion of non-existing tags:** * **Alternative 1(current choice):** Simply ignore such deletions. * Pros: Users will not be blocked from their action(other tags will still be added/deleted) even though the command consists of such deletions. @@ -772,9 +758,8 @@ Priorities: High - `* * *`, Medium - `* *`, Low - `*` **Use Case: UC01 - add a customer** **MSS:**
- 1. User enters the details of a customer to be added.
- 2. System adds the customer.
- 3. System displays the details of customer added by user.
+ 1. User provides the details of a customer to be added.
+ 2. System displays the details of the customer added by user.
 Use case ends. **Extensions:**
@@ -922,19 +907,24 @@ Priorities: High - `* * *`, Medium - `* *`, Low - `*` **Use Case: UC09 - update tags of a customer** **Mss:**
- 1. User requests to list out the customers.
+ 1. User requests to see a list of customers.
 2. System displays the requested list of customers to the user.
- 3. User enters index of targeted customer and information of tags to add or delete.
- 4. System updates the tags of the specified customer accordingly.
- 5. System displays the details of the updated customer.
+ 3. User provides index of the targeted customer to update tags.
+ 3. User provides information of tags to add to and/or delete from the targeted customer.
+ 4. System displays the details of the updated customer.
 Use case ends.
**Extensions:**
- 3a. User provided invalid index or information.
+ 1a. Requested list is empty.
+  Use case ends.
+ 3a. User provided invalid index.
  3a1. System displays an error message to alert the User.
  Use case ends.
- 3b. User provided information that will not update the specified customer.
-  3b1. Systems displays an error message to alert the User.
+ 4a. User provided invalid information of tags.
+  4a1. Systems displays an error message to alert the User.
+  Use case ends.
+ 4b. User provided information of tags that will not update the targeted customer.
+  4b1. Systems displays an error message to alert the User.
  Use case ends.
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml index 40ea6c9dc4c..21c6d5d52d6 100644 --- a/docs/diagrams/DeleteSequenceDiagram.puml +++ b/docs/diagrams/DeleteSequenceDiagram.puml @@ -65,6 +65,10 @@ deactivate CommandResult DeleteCommand --> LogicManager : result deactivate DeleteCommand -[<--LogicManager +'Hidden arrow to position the destroy marker below the end of the activation bar. +DeleteCommand -[hidden]-> LogicManager +destroy DeleteCommand + +[<--LogicManager : result deactivate LogicManager @enduml diff --git a/docs/diagrams/tag-feature/ExecuteActivityDiagram.puml b/docs/diagrams/tag-feature/ExecuteActivityDiagram.puml index efcaca2d4c4..85e7f3ad008 100644 --- a/docs/diagrams/tag-feature/ExecuteActivityDiagram.puml +++ b/docs/diagrams/tag-feature/ExecuteActivityDiagram.puml @@ -3,19 +3,27 @@ skin rose skinparam ActivityFontSize 15 skinparam ArrowFontSize 12 start -:User provides tags to add and delete; +:User provides index of the targeted +customer in the displayed list; -'Since the beta syntax does not support placing the condition outside the -'diamond we place it as the true branch instead. if () then - :Update tags of targeted customer; + :User provides tags to add to and/or \ndelete from the targeted customer; + + 'Since the beta syntax does not support placing the condition outside the + 'diamond we place it as the true branch instead. if () then - :Save updated customer to Model; - else ([updated customer's tag set unchanged or invalid]) + :System update tags of targeted customer; + if () then + :System saves updated customer to Model; + else ([updated customer's tag set is not valid]) + stop + endif + stop + else ([tags provided is not valid]) stop endif - stop -else ([has conflicting tags to add and delete]) +else ([index provided is not valid]) stop endif + @enduml diff --git a/docs/diagrams/tag-feature/ExecuteSequenceDiagram.puml b/docs/diagrams/tag-feature/ExecuteSequenceDiagram.puml index 27d854f54cd..aec5878ae29 100644 --- a/docs/diagrams/tag-feature/ExecuteSequenceDiagram.puml +++ b/docs/diagrams/tag-feature/ExecuteSequenceDiagram.puml @@ -16,7 +16,7 @@ end box TagCommand -> TagCommand: verifyCommandExecutable(m) ||| -ref over TagCommand, Model: retrieve information required +ref over TagCommand, Model: retrieve information required\n(i.e. personToUpdate, tagsToAdd, and tagsToDelete) ||| TagCommand -> PersonClass: createPersonWithUpdatedTags(personToUpdate, tagsToAdd, tagsToDelete) diff --git a/docs/diagrams/tag-feature/ParseSequenceDiagram.puml b/docs/diagrams/tag-feature/ParseSequenceDiagram.puml index afa16f2a540..e00d7c57913 100644 --- a/docs/diagrams/tag-feature/ParseSequenceDiagram.puml +++ b/docs/diagrams/tag-feature/ParseSequenceDiagram.puml @@ -7,17 +7,25 @@ participant ":UpdatePersonTagsDescriptor" as UpdatePersonTagsDescriptor LOGIC_CO participant ":TagCommand" as TagCommand LOGIC_COLOR [-> TagCommandParser : parse("1 at/tall \ndt/short at/handsome") -ref over TagCommandParser: parse command arguments + +||| + +TagCommandParser -> TagCommandParser: parseArguments("1 at/tall dt/short at/handsome") + ||| + create UpdatePersonTagsDescriptor -TagCommandParser -> UpdatePersonTagsDescriptor +TagCommandParser -> UpdatePersonTagsDescriptor: UpdatePersonTagsDescriptor(tagsToAdd, tagsToDelete) activate UpdatePersonTagsDescriptor return descriptor + ||| -ref over TagCommandParser: verify has tag to update + +TagCommandParser -> TagCommandParser: verifyHasTagToUpdate(descriptor) + ||| create TagCommand - TagCommandParser -> TagCommand: TagCommand(1, descriptor) + TagCommandParser -> TagCommand: TagCommand(index, descriptor) activate TagCommand return command [<--TagCommandParser : command diff --git a/docs/diagrams/tag-feature/PersonClassDiagram.puml b/docs/diagrams/tag-feature/PersonClassDiagram.puml index b5c0414b584..903e7b26f83 100644 --- a/docs/diagrams/tag-feature/PersonClassDiagram.puml +++ b/docs/diagrams/tag-feature/PersonClassDiagram.puml @@ -11,6 +11,7 @@ note right of Person which are ommited here as they are irrelevant when discussing the tag feature. end note + Class Tag Person --> "*" Tag diff --git a/docs/diagrams/tag-feature/TagCommandClassDiagram.puml b/docs/diagrams/tag-feature/TagCommandClassDiagram.puml index 21ebf223c9e..62c4c253185 100644 --- a/docs/diagrams/tag-feature/TagCommandClassDiagram.puml +++ b/docs/diagrams/tag-feature/TagCommandClassDiagram.puml @@ -11,7 +11,7 @@ Class Tag TagCommand --> "1" Index TagCommand --> "1" UpdatePersonTagsDescriptor -UpdatePersonTagsDescriptor --> "~* tags to add" Tag -UpdatePersonTagsDescriptor --> "~* tags to delete" Tag +UpdatePersonTagsDescriptor --> "~* tagsToAdd" Tag +UpdatePersonTagsDescriptor --> "~* tagsToDelete" Tag @enduml diff --git a/docs/diagrams/tag-feature/TagSequenceDiagram.puml b/docs/diagrams/tag-feature/TagSequenceDiagram.puml index 34bcf54fb0c..8354bd8ac43 100644 --- a/docs/diagrams/tag-feature/TagSequenceDiagram.puml +++ b/docs/diagrams/tag-feature/TagSequenceDiagram.puml @@ -57,6 +57,6 @@ deactivate TagCommand TagCommand -[hidden]-> LogicManager destroy TagCommand -[<--LogicManager +[<--LogicManager : result deactivate LogicManager @enduml diff --git a/src/main/java/seedu/address/logic/parser/TagCommandParser.java b/src/main/java/seedu/address/logic/parser/TagCommandParser.java index 5c1576b4c49..5b7c6d6bf02 100644 --- a/src/main/java/seedu/address/logic/parser/TagCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/TagCommandParser.java @@ -1,6 +1,7 @@ package seedu.address.logic.parser; import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_TAG; import static seedu.address.logic.parser.CliSyntax.PREFIX_DELETE_TAG; @@ -27,6 +28,10 @@ public class TagCommandParser implements Parser { private static final Prefix[] validPrefixes = new Prefix[] { PREFIX_ADD_TAG, PREFIX_DELETE_TAG }; + private Index index; + private Set tagsToAdd; + private Set tagsToDelete; + /** * Parses the given {@code String} of arguments in the context of the TagCommand * and returns a TagCommand object for execution. @@ -36,14 +41,28 @@ public TagCommand parse(String args) throws ParseException { requireNonNull(args); logger.fine("TagCommandParser parsing: " + args); - ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, validPrefixes); + parseArguments(args); + requireAllNonNull(index, tagsToAdd, tagsToDelete); // defensive, to ensure that parsing succeeded + + UpdatePersonTagsDescriptor descriptor = new UpdatePersonTagsDescriptor(tagsToAdd, tagsToDelete); + verifyHasTagsToUpdate(descriptor); // defensive, verifies that at least one tag is provided - Index index = extractIndex(argMultimap); - UpdatePersonTagsDescriptor updatePersonTagsDescriptor = extractUpdatePersonTagsDescriptor(argMultimap); + return new TagCommand(index, descriptor); + } - verifyHasTagsToUpdate(updatePersonTagsDescriptor); + /** + * Parses a {@code String index} into a {@code Index}. + * @throws ParseException if {@code index} could not be successfully parsed. + */ + private Index parseIndex(String index) throws ParseException { + requireNonNull(index); - return new TagCommand(index, updatePersonTagsDescriptor); + try { + return ParserUtil.parseIndex(index); + } catch (ParseException pe) { + logger.finer("TagCommandParser parse failed due to invalid index: " + index); + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE), pe); + } } /** @@ -60,33 +79,14 @@ private Optional> parseTags(Collection tags) throws ParseExcept return Optional.of(ParserUtil.parseTags(tags)); } - /** - * Extracts and returns the index from the {@code argMultimap}. - * @throws ParseException if the index is not an unsigned positive integer. - */ - private Index extractIndex(ArgumentMultimap argMultimap) throws ParseException { - requireNonNull(argMultimap); - - try { - return ParserUtil.parseIndex(argMultimap.getPreamble()); - } catch (ParseException pe) { - logger.finer("TagCommandParser parse failed due to invalid index: " + argMultimap); - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, TagCommand.MESSAGE_USAGE), pe); - } - } + private void parseArguments(String args) throws ParseException { + requireNonNull(args); - /** - * Extracts the tags to add and delete from the {@code argMultimap}, - * and returns a {@code UpdatePersonTagsDescriptor}. - * @throws ParseException if there are tags that are invalid. - */ - private UpdatePersonTagsDescriptor extractUpdatePersonTagsDescriptor(ArgumentMultimap argMultimap) - throws ParseException { - requireNonNull(argMultimap); - Set tagsToAdd = parseTags(argMultimap.getAllValues(PREFIX_ADD_TAG)).orElse(new HashSet<>()); - Set tagsToDelete = parseTags(argMultimap.getAllValues(PREFIX_DELETE_TAG)).orElse(new HashSet<>()); - return new UpdatePersonTagsDescriptor(tagsToAdd, tagsToDelete); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, validPrefixes); + index = parseIndex(argMultimap.getPreamble()); + tagsToAdd = parseTags(argMultimap.getAllValues(PREFIX_ADD_TAG)).orElse(new HashSet<>()); + tagsToDelete = parseTags(argMultimap.getAllValues(PREFIX_DELETE_TAG)).orElse(new HashSet<>()); } /** From e38841adef34b4bd4c6fcbc405d7f33367570336 Mon Sep 17 00:00:00 2001 From: Yucongkoo Date: Sat, 11 Nov 2023 15:11:09 +0800 Subject: [PATCH 4/5] Update use case Updated use case --- docs/DeveloperGuide.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 597cec2c62e..63af6276964 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -907,24 +907,23 @@ Priorities: High - `* * *`, Medium - `* *`, Low - `*` **Use Case: UC09 - update tags of a customer** **Mss:**
- 1. User requests to see a list of customers.
- 2. System displays the requested list of customers to the user.
- 3. User provides index of the targeted customer to update tags.
+ 1. User requests a list of customers by filtering customers(UC02).
+ 2. User provides index of the targeted customer in the displayed list.
 3. User provides information of tags to add to and/or delete from the targeted customer.
- 4. System displays the details of the updated customer.
+ 4. System displays the details of the updated customer to the User.
 Use case ends.
**Extensions:**
 1a. Requested list is empty.
  Use case ends.
- 3a. User provided invalid index.
-  3a1. System displays an error message to alert the User.
+ 2a. User provided invalid index.
+  2a1. System displays an error message to alert the User.
  Use case ends.
- 4a. User provided invalid information of tags.
-  4a1. Systems displays an error message to alert the User.
+ 3a. User provided invalid information of tags.
+  3a1. Systems displays an error message to alert the User.
  Use case ends.
- 4b. User provided information of tags that will not update the targeted customer.
-  4b1. Systems displays an error message to alert the User.
+ 3b. User provided information of tags that will not update the targeted customer.
+  3b1. Systems displays an error message to alert the User.
  Use case ends.
From 07afb65a43238fae6862e0d93331a9a7a0dfebbc Mon Sep 17 00:00:00 2001 From: Yucongkoo Date: Sat, 11 Nov 2023 15:44:30 +0800 Subject: [PATCH 5/5] Update NFR Updated NFR --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 63af6276964..77429b4373b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -958,7 +958,7 @@ Priorities: High - `* * *`, Medium - `* *`, Low - `*` 5. The application should gracefully handle errors to prevent system crashes and data corruption. 6. The application should be offered as a free service to the public. 7. The application should be able to respond within one second. -8. The application should be able to handle and support manual edits to the data file. +8. The application should be able to handle and support manual edits to the data file, erroneous data files should not crash the application. ## Glossary