views:

90

answers:

6

I am struggling to see the real-world benefits of loosely coupled code. Why spend so much effort making something flexible to work with a variety of other objects? If you know what you need to achieve, why not code specifically for that purpose?

To me, this is similar to creating untyped variables: it makes it very flexible, but opens itself to problems because perhaps an unexpected value is passed in. It also makes it harder to read, because you do not explicitly know what is being passed in.

Yet I feel like strongly typed is encouraged, but loosely coupling is bad.

EDIT: I feel either my interpretation of loose coupling is off or others are reading it the wrong way. Strong coupling to me is when a class references a concrete instance of another class. Loose coupling is when a class references an interface that another class can implement.

My question then is why not specifically call a concrete instance/definition of a class? I analogize that to specifically defining the variable type you need. I've been doing some reading on Dependency Injection, and they seem to make it out as fact that loose coupling better design.

+1  A: 

If you know what you need to achieve, why not code specifically for that purpose.

Short answer: You almost never know exactly what you need to achieve. Requirements change, and if your code is loosely coupled in the first place, it will be less of a nightmare to adapt.

mootinator
But really, isn't it "You almost never know exactly what you need to achieve in the end"? How does making something loosely coupled make it easier to adapt? That's like saying, "this variable should be a string, but since I can't know for sure, better make it untyped".
JLX
Now you're assuming there *is* an end ;)
mootinator
The answer is that if you're thinking strongly typed != loosely coupled, you're thinking on much too small a scale to understand why loosely coupled is good.
mootinator
+3  A: 

Strongly typed is good because it prevents hard to find bugs by throwing compile-time errors rather than run-time errors.

Tightly coupled code is bad because when you think you "know what you need to achieve", you are often wrong, or you don't know everything you need to know yet.

i.e. you might later find out that something you've already done could be used in another part of your code. Then maybe you decide to tightly couple 2 different versions of the same code. Then later you have to make a slight change in a business rule and you have to alter 2 different sets of tightly coupled code, and maybe you will get them both correct, which at best will take you twice as long... or at worst you will introduce a bug in one, but not in the other, and it goes undetected for a while, and then you find yourself in a real pickle.

Or maybe your business is growing much faster than you expected, and you need to offload some database components to a load-balancing system, so now you have to re-engineer everything that is tightly coupled to the existing database system to use the new system.

In a nutshell, loose coupling makes for software that is much easier to scale, maintain, and adapt to ever-changing conditions and requirements.

EDIT: I feel either my interpretation of loose coupling is off or others are reading it the wrong way. Strong coupling to me is when a class references a concrete instance of another class. Loose coupling is when a class references an interface that another class can implement.

My question then is why not specifically call a concrete instance/definition of a class? I analogize that to specifically defining the variable type you need. I've been doing some reading on Dependency Injection, and they seem to make it out as fact that loose coupling better design.

I'm not really sure what your confusion is here. Let's say for instance that you have an application that makes heavy use of a database. You have 100 different parts of your application that need to make database queries. Now, you could use MySQL++ in 100 different locations, or you can create a separate interface that calls MySQL++, and reference that interface in 100 different places.

Now your customer says that he wants to use SQL Server instead of MySQL.

Which scenario do you think is going to be easier to adapt? Rewriting the code in 100 different places, or rewriting the code in 1 place?

Okay... now you say that maybe rewriting it in 100 different places isn't THAT bad.

So... now your customer says that he needs to use MySQL in some locations, and SQL Server in other locations, and Oracle in yet other locations.

Now what do you do?

In a loosely coupled world, you can have 3 separate database components that all share the same interface with different implementations. In a tightly coupled world, you'd have 100 sets of switch statements strewn with 3 different levels of complexity.

