views:

61

answers:

4

I have a function that returns the orders for a given period. I've create a Period object which ensures that, when specifying a date range, the start date is <= to the end date. Likewise, if dealing with a month period, the start and end dates of the period should be the first and last days of the month, respectively.

My question is this:

I thought that in Object Oriented Design principles, coupling was bad. Am I introducing coupling between the Order and Period classes by having the Order class use a Period class as a parameter in one of its methods?

My guess is yes, but that there are advantages of doing so, namely, once the objects are defined, one doesn't have to perform the same parameter validation checks every time a period is passed as a parameter to different methods of the Orders class.

Besides, doesn't Microsoft constantly pass non intrinsic objects of one type to other objects?
Avoiding coupling sounds like avoiding re-use to me, which OOP was supposed to promote. This sounds like competing goals.

Can someone clarify.

Public Class Order

   Public Shared Function GetOrders(ByVal customerId As Integer,
                                    ByVal forPeriod As Period) As Orders

       **'Should the param object MonthPeriod be replaced with 2 date params?
       'Would I be "reducing coupling" by doing so, a good thing.**

   End Function

End Class

Public Class Period

    Property FromDate As Date
    Property ToDate As Date

    Public Sub New(ByVal fromDate As Date, ByVal toDate As Date)

        If fromDate > ToDate Then
            Throw New ArgumentException("fromDate must be less than Or equal toDate")
        End If

        _FromDate = fromDate
        _ToDate = toDate

    End Sub

End Class

Public Class MonthPeriod : Inherits Period


    Public Sub New(ByVal fromDate As Date, ByVal toDate As Date)

        MyBase.New(fromdate, toDate)

        If fromDate.Date <> New Date(fromDate.Year, fromDate.Month, 1) Then
            Throw New ArgumentException("fromDate must be the first day of the month")
        End If

        If toDate.Date <> New Date(toDate.Year, toDate.Month, Date.DaysInMonth(toDate.Year, toDate.Month)) Then
            Throw New ArgumentException("fromDate must be the last day of the month")
        End If

    End Sub

End Class
+1  A: 

Loose coupling and reuse are indeed competing concepts. When designing software you have to constantly balance the use of both.

DancesWithBamboo
OK, based on your answer, I think I understand the concepts.
Chad
+1  A: 

It is ok for services (like GetOrders) in your system to depend on small, easy to create, Value Objects (like Period). This lets your service objects talk in terms of the domain you are working in rather than always in basic types.

Therefore, I would say passing Period into GetOrders is correct in this scenario. It raises the level of abstraction. GetOrders is interested in all of the Period class, so you are not unnecessarily widdening the scope of concepts that GetOrders knows about (it's just in a different form). If Period was a much bigger class containing a bunch of other stuff, then coupling would be much more of a problem.

The second factor that makes this ok, is that creating a Period object is easy. If it required you to created a whole series of other objects, the the coupling would be a concern. This is why you do not have your value objects send emails and save themselves to the database, etc.

WW
+1  A: 

Everything in .Net is an object, and yet objects seldom exist in isolation so there will be a certain amount of coupling between classes yes. The question you need to ask is are the classes tightly coupled, somewhat coupled, or loosely coupled. Tightly coupled classes make for a brittle architecture, in that changes may have a ripple effect throughout a model or a system. Maintenance of the classes tends to become progressively more difficult over time. Making your classes more loosely coupled tends to alleviate some of these issues. In terms of whether something is loosely coupled or not (from here):

Coupling refers to the degree of direct knowledge that one class has of another. This is not meant to be interpreted as encapsulation vs. non-encapsulation. It is not a reference to one class's knowledge of another class's attributes or implementation, but rather knowledge of that other class itself. Strong coupling occurs when a dependent class contains a pointer directly to a concrete class which provides the required behavior. The dependency cannot be substituted, or its "signature" changed, without requiring a change to the dependent class. Loose coupling occurs when the dependent class contains a pointer only to an interface, which can then be implemented by one or many concrete classes.

In your example you introduced some coupling between the Order class and the Period class. You presumable needed to pass two related dates to the Order method and you chose to create a Period class to do this with. Why? Because you had two dates; a from date and a to date; and you wanted to validate that the to date was later than the from date from one and only one spot in your code. This is an application of the DRY principle; and that is a good thing. The application of the DRY principle is, while related, different from code reuse (from here):

Some characteristics that make software more easily reusable are modularity, loose coupling, high cohesion, information hiding and separation of concerns.

Loose coupling is just one of several characteristics enable code reuse. Code reuse would be to some extent the ability for you to use the Period class elsewhere in your code, rather than just for the Order class. If you were to add an interface to abstract away your use of the Period class, that would make your Order class and Period class more loosely coupled, but that would not take away your ability for code reuse (your ability to use the Period class elsewhere in your code).

Steve Ellinger
Excellent answer. Thanks
Chad
+1  A: 

Unnecessary coupling should be avoided but in your scenario, Period is just use to define a value type that aggregate some concept about your domain so it is not bad at all. If it is beyond value type usage, you will want to decouple them using technique like dependency injection (DI) and inversion of control (IoC).

In term of you measuring design, when it comes to dependency, you will have to look beyond class level but more at namespace or assembly level. In your case, if Period lives in the same namespace or assembly, then you still have very good Relational Cohesion between your types in the package. Your Efferent and Afferent coupling of your namespace will still remain unchanged/low in the scenario above.

Fadrian Sudaman