objA querying objB – vague OO-speak

Update — I think architects and “savvy communicators” often practice vague OO-speak to perfection. We may need to practice it.

In OO discussions, we often say “Look here, objectA will query objectB”, by calling getTimestamp(). This is a typical example of vague/misleading OO-speak. It’s as vague as a presidential candidate promising to “reduce deficit in 4 years” without any concrete details.  Note non-OO programmers don’t develope such vague communication habits.

Here are some of the fundamental amgiuities.

* A must get a handle on B before calling B’s non-static methods. The way to get the correct B instance is often non-trivial. That sentence invariably glosses over such details.

* It’s a method in A — methodA1 — not just “object A”, that queries B. This is a crucial point glossed over in that sentence.

** The original sentence implies A is some kind of active object that can initiate actions, but actually method A is called by another method, so the real initiator is often an external entity such as a GUI user, an incoming message, the main thread of a batch job, or a web-service/EJB request. ObjectA is NOT the initiator entity.

* Return value of the query is either saved in A or used on the fly in the methodA1. The original sentence doesn’t mention it and implies objectA has some kind of intelligence/bizlogic about how to use the return value. In some cases indeed the method in objectA has that “intelligence”, but it should not be glossed over. More often, methodA1 simplify passes the query result to the upstairs method above methodA1. The upstairs method may “belong” to a different object. All the details are glossed over in the original sentence.

Here’s an even more vague phrase – “A calling B”. This glosses over the essentials of the arguments and where they come from.

Advertisements

a "service" having exclusive know-how about a "resource&quot: eg@vague OO-speak

Here’s another eg of vague OO-speak (see other posts on vague OO-speak)

We often say “This intelligentService class KNOWS how to use this db/inet/MOM/calc-library, so a client can invoke this command/service method on intelligentService.”

What we mean is, intelligentService class 1) has a private field for locating the resource, and 2) the command method Body can intelligently use it to satisfy the request.

The private resource field and usage logic is not exposed to clients. Encapsulated, so intelligentService class alone “knows” about it.

It’s often assumed the intelligentService developer is the only person who needs that knowledge. In practice intelligentService developer is often the same developer of the client classes, but it’s good to conceptually separate the 2 roles.

All(?) OO methods are "static" under the hood

C++ supports “free functions”, static method and non-static method. 
– Static method are very similar to free functions. (Difference? Perhaps inheritance and access modifiers.)
– Non-static methods are implemented as free functions accepting “this” as first argument.

C++ is largely based on classic-C. Basically everything translates to classic-C code, which uses free functions only.

Once we understand the c++ world, we can look at java and c# — Essentially same as c++.

Looking deeper, any method, function or subroutine consists of a sequence of instruction — a “code object” if you like. This object is essentially singleton because there’s no reason to duplicate this object or pass it by value. This object has an address in memory. You get that address in C by taking the address of a function — so-called function pointers.

In a multi-threaded environment, this code object is kind of singleton and stateless (if you know what I mean!). Think of Math.abs(). The code object itself is never thread-unsafe, but invoking it as a non-static method often is. Indeed, Invoking it as a free function can also be thread-unsafe if the function uses a stateful object. Example — localtime().

Non-static method has to be implemented based on this code object.

superclass param, subclass argument

      Dog(Number o) {
      }
      Dog(Integer s) {
      }
      public static void main(String[] a) {
            Number ptr = new Integer(22);
            /**
             * won’t call the (Integer) ctor.
             * Won’t compile if you remove the (Number) ctor. Compiler doesn’t know
             * ptr points to an Interger object. Compiler only knows ptr is a Number (or
             * subclass) object. Runtime type of the pointer ptr is known only at runtime.
             */
            new Dog(ptr);
      }
}

has-a vs is-a — a fine point clarified

People say “Mortgage is-a Loan” — fine. You may say a HashMap has-a Entry — you mean a HashMap instance has-a Entry instance. The distinction between Class and Instance becomes critical when you study inner classes.

Generally, it’s more accurate to say an object (of class A) has-a pointer to another object (of class B). Usually, such a relationship is defined at compile time Before instance creation.

Therefore, we could afford to be imprecise as to say “class A has-a class B”.

In summary,
* is-a could be said of classes OR instances.
* has-a should be said of instances.

