This is the first chapter from the book.
Terminologies are abundant in the realm of design patterns. Without the terms being defined the interpretations vary which often lead to confusion. In this chapter, we try to define the various terms that we use so that there is less ambiguity in the concepts.
So
what are the basic tools you have?
Forget
Eclipse, I'm talking of the essential constructs using which you always write
code; and you can consider them also as the various tools using which you
design your code, important ones among these are
1.
Method or a function
2.
Object
3.
Class
4.
Interface
5.
Understanding the term implements
6.
External system
7.
Defining an object to use
8.
External view of objects
9.
Concept of terms such as
implements/behavior
10. State
of an object
The aim of this chapter is to revisit
these basic constructs and use them as tools to implement the design.
What
is the method or a function?
A piece of reusable code! Who said you
did not write reusable code? Every method is reusable; to what extent and if it
ever has been reused is the question. When we write a method we often think of what
will go inside the method; at least that is where it mattered most for grades.
It is indeed the logic within the method
and if you are thinking of theta and bigoh
(complexity measures) then logic within the method is the place where you focus
most. Our focus is different; apart from the complexity, we are thinking on
modularity, reusability, scalability etc. What we are more interested in (you
should be also) is the access level of
the method that is who can access it; what are the arguments it takes; what it
returns? Do I want to make an addition method so generic that it can add both
strings and two numbers? Further, when we write a method, we need to understand
whether the method can be called or needs to be called without instantiating
the class. Should the method belong to the class? Or should it belong to the
objects? So when we write a method we must not only think of what goes inside
the method but also on what are the access level
of the method, inputs and outputs of the
method etc..
Six
fundamental considerations towards defining a method - In
the treatment for Singleton pattern, we identify six important questions that
the reader can ask to design a method that is most appropriate for the problem
at hand. These are
1.
What should be the output of the
method?
2.
What would be the access level of the
method?
3.
What should be the inputs of the
method?
4.
What should be the logic within the
method?
5.
Who will be calling it?
6.
Is the place being considered to
define the method, the right place for defining the method?
We shall
demonstrate the usage of these questions in the Singleton pattern. For
subsequent patterns, we ask only those
questions which are relevant.
What
is an object?
An object is a
way to encapsulate data/variables and methods so that we can consider them in
isolation. We in general look for this data to be not available outside this
object and to be only available to
methods inside the object. That is the ideal scenario; however, sometimes we
need data to be set from an external piece of code. Now this can happen only
two times, either during its creation or
during the lifetime of the object. If it is during creation, then they should
be passed as arguments in the constructor. If the data requires being set
during the life cycle of the object then we must use setters for that
particular variable. It is the not particularly nice to use the Eclipse feature
of generating all getters and setters indiscriminately. Similar to the setting
of a variable, getters should only be
used for a variable if the object requests to part with their piece of data to
the external world. The other thing that
objects contain is the methods about which we have just discussed.
What
is a class?
Now there can
be many objects, each behaving differently, some of them may be the same or
behave similarly, how do we then give a name
to the feature? We do this by saying some object belong to a particular type
while others are of a different type. A synonym for type is class. This
concept was so common that language designers went ahead and made this a
language construct or feature itself called Class. So if you have to
create objects of a certain type, you defined first the type. To convey to the
machine that it is a type you are defining you use the term, Class. Later using this feature you can define many objects
and it all those object would be said to be objects of that Class. Thus, the class is defined as a template for
creating objects.
What
is an interface?
It is a set of
methods.
What
are the different ways in which you can interact with an object? You
can call new upon the constructor, use the dot notation to access
one of its variables (if accessible) or you can call one of its methods. Interface is a name to denote a set of methods with which you can
interact with a class (or one of its objects) excluding the constructor. We can
say that an object interfaces (interacts) with the external world via this
interface. Thus, every class (or one of
its objects) has an interface. We often need to define this set (read
interface) of methods in advance. This is sometimes helpful and that itself is
a fundamental pattern, and thus again included in the language construct itself
by the designers, so that we can define just the interactions, without even
thinking of classes which will provide (read implement) these methods.
What
do implements mean?
The classes
created later which are required to provide this set of methods thus use the
word “implements” i.e. public ClassA implements InterfaceI.
Can
an object have multiple interfaces?
Yes, it can.
Let us say an object has methods m1, m2, m3 apart from the constructor of the
object. So there can be six total possible permutations
of these methods and thus six total interfaces possible. Now in the design, we may define only a few of these as required.
Do interface/implements
and behavior refer to the same thing?
This is often
a source of confusion. All such classes which implement a particular interface
can be expected to behave in the same way, that is one can call the same
method (of the implemented interface) over each of this classes. Thus, the term behavior is also
sometimes used to describe an interface. But this is incorrect. Interface and
behavior are not the same. Interface
refers to the set of methods and their signature while behavior refers to logic
within the method. So two classes implementing the same interface will have
same methods but can have different
behavior of the methods depending upon the logic that is implemented within the
methods.
What
do we mean by same behavior?
Objects of a
class would have the same logic within its methods, so they are in general
referred to as having the same behavior
(usually). Again two classes implementing the same interface will, at least, have same methods but can have different behavior of the methods depending
upon the logic that is implemented within the methods. Note that a different
class implementing the same interface does not automatically mean different
behavior.
What
is an external system?
An external
system is any piece of code(s), systems, actors
which interact or call or invoke the code that we are designing. This is not so
much of a tool but helps in thinking; that is to consider everything within the
class(es), objects and interfaces being considered as internal; outside it as
external. The external system can vary to a very great degree, if the
classification factor used is form,
for example, it can be just another class or the code using which I am testing
the class in question. The class again could be in the same package or
different package. It could be within our systems or residing within a system
situated miles apart! We do not need to make a distinction beyond this, it
suffices to consider the external system
as any users of the class (or framework or pattern) in question and leave rest
upon the context.
The
fundamental design patterns
We earlier
noted that terms class, interface, implements are very basic, so much so
that it is incorporated as keywords within the language, but more deeply, do
you see that these are also design patterns? It is possible that you may not
have realized this before and it is the core essence of design patterns. Treated in this light, design pattern would
be any processes that have been previously known to work for certain problems.
In certain domains, the process could be proved mathematically or are based on
certain set of axioms or theories. In our case and at present our processes are
not mathematically based, however, the processes are known to work based on
previous experience. I think you get the idea now.
How
would you define an object to use the object?
Alternatively,
we can rephrase the question as to what are the various ways in which we can
refer to an object within a code? There are three ways of doing this
1.
Using the class - e.g. ClassA varA;
2.
Using the base class - e.g. BaseClassA
varA;
3.
Using the interface - e.g. InterfaceA
varA;
Here the
assumption for point 2 is that ClassA extends BaseClassA. For point 3, we
assume ClassA implements InterfaceA.
What
does an external system see within an object?
Now that we
have said about the external system let us go back to our example to show an
important viewpoint. Let us say an object has methods m1, m2, m3 apart from the
constructor of the object. Let us suppose (say) Interface1 has only one method
m1, Interface2 has only two methods m1 and m3 while Interface3 has all the
three methods m1, m2 and m3. Further, assume our class in consideration (say)
ClassA implements only Interface2 and Interface3. Note that though ClassA has
method m1, it does not mean it implements Interface1 unless it explicitly does
so in the code. Now consider an external system which refers to the objects of
ClassA by Interface2, in this case, the
external system will not see or know the presence of method m3 within the
object even though it is present. Seen in this way Interfaces are a means of
hiding methods within a class like access restrictions is for a variable. It
also means an object may have multiple methods but only those would be visible
to an external system which is defined by
the interface that the external system is using to refer to the object.
What
is an abstraction?
This term is
quite hard to understand at first. There is a dedicated page for this on the
Wikipedia, however, that page may not be of much help in understanding what it
is (true to its nature of being abstract), certainly it will make your
understanding about abstraction more concrete provided you already know about
abstraction, but that is if you know!. So here is the working definition; an
abstraction is a model. And what is a model? Again a working definition
would be; a model is an easy way of conveying ideas about a complex thing. Next
point is how would we represent an abstraction? Or simply put how a person
would represent a model in a programming language. Perhaps you guessed it, it
is a class. So when we define a class representing say a car CarA, then CarA
does not represent a real world car, you cannot drive it! So this CarA is a
small representation of our real thing, which is what a model essentially
is. In this book, we refrain from using the word
unless the lack of it causes ambiguity.
The
point in time when we are designing:
This is not a
term that we need to define. It is rather an important aspect that we need to
be aware of when embarking on learning design patterns. The question being
asked is about the time when the design comes into effect. It certainly depends
upon the problem we are solving. The problem may arise when we are designing
the solution or running the solution. Following are some educated guess of the
possible situations.
1.
Design
time
– This refers to the time that the code is being created, i.e., you are creating
some basic code which other will programmers will use to develop the system. An example of this could be you create an
interface which others programmers will implement. Now this implementation
could be in immediate future or in future when the code is released and
required to be maintained during subsequent releases. The designer must have in
mind both the immediate concerns and the future concerns. The future concerns
can be accumulated based on experience or requirements assuming it exists.
2.
Compile
time
– Here the issue is within the interactions between classes or interfaces and
these classes or interfaces already exists at the time of compilation. In this
scenario, there cannot be objects or unknown classes or interfaces that the
design may interact with.
3.
Runtime -
Here the classes or interfaces already exists at the time of compilation plus
classes or interfaces which could be dynamically loaded. In this scenario,
there can be new objects or classes or interfaces that were not present during compile time and that interacts with the
design. Here we can be concerned about runtime issues of (say) performance or
restrict inclusion/behavior of new classes that may come into play.
4.
Post-release – Here we tackle the scenarios
after the code is released and when subsequent teams have taken this code in
part or entirety and are using them in their design.
Why
is this important? This is important
because often during learning design patterns the designer considers only the
immediate issues while challenges of post release and maintenance aspects /
problems are neglected. So considerations of post release / maintenance
situation are also beneficial to any design in general.
The state of an object
The state of
an object means the values of the different important subset of all variables
within that object. Different because there could be multiple variables
which define the state of an object. Important
variables because, the object may have other variables also but it may not be
included in the definition of the state of the object. Subset because
not all variables may be used to define the state of an object.
Name
conventions
All classes, interfaces and objects are suffixed with Class,
Interface, and Object respectively. So if there was an existing class serving
some purpose, we name it as ExistingClass. An object of this class is written
as existingObject.
Italics are used for two purposes Firstly,
for forming questions that are asked in
between so that we are able to discuss the situation before we delve into the
answers. Secondly, it is used for words, where we are not referring to the
literal meaning but to the contextual meaning or laying emphasis on the word.
All methods are suffixed with parenthesis. Methods do not have the suffix method
as we are using parenthesis to denote this.
Please note,
this is not the standard way of naming, it is used for the sake of making the
explanation very lucid.
The
sub-headings used in the chapters
Each chapter has the following
sub-headings
Stage –
In this section, we set the scene, we identify the situation. Often when this
is very evident or there is nothing specific, this section is ignored.
Requirement –
In this section, we identify and define the requirement.
Discussion –
In this section, we identify the questions we face and discuss these questions.
In this section, we try to capture the thought process which is essential to understand the design patterns.
The discussions lead us to the solution. This is the core part of the book for
each pattern.
Participants –
In this section, for a given situation, we discuss some guidelines to identify
which object/class should server which role.
Steps –
In this section, we identify the generic few steps that we can apply in most
cases to apply a design pattern.
Example
code
– In this section, links are given to internet repositories where we have
examples of the code.
Further
notes
– In this section, we add few other viewpoints related to the design pattern,
if required.
No comments:
Post a Comment