Programming for future use of interfaces

I have a colleague sitting next to me who designed an interface like this:

public interface IEventGetter {

    public List<FooType> getFooList(String fooName, Date start, Date end)
        throws Exception;
    ....

}

The problem is, right now, we are not using this “end” parameter anywhere in our code, it’s just there because we might have to use it some time in the future.

We are trying to convince him it’s a bad idea to put parameters into interfaces that are of no use right now, but he keeps on insisting that a lot of work will have to be done if we implement the use of “end” date some time later and have to adapt all the code then.

Now, my question is, are there any sources that are handling a topic like this of “respected” coding gurus that we can link him to?

17

Invite him to learn about YAGNI. The Rationale part of Wikipedia page may be particularly interesting here:

According to those who advocate the YAGNI approach, the temptation to write code that is not necessary at the moment, but might be in the future, has the following disadvantages:

  • The time spent is taken from adding, testing or improving the necessary functionality.
  • The new features must be debugged, documented, and supported.
  • Any new feature imposes constraints on what can be done in the future, so an unnecessary feature may preclude needed features from being added in the future.
  • Until the feature is actually needed, it is difficult to fully define what it should do and to test it. If the new feature is not properly defined and tested, it may not work correctly, even if it eventually is needed.
  • It leads to code bloat; the software becomes larger and more complicated.
  • Unless there are specifications and some kind of revision control, the feature may not be known to programmers who could make use of it.
  • Adding the new feature may suggest other new features. If these new features are implemented as well, this could result in a snowball effect towards feature creep.

Other possible arguments:

  • “80% of the lifetime cost of a piece of software goes to maintenance”. Writing code just in time reduces the cost of the maintenance: one has to maintain less code, and can focus on the code actually needed.

  • Source code is written once, but read dozens of times. An additional argument, not used anywhere, would lead to time wasted understanding why is there an argument which is not needed. Given that this is an interface with several possible implementations makes things only more difficult.

  • Source code is expected to be self-documenting. The actual signature is misleading, since a reader would think that end affects either the result or the execution of the method.

  • Persons writing concrete implementations of this interface may not understand that the last argument shouldn’t be used, which would lead to different approaches:

    1. I don’t need end, so I’ll simply ignore its value,

    2. I don’t need end, so I’ll throw an exception if it is not null,

    3. I don’t need end, but will try to somehow use it,

    4. I’ll write lots of code which might be used later when end will be needed.

But be aware that your colleague may be right.

All previous points are based on the fact that refactoring is easy, so adding an argument later won’t require much effort. But this is an interface, and as an interface, it may be used by several teams contributing to other parts of your product. This means that changing an interface could be particularly painful, in which case, YAGNI doesn’t really apply here.

The answer by h.j.k. gives a good solution: adding a method to an already used interface is not particularly hard, but in some cases, it has a substantial cost too:

  • Some frameworks don’t support overloads. For example and if I remember well (correct me if I’m wrong), .NET’s WCF doesn’t support overloads.

  • If the interface has many concrete implementations, adding a method to the interface would require going through all the implementations and adding the method there too.

2

but he keeps on insisting that a lot of work will have to be done if we implement the use of “end” date some time later and have to adapt all the code then.

(some time later)

public class EventGetter implements IEventGetter {

    private static final Date IMPLIED_END_DATE_ASOF_20140711 = new Date(Long.MAX_VALUE); // ???

    @Override
    public List<FooType> getFooList(String fooName, Date start) throws Exception {
        return getFooList(fooName, start, IMPLIED_END_DATE_ASOF_20140711);
    }

    @Override
    public List<FooType> getFooList(String fooName, Date start, Date end) throws Exception {
        // Final implementation goes here
    }
}

That’s all you need, method overloading. The additional method in the future can be introduced transparently without affecting calls to the existing method.

2

[Are there] “respected” coding gurus that we can link him to [to persuade him]?

Appeals to authority are not particularly convincing; better to present an argument that is valid no matter who said it.

Here’s a reductio ad absurdum that should persuade or demonstrate that your co-worker is stuck on being “right” regardless of sensibility:


What you really need is

getFooList(String fooName, Date start, Date end, Date middle, 
           Date one_third, JulianDate start, JulianDate end,
           KlingonDate start, KlingonDate end)

You never know when you’ll have to internationalize for Klingon, so you better take care of it now because it will require a lot of work to retrofit and Klingons are not known for their patience.

5

From a software engineering perspective, I believe the proper solution for this kind of problems is in the builder pattern. This is definitely a link from ‘guru’ authors for your colleague http://en.wikipedia.org/wiki/Builder_pattern.