treat verb as noun(OO design

So many OO patterns and designs model a verb as a noun that we don't even notice them — we model an operation as an object, an
action, a process, a behaviour as a thingy….

In my projects, verb objects out-number nount objects. Bulk of business logic is in verb objects, so we often need to break each
into many objects and perhaps apply patterns.

* command pattern
* strategy pattern
* visitor pattern
* observer pattern
* factory pattern — object-creation
* processor objects
* loader objects
* controller in MVC
* message routers
* DAO — read operations and writes
* logger
* MessageDrivenBean
* listener, publisher, consumer

OO modelling to mirror real-world relationship@@

One of the OOM principles is “mirror real world relationships” — Be careful.

It’s fine to create a class for each real world entity. However, this principle is less important than other OOM principles such as

* testability
* flexibility, adaptability
* de-coupled

Real-world relationships show lots of IS-A but these are troublesome in OOM. Often you need to model them as HAS-A.

I think mature and sophisticated OOM often uses far more class than there are real world entities. In such cases, i think those classes are often required to support flexibility.

subsumption — mouse with 2 buttons

when you assign an actual Integer to a Number variable named “n1″[1], compiler compares the 2 pointers’ types [2]. Start with the “expected” type. If Expected type has 2 methods, then the actual type “received” must support these methods. So that the Integer received can stand in as a Number.

Conceptually, we can think of the expected type’s class object to expose those 2 methods. The actual object’s class object must expose the same methods.

As an analogy, a customer (compiler) expects a mouse with 2 buttons (ie methods), so any mouse given to the customer must expose these 2 named buttons (ie methods), and can optionally have 8 other buttons(methods).

How, how does this analogy compare to the onion and remote control analogies elsewhere in this blog?


When you assign an array of Integers to a reference declared as Number[], same thing. System knows the expected type and the actual type and is happy. But ArrayList is not array. When you assign an ArrayList of Integers to a reference declared as ArrayList, compiler breaks.

[1] or pass the reference to a method argument
[2] represented by 2 class objects. Even if the 2 types are 2 interface, still there are 2 class objects.

interface, dependency&&loose coupl`

If all of YOUR instance/local vars are declared as interfaces, then

1) I can more easily reuse YOUR class in my new project. I can instantiate your object more easily.

2) I can compile it with just those interface source files, without the class source files.

3) Your class doesn’t “depend” on those classes. When those classes change, your class need not recompile.

4 types of methods to instantiate a new object

1) constructor — invoked directly by client methods
2) factory
3) special instance[1] methods to return a new object of its own class. Could be public or private.
4) singleton’s getInstance(). Static

Example of (3): shortcut constructor method.

#1 key question: How do you control access to these methods?
3) you need to get an instance of this class before calling this method. Get a chicken, then an egg.
1) no control
4) no control due to staticity
2) a static factory method offers limited control.

[1] static? less common.

Objects used by each method call

When studying method calls (aka messages) among objects, look for the objects used by each call. For a “call” (a better focus than “method”), the most important objects in practice are, ranked by usage

– member objects in the args — folks often pass in a collection or “composed” object just to pass in member objects.

– member objects in the host

– args

– host object — If the host object is not used by the call, then this method should be static.

– caller object must appear as args, like m1(this,.) — Without “this” as an argument, the call can’t access the caller object. Caller object exists as a “local” variable upstairs the call stack (thread).

a class HAS-A instance of the same class

The /casual/ observer encounters many patterns where Object1.java HAS-A instance of Object1.

if the nested instance is a static instance (static member or a local var in a static block), … i feel there’s no OO principle behind the pattern. The hosting object (a class object) and the nested object are very different — class object vs instance of Object1.

From now on, we exclude static instances.

If a domain object follows this pattern, usually(?) there’s a real-world relationship to explain it. Perhaps a parent HAS-A child, a course has a pre-requisite course, a company has an institutional shareholder …

most common types of OO classes

There are many types of classes you encounter as an OO designer, such as when you study design patterns. Here are some common types of classes — we are not saying “objects”.

* domain objects — classes representing real-world entities specific to your business domain, including abstract things like a reimbursement, enrollment. FTTP projects is typical. “data-model-object” is the term used in [[ hardcore java ]]

* data objects — typically one class for one db table, one object for one row.

* state+operation object (s+o objects) — a class primarily made up of state variables, with operations defined /based-on/ the object state.

* Software-engineering objects — No better name. These classes have no real-world counterparts. These classes were written purely for software engineering. Eg: wrapper, adapter, connection, message-receiver, controller, DAO …

Some less common types of classes:
* process-objects — modeling a real process, in workflow applications …

java constructor^method: more differences than similarities

— diff:
* static constructor? illegal. i thought they are all static by default
* abstract constructor? illegal.
* final constructor? illegal. no overriding anyway
* return type? illegal
* throws? constructors can’t declare a “throws”, but both constructors and methods can throw.
* inheritance@@ NO, constructors aren’t inherited. A subclass can invoke super() in a very strict way. In other classes, if you have a pointer to “my” subclass, u can’t call “me”, the superclass constructor
* overriding? NO, because not inherited. subclass can access super(). No way to override super()

–similar:
* protected constructor? yes
* private constructor? yes.
* overloading? yes

java static^non-static method: 3 fundamental diffs #need polishing

See other blog posts why the author is biased towards static methods.

The more you study how non-static CALLS (we didn’t say “method”) work, the more you appreciate the huge differences between static vs non-static methods.

Compared to instance methods, static methods are much, much simpler to use by callers. (See reasons below.) Perhaps the only major complication is access modifier. Static methods are like Thread.sleep() and Math.abs… They don’t have a receiver-object or host-object. Often[2] a caller-METHOD (we didn’t say “object”) calls a static method to retrieve [1] something in read-only mode. The “customer-object” [3] of such a call is … well, can’t be the host-object. Obvious, but sometimes u need to bear it in mind.

Handle-perspective + messaging-perspective — when a client needs to call a target method M(), usually you need to plan how the client first gets a handle on the msg-receiver object , before “sending the message”. But static methods are completely simple.

Service/resource-perspective — an instance method publishes a service to caller methods. This service is *provided* by the host-object to the caller. The provider object has resources represented by its state. Caller-method must get a handle on the host-0bject first. Example — resource/”state” is a pool of database connections and the “service” is access to database. No such service without that resource.

Operation-perspective — an instance method exposes an operation. The operation is *performed* by this very receiver-object on behalf of the caller-method.

[1] or compute, or extract
[2] exception to the rule: Thread.sleep() actually affects the caller-thread by putting it to sleep!
[3] see earlier blog post

dependency, rigid, fragile — OO design concepts

— based on http://www.objectmentor.com/resources/articles/oodmetrc.pdf

rigidity (in-flexible, un-adaptable) is due to the fact that a single change to heavily interdependent software begins a cascade of changes in dependent modules. When the extent of that cascade of change cannot be predicted by the designers or maintainers the impact of the change cannot be estimated. This makes the cost of the change impossible to estimate. Managers, faced with such unpredictability, become reluctant to authorize changes.

Fragility (non-robust) is the tendency of a program to break in many places when a single change is made. Often the new problems are in areas that have no conceptual relationship with the area that was changed. Simple changes to one part of the application lead to failures in other parts that appear to be completely unrelated.

———————
I think this “change-impact” analysis would help answer the question “how to reduce subclass/superclass dependency”

picture button – HASA^ISA

Q: In real world, given a family of button objects/interfaces, perhaps in an inheritance hierarchy, and a family of picture objects/interfaces, how do you provide a button with a picture on it. Use ISA and then use HASA

Design 1: MyButton extends Button, and has-a pointer to an abstract picture type.

Design 2 — ISA: MyButton extends Button implements Picture => implements some of the Picture.java methods.
The existing environment may favor this design if Picture.java interface is the only thing there is, and everyone implements it and no one extends it.

Design 3: dependency injection. a container containing 2 pointers to a button and a picture. Most flexible. An end-user can choose the picture/button at run time and our class could setPic() and setButton() at run-time.

How about visitor pattern linking the 2 families?

How object A gets a reference to B

Background: when applying design patterns to your business logic, you need to describe your business-logic using domain object names (example? no)

For an Object A to get access to Object B, there are some extremely common patterns, ranked in terms of /incidence/ (ie how common they occur):

* A.method1 receives an \\arg//B
** A.method1 receives an \\arg//Y which is a collection containing B
** A.method1 receives an \\arg//K with a getter returning B

* A calls some method that returns a B [1]
** A calls some method that returns a collection containing B
** A calls some method that returns a D with a getter returning B

* A makes an explicit call to new B() [2] [3]. Common
* A “knows” B from birth — A’s constructor initializes an instance variable to a B object

[3] and invariably saves it in some instance/method-local variable
[2] or new C() which connects to a B via a collection or getter
[1] Longer version: A.method2 (usually interpreted as a behaviour of object A) calls some method (defined in any class) returning a B

IS-A => subtype methods be "compatible" with supertype

In an earlier post we reasoned that a concrete method from an interface must be public. We can now extend it to all method-overriding and all method-implementation. The rules of method overriding are well-documented on the Net. I think all the rules exist due to the IS-A principle.
 
IS-A => “repeated” methods in subtypes must support the expected services of the supertype
 
If we can use a supertype remote-control to invoke method1(), then we can use a subtype, too. All the subtypes’ method1() implementations are “compatible” with the supertype’s method1(). Compatibility is defined by the 4 or 5 method-overriding rules.

subclass obj always contains a superclass obj

(A letter I wrote but did not send. ) Hi Elisha,
You once told me something interesting about subclass instantiation.

Suppose concrete Class C extends concrete Class B.
Suppose B has instance variable bi and static variable bs
Suppose B has non-static method bn() and static method bm()

When we call new C(), JVM allocates a chunk of memory for the new object. What you said that surprised me is — right inside that chunk of memory, there’s a complete B object.

We know C() automatically calls B(), which allocates a chunk of memory for the new B object.

Q: is the B chunk inside the C chunk?
A: yes for C++, the derived object as the same address as the base object – post on AOB.
A: yes. I just found a DIAGRAM on http://courses.csail.mit.edu/6.170/old-www/2000-Spring/handouts/lect11/lect11.pdf

Note an Object instance is inside every java object.

IS-A principle => interface methods are ALL public

An earlier post asked Q: Must concrete methods be public if born in an interface?
%% A: I think so. why?

short answer: a subtype must appear a good member of the “family”, supporting all expected services. A non-public method would not support the expected service.

We call each method a “service” because the client will use it and depend on it.

long answer:

Suppose a caller method M1 calling a method M2, perhaps a factory method.
Suppose M2 returns a Company which is an interface.
Suppose M1 puts the object into a variable “company” of type Company, and calls company.payTax().

Suppose the object is actually a Shop, a subtype of Company.

Since Company.java is an Interface, java syntax dictates Company (or its ancestors) declaring payTax() as public.

Q: can Shop.java define payTax() as private?
A: no. M1, the client, would fail when calling payTax(). In fact, Shop.java would probably fail to compile if payTax() is protected, default or anything but public.
A: You break the IS-A principle — Shop no longer IS-A Company.
A: a public callable payTax() method is part of the IS-A.
A: a public callable payTax() method is part of being a Company
A: a public callable payTax() method is part of the expected services of the Company family.
A: Every subtype of Company, be it a sub-interface, abstract class or concrete class, must expose a public callable payTax(), otherwise clients will die.

A more real example: Runnable.run() is, thanks to the interface, public ==> concrete run() method is always public. Suppose you instantiate an object R implementing Runnable but with a private run(). Suppose a 3rd-party client receives this object as a Runnable type and faithfully invokes its run(). Bang! The client has to disqualify this object as a genuine Runable.

OO features in FTTP Parser

* depend on interfaces, not concrete classes
* heavy use static methods
* validity interface
* replicate LISP multiple inheritance
* break long methods into multiple screenful methods
* maximize object reuse and minimize duplicate objects
* singleton in multi-threaded environment

— OO-related features
* custom exceptions
* JUnit
* thread-safety

layered OO design: testing, modular code reuse..

From experts to novice, everyone uses the “layer” jargon in the context of testing, code reuse, modular design,

For starters, i have a blog post on “DB entity object HAS-A DAO”.
* import — Ideally, a upper-layer class imports lower-layer classes. Shared-layer classes can be imported by all.
* compile-time dependency — Ideally, low-layer classes should be compilable without upper-layer classes.
* reusable components — therefore, lower-layer classes should be reusable in other projects in the absence of upper-layer classes.
* testing — To test a upper-layer method (we didn’t say “class”), you often need to instantiate (or mock) the lower-layer objects. Even if you use interfaces, you still need to instantiate these lower objects to run their methods.

(Suggestion: reduce cross-layer inter-dependencies.)

* use-a, has-a — upper-layer classes could use-a or has-a lower-layer class, but not vice versa.
* separation of concern — lower-layer objects should not need to know about upper-layer. If my class uses xstream (or a mailer, a scheduler, a serializer, a parser, a timer…), then xstream should be oblivious of my class.

loose coupling in OO and beyond

See also posts on
[[ facade: loose coupling && fewer dependencies ]]

— examples
synchronous ^ mq
mvc — loose coupling between M, V and C
javascript + java + stored proc

web service client and server rely on RMI/RPC and are more coupled (than http client/server), but both agree on an xml format to reduce coupling.

— keywords (and synonyms)
easy edits — not possible in an entangled system. Edits to source code should not break other (battle tested, production quality) classes. [[ declarative control — enterprise design pattern ]]

change isolation — “changes” to one system component had better be isolated from the other components. I think isolation is shown between javascript, java and stored proc

“runtime change” — to object behaviour, without breaking other classes [[ runtime change to object behaviour ]], [[ create functionality without jvm restart]strategy ]]

“expected services” — [[ de-couple – using abstract^concrete class ]]

knowledge — “Object A must know everything about Object B” means tight-coupling. Loose-coupling means A only need to know the expected services of the interface B implements. The interface specifies/constitutes often a very loose contract between A and B. “So long as you support the expected service, i don’t care how you implement it internally.” Consider SSH client/server.

cohesion

both hasa + isa at the same time

HAS-A has its attractions. IS-A has its powers too. You must choose one or the other. Or must you?

1) Well if you accept additional complexities, Decorator pattern gives you some if not all the combined benefits of composition and inheritance. In one sentence, “A decorator wraps a base object and extends[1] that decoratee object.” It’s kind of unusual and complex. I think it’s good to remember a few examples to justify it.

2) MacroCommand is another design pattern combining both hasa+isa at the same time.

[1] or “implements”