Перейти к основному содержимому

Tutorial

Let's look at the principles of Feature-Sliced Design by building a simple web notes app. We will start theoretical, so don't worry if you don't know the stack. Here's how the app looks like, nice and simple, only for mobile:

Notes application screens Notes application screens

Decomposing the user interface

Most user interfaces are made up of distinct pages or screens, so this is an easy starting point for decomposition. We have just 2 screens here (told you it'd be simple!):

  1. Note list screen, where the notes are presented for detailed reading, where you can create a new note and sign in for synchronizing your notes.
  2. Note creating/editing screen, where you can edit the note's title and body, as well as delete it.

The login form is a part of the note list screen.

Business domain

The business domain is a fancy word for "what your application is about". In our case, it's notes. Therefore, an entity in this domain is the note itself. This is important because we can think of our application as a set of actions on entities:

  • reading a note;
  • creating/editing a note;
  • deleting a note;
  • uploading your notes to the cloud.

Pay attention to this last action. Our application does it automatically, but it's an action on behalf of the user and it delivers value for them. Therefore, it is a feature of our product.

Individual UI elements that are important to the business

If an element is important to the business, it must either be a representation of one of the entities or an action on them. In FSD, we call them entities and features respectively.

Let's locate such elements in our UI. Try it yourself first on the image below, and then drag the slider to reveal our solution.

tip

Useful questions to ask yourself when determining whether an element is an entity or a feature:

  • If an element is non-interactive:
    • Is this element representing some real-life object or concept? If yes, it's an entity.
    • Does this element identify you as a user? If yes, it's an entity.
  • If an element is interactive:
    • Does this element allow you to change something about an entity? If yes, it's a feature.
    • Does this element allow you to change your own identity (e.g., a login button)? If yes, it's a feature.
    • Does this element tell you something about the state of the action you're taking on an entity? If yes, it's part of a feature.
    • Does this element help you accomplish your human goal when you use it? If yes, it's a feature.
Screens, annotated with entities and features
Screens, unannotated

Drag the slider above from right to left!

Combining entities and features into meaningful blocks

Now that we have our entities and features identified and separated, we can start putting them together. In Feature-Sliced Design, we do this in the compositional layers: Widgets and Pages. As you may have guessed from the name, one is used to compose blocks of the UI, and the other is used to compose entire screens. Let's identify the blocks that make up our application:

Screens, annotated with widgets
Screens, unannotated

We have three different blocks here: a note card, a note editor, and the application bar. A note card, for example, is made up of a UI skeleton, the data, and an external link component to handle navigation on click. It is a small component, so we can compose it on the Widgets layer:

Note card composition Note card composition

The note editor in our case is a complete page, so we will compose it on the Pages layer. It's also more complicated, so there are more components involved. We have a skeleton again, the data to populate the editor, the editor component itself, a link button from our internal UI kit that handles navigation, and a button to delete the note, coupled with the click handler:

Note editor composition Note editor composition

Note that we have a UI skeleton component inside pages/edit-note/ui/, and the composed component is also in this folder. Sometimes it's more practical to have smaller components like this simply alongside the main component of the slice as opposed to having them in layers below (like the note card skeleton in the previous example).