Introduction

The following text is a set of recommendations for the implementation of UML structures required for mini-project 1 (MP1).

In accordance with the requirements described in point 3 of the requirements document, each structure should have a separate business example (do not combine the structures listed in the mini-project requirements).

  1. Class extent

    It is a set of all correctly created objects of a given class.

    • Each newly created object (as long as there were no errors during initialization) should be automatically placed in the appropriate collection - for this purpose, you should take care of the appropriate implementation of the object’s constructor (or constructors).
    • This collection should be common to all instances of this class (static).
    • It is important to remember about the principle of encapsulation and to prevent modification of the extent outside the class. In particular, this applies to:
      • Securing the collection field with an appropriate access modifier
      • There are no public methods to modify this collection. The exception may be the method removing the object from the extent, however, it is not required for this project.
      • The method that gets the extent (getter) should return a copy of the collection, or a reference that prevents its modification (e.g. created using the java.util.Collections.unmodifiableList(…) function)
  2. Class extent - persistence

    The extent must be able to be written to and read from the permanent storage after restarting the application. For the purposes of this mini-project, the persistence obtained by object serialization and writing (reading) to (from) the file is sufficient.

    • Model classes should implement the appropriate interface (java.io.Serializable)
    • All class attributes should be of a type that implements java.io.Serializable
    • Create static methods to write to and read the extent from the file
    • These methods should handle exceptions properly. It is recommended to use the try-with-resources construct
    • If there are many class extents in the program, you should create one pair of methods that reads and writes on all class extents and uses one file.
  3. Complex attribute.

    It contains two or more fields as a whole, inextricably linked with the object that owns it (not to be confused with an association).

    • Custom class containing the members of a complex attribute
    • Be sure to serialize this class
    • You should remember about the principle of class encapsulation, both in the class representing the complex attribute and in the owner of this attribute. In particular, this applies to:
      • privacy of the fields
      • the correct get and set methods
      • a constructor that initializes the required components of the object
  4. Optional attribute

    Its value may be unknown at the time the object was created.

    • An appropriate type must be used that allows null assignment. Simple types (such as int or double) do not satisfy this requirement.
    • The setter method accepts a null value as a parameter. Still, however, a not-null value may have certain constraints (e.g., a non-empty string, a number within a certain range, etc.). In such a case, an appropriate check should be made when setting a new value and, if necessary, an exception signaling a validation error should be thrown.
    • As for other attributes, the principle of encapsulation is used.
    • It’s a good idea to create an additional constructor to initialize both required and optional attributes at once.
  5. Mandatory attribute

    Any non-optional attribute is mandatory. It must be of value throughout the life of the object. Usually, an empty string is not allowed either.

    • A simple type (e.g. int, double) can be used to prevent null values from being set for numeric types.
    • For object types, it is necessary to make an appropriate validation of the value in the setter method and, if necessary, throw an exception in the case of setting an incorrect value
    • Create a constructor that sets all the mandatory attributes. If the conditions for validating the attributes are not met, the object cannot be placed in the class extent.
    • As for other attributes, the principle of encapsulation is used
  6. Multi-value attribute

    May contain more than one value.

    • Implemented with a collection (more often) or an array (in special cases).
    • The mandatory multi-value attribute should always have at least one value.
    • Create methods to add and remove the value of the attribute (addXXX (…) removeXXX (…))
    • When adding, you need to check if the value passed is correct (e.g. if it is not null, empty string, number out of range, etc.)
    • If the attribute is required during deletion, make sure that the last value is not deleted.
    • A collection replacement method (setXXX (…)) is not required. If it is implemented, it should be ensured that all elements of the given collection meet the validation conditions.
    • The method that gets the attribute must be secured against unauthorized modification of the collection, similar to a class extent collection.
  7. Class attribute

    Contains values common to all objects of a given class. Its value can be modified as long as there are no additional constraints.

    • Implementation using a static field and a pair of get and set methods
  8. Derived attribute

    Its value is calculated on the basis of other data (other attributes, associations, etc.)

    • Implementation typically with a getXXX method that computes and returns the value of the attribute.
    • In special cases (rare write operations on the base data, frequent readings of the derived attribute) it is possible to ‘cache’ the calculated value in the class field. You should then make sure that it will be updated every time the data on which the attribute is based is changed (usually it is difficult or even impossible to implement).
    • When calculating the value, pay attention to potential errors (e.g. when the base attribute is optional)
  9. Class method

    It is a method that is common to all objects of a given class (static) and operates on the class extent.

  10. Method overriding

    This is an override of the implementation of the superclass method. If you do not have our own class inheritance hierarchy, you can override the method from the base class java.lang.Object (e.g. toString or equals with hashCode).

    • The overridden method has a signature that is compatible with the overridden method.
    • The static method cannot be overridden.
  11. Method / constructor overloading