In the builder pattern, user creates an object that contains the parameters. This parameter container will then be passed into the method. This will take care of any extension and overloading of parameters that your colleague would need in the future while making the whole thing very stable when changes need to be made.

Your example will become:

public interface IEventGetter {
    public List<FooType> getFooList(ISearchFooRequest req) {
        throws Exception;
    ....
    }
}

public interface ISearchFooRequest {
        public String getName();
        public Date getStart();
        public Date getEnd();
        public int getOffset();
        ...
    }
}

public class SearchFooRequest implements ISearchFooRequest {

    public static SearchFooRequest buildDefaultRequest(String name, Date start) {
        ...
    }

    public String getName() {...}
    public Date getStart() {...}
    ...
    public void setEnd(Date end) {...}
    public void setOffset(int offset) {...}
    ...
}

3

You don’t need it now, so don’t add it. If you need it later, extend the interface:

public interface IEventGetter {

    public List<FooType> getFooList(String fooName, Date start)
         throws Exception;
    ....

}

public interface IBoundedEventGetter extends IEventGetter {

    public List<FooType> getFooList(String fooName, Date start, Date end)
        throws Exception;
    ....

}

1

No design principle is absolute, so while I mostly agree with the other answers, I thought I’d play devil’s advocate and discuss some conditions under which I would consider accepting your colleague’s solution:

  • If this is a public API, and you anticipate the feature being useful to third-party developers, even if you don’t use it internally.
  • If it has considerable immediate benefits, not just future ones. If the implied end date is Now(), then adding a parameter removes a side effect, which has benefits for caching and unit testing. Maybe it allows for a simpler implementation. Or maybe it is more consistent with other APIs in your code.
  • If your development culture has a problematic history. If processes or territoriality make it too difficult to change something central like an interface, then what I’ve seen happen before is people implementing client-side workarounds instead of changing the interface, then you’re trying to maintain a dozen ad hoc end date filters instead of one. If that sort of thing happens a lot at your company, it makes sense to put a little more effort into future proofing. Don’t get me wrong, it’s better to change your development processes, but this is usually easier said than done.

That being said, in my experience the biggest corollary to YAGNI is YDKWFYN: You Don’t Know What Form You’ll Need (yes, I just made that acronym up). Even if needing some limit parameter might be relatively predictable, it might take the form of a page limit, or number of days, or a boolean specifying to use the end date from a user preferences table, or any number of things.

Since you don’t have the requirement yet, you have no way of knowing what type that parameter should be. You often end up either having an awkward interface that isn’t quite the best fit for your requirement, or having to change it anyway.

There is not enough information to answer this question. It depends on what getFooList actually does, and how it does it.

Here is an obvious example of a method which should support an additional parameter, used or not.

void CapitalizeSubstring (String capitalize_me, int start_index);

Implementing a method that operates on a collection where you can specify the start but not the end of the collection is often silly.

You really have to look at the problem itself and ask whether the parameter is nonsensical in the context of the whole interface, and really how much burden the additional parameter imposes.

I’m afraid your colleague may actually have a very valid point. Although his solution is actually not the best.

From his proposed interface it is clear that

public List<FooType> getFooList(String fooName, Date start, Date end) throws Exception;

is returning instances found within an interval in time. If clients currently don’t use the end parameter, that does not change the fact that they expect instances found within an interval in time. It just means that currently all clients use open ended intervals (from start to eternity)

So a better interface would be :

public List<FooType> getFooList(String fooName, Interval interval) throws Exception;

If you supply interval with a static factory method :

public static Interval startingAt(Date start) { return new Interval(start, null); }

then clients won’t even feel the need to specify an end time.

At the same time your interface more correctly conveys what it does, since getFooList(String, Date) does not communicate that this deals with an interval.

Note that my suggestion follows from what the method currently does, not from what it should or might do in the future, and as such the YAGNI principle (which is very valid indeed) does not apply here.

Adding an unused parameter is confusing. People might call that method assuming this feature will work.

I wouldn’t add it. It is trivial to later add it using a refactoring and mechanically fixing up the call sites. In a statically typed language this is easy to do. Not necessary to eagerly add it.

If there is a reason to have that parameter you can prevent the confusion: Add an assert in the implementation of that interface to enforce that this parameter be passed as the default value. If someone accidentally uses that parameter at least he will immediately notice during testing that this feature is not implemented. This takes away the risk of slipping a bug into production.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật