The first type of diagram is called an activity diagram. These show various processes in a flowchart-like format and are normally used when only one class or function is involved. They start with a large dot, which represents the beginning of the activity. It progresses by following the arrows through the diagram. Ellipses tell you what occurs at a certain stage. When some type of decision-making is required, a diamond with arrows pointing away from it is used. The arrows list the conditions that must be true in order to follow that path. Finally, the activity terminates at a dot similar to the starting one, but it has an extra ring around it. If you're still confused, you can check out Fig.1.
![]() |
| Fig.1 - An activity diagram outlining how the light is turned on |
Fig.2 is also an activity diagram, but it outlines how the Scheduler decides when to run tasks.
![]() |
| Fig.2 - An activity diagram explaining how the Scheduler will do tasks |
If you read the comment box, you will see that this function cycles through a list of tasks. There is a little bit of a disclaimer here as the task times can not be grouped together, as in an array, because the object that each corresponds to must be preserved. Therefore, this part will consist of adjacent if statements rather than something like a for loop.
The next type of diagram is called a sequence diagram. These show processes that occur between multiple objects. Objects are created from classes and they are the parts that do the work of the program. A sequence diagram shows interactions in relation to time, from top to bottom. On the left side, there is the familiar Actor which has a long rectangle under it to show that it is active. To the right of the Actor, there are boxes that represent each of the objects involved. They have a line under them that shows when the object exist. It is aptly called a lifeline. Lines drawn horizontally from any of the aforementioned entities represent actions in the sequence. They are called messages. If this description still leaves something to be desired, you can take a look at Fig.3.
![]() |
| Fig.3 - A sequence diagram showing the automatic refreshment of the pH level |
Fig. 4 shows what happens as soon as the program starts;
![]() |
| Fig.4 - A sequence diagram outlining what occurs on start-up |
You might be wondering why MyReporter is not created by MyInterface, which is the object that would use it. The reason is that the Reporter class requires a parameter (bool RunMode) in order to be created. This means that it would need to be given to MyScheduler and then to MyInterface, and finally to MyReporter in a cascading fashion. Because the parameter is not used in the former two objects, using this style does not make sense. If one extends this logic to the various Circuit classes, parameters would be handed-off four times without being used. Therefore, the constructor of Scheduler may look something like this:
Scheduler(HydrogardenInterface* MyInterface, Light* MyLight, Water* MyWater, Pump* MyPump, Reporter* MyReporter, Circuit* pH, Circuit* Nutrient, Circuit* Level, int pHIn, int pHOut, int NutrientIn, int NutrientOut, int LevelIn, int LevelOut, bool RunMode)
I think this goes without saying, but this function prototype is extremely long.
This is also why various members are assigned using external variables (they also make maintenance easier as the values are together rather than being scattered throughout the program).
That is all for the design workflow, meaning that next time we will actually be building the hydrogarden.















