Question

Lets say I have a function called do3() In order for that function to work I need the functions do1() and do2() be executed.

However, do1() and do2() could also be needed for other stuff (maybe for do4())

All these functions are public (and must be public).

Question, how should i implement the code?

Option 1 :

function do3() {
    do2()
    do whatever is needed for do3
}

function do2() {
    do1()
    do whatever is needed for do2
}

function do1() {
    do whatever is needed for do1
}

So if i call do3(), i am sure that everything will be done, although coupling will appear

Option 2

function do3() {
    do whatever is needed for do3
}

function do2() {
    do whatever is needed for do2
}

function do2() {
    do whatever is needed for do1
}

So when i want to call do3() i have to

do1()
do2()
do3()

I feel that the second option is better as it has less coupling, however I cannot really explain why, it is more like a feeling. I think that if I use option one and one day I change do2() I may have problems.

With option 2 however I must be sure to call do1 and do2 every time i want to use do3.

If someone has a better idea (option 3?) would be great to.

Thanks

Was it helpful?

Solution

"Lets say I have a function called do3() In order for that function to work I need the functions do1() and do2() be executed. "

Juan: As per your description do3() is dependent on do1() and do2(). The dependency Graph is

    - ->do2()
do3()
    - ->do1() 

In this case you should go for the second approach.

If your dependency graph is:

do3()- ->do2() - -> do1()

ie

  • do3 depends on do2

  • do2 depends on do1

In this case you should go for first approach.

--> : shows the dependency.

OTHER TIPS

Coupling is a concept related to classes not functions. A function should be able to call any other function of the same class that it lives in. There is no coupling issue there.

Your first option is fine there is nothing wrong with do3 calling do2 and do2 calling do1 as long as they all are in the same class.

You shouldn't go for option 2 of yours since it would require you to repeat code everywhere.

The short answer is that if do3() always must proceed a call to do2/do1 and there are not contexts when a caller may need to perform some action between those calls, then do2 should indeed be included in do3 and so on. I would also assert that unless the doX calls are part of an API or other difficult to change environment, it would be wise to avoid separating the calls "just in case" some case arises in the future that requires their splitting (principle of cautious design).

Longer answer: One way to test the truth of something is to explore pathological cases. Taking your second option to the extreme would basically entail complete unraveling of functional composition to the point of elimination of functions entirely; after all, some function is calling do1() do2() do3() and is thus "coupled" to those functions.

[soap box] It is simply not a true proposition that static dependencies (coupling) are necessarily a vice, though this notion is popular right now. Static dependencies may seem inflexible, but they are also easy to comprehend, machine verifiable, and highly optimizable. To illustrate the point, consider this hypothetical code:

person = WebRequest('/GetPerson');
if (person.Phone.AreaCode = '')
    person.Phone.AreaCode = GetAreaCodeFromZip(person.Zip);
...

Logic like this can be, and often is decompose for a myriad of reasons into perhaps:

requestService = CreationFactory(IRequest);
requestService.Configure(ConfigurationService.GetConfiguration(requestService));
requestService.SetEntityContext('Person');
response = requestService.Invoke();
entity = EntityService.ProcessEntity(response.Data);
EntityService.RegisterEntityCorrectionService(entity, IAreaCorrectionService);
...
interface IAreaCorrectionService
...
class AreaCorrectionService : IAreaCorrectionService
...
ServiceFactory.Register(AreaCorrectionService...

My point is simply that there is a cost in terms of performance, readability, and even decreased declarativeness to "decoupling". This is rarely explicitly considered when inversion of control, and other frameworks are considered.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top