45

This is a question about how to work in teams.

Recently I worked on my first larger (~80 classes, Java) programming project with a team of 6 people, though only 4 of us were continously working on the code. We distributed the work to be done early on and at some point I needed to call a method that was not yet implemented by one of my co-programmers. How is the recommended way to deal with this?

Options I saw, though I don't really like any of them:

  1. Writing myself a //TODO and revisiting this line of code later to check if the method has been implemented in the meantime.

  2. Asking the corresponding team member to implement that now.

  3. Throwing a custom runtimeException with a clear description of what is not yet implemented. (At least we don't have to search for a long time to find out what is missing)

  4. Adding the needed method to their class and writing them a //TODO in the message body, possibly also send them a quick message about that change. (Now it's not my problem anymore, but this can cause annoying merge conflicts if they were working on this method in the meantime)

  5. Defining abstract classes or interfaces for everything before actually writing the code that does the work. (Didn't work too well because these interfaces were often changed)

  • 51
    I think that workflow where you need a method written by someone else is not right one. You are working on a feature. If that feature requires a method, YOU implement it. If two people are to implement single feature, they either pair, or integrate and communicate so frequently that it almost looks like they pair. – Euphoric Dec 28 '17 at 17:31
  • 8
    @Euphoric Multiple times have I come across a situation where a quite big new feature was to be developed within a relatively short timeframe and as such the user interface, business logic and API layers had to be split into different tasks to be worked on simultaneously, otherwise the deadline could never be met. That is exactly where a person working on the UI should only declare data access methods and commands to BL as interfaces and let the other people work on the implementation, while working solely on the UI. – Andy Dec 28 '17 at 18:06
  • 15
    @DavidPacker What you describe is not the only way to resolve that problem. Vertical slices, frequent integration, small features are all better solutions than Horizontal slices with each person working on separate part. – Euphoric Dec 28 '17 at 18:09
  • 3
    @Euphoric I cannot agree more with you. When possible, we go with the way of stripping the complex new feature of non-critical parts (i.e. those which would only improve the UX but are not necessary right away). Sadly, sometimes the options you mentioned, neither the feature stripping, are not possible. Business say, developers do. So while your points are solid, there is also likelihood someone would and will encounter a situation where some kind of feature work-split has to be done in order to fulfil the business' needs. – Andy Dec 28 '17 at 18:20
  • 2
    what about talking to him how he wants to handle it? – Aganju Dec 29 '17 at 4:18
5

It is an interesting question and the answer might be easier than you think.

Simply put, write tests that validate your assumptions. It does not matter if you do the implemenation or your fellow programmers

The long answer.

Any of the options that you list are somewhat passive and require you to come back and revisit the code (if any exists) sooner or later.

  • Comments need to be read and handled by your counterpart responsible for the implementation. Your code cannot be compiled in the meantime. If you check such state in a code repository, your continuous integration pipeline will not work, and it is bad practice anyways ... never check in broken code
  • Runtime exceptions seem better, but are still toxic, because your fellow programmer could assume that the implementation was already done without checking, leaving the system in an unstable state as well. If the method is triggered not so often, it could lead to broken production code ... bad practice as well ... never check in "not-implemented" exceptions
  • Waiting for your fellow programmers for implementation of the methods or a stub is also daunting. It breaks your workflow and the workflow of your fellow programmers. What happens if they are sick, in a meeting a g, on coffee break, do you want to spend your time waiting? ... don't wait for somebody if you don't have to
  • implement the missing methods definitely the best way to go forward. But what happens if your implementation does not satisfy the whole use case and your fellow programmers need to amend or change it? How do you and they make sure that it is still compatible with your intended? The answer is easy again. Write tests that verify, describe and document your intentions. If the tests break, it is easy to notice. If changes in that method need to be done that break your feature ... you see it immediately. You both have a reason to communicate and decide what to do. Split the functionality? Change your implementation, etc... never check in code that is not sufficiently documented by tests

To achieve a sufficient level of testing I would suggest you have a look at two disciplines.

  1. TDD - test-driven development - this will make sure you describe your intent and sufficiently test it. It also gives you the possibility to mock or fake methods and classes (also by using interfaces) that are not implemented yet. The code and tests will still compile and allow you to test your own code in isolation of your fellow programmers' code. (see: https://en.wikipedia.org/wiki/Test-driven_development )

  2. ATDD - acceptance test-driven development - this will create an outer loop (around the TDD loop) which helps you to test the feature as a whole. These tests will only turn green when the whole feature is implemented, thus giving you an automatic indicator when your fellows complete their work. Quite neat if you ask me.

Caveat: In your case, I would only write simple acceptance tests and not try to bring in too much of the business side, as it would just be too much to start with. Write simple integration tests that put together all the parts of the system the feature requires. That's all that is required

This will allow you to put your code in a Continous Integration pipeline and produce a highly reliable implementation.

If you want to get further in that topic check the following links:

105

Ask for stubs.

Or write them yourself. Either way, you and your coworkers need to agree on the interfaces and how they're intended to be used. That agreement needs to be relatively solidified so you can develop against stubs -- not to mention, so you can create your own mocks for your unit testing...

  • 25
    ^^ This. If you're properly using interfaces, you shouldn't need the implementations until the other guy is done writing them. – Robert Harvey Dec 28 '17 at 19:40
  • 13
    And to further Robert's comment, if you're not properly using interfaces in a project specifically designed to be split among multiple people, well you're gonna have a bad time... – corsiKa Dec 29 '17 at 1:35
  • 1
    It's a shame that Java doesn't have header files. In the C/C++ world you can work out your APIs and write all your headers first, a lack of implementation then becomes a problem for the linker. (Slight simplification, the ABI needs to remain constant as well for it to just be a linker matter). – Wes Toleman Dec 29 '17 at 7:09
  • 16
    @WesToleman Amusingly, one of my favorite things about Java is that it doesn't have header files. The "interfaces" that Robert and corsiKa mentioned fill that role perfectly. You work out your APIs first, write the interfaces, and a lack of concrete implementation isn't a problem for the compiler. – GrandOpener Dec 29 '17 at 7:58
  • 1
    @WesToleman Does that work out well for you? In my ears that sounds a hell of a lot like water-fall style, and my guess is that you have to update the interface further when you realize that you've misse this "important parameter"? – netigger Dec 29 '17 at 19:00
6

In your situation, I would talk to the team member with responsibility for that function. It may be that they are in a position to prioritise the development of that function so you are able to start using it sooner.

I would steer clear of your fourth option. You've written all your code, and as you say, you no longer consider it to be your problem. Your colleague then writes the implementation of the function, and no longer considers it to be their problem. Who's actually going to test that the code YOU wrote works correctly?

  • You should ask for the API for that function which should result in one or more interfaces. It might be a good idea to do this together, as you will need to use this interface so you can design the initial test cases based on your input. The actual implementation can then come later (including possible API changes) – Thorbjørn Ravn Andersen Dec 30 '17 at 5:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.