Please feel free to suggest a better name or way of explaining this question - I wasn't quite sure what to call it.
The situation is one that may just come under the heading of "be organized" but I often find myself passing around either big blobs of data or many smaller sub-blobs (blob in the non-technical meaning of the word =o), to be used in various parts of my web apps.
For example, building a small task manager that allows someone to create a task that ends up being represented like this:
- With a title, initial date, user, client, etc. (simple attributes).
- Zero or more temporal expressions that represent "schedules" for when the task must be done - periodically, by day of week, by day of month, etc.
- A tree-list of sub-tasks that can be nested to any level.
This is all easy enough to represent in the database with a few tables.
It's also easy enough to pack into a series of arrays and pass around (for example, passing an array of a task template, subtasks, and schedule data via JSON to a jQuery object that will build a tasklist on the client side.
Between creating, updating, displaying, etc., the tasks, tasklists, etc., there are any number of places where I might find myself passing a big collection of data from one place to another (especially working with AJAX with much client-side processing), and it often looks pretty much the same - just a big array that says "here is the data for your task and related 'stuff'".
How do you (or would you) keep this organized? For example, below is an array that has been pulled out of a "Task Template" object, and will be passed via JSON to a JS object that will dynamically build and display a list of tasks on the client side.
I guess the question is whether and how you define the structure of such an 'object' outside the database, code, etc., and how you document it.
For example, while the nested subtasks are pretty explanatory (and duplicate data, available only for convenience), it's not readily apparent that the "SubTasks" array MUST have each subtask appear in the array AFTER (higher index than) it's parent subtask, and BEFORE (ie: with lower index than) any child subtasks, so that they arra can be processed in order with the assurance that each subtask can be appended to it's already existing parent subtask.
There are a number of rules like that here, and if a "relatively" similar array is used in 9 different places, documenting in comments/class documentation, etc sort of ends up sucking.
[43] => Array
(
[Meta] => Array
(
[SubTaskCount] => 6
[TemporalExpressionCount] => 3
[NumInstances] => 0
[OutOfSync] => 0
)
[Fields] => Array
(
[UserID] => 1
[ClientID] => 1
[StatusID] => 1
[Title] => Keep Testing
[Body] => How are you? Because I am a potato.
[UserName] => Wheatley
[ClientName] => Wheatley Laboratories
[BodyHTML] => Etc.
)
[Sched] => Array
(
[TemporalExpressions] => Array
(
[0] => Array // Every Monday every month
(
[type] => dw
[ExpressionID] => 1
[ord] => 0
[day] => 1
[month] => 0
)
[1] => Array // Every Tuesday every month
(
[type] => dw
[ExpressionID] => 2
[ord] => 0
[day] => 3
[month] => 0
)
[2] => Array // The last of every month
(
[type] => dm
[ExpressionID] => 3
[day] => -1
[month] => 0
)
)
[TaskInstances] => Array
(
// This would have data on "complete" status of tasks by date...
)
[InitialDate] => 2011-12-02
[DueTime] => 14:55:00
[SchedDates] => Array
(
[1322812800] => 2011-12-02
[1323072000] => 2011-12-05
[1323244800] => 2011-12-07
[1323417600] => 2011-12-09
[1323676800] => 2011-12-12
// ... List of dates between externally defined date range parameters...
)
)
[SubTasks] => Array
(
[1355] => Array
(
[SubTaskID] => 1355
[ParentST] =>
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1356] => Array
(
[SubTaskID] => 1356
[ParentST] => 1355
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1357] => Array
(
[SubTaskID] => 1357
[ParentST] => 1355
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1358] => Array
(
[SubTaskID] => 1358
[ParentST] => 1355
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1359] => Array
(
[SubTaskID] => 1359
[ParentST] =>
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1360] => Array
(
[SubTaskID] => 1360
[ParentST] =>
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
)
[SubTasksNested] => Array
(
[1360] => Array
(
[SubTaskID] => 1360
[ParentST] =>
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1359] => Array
(
[SubTaskID] => 1359
[ParentST] =>
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1355] => Array
(
[SubTaskID] => 1355
[ParentST] =>
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
[SubTasks] => Array
(
[1358] => Array
(
[SubTaskID] => 1358
[ParentST] => 1355
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1357] => Array
(
[SubTaskID] => 1357
[ParentST] => 1355
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
[1356] => Array
(
[SubTaskID] => 1356
[ParentST] => 1355
[RootT] => 43
[UserID] => 1
[Title] => New Subtask Title
[Body] =>
[DueDiff] => 0
[UserName] => Eli
)
)
)
)
[TemplateID] => 43
)