Practical Use of Lightning Data Service
The biggest advantage of the LDS to me are below which avoids some apex code
1.Not having to write code to check for CRUD/FLS in LDS .In apex you would end up writing this yourself .This will lead to consuming more CPU limits , deployment time and additional support cost .
2.Not having to write test classes .In apex you will end up needing test code .
3.Also quite useful when you have to have fields on the layout based on the page layout assigned to user .
Makes it real easy with layoutType=FULL option as below
<force:recordData aura:id="recordLoader"
recordId="{!v.recordId}"
layoutType="FULL"
targetRecord="{!v.record}"
targetFields="{!v.simpleRecord}"
targetError="{!v.recordError}"
recordUpdated="{!c.handleRecordUpdated}"
/>
Real life it is useful if you have to simple form with insert,update or delete operations or if you need a detail view of the record on your custom component .Specifically while dealing with one record at a time .
For any complex use cases and collection types prefer @AuraEnabled methods and apex
I haven't used LDS yet to replace Apex code, or for inserting/updating records. But an incredibly useful ability I found is using LDS to monitor for updates to records and then acting upon that update.
For example, I have one component that presents multiple records in kanban type view. I use an aura:iteration to create an LDS instance for each record, with a handler for updates.
If the user makes an update to any of those records anywhere in the app, even if it's using standard built-in functionality (such as an update record screen somewhere else), my component can detect those updates via LDS and refresh itself.
Using this approach, I was able to do away with things like firing events from all other customer components when records were updated, or trying to catch force:refreshView events if a standard component made an update (which never worked very well).
This is an ability in LDS that cannot be reproduced using Apex code. Even though trigger code might run when records are updated, there's no way for them to tell a component that the update occurred unless you publish a Platform Event as part of trigger execution, and the component listens for the Platform Event. I find LDS to be simpler right now than trying to wire up Platform Events, even though LDS's scope of listening to updates is only within the same user's app, and Platform Events could be more global.
Anyway, hope this info helps.