Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Designing static - dynamic table and implementing in c++

Status
Not open for further replies.

simluk

Programmer
Aug 16, 2005
10
LT
Hi to all
In advance: sorry for my english

Problem:
Design table that contain columns with data that is taken from database.
Using designed structure there should be possibility to create statical table - that consist of fixed number of columns and rows.
I also work with filer, so designed structure has to have the ability to file itself.
My solution for now:

Class BaseCell(abstract);
Class TextCell : BaseCell;
Class CellContainer(abstract): BaseCell;
Class Table : CellContainer;
Class Row : CellContainer;
Class Column(abstract) : CellContainer;
Class Header : CellContainer;
Class Footer : CellContainer;
Class StaticColumn : Column
Class DynamicColumn : Column

CellContainer contains array of BaseCell pointers. So i get recursive structure.

Table consist of header, footer and columns.

Columns consist of header, footer and TextCells

Header and footer can be more than one cell, it could contain several rows with several cells

I can not have multiple pointers to same object because i have to file only one object.

My question would be:
Should i declare header and footer class as containment classes or should i separate them?
Does this recursion makes sence?
Can CellContainer class know something about its child classes?
Can CellContainer child class know about "brother" (other child classes)?

Many thanx for any assistance!
 
You might want to look at the Composite pattern. If so, check this thread: thread678-1105658

If you implement this as the composite pattern, your BaseCell is Component, your TextCell is a Leaf, and your CellContainer, Row, Table, and Column are all Composites. Your Header and Footer appear to be Leaf classes, in that they do not contain any other classes.

If you have any questions on reading UML, feel free to ask. I believe that all your questions will be clarified if you apply this pattern to your problem domain. (Yes, this recursion does make sense!)

HTH

Bob
 
Thanks Bob for reply.
Other thing that i can't figure out is how could i separate header and footer class? As u wrote, they actualy are leaf classes, but they also can contain several TextCell objects.. so they are also containers???
Also i know that column, row or table can only have one header and footer. So now i am all mixed up. How this class diagram should look like???

And also another question: this column - row - cell structure, what relation should i have between these classes? Its not clear to me because column and row always contains one same cell. I understand that it's implementation question (not design pattern) but i would be greateful if someone could help me out.

Thank u people ;)

Simas
 
Now, to unmix yourself up, first read this.
Then, see if you can put together a class diagram. Start with the classes involved, then attempt the links, then the multiplicities. (Most of your questions are about mulitiplicity, and reading the above will answer them.) Use the Composite pattern. (Leave off Header and Footer until you have the basic cell row col table structure in place.) As for your question about the relation between the row-col-cell structure, first figure out what is composed of which, then we'll look into relating the rows and columns. (For now, just keep in mind that tables are composed of rows and columns and cells, and that rows and columns only relate indirectly through the table, and that you will use constraints to define which cells go where.)

Do all that, and we'll talk about headers and footers.

Bob
 
I understand the basics of uml, but what mixes me up is this column row table relation.
As i understand, i have 3 options:

1) to have table-comlumn-cell structure, excluding rows, where table contains columns ("one to many") and columns contains cells ("one to many" or sometimes "many to many" when cells are merged through several columns(this is another problem)). Rows could be constructed through the table (getRow(index)) which would use cells from columns to construct row(use some kind of algorythm).

2) to have table-row-cell structure, identical to previous solution but with rows insted of columns

3) to have two dimentional cell array in a table and use columns and rows as logical cell containers. Use them just to set some properties to arrays of cells in a table.

These r my solutions.. i think there r number of other solutions far better than mine ;), but thats what i can think of for now.

Thanks for help
 
Option 2 sounds better.

Most tabular data originates from databases, and so fits well with the table-row-cell structure. (HTML tables, for example). If 'cell' is a composite as BobRodes suggests, then it could contain another table which could allow you to handle your other complex issues.
 
This table that i try to implement consist of two states:
- creating table template - just seting columns(object properties) that has to be displayed, setting up header and footer
- and concrete table creation - getting objects, their properties and filling table with data.

I think, option that u choose totaly depends on features that u have to implemen but in my case i prefer table-column-cell. Correct me if i am wrong, but u can have column consisting of leaf cells, header and footer, where header and footer are also containers that consist of rows(or columns, or even other table).

