Object-oriented designing
Just like before designing an application on the web, we have to think about its visual design, while developing a JavaScript program, things can't really begin until we are ready with a rock solid design to implement.
In the case of an object-oriented JavaScript program, this design stage simply puts forward a generalized plan to implement while developing. We get to know about the classes required, the properties and methods of those classes, how the classes interact with one another, and much more.
After the design, the next step is programming. For intuitive programming, it's imperative to have an intuitive design at hand.
So let's start building up the design for this thing.
To begin with, let's first just think about all the classes we'd need for our clock.
An obvious one is Clock
, meant to represent the whole analog clock. Then since a clock consists of three hands, we can have another class ClockHand
to represent each of those hands.
It might be really tempting to think that we'd need more classes at this stage such as ClockHoursHand
, ClockMinutesHand
and ClockSecondsHand
to denote one of the hands of the clock, and even classes like ClockGraduation
for its graduations. However, that's not the case!
We need to ask ourselves one simple question before creating a given class — is there even a need of the class in the program.
For instance, in a live ticking clock, there is absolutely no need to keep track of every individual graduation (in fact, any graduation at all). What we need is only to keep track of the hands of the clock that have to continuously move with every passing second.
So the outcome of this discussion is that we need two classes Clock
and ClockHand
for our program.
There isn't always a need of a separate class!
A fair question that might be in your mind right now is that why don't we create separate classes for the three hands of the clock, such as ClockHoursHand
, ClockMinutesHand
and ClockSecondsHand
?
Well, surely we could, and there would be absolutely no issues if we did so. However, if we think practically, there is no need of doing so.
Yes, we want to be able to distinguish between the three different ClockHand
instances of a Clock
instance, but instead of making them as instances of separate classes, we can use some kind of a property on each instance to help us figure out which ClockHand
is which hand of the clock.
For instance, instead of creating two instances, one from a class such as ClockHoursHand
and the other from ClockMinutesHand
, we can create two ClockHand
instances, one whose type
property is 'hours'
and one whose type
is 'minutes'
.
Thus, just by inspecting any arbitary ClockHand
instance, we can rightaway tell exactly which hand does it represent.
Note that amongst the many ways to make this distinction between the three hands of the clock, this is just one. Another could be to use an integer to represent the type of the hand.
So with the classes decided, let's now think about their properties and methods. Note that at this stage, we can't always be perfect and come up with literally every method of a given class. Some methods come across us as we develop the program.
Hence, below we'll try to come up with the most basic properties and methods that we could easily think of being needed for the operation of the respective classes.
Starting with Clock
.
Here are its properties:
element
— holds the underlying.clock
element that can later be used to add the component elements of the clock inside it.hoursHand
holds aClockHand
instance representing the hours hand.minutesHand
holds aClockHand
instance representing the minutes hand.secondsHand
holds aClockHand
instance representing the seconds hand.
And here are its methods:
startTicking()
gets the clock to start ticking. This is more like anon
button on a real analog clock.tick()
contains the real logic to tick the clock with every passing second. It's what moves all the three hands of the clock.addElement()
adds all the desired elements into the underlying.clock
element.
Next, we have ClockHand
.
As before, starting with its properties:
clock
— holds a reference to the ownerClock
instance.element
— holds the underlying.clock_hand
element for this instance.angleIncrement
— holds the smallest angle increment of this hand that must be made with every passing second.
Over to the methods of this class:
update()
makes the current hand rotate according to the current time.
And that's it.
This is all that we need in order to power our clock. Now, it's time to finally start the programming.