Java

An issue I ran into when using IntelliJ IDEA is not being able to view Java source code, declarations, and Javadocs. This can be resolved by going to your src folder (i.e., where your source code is located). Right click, navigate and toggle: Mark Directory As > Sources Root (link).

Meaning of public class?

A public class has “public” visibility which means that it is accessible to any class in any package. If a class does not have the public access modifier, then it has “default” package visibility which means that it is accessible only to classes inside the same package.

What is transient keyword?

The transient keyword in Java is used to indicate that a field should not be part of the serialization. A transient variable is not part of the persistent state of an object. For example, if you have fields that are derived from other fields (programatically) then we can mark them as transient to prevent their state from being persisted during serialization. This helps save memory and increases speed of serialization / deserialization process. Say we have a GalleryImage class that implements Serializable. Among other instance variables / methods, assume this class contains two instance variables: image and thumbnailImage. The thumbnailImage is derived from the gallery image. Upon deserialization, the readObject method is called to perform any operations necessary to restore the state of the object. In this example, the thumbnailImage needs to be regenerated. Thus, we override the readObject method do that the thumbnail will be generated by calling a generateThumbnail method (link).

Software Design

What is Software Design?

  • Software design helps us provide structure to an application
  • Process of decomposing a system into smaller, modular parts
  • Ideally, we want to design for change… in software it’s best to always anticipate change in requirements
  • Because of constant change, we want to address maintainability during design
    • ideally, we want ease of modification / adaptation
    • reduction of maintainance

Change in Software

Change is distinguishing feature that makes software different from any other human produced artifact:

  • Since the 1970’s, change in software is constant, urgent, and unavoidable. Mastering change is inevitable.
  • Software technology has made progress but change is treated as an afterthought.
  • Change has to become a first class concept
    • development tools, runtime environment, and design process should naturally accomodate change

Two types of change: (1) Evolution and (2) Adaptation

Evolution: enhancing the software with new functions and features

Adaptation: retrofitting or improving the relevance of a software system in a new environment (e.g., building mobile versions of desktop apps, porting Windows based app to MacOS).

Change of Social Environment

  • change is necessary due to external influence
  • factors beyond the control of software organizations, clients, and users
  • changes are often hard to anticipate and difficult to implement
  • often, programmers have to respond to these changes under severe time pressure

Examples of types of changes:

  • Replacing an existing algorithm by a more efficient one
  • Change the data representation
  • Porting code for new architecture
    • different OS / arch may have different system calls, different DBMS calls
    • Java strives to solve this problem via the JVM (“write once, run anywhere”)
  • change in peripheral devices
  • change of “sovial environment”
    • new tax laws (for a tax software.. e.g., TurboTax)
    • move of EU to common currency
    • change in safety requirements (e.g., Boeing)

Modules

Module: a well defined component of a software system which may provide services to other modules

Properties of USES relationship

fan-in: number of incoming edges indicates the number of modules that use (or “depend”) on this module.

fan-out: number of outgoing edges indicates the number of modules this module depend on

Low fan-out / high fan-in is desirable because:

  • this implies loose coupling (modules are not highly dependent on each other). Loose coupling increases maintainability, scalability, and reduces bugs
  • implies that modules are a good abstraction

“Is Component of Of”

Mi IS_COMPONENT_OF Mj: Mj consists of several modules of which one is Mi Image of Is Component Of

“Comprises” Mj comprises Mi: means that Mi is a component encapsulated within Mj Image of Comprises

“IMPORTED” module: other modules or services that a module needs to import in order to work

“EXPORTED” module: parts of the module others can use

Advantages of modular design

  • reduces complexity by breaking problem down into sub-problems
  • facilitates change, maintainability, and bug reduction by reducing surface area a module covers within an application.. less surface area = low coupling -> easier to make changes
  • increases development speed by encouraging parallel development
  • allows for code reuse

Properties of modular design

Principles:

  • each module should address a specific subfunction of the requirements
  • each module should have a simple and clean interface

Module independence measured using two criteria:

  1. Cohesion: degree to which a module focuses on a group of related functions
  2. Coupling: degree to which a module is connected to / depends on other modules

Good design = high cohesion and low coupling.

Product family: set of software intensive systems that share a common set of features.

  • Design and implement core features just once
  • Differences or variations are pushed down the stack (think of abstraction of functionality, parent child relationships, inheritance, and polymorphism)

OO Design

How to find / determine what should be a class?

Heuristic: classes correspond to nouns in the natural language decomposition of the problem.