Gerald
Maybe I'm misinterpreting loosely coupled. I see this as, "instead of directly referencing an object to do a particular task, I am going to create an interface that my object can implement. That way I can implement the interface in any way and not be tightly coupled to it." I don't see how making this an interface instead of a direct class reference makes it any easier to adapt.
JLX
Strong typing != static typing, see [here](http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html).
zoul
@Zoul... no, strong typing != static typing, but strong typing == type restrictions that are enforced by the compiler.
Gerald
@Gerald: your db example assumes that you either have 100 different places where you're repeating your db call ("uncoupled" for lack of a better term) OR you can use an interface (loosely coupled). It doesn't talk about just concretely referencing a single class to call the query (strongly coupled).
JLX
@Gerald: also, if I had to use three different dbs in my code, I would prefer referencing three different db classes in each of those areas. Otherwise, I would have no real idea which db to look into to see where my data was being written to--I would only know that it was written to "some database".
JLX
@JLX... of course you would know. The application isn't just going to pick an implementation at random, you have to define which implementation it's going to use some way; probably through a configuration file.
Gerald
@JLX... if your introduction to loose- and tight-coupling is through reading about Dependency Injection, I could possibly see the confusion. Dependency Injection is on the extreme side of loose-coupling. Loose- and tight-coupling are relative terms though. When you are "concretely referencing a single class", that is more loosely-coupled than stringing a bunch of low-level database function calls throughout your code. If that concrete class has a more generic interface that isn't specific to it's internal implementation, that is looser still.
Gerald
@Gerald: Perhaps that's where my confusion is. I was attributing loose coupling solely to DI, because I've seen DI folks use it as a main reasoning behind that design.
JLX
@JLX... it is. And it's not a bad premise. Following in the database example, in DI the coupling is often so loose that you can create new database implementations without even re-compiling the rest of the application. In many cases you don't even need to shut the application down, you can just add a new DLL and make a change in a configuration file. That can be overkill for many applications, and isn't necessarily a good design idea in all cases, but it is in some. Generally speaking, the looser the coupling, the more flexible are your options for adapting, scaling and maintaining the code.
Gerald
+3  A: 

First of all, you're comparing apples to oranges, so let me try to explain this from two perspectives. Typing refers to how operations on values/variables are performed and if they are allowed. Coupling, as opposed to cohesion, refers to the architecture of a piece (or several pieces) of software. The two aren't directly related at all.

Strong vs Weak Typing

A strongly typed language is (usually) a good thing because behavior is well defined. Take these two examples, from Wikipedia:

Weak typing:

a = 2
b = '2'

concatenate(a, b) # Returns '22'
add(a, b)         # Returns 4

The above can be slightly confusing and not-so-well-defined because some languages may use the ASCII (maybe hex, maybe octal, etc) numerical values for addition or concatenation, so there's a lot of room open for mistakes. Also, it's hard to see if a is originally an integer or a string (this may be important, but the language doesn't really care).

Strongly typed:

a = 2
b = '2'

#concatenate(a, b)     # Type Error
#add(a, b)             # Type Error
concatenate(str(a), b) # Returns '22'
add(a, int(b))         # Returns 4

As you can see here, everything is more explicit, you know what variables are and also when you're changing the types of any variables.

Wikipedia says:

The advantage claimed of weak typing is that it requires less effort on the part of the programmer than, because the compiler or interpreter implicitly performs certain kinds of conversions. However, one claimed disadvantage is that weakly typed programming systems catch fewer errors at compile time and some of these might still remain after testing has been completed. Two commonly used languages that support many kinds of implicit conversion are C and C++, and it is sometimes claimed that these are weakly typed languages. However, others argue that these languages place enough restrictions on how operands of different types can be mixed, that the two should be regarded as strongly typed languages.

Strong vs weak typing both have their advantages and disadvantages and neither is good or bad. It's important to understand the differences and similarities.

Loose vs Tight Coupling

Straight from Wikipedia:

In computer science, coupling or dependency is the degree to which each program module relies on each one of the other modules.

Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa. The software quality metrics of coupling and cohesion were invented by Larry Constantine, an original developer of Structured Design who was also an early proponent of these concepts (see also SSADM). Low coupling is often a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability.

In short, low coupling is a sign of very tight, readable and maintainable code. High coupling is preferred when dealing with massive APIs or large projects where different parts interact to form a whole. Neither is good or bad. Some projects should be tightly coupled, i.e. an embedded operating system. Others should be loosely coupled, i.e. a website CMS.

Hopefully I've shed some light here :)

David Titarenco
+1  A: 

Yet I feel like strongly typed is encouraged, but loosely coupling is bad.

I don't think it is fair to say that strong typing is good or encouraged. Certainly lots of people prefer strongly typed languages because it comes with compile-time checking. But plenty of people would say that weak typing is good. It sounds like since you've heard "strong" is good, how can "loose" be good too. The merits of a language's typing system isn't even in the realm of a similar concept as class design.

Side note: don't confuse strong and static typing

jayrdub
A: 

I think you're analogy to static vs dynamically typed languages is valid if not perfect. Similar religious arguments might apply on either side. (For my part I haven't seriously programmed a statically typed language in about 20 years, and every time I do, I feel like I'm crawling through mud.)

However what I've found with web services is that their internal workings are so varied, specialized, complicated, and sketchily documented; that it's practially impossible to precisely define optimal interfaces up front. Loose coupling is just good defensive programming.

mjhm
A: 

strong typing will help reduce errors while typically aiding performance. the more information the code-generation tools can gather about acceptable value ranges for variables, the more these tools can do to generate fast code.

when combined with type inference and feature's like traits (perl6 and others) or type classes (haskell), strongly typed code can continue to be compact and elegant.

brad clawsie