Other problem that i can't solve is what should i do with merged cells.. For example if i merge two cells from different columns, which cell should i destroy and which column should contain merged cell?
 
I'd argue that table-row-cell is easier to manage if you want to merge two cells from different columns, as then you only need to merge two cells in the same row, rather than two cells from different columns.

An alternative to destroying one of the cells in a merged cell, consider making a merged cell that contains the original cells, but uses them as the source of its display data rather than displaying them as cells. That way, you don't lose the original cells in case you need to do an 'undo'.
 
If u choose table-row-cell in that way u will have same situation merging two cells from different rows. Same problem.

As for merging two cells from differen columns, i could do as u say, but this is what i will get:

Before merge:
column_1 contains cell_1
column_2 contains cell_2

After merge:
merged_cell contains cell_1 and cell_2
column_1 contains merged_cell or(and?) cell_1
column_2 contains merged_cell or(and?) cell_2

Do i get dublicates or what? What should i use here? Tags..?
 
If I suggested that cell was a composite, I'm unclear as to where, steve, and perhaps you can show me where I gave that idea unintentionally.

Simluk, if you apply the composite pattern, then it's clear that cell is a leaf, and row and column are both composites. Since a row contains cells that a column doesn't, and vice versa, neither contains the other.

So, your composites are table, row, column, your leaf is cell. Tables are composed of cells; they do not derive this relationship from the fact that they are composed of rows and columns that are composed of the same cells. Their composition relationship to cell is direct. Tables are also composed of rows and columns, independently of the fact that they are composed of cells.

The fact that the composites share the same cells is irrelevant to the structure.

As for Header and Footer, is a header a row? Is a footer a row?

Try that, and see how it works for you. As for my continued mention of the Composite pattern: the point about design patterns is that they are distilled from a lot of experience over time as generalizations, or patterns, of usage that come up time and time again in software architecture. Most of the time, a given architectural situation represents an instance of one of these patterns, and implementation along the lines of the defined pattern leverages a great deal of trial and error experience.

HTH

Bob
 
As for merging cells, it's just like on any spreadsheet: you can either copy the value to another cell, or reference the source cell in the new cell. If there are usage reasons to do either, both should be supported.

Regarding your 3 options, I'd say 3 is the closest to what I'd do. Rows and columns have arrays of references to cells. Tables have an array of cells. (Interestingly, it's not clear to me that this array has to be two dimensional: why? Perhaps it's more efficient to have only 1 dimension.) So, a cell has (among others) two attributes: a reference to a column entity and a reference to a row entity. Rows/cols also have an array of references to cells.

One more thing. It's easy to confuse inheritance hierarchies and associations. Easy way around that is to work on the inheritance hierarchy first and then work out the associations.

So, my first stab at your hierarchy is as follows. First, there's the base abstract class, we'll just borrow from the Composite pattern and call it Component. From Component derive Composite and BaseCell. From Composite derive Table, BaseRow, and Column. From BaseRow derive HeaderRow and Row. From BaseCell derive HeaderCell and Cell.

As for associations: Composite relationship between Component and Composite. That's it! That's the beauty of the composite pattern. If you think about it, all of the varied associations between rows, columns, tables and cells can be expressed in this way. Since every entity derives from component, all composites are composed of components, whether composites in their own right or leaves. So, tables are composed of rows, columns and cells, rows are composed of cells, cells aren't composed of anything, since they are leaves.

HTH

Bob

Bob
 
In first message i wrote that table, column and row contains cellBase - which can be cell(leaf) or other container. So any column(row, column) could be constructed from several columns (rows, tables).

I'm not sure if i uderstand your point Bob.. U say that:

table 1 -> 0..* cell
table 1 -> 0..* column 1 -> 0..* cell
table 1 -> 0..* row 1 -> 0..* cell

So every cell in table will also be in specific row and column? I'm sorry, its a bit confusing for me.. Could you be more specific or give me any example?

As for header and footer, they could contain rows (or columns) that would have number of cells. Table could also have header - container of columns headers.


Simas
 
