4

I need some help with a correct design.

I have a class called BufferManager. The push() method of this class reads data from a source and pushes it to a buffer repeatedly until there is no more data left in the source.

There are also consumer threads that read data from this buffer, as soon as new data arrives.

There is an option to sort the data before it comes to buffer. What I do right now is that BufferManager, instead of pushing data to the buffer, pushes it to another "sorting" buffer and starts a sorting thread. SorterManager class reads the data, sorts it in files and push()es the sorted data into the buffer.

There will be a bottleneck (I use merge sort with files) but this is something I can't avoid.

This is a bad design, because both BufferManager and SorterManager push data to a buffer (that consumers read from). I think only BufferManager should do it.

How can I design it?

2
  • Can you provide more details on what the sorting is for? For example, is this priority sorting to ensure higher priority items get removed from the buffer earlier?
    – JoeGeeky
    Dec 23, 2011 at 8:42
  • sorting is string-based sort, I need to sort all input from source and only after every thing is sorted I can push() data to buffer for consumer to read, actually as I start merge sorting the files I can start pushing the results to buffer
    – kenny
    Dec 23, 2011 at 9:07

3 Answers 3

1

A lot of design problems go away when you use composition instead of inheritance.
For clarity, let's say the source you're reading from is a socket.
You can create an abstract Reader with read() method that reads a single string.
It will have 2 subclasses - SocketReader and FileReader.
Add a Reader data member to BufferManager initialized in the c'tor.
To create a 'regular' BufferManager, create a BufferManager and pass it a SocketReader instance in the c'tor.
Instead of creating a SorterManager, create a BufferManager and pass it a FileReader instance in the c'tor.
The push() method should be implemented as follows:

while (!mReader.eof()) {
  String s = mReader.read();
  writeToBuffer(s);
}

For summary - you will have a single BufferManager class which will work with sockets or sorted files depending on the Reader you initialize it with.

1

Let's start from what we have?

  • A source of list exists somewhere.
  • The items of this list should be sorted.
  • There is a destination buffer which is consumed by others.

'It is a must's:

  • Sort process must precede source extraction.
  • Destination buffer flush must precede sort process.
  • All work must done asynchronously.
  • But steps of process must be preserved.

Process steps:

  1. Get source list.
  2. Sort it.
  3. Write to buffer.

Design Steps:

  1. SourceManager
  2. SortingManager
  3. BufferManager

Eventually here is your solution from my point of view:

  1. When SourceManager finishes its work; it passes list to SortingManager
  2. SortingManager sorts the list taken asynchronously.
  3. When SortingManager finishes its work; it passes sorted list it produced to BufferManager.
  4. BufferManager behaves like a data server to all other consumer threads by its buffer.

Warnings:

  1. Do not give two responsibilities to a single class. All monads of a program must serve for only and only one responsibility.

  2. While programming asynchronous tasks; make distinction between tasks which must not start unless another task finishes and task which starts and runs independently relying on none of other tasks.

0
0

Rambling answer follows :-)

  1. I'm nit picking here, but your push() method should probably split out the reading of data from a source into another method, i.e. Follow the Single Responsibility Principle (SRP)

  2. What sort of buffer do you have? I'm curious since you state that you have multiple consumers. I assume you're using a java.util.concurrent (j.u.c) data structure?

  3. Depending on your buffer data structure, you might be able to push to the buffer in a sorted manner (whatever sorted means to you)

  4. I think your design problem comes from higher up in the method call stack. I think you're trying to model this:

    BufferManager manager = new BufferManager();
    manager.getDataFromSource();
    if (sortData) {
        manager.sortData();
    }
    
    manager.push();
    

Above is very much a strawman as the BufferManager methods could easily be static (depending on your mutability traits) and it depends on how you're reading in the data (bulk read or firehose style).

Hope that helps a little! And apologies for the non styling of the code block, not sure what's going on there, couldn't get the usual tool to work.

4
  • yes for buffer I use java.util.concurrent. I read the data from source string by string and push(currentString). So getting data and pushing must work in parallel and not like you offered. In the scenario without sorting the push method executes in loop: String str =getNextString(); pushtobuffer(str); So I can't split
    – kenny
    Dec 23, 2011 at 11:58
  • So what exact data structure are you using? Hmm, this calls for an embedded drawing tool in StackExchange so we can exchange diagrams. Dec 23, 2011 at 18:05
  • what drawing tool in StackExchange ? I am not familiar with it
    – kenny
    Dec 23, 2011 at 22:05
  • There is no drawing tool :), its a feature request I'll send in! Dec 25, 2011 at 13:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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