Some nouns do not correspond to classes:

  • items outside the problem boundary
  • some nouns are just attributes (e.g., student id, birthday, student email)
  • synonyms or words used to refer to a single concept

Tangible: physical objects or object groups that are tangible (e.g., Medication, Receipt, Prescription, Medical Record)

Roles: people who perform certain actions or have responsabilities or duties (e.g., Doctor, Nurse, Administrative assistant)

Events: things that can happen

Interactions between roles: e.g., exams, immunizations, diagnosis

Other systems: external events or systems with which the system interacts (e.g., credit card system, insurance system..)

Comparison between interface and the “tip of the iceberg”

  • possible for a ship to avoid an iceberg simply by viewing the top
  • possible for a client to use a module by knowing its interface

Symbol Table

get: returns value

put: store / update value

get method should only return the value of the variable. It should not return the variable location (i.e., memory address). If memory address is returned, then user can access location directly and modify the value of the variable rather than doing it through the put method.

Documentation should be structured top down:

  • level of detail increases as one proceeds down
  • big picture first, provide additional details as you drill down into specifics

Interface hides implementation details like:

  • algorithm
  • data structure
  • external services integration
  • policy

How does inheritance promote re-use?

  • promotes re-use because child class inherits data & behaviour from the parent class
  • code does not need to be re-written for the child
  • child can refer to and use data + methods from parent

Conflict in inheritance (Extension or Restriction) ??? Extension:

  • behaviour / data in a child class are an extension an extension of parent class
  • child class has all properties of parent class and adds some more

Restriction View:

  • child class is a more specialized (restricted) case of a parent
  • contraction

Functional or procedural programming

  • program divided into smaller parts functions
  • start with a problem and break it down into smaller problems
  • break down sub-problems continually in a process called functional decomposition
  • continue until each sub-procedure is simple enough to be implemented in code

OOP

  • program divided into small parts called objects (bottom up design approach)
  • start with basic level of classes and build upon those classes

Composition

Describes “has a” relationship

Inheritance

Describes “is a” relationship

has-a is-a
car has-a engine dog is-a animal
game has-a player car is-a vehicle
db has-a entry employee is-a person
university has-a student orange is-a fruit
playlist has-a song  

Advatages of composition over inheritance

  1. Java does not support multiple inheritance. For reading and writing you can compose your class with Reader and Writer. You cannot implement more than one interface.

  2. Easier testing. You can easily create a mock object and inject that as a dependency to test vs. having to implement and inherit super class.

  3. Inheritance provides “tight coupling.” If parent changes, child may break (e.g., removal of class in parent that is used in child).

  4. Flexibility. For example, Comparator can be passed to Collections.sort() for custom sorting behaviour. This is convenient if you want to provide sorting behaviour other than default (see).

UML

”+” indicates field or method is public

”-“ indivate field or method is private

Understanding the Utility of Classes

  • Inheritance and delegation facilitate re-use

We can breakdown the classes in a software application into these groups:

  1. Domain-independent (20%):
    • provide functionality regardless of domain
    • e.g., data structures, math functions, file IO, UI components
  2. Domain-specific (65%):
    • functions that function specific to a domain
    • e.g., inventory control (inventory of video tape rentals, auto parts)
    • likely to be used in current and future projects
  3. Application-specific (15%):
    • special purpose, classes that implement custom logic specific to application

“85% of code is reusable”: organizations should strive for domain-independent and domain-specific use

Composition (i.e., Containment)

  • class spawns and contains instances of other classes within it
  • “part-of” relationship
  • if containing class is freed by garbage collector, then so are all of its composing actors / entities

Inheritance

  • re-use of code from another class
  • child inherits data + methods from parent (if accessibility is public or protected)
  • “is-a” relationship

Inheritance vs Composition

  • with inheritance we focus on defining / implementing things based on what they are
    • is “B” a kind of “A”? if yes -> use inheritance
  • with composition we focus on defining / implementing things based on what they do
    • does B have an A? if yes -> use composition

With inheritance we often face the gorilla banana problem.. which is when we only ask for a banana but we get a gorilla holding a banana with the entire jungle in the background. In other words, we get more than we ask for and make the code more bulky / convoluted. See this: watch

Class Relationships

  1. Association
  2. Aggregation
  3. Composition

Association

  • objects of one class are associated with objects from another class
  • a relationship where all objects have their own lifecycle and there is no owner

Aggregation

  • more specific variant of aggregation
  • “has-a” relationship
  • superset class made up of components from subset classes
  • no existence dependency between superset and subset classes (i.e., superset can be removed w/o needing to remove subset class)