Ok, let's make sure I'm clear on how you're putting tables and rows and columns and cells together.

First, I can see now that my description implies that a row can be composed of tables, for example, when it can't. So, I take back what I said about the associations. You can more narrowly define the associations by running them between table and row, table and column.

Table has an array of cells.
Table has an array of columns.
Table has an array of rows.
Rows and columns have arrays of cells.
Cells have a row attribute and a column attribute.
So yes, every cell in a table will be in a specific row and column.

Table 1 -> 1..* Cell
Table 1 -> 1..* Row
Table 1 -> 1..* Column

Row 1 -- 1..* Cell
Column 1 -- 1..* Cell

Note that the associations between cells and rows/cols are bidirectional, since each has to know which of the other it's associated with. Furthermore, a table isn't a table without cells, rows and columns, so these are black diamond composition associations. Same with row/col to cell. As for multiplicity, I put ones instead of zeros because a table will always have one cell, one row and one column at least.

Constraints: All cells in table are in one and only one row and one and only one column. Each row has the same number of cells. Each column has the same number of cells. The number of cells in a row times the number of cells in a column equals the number of cells in the table with which they are associated.

Some Attributes:
Table has an array of cellids, an array of rowids, and an array of colids.
Cell has a cellid (a key), and a rowid and colid (foreign keys), and contents.
Row has a rowid and an array of cellids.
Column has a colid an array of cellids.

Some Methods:
Table has CreateCell():CellId, DeleteCell(CellId), Deleterow(RowID), DeleteCol(ColID). DeleteCell removes the CellID from the array and destroys the cell instance, and is not to be confused with deleting the contents of the cell. DeleteRow iterates through the row to be deleted's cellid array, and calls deletecell for each one of them, and then destroys the row instance. Table would also have createrow and createcolumn.

Row and Column have things like show and hide.

I can't think of a behavior that Cell has offhand, that doesn't imply a simple attribute change.

As for header and footer, they get created and destroyed in much the same way as ordinary rows. They have cells, too, but they're always the top ones, and they're accessible in different ways. For example, they might not be focusable.

I'm looking over your post again. I'm not quite sure why you're confused about a cell being in a specific row and column. If I haven't explained it yet, let me know and I'll give it another go.

HTH

Bob
 
Thanks for explain. This time its much clearer for me what your solution would be. So class diagram for this would be:

[tt]
1 1..*
Container ---> Cell(leaf)
^
/|\
|
-----------|----------
| | |
Column <-- Table --> Row
[/tt]

But is this a composite pattern? And i think its harder to solve more complex issues having such constraints.
Other question would be: how can u handle cell merging with this structure?
And one more thing, u told that table has method DeleteRow. Ok. Now if u delete row in a table u have to complete these steps:
1) Get all cell indices in this row;
2) Remove row id from table and delete row object;
3) From table cell id array remove row(deleted) cells;
4) Loop through all columns and remove cell ids that were removed.

Is this correct? Well... maybe it does make sence if u think for a while.. :)
As for header and footer i can have several rows. So u mean, i should have something like header row or header column which table could contain (similary like row and column)?

As i wrote this message, i finaly begin to understand this logic. But still, if i had structure where any cell could be table, row or column, i think it would be more dynamic. Maybe its just a begginer mistake..

Sorry for writing at night, i think i am on the other side of planet ;)


Simas
 
Not quite. The top Container, and Cell, both derive from the same class, called Component in the Composite pattern. Note that containers can contain containers, not just cells. Work out the diagram so that you don't have to show the concept of containership differently between containing leaves and containing containers. You see that tables work with rows/columns and cells in the same way, and your diagram doesn't quite show that. So, derive a superclass called Component in your diagram, and show that Containers both ARE Components and can contain them too. This is the Composite pattern.

If you want to solve more complex issues in new ways, go right ahead!! You might find something new.

You talk about cell merging. That's alterations of state through behavior: in other words you use methods to alter attributes.

As for DeleteRow, you're getting the hang of this! Put all of that detail into a Comment.

As for header and footer, yes to that too. Look for the things that are similar in HeaderRow and Row, and generalize a superclass from which both derive.

As for your last, I don't understand. How can a cell be a table?

Bob
 
