The beautiful part about Lightning is that you're allowed to separate the main logic from the UI in various ways, and reuse the parts you like as you'd like. For example, in a multistep wizard, your main component might look like this:
<aura:component controller="ABCController">
<aura:attribute name="record" type="Map" default="{}" />
<aura:attribute name="page" type="Integer" default="1" />
<aura:attribute name="content" type="Aura.Component[]" default="[]" />
{!v.content}
<ui:button disabled="{!v.page eq 1}" label="Previous" action="{!c.goBack}" />
<ui:button disabled="{!v.page eq 7}" label="Next" action="{!c.goNext}" />
<ui:button disabled="{!v.page ne 7}" label="Finish" action="{!c.finish}" />
</aura:component>
At this point, you can specify the content that should be currently displayed by using $A.createComponents:
$A.createComponents(
[["c:wizardContentPage1", { record: component.getReference("v.record") }]],
function(components) {
component.set("v.content", components);
}
);
Most likely, the setup would be more complicated, as you might need to arrange for an event, validation, etc, but the main trick here is Aura.Component[]
. Using this technique, you can keep the majority of the UI in separate components for legibility, and those can have extended controllers that do other things, and you can communicate with the main component via events.
As far as reusing the same component in a page, it's simply a matter of putting that component into an app:
<aura:application extends="force:slds">
<aura:attribute name="id" type="String" access="global" />
<c:mainComponent recordId="{!v.id}" />
</aura:application>
Which you provide the record Id just like in Visualforce:
/c/wizard.app?id=0012...
The application automatically parses the query string and puts the values into exposed attributes.
Without knowing the full scope of what you're trying to do, this advice is pretty generic, but the main takeaway is that it is possible to arrange for most of the logic to be kept in a single component, and move the UI into a separate component (or as many as you need).
As far as best practices go, you should be aiming to build reusable components as much as possible. UI elements, for example, can often be decomposed into smaller components that can be reused frequently. Don't worry too much about getting it "just right," just try to make the code reasonably legible (e.g. if your component is 2,000 lines big, it's probably too big) and reasonable practical.