Composition

  • more specific variant of aggregation
  • “part of” relationship
  • object of a subset class cannot exist w/o being linked to an object of the superset class
  • if we destroy a superset object, then we must delete the subset object as well

Aggregation vs Composition

Simple rules:

  1. A “owns” B = Composition : B has no meaning or purpose in the system without A
  2. A “uses” B = Aggregation : B exists independently (conceptually) from A

Example:

A Text Editor owns a Buffer (composition). A Text Editor uses a File (aggregation). When the Text Editor is closed, the Buffer is destroyed but the File itself is not destroyed.

  • Composition is an Association

  • Aggregation is an Association

  • Composition is a strong Association (If the life of contained object totally depends on the container object, it is called strong association)

  • Aggregation is a weak Association (If the life of contained object doesn’t depends on the container object, it is called weak association)

Good read: https://softwareengineering.stackexchange.com/questions/61376/aggregation-vs-composition

Also, difference between Inheritance vs Aggregation in Maven documentation: https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#project-inheritance-vs-project-aggregation

Image of UML Notations

When to use inheritance

  • “is-a” test
  • code reuse

Polymorphism / Dispatching

  • Runtime or dynamic choice of the method to be invoked depending on the class of the invoking object
  • polymorphism is based on inheritance.. parent child relationship is required

Polymorphism benefits

  • offer versatility in hierarchy and code development
  • makes code more generic and increases reuse

Principles of Substitutability

  • If A is a subclass of B, instances of A can be substituted for instances of B in any situation without any observable effect

Subtype vs Subclass

  • A is a subclass of B merely asserts that A is formed using inheritance
    • refers to a general inheritance relationship that may or may not satisfy the substitutability principle
  • A is a subtype of B means A preserves the meaning of all operations in B
    • refers to an inheritance relationship that satisfies the substitutability principle
  • good reads here and the course directory here

Overiding

  • child class overides a method in the parent class (i.e., child class provides new implementation for method inherited from parent)
  • overridden method has same name and type signature as the parent class, but changed implementation

Specialization Inheritance

  • each child class preserves the behaviour of the parent
  • may add more functions / data
  • preserves substitutability

Specification Inheritance

  • all child classes implement the methods defined in the parent
  • more specific version of specialization inheritance
  • preserves substitutability

Construction Inheritance

  • parent class is used as a source of behaviour
  • child class has no “is-a” relationship to the parent
  • child class may modify arguments
  • may not preserve the behaviour of the parent
  • violates substitutability

Generalization

  • adds new features reutnrs existing ones
  • preserves

Limitation

  • child class overrides a method inherited from a parent in a way that makes it unusable or limits certain functions
  • e.g., list data type that allows items to be inserted at either end
  • e.g., limit by allowing insertion only at one end to create a stack
  • violates

Variance

  • Two or more classes that seem to be related but not clear which is child and which is parent
  • May or may not preserve substitutability principle

Correctness vs Reliability

  • Reliability encompasses correctness

When is a software system: correct yet unreliable or reliable yet incorrect

  • requirements may not be well understood or an accurate representation of what the user wants
  • requirments may not be known to user.. if this is the case, then software builds for these incorrect reqs will never behave as expected to the user -> not reliable from the user’s perspective
  • software system may perform critical functions w/o failure but may be able to tolerate some flaws in non-critical functions
  • system is incorrect yet reliable

Robustness vs. Application Domain

  • How a particular unforeseen circumstance can occur will depend on the application domain
  • if software is developed for users who are not conversant with tech, application must be prepared to accept ill-formatted or incorrect inputs
  • embedded systems never use input from users, but interface with sensors and may need to handle sensor and hardware failure
  • amt. of code dedicated to handling errors depends on domain and consequences of failures

Relationship between requirements, correctness, reliability, and robustness

  • if requirements are specified then ensuring is a matter of correctness / reliability
  • if requirements are not specified then it is a matter of robustness

Three levels of interoperability

  1. Minimum: multiple applications must coexist on the same machine
  2. Medium: one application must be able to embed or import data from another application (e.g., import powerpoint into google slides)
  3. Maximum: software sytem must interface and exchange data with other systems

How reusability affects reliability

  • as more components are reused they are more likely to become reliabled since residual errors are progressively eliminated
  • reliability of components improves leading to an improvement in sys. reliability
  • components may also behave in unexpected ways which would lead to lower component and system reliability

Real-time system

  • correct answer generated within a specified time delta
  • tradeoff precision for timeliness
  • performance is most important

Information system

  • e.g., payroll system
  • live much longer than originally planned
  • adapted to new environments, enhanced with new features
  • maintainability

UI and reliability

  • well designed UI can direct a user through the sequence of necesarry steps to complete a task
  • bad UI may cause a user to try alternate things and crash the app

SWE - Software Engineering Principles

What is a principle?

Abstract high level statements that must be followed.

Why are principles needed?

They become practice through methods and techniques.

Modularity is the cornerstone principle supporting software design

Seven important principles that may be used in all phases of software development

(Tools) -> (Methodologies) -> (Methods and Techniques) -> (Principles)

Key principles:

  • Rigor and formality
  • Separation of concerns
  • Modularity
  • Abstraction
  • Anticipation of change
  • Generality
  • Incrementality

SWE - Software Specification - Entity Relationship Diagrams (ERD)

Overview:

  1. Based on entities, relationships, and attributes
  2. Used for modeling a system’s data, it’s flow, and how it’s related

What is the difference between UML and ERD?

Key Difference: UML stands for Unified Modeling Language. ERD stands for Entity Relationship Diagram. UML is a popular and standardized modeling language that is primarily used for modeling object oriented software. Entity-Relationship diagrams are used in structured analysis and conceptual database modeling (source).

For data modeling (relational databases) we use ERD diagram, for storing data in object systems we can use ORM (object relational model – it is a mixed UML/Data model), for modeling object oriented systems we use UML.

Data objects (Entities)

A person place or thing to be represented in the system. E.g.:

  • person
  • event
  • organizational unit (e.g., university)

Entity Type: definition for an entity. E.g.: Employee(ID, Name, SSN, Birthdate)

Entity Instance: concrete instance of an entity type. E.g.: (1234, John Smith,2345423345, 08/31/1972)

Similar concept to class and object in OOP.

Entities are represented by rectangles.

Weak entities: entity which cannot exist without the existence of some other (think composition in OOP) (e.g., concept of Employee and Dependent – one does not exist without the other)

Attributes

Define property of an entity. Represented by an oval attached to an entity.

Attribute examples: employee name, id, ssn, birthdate.

Identifier attribute: a “key” is an attribute that uniquely identifies the entity it is attached to

There exist single value attributes (e.g., “Name”) and multi value attributes (e.g., “Skills”)

Relationships

Logical association between two entities. Relationships are represented by diamonds. Examples:

  • Bookstore orders Book
  • Bookstore sells Book
  • Bookstore buys Book
  • Student enrolls in Course

Cardinality:

  • one to one relationship (1:1) (e.g., Course - Instructor)
  • one to many (1:N) (e.g., Insructor - Student)
  • many to many (M:N) (e.g., Course - Student)

Modality:

  • 0: relationship is optional
  • 1: relationshop is mandatory

Modality & Cardinality denoted as: (min, max)

  • min = modality
  • max = cardinality

Effective Java

[Item 11] Always override hashCode when you override equals

When you invoke get(Object key) method from Java’s Map interface (as well as various other collections methods), Java uses the generated hashCode to know what bucket to look into. Once it knows that bucket to look into, it searches for the element using equals. So, if two objects are equal (as defined by the overrided equals method), then their hashcodes must be equal as well. Otherwise, Java will not look into the correct bucket.

Bottom line: some collections, like HashSet, HashMap or HashTable use hashCode to store its data and to retrieve it. If you don’t implement hashcode() and equals() in a consistent manner, then they will not function properly.

In Java, String class already overrides equals and hashCode method such that two Strings which are equal to each other also yield the same hashCode. Because of this, you get expected functionality when you use String as a key in a HashMap. If String did not override equals and hashCode then the following would not work:

1
2
3
4
5
6
  HashMap<String, Integer> map = new HashMap<String, Integer>();
  String a = new String("foo");
  String b = new String("foo");
  map.put(new String("foo"), 4);
  map.put("bar", 7);
  map.containsKey(new String("foo")); // false

This would not work because even though we expect that a equals b (because they both contain “foo”) applying equals would not return true unless we implement it to follow this business logic. Moreover hashCode would return different numbers for a and b beacause, by default, in Java hashCode is based of memory address. Due to this, Java would end up looking for a and b in different buckets. Luckily, this does not happen with Java String because it overrides equals and hashCode to behave like how we expect (namely, two Strings have same hashCode if they are equal)

Additional References:

  • https://stackoverflow.com/questions/2265503/why-do-i-need-to-override-the-equals-and-hashcode-methods-in-java
  • https://stackoverflow.com/questions/14608683/java-what-happens-if-hashcode-is-not-overriden
Written on January 2, 2020