I understand that i have to have base cell class which would be super class for leaf and container. That is what i ment when i told that cell (base cell) can be table (row, column or leaf cell).

Befor posting here i was trying to implement a bit different structure, where i had:

Table <>---> Column <>---> Cell

Table and column are containers and have array of poiners to BaseCell (base class). In this case table doesn't contain rows. But i can also define constraints of how to form row from table's columns by having (for example) method GetRow. Row would be also BaseCell container.

Basicaly i think we are talking about same things but in different way.. U can implement table in n different ways, but the base would be the same if composite pattern is used.

When (if) i finish my implementation then i think i will find number of better ways to do that ;)


Simas
 
<Table and column are containers and have array of poiners to BaseCell (base class).

See, I don't buy that as the simplest way to do things. You have to put a lot of constraints on which type of basecell can be pointed to by which type of basecell, and my feeling is that that will be needlessly complicated. You even give a good example of that complication. To do a GetRow, you have to go to a different object for each cell. So, you have to keep track of two sets of arrays, the array of columns in the table and the array of cells in the column. If you go to the table for your row, you only have one array to deal with.

Another problem with using row or column as an intermediary container for cells is that you can't easily implement same behaviors for a row and a column in the same way. If, say, you use a column to hold cells, but not a row, you're going to have to do something very different to implement show and hide behavior for each.

Finally, that model isn't a Composite pattern, since Row isn't a "basecell container" (in my terms, a composite), since it has an association with a class that it doesn't contain (columns) and is not contained by it either.

So, I don't see how you can implement the table in different ways, and still be consistent with the Composite pattern. Perhaps you can explain further.

Here's my case for using software design patterns in general. Software design patterns evolve because of two phenomena: certain problems in design occur throughout the software architecture domain, and the intuitive (first pass) models for those problems don't work as well as expected. Patterns represent the result of incremental improvements in models of these problems over time. (This suggests that patterns are counterintuitive to some degree--a very important point.)

That said, I find that I'm suspicious of intuitive models that run counter to models in established patterns. I find patterns to be tried and true ways of accomplishing certain recurring goals in software architecture. (The "arch" is a good example of the same in building architecture.)

So that's the case for patterns, take it or leave it. :)

Best regards,

Bob

Bob
 
I agree that it's not the easiest way to do things, but i think its more flexible than using table row and column structure. For example if i want to have nested table or if i want to merge cells. Its easier to manipulate cell objects in a table, having only columns as real cell containers.

As for complexity, i dont think that monitoring column and row indexes is easier. If u remove cell from table, u also have to find and remove its index from row and column objects. Remove row, and u have to deal with table columns. Its the same, isn't it? As for me, i do have to define constraints for row and column classes, but its imposible to design a structure that hasn't constraints. Maybe implementation of row and column methods will be different, but that is why i have different classes for that.

And i don't understand why its not a composite pattern. Having table which contains columns and columns that contain cells and (or) other columns or even rows is worth calling it composite pattern ;)

Maybe i am wrong about all this, but i think its still posible to create table that way. Maybe its not the easiest way, but i will try (not just because i started it already ;)).

Actually the task is more of creating table out of columns to put data, maybe thats why i'm so related to table - column - cell model.

As for design patterns, i am just a begginer. Never red a book about patterns, altough i'm trying to find suitable for me. Any suggestions?

Thanks for help

Simas
 
Read the GOF (Gang of Four) Design patterns book, that's the main one.

A table is composed of columns is composed of cells pattern works as a composite pattern, as long as you don't need to use any sort of row functionality. As soon as do, your design fractures. If you never need to do anything to a row, your design holds up.

Therefore, I don't believe your design will hold up. Feel free to implement it and tell me I'm wrong afterwards. :)

Good Luck,

Bob
 
As Bob says, the GoF book is the daddy. However, it's getting a bit long in the tooth, and some of the patterns like Iterator have been implemented in the Java and .NET framework classes. It also uses OMG notation rather than UML. I recently bought Design Patterns in C# [Steven John Metsker, Addison Wesley] which takes the GoF patterns book and updates it with all examples in C# and all diagrams in UML. He also has little tests as you go through, with answers in the back.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top