DataTable and supporting modules were rebuilt in version 3.5.0. The new architecture is not fully backward compatible with versions 3.4.1 and prior. This guide is to help answer questions that may come up when upgrading to the latest version.
This guide focuses on 3.4.1 API compatibility. It does not describe new features added in 3.5.0 (there were a lot). Refer to the updated DataTable user guide for that.
        If you are unable to upgrade due to unresolvable issues, you can use the
        datatable-deprecated
        module suite, which is equivalent to the 3.4.1 implementation.  But be
        aware that these modules will be removed in a future version of YUI.
    
Overview of API changes from 3.4.1
The architectural change resulted in the deprecation, replacement, or removal of nearly all attributes and properties from the version 3.4.1 implementation. Here is a quick list of the changes most likely to affect your upgrade:
- 
        new Y.DataTable.Base(...)→new Y.DataTable({ ... })
- 
        new Y.DataTable.Base({ columnset: [ ... ], recordset: [ ... ] });→ new Y.DataTable({ columns: [ ... ], data : [ ... ] });
- 
        (cells rendered as HTML by default) →
        columns: [ { key: 'email', allowHTML: true }, ... ]
- 
        table.plug(Y.Plugin.DataTableSort)→ (plugin not needed) See below or read the user guide
- 
        table.plug(Y.Plugin.DataTableScroll, ...)→ (plugin not needed) See below or read the user guide
- 
        columnset: [ { formatter: function (o) { ... } } ]→ (formatter changes) See below or read the user guide
- 
        record.getValue(fieldName)→record.get(fieldName)
Instantiation and Instance Configuration Changes
    As of 3.5.0, Y.DataTable is no longer just a namespace, but is now the
    preferred constructor for DataTable instances.
var table = new Y.DataTable({
    // Column configuration looks much the same except the attribute name
    columns: [
        { key: 'name', label: 'Name', sortable: true, width: '200px' },
        {
            key: 'birthdate',
            label: 'Age',
            sortable: true,
            formatter: function (o) {
                var now = new Date(),
                    years = now.getYear() - o.value.getYear();
                now.setYear(o.value.getYear());
                return years - (o.value < now);
            }
        }
    ],
    // Passing in row data looks much the same except the attribute name
    data: [
        { name: 'Tom Brokaw',     birthdate: new Date(1940, 1, 6) },
        { name: 'Peter Jennings', birthdate: new Date(1938, 6, 29) },
        { name: 'Katie Couric',   birthdate: new Date(1957, 1, 7) },
        { name: 'Brian Williams', birthdate: new Date(1958, 4, 5) },
        { name: 'Matt Lauer',     birthdate: new Date(1957, 11, 30) }
    ]
}).render('#over-there');
    The Y.DataTable.Base class still exists, but is useful primarily as a
    superclass for extension.  The attributes of Y.DataTable.Base are the
    same as those of Y.DataTable, less any attributes added by class
    extensions (see below).
Configuration attributes that have changed from 3.4.1 are:
| Attribute | Change | 
|---|---|
| columnset | Deprecated.  Use columns.columnsetwill
            behave as an alias forcolumnsfor a short time, but will be
            removed in future versions. See below. | 
| recordset | Deprecated.  Use data.recordsetwill
            behave as an alias fordatafor a short time, but will be
            removed in future versions. See below. | 
| tdValueTemplate | Removed. Use column formatter,cellTemplate,
            or override theY.DataTable.BodyViewinstance'sCELL_TEMPLATE. | 
| thValueTemplate | Removed. Use column label,headerTemplate,
            or override theY.DataTable.HeaderViewinstance'sCELL_TEMPLATE. | 
| trTemplate | Removed. Use column nodeFormatteror override
            theY.DataTable.BodyViewinstance'sROW_TEMPLATE. | 
Table and Cell Formatting Changes
The following changes apply to table and column cell formatting:
- 
        If cell values include HTML, add allowHTML: trueto the column configuration. HTML is escaped by default for security.
- 
        o.classnamesin the formatter parameter is nowo.className.
- 
        o.columnin the formatter parameter is now the plain JavaScript object containing the column configurations rather than aY.Columninstance.
- 
        o.recordin the formatter parameter is now a Model instance instead of aY.Recordinstance.
- 
        this.createCell(o),o.td,o.tr, ando.tbodyno longer exist on the parameter passed toformatterfunctions. UsenodeFormatters.
- 
        o.headersis now ato.column._headers, but is read-only forformatterfunctions. If you need to change the cell's headers attribute, add a {placeholder} for them to a customcellTemplatefor the column, or use anodeFormatter.
- 
        The table's tdValueTemplate,thValueTemplate, andtrTemplateno longer exist, nor do the DataTable instance propertiestdTemplateandthTemplate. Useformatterstrings or functions to customize the content of data cells in a column andlabelstrings to customize the content of header cells. To modify the<td>or<th>entirely, set the column configurationcellTemplateorheaderTemplate.
3.4.1
var table = new Y.DataTable.Base({
    columnset: [
        { key: "id",
          emptyCellValue: "<em>new</em>" },
        { key: "name" },
        { key: "price", formatter: "${value}" },
        { key: "price",
          formatter: function (o) {
            if (o.value > 4) {
                o.classnames += "spendy";
            }
            return '$' + o.value.toFixed(2);
          }
        },
        { key: "price",
          formatter: function (o) {
            var cell = this.createCell(o);
            if (o.value > 4) {
                cell.addClass('spendy');
            }
            cell.setContent('$' + o.value);
          }
        }
    ],
    data: [
        { id: 1, name: "Bread", price: 3.45 },
        { id: 2, name: "Milk",  price: 4.99 },
        { id: 3, name: "Eggs",  price: 2.75 }
    ]
}).render("#over-there");
    3.5.0
var table = new Y.DataTable({
    columns: [
        { key: "id",
          emptyCellValue: "<em>new</em>",
          allowHTML: true },
        { key: "name" },
        { key: "price", formatter: "${value}" },
        { key: "price",
          formatter: function (o) {
            if (o.value > 4) {
                o.className += "spendy";
            }
            return '$' + o.value.toFixed(2);
          }
        },
        { key: "price",
          nodeFormatter: function (o) {
            if (o.value > 4) {
                o.cell.addClass('spendy');
            }
            o.cell.setContent('$' + o.value);
            return false;
          }
        }
    ],
    data: [
        { id: 1, name: "Bread", price: 3.45 },
        { id: 2, name: "Milk",  price: 4.99 },
        { id: 3, name: "Eggs",  price: 2.75 }
    ]
}).render("#over-there");
    Read the Formatting Cell Data section in the DataTable user guide for more details.
Column Configuration Changes
    As of 3.5.0, the Y.Columnset and Y.Column classes have been deprecated.
    The DataTable configuration attribute columnset has been deprecated in
    favor of the columns attribute.  The columnset attribute has been
    retained for partial backward compatibility.  Columns are now
    stored as an array of simple JavaScript objects rather than class instances.
var table = new Y.DataTable({
    columnset: [ 'name', 'age' ],
    ...
});
// columnset passes through to columns
var columns = table.get('columns'); // => Array, not Columnset instance
table.set('columnset', [ ... (new column configurations) ... ]);
// backward compatibility stops here
var columnset = table.get('columnset'); // => Array, not Columnset instance
    Strings passed into the column configuration will become objects with those
    strings as the value of the key property.
See the Column configuration section in the user guide for more details.
Row Data Configuration Changes
    As of 3.5.0, DataTable uses Y.Model and Y.ModelList to store row data.
    Y.Recordset and Y.Record haven't been deprecated, but may be in the
    future.  The recordset attribute has been retained for partial
    backward compatibility.  The data ModelList can be assigned to, but
    retrieving the value of the attribute will return the ModelList, not
    a Y.Recordset instance.
var table = new Y.DataTable({
    columnset: [ ... ],
    recordset: [
        { name: 'Tom Brokaw',     birthdate: new Date(1940, 1, 6) },
        { name: 'Peter Jennings', birthdate: new Date(1938, 6, 29) },
        { name: 'Katie Couric',   birthdate: new Date(1957, 1, 7) },
        ...
    ]
});
// recordset passes through to data.
var data = table.get('data'); // => ModelList instance
table.set('recordset', [ ... (new data records) ... ]);
// backward compatibility stops here
var recordset = table.get('recordset'); // => ModelList, not Recordset
    Y.Record stores all values in a single attribute named data, where Y.Model uses individual attributes for each value.
3.4.1
// Y.Record
var record = oldTable.get('recordset').item(0);
record.getValue('birthdate'); // => Date(1940, 1, 6)
record.get('data').birthdate; // => same
    3.5.0
// Y.Model
var model = newTable.getRecord(0);
model.get('birthdate'); // => Date(1940, 1, 6)
    
    This change breaks column/record keys that contain periods.
    Attribute treats periods as subproperty indicators, so periods are no
    longer allowed;  use an alternate character.  In the case of remote data
    that is parsed by Y.Plugin.DataSourceJSONSchema, use the locator
    configuration for fields to extract subproperty values.  A benefit to doing
    this is that you may not need to specify a column label.
3.4.1
var table = new Y.DataTable.Base({
    columnset: [
        { key: "id" },
        { key: "Product.Name",  label: "Product" },
        { key: "Product.Price", label: "Price" }
    ],
    caption: "Price List"
}).plug(Y.Plugin.DataTableDataSource, {
    datasource: new Y.DataSource.IO({
        source: "/service/price-list"
    }).plug(Y.Plugin.DataSourceJSONSchema, {
        schema: {
            resultListLocator: "items",
            resultFields: [
                { key: "id" },
                { key: "Product.Name" },
                { key: "Product.Price" }
            ]
        }
    })
});
table.datasource.load(...);
    3.5.0
var table = new Y.DataTable({
    columns: [ "id", "Product", "Price" ],
    caption: "Price List"
}).plug(Y.Plugin.DataTableDataSource, {
    datasource: new Y.DataSource.IO({
        source: "/service/price-list"
    }).plug(Y.Plugin.DataSourceJSONSchema, {
        schema: {
            resultListLocator: "items",
            resultFields: [
                { key: "id" },
                { key: "Product",
                  locator: "Product.Name" },
                { key: "Price",
                  locator: "Product.Price" }
            ]
        }
    })
});
table.datasource.load(...);
    If you are using any Recordset plugins, your code will need to be modified. Some loss of functionality may result.
- Y.Plugin.RecordsetSort
- 
        This plugin was formerly applied by the Y.Plugin.DataTableSortplugin to the DataTable's Recordset instance. Sorting is now enabled through a class extension.
- Y.Plugin.RecordsetFilter
- 
        The default ModelList implementation only supports a filter(function)method. If you were relying on this plugin'sgreporrejectmethods or thefilter(key, value)functionality, you will need to replace that functionality through custom code.
- Y.Plugin.RecordsetIndexer
- 
        The default ModelList implementation does not support multiple custom
        indexes, though it does maintain an index for id(or another, assigned primary key attribute) andclientId. See the Model user guide for more information on customizing the primary index. If multiple custom indexes are required, DataTable supports the use of custom Model subclasses to store the record data.
See the Data Configuration section of the DataTable user guide for more information.
Feature Configuration Changes
    The two optional features available for DataTable in 3.4.1 were sorting and
    scrolling.  Both features exist in 3.5.0, but are implemented as class
    extensions for Y.DataTable.  Simply including the datatable-sort or
    datatable-scroll module in your use(...) will enable the feature for
    all new DataTables.
YUI().use('datatable-sort', 'datatable-scroll', function (Y) {
    // Create a DataTable that is sortable by the "name" column, and is
    // configured to scroll vertically within 300px.  Because scrollable is
    // set to "y", not "x" or "xy", it will not attempt to scroll horizontally.
    // Instead the table width will be set to 100%.
    var table = new Y.DataTable({
        columns   : [ { key: 'name', sortable: true }, ... ],
        data      : [ ... ],
        scrollable: "y",
        height    : "300px",
        width     : "100%"
    });
    // No plugins necessary
    table.render('#over-there');
});
Column Sorting Changes
    Configuring sortable columns may be done as it was in 3.4.1, by setting the
    column configuration property sortable: true, but may also be done by
    setting the DataTable's sortable configuration to true or an array of
    column names.
3.4.1
// Assumes use('datatable-sort') or use('datatable')
var table = new Y.DataTable.Base({
    columnset: [
        { key: "id" },
        { key: "name", sortable: true },
        { key: "price", sortable: true }
    ],
    recordset: [
        { id: 1, name: "Bread", price: 3.45 },
        { id: 2, name: "Milk",  price: 4.99 },
        { id: 3, name: "Eggs",  price: 2.75 },
        ...
    ],
    caption: "Price List"
});
table.plug(Y.Plugin.DataTableSort);
table.render('#sort-demo');
// Sorting API is on the Recordset's plugin
table.get("recordset").sort.sort("name");
    3.5.0
// Assumes use('datatable-sort') or use('datatable')
var table = new Y.DataTable({
    columns: [ "id", "name", "price" ],
    data: [
        { id: 1, name: "Bread", price: 3.45 },
        { id: 2, name: "Milk",  price: 4.99 },
        { id: 3, name: "Eggs",  price: 2.75 },
        ...
    ],
    sortable: [ "name", "price" ]
});
table.render('#sort-demo');
// Sort method is on the instance
table.sort("name");
//-------------------------------------------------
// Alternate methods
//-------------------------------------------------
var table = new Y.DataTable({
    columns: [ "id", "name", "price" ],
    data: [ ... ],
    sortable: true // makes all columns sortable
});
// OR the old way works, too
var table = new Y.DataTable({
    columns: [
        { key: "id" },
        { key: "name", sortable: true },
        { key: "price", sortable: true }
    ],
    data: [ ... ]
});
    
    Since there is no plugin, the sort method is now on the DataTable instance
    itself, as are the related attributes.  In particular, the lastSortedBy
    attribute from the plugin implementation has been replaced by the sortBy
    attribute added by the class extension.
    As of 3.5.0, DataTables configured with sortBy will have their rows
    sorted automatically upon inserting into the table.  You do not need to
    presort data for the initial render.
    The trigger attribute of the sorting plugin was not retained in
    the 3.5.0 class extension.  If you require an alternate triggering
    event, detach and replace the table's _sortHandle property after
    render().
var table = new Y.DataTable({ ... }).render("#over-there");
table._sortHandle.detach();
table._sortHandle = table.delegate(["dblclick", "keydown"],
    table._onUITriggerSort, ".yui3-datatable-sortable-column", table);
See the Column Sorting section of the user guide for details about the APIs and attributes.
Scrollable Table Changes
    Like sorting, the scrolling functionality has been moved to a class
    extension, making it unnecessary to plug the DataTable instance with the
    (now deprecated) Y.Plugin.DataTableScroll plugin.
    datatable-scroll is no longer included in the datatable
    rollup, and must be explicitly included in your use() statement.
    To enable scrolling in 3.5.0, set the table's scrollable attribute to "x",
    "y", or "xy".  The configured height and width for the DataTable are
    used to bound the overall widget dimesions.  Scrolling will only be applied
    on the axis or axes specified in scrollable.  However, if scrollable is
    set to "y", but the height isn't set, it will not be made scrollable.
    Likewise for "x" and width.
3.4.1
// Assumes use("datatable-scroll") or use("datatable")
var table = new Y.DataTable.Base({
    columnset: ["id", "name", "price"],
    recordset: [
        { id: 1, name: "Bread", price: 3.45 },
        { id: 2, name: "Milk",  price: 4.99 },
        { id: 3, name: "Eggs",  price: 2.75 },
        ...
    ]
});
table.plug(Y.Plugin.DataTableScroll, {
    height: "175px"
});
table.render("#over-there");
    3.5.0
// Assumes use("datatable-scroll")
var table = new Y.DataTable({
    columns: ["id", "name", "price"],
    data: [
        { id: 1, name: "Bread", price: 3.45 },
        { id: 2, name: "Milk",  price: 4.99 },
        { id: 3, name: "Eggs",  price: 2.75 },
        ...
    ],
    scrollable: "y",
    height: "175px"
}).render("#over-there");
    Markup and CSS Changes
    DataTable in 3.5.0 applies more CSS classes to Nodes, stamps fewer nodes
    with guid ids, and does not render header and cell liner <div>s.
Below are examples of the same table rendered in 3.4.1 and 3.5.0. The 3.5.0 table has comments indicating markup added by feature modules.
3.4.1
<div id="(guid)" class="yui3-widget yui3-datatable">
  <div id="(guid)" class="yui3-datatable-content">
    <table>
      <caption>
        Example table with simple columns
      </caption>
      <colgroup>
        <col>
        <col>
        <col>
      </colgroup>
    <thead class="yui3-datatable-columns">
      <tr id="" class="yui3-datatable-first yui3-datatable-last">
        <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-id" abbr="">
          <div class="yui3-datatable-liner">
            id
          </div>
        </th>
        <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-name" abbr="">
          <div class="yui3-datatable-liner">
            name
          </div>
        </th>
        <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-price" abbr="">
          <div class="yui3-datatable-liner">
            price
          </div>
        </th>
      </tr>
    </thead>
    <tbody class="yui3-datatable-msg">
    </tbody>
    <tbody class="yui3-datatable-data" id="(guid)">
      <tr id="(guid)" class="yui3-datatable-even">
        <td headers="(guid)" class="yui3-column-id">
          <div class="yui3-datatable-liner">
            1
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-name">
          <div class="yui3-datatable-liner">
            Bread
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-price">
          <div class="yui3-datatable-liner">
            3.45
          </div>
        </td>
      </tr>
      <tr id="(guid)" class="yui3-datatable-odd">
        <td headers="(guid)" class="yui3-column-id">
          <div class="yui3-datatable-liner">
            2
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-name">
          <div class="yui3-datatable-liner">
            Milk
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-price">
          <div class="yui3-datatable-liner">
            4.99
          </div>
        </td>
      </tr>
      <tr id="(guid)" class="yui3-datatable-even">
        <td headers="(guid)" class="yui3-column-id">
          <div class="yui3-datatable-liner">
            3
          </div>
        </td>
        <td headers="(guid)" class="yui3-column-name">
            <div class="yui3-datatable-liner">
              Eggs
            </div>
          </td>
          <td headers="(guid)" class="yui3-column-price">
            <div class="yui3-datatable-liner">
              2.75
            </div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
3.5.0
<div id="(guid)" class="yui3-widget yui3-datatable">
  <div id="(guid)" class="yui3-datatable-content">
    <table cellspacing="0" class="yui3-datatable-table" id="(guid)">
      <caption class="yui3-datatable-caption">
        Price List
      </caption>
  
      <!-- colgroup only renders if datatable-column-widths is use()d.
           Note, datatable-column-widths is included in the datatable rollup -->
      <colgroup id="(guid)">
        <col>
        <col>
        <col>
      </colgroup>
  
      <thead class="yui3-datatable-columns" id="(guid)">
        <tr>
          <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-first-header yui3-datatable-col-id" scope="col" data-yui3-col-id="id">
            id
          </th>
          <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-col-name" scope="col" data-yui3-col-id="name">
            name
          </th>
          <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-col-price" scope="col" data-yui3-col-id="price">
            price
          </th>
        </tr>
      </thead>
      <!-- The message tbody only renders if datatable-message is use()d.
           Note, datatable-message is included in the datatable rollup -->
      <tbody class="yui3-datatable-message" id="(guid)">
        <tr>
          <td class="yui3-datatable-message-content" colspan="3">
            No data to display
          </td>
        </tr>
      </tbody>
      <tbody class="yui3-datatable-data">
        <tr id="(guid)" data-yui3-record="record_1" class="yui3-datatable-even">
          <td class="yui3-datatable-col-id  yui3-datatable-cell">
            1
          </td>
          <td class="yui3-datatable-col-name  yui3-datatable-cell">
            Bread
          </td>
          <td class="yui3-datatable-col-price  yui3-datatable-cell">
            3.45
          </td>
        </tr>
        <tr id="(guid)" data-yui3-record="record_2" class="yui3-datatable-odd">
          <td class="yui3-datatable-col-id  yui3-datatable-cell">
            2</td>
          <td class="yui3-datatable-col-name  yui3-datatable-cell">
            Milk
          </td>
          <td class="yui3-datatable-col-price  yui3-datatable-cell">
            4.99
          </td>
        </tr>
        <tr id="(guid)" data-yui3-record="record_3" class="yui3-datatable-even">
          <td class="yui3-datatable-col-id  yui3-datatable-cell">
            3
          </td>
          <td class="yui3-datatable-col-name  yui3-datatable-cell">
            Eggs
          </td>
          <td class="yui3-datatable-col-price  yui3-datatable-cell">
            2.75
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
What Did I Miss?
Obviously, there were a lot of changes to DataTable from 3.4.1 to 3.5.0. It's entirely likely that I have missed something here. If you experience trouble with your upgrade and find this migration guide is missing something important, please file a ticket and I'll update it as soon as possible.
Additional resources to help with the upgrade include the forums, and the #yui IRC channel on freenode.net.