0

For most apps I've built which deal with CRUD operations, I end up two very similar UI pages: one for the creation of the object, one for updating it.

An example would be StackExchange's UI for creating a question and the UI for editing a question (but very similar, but slightly different).

How can we minimize duplication of UI code in this situation?

(I mostly program for the web with React but I am also interested in generic advice.)


Clarification: I have used strategies to minimize code duplication in the backend/db layer (e. g. using ORMs, UPSERT statements) which let me share the data plumbing code between add and update operations.

However, in most projects I've worked on, the frontend code for add and update screens was duplicated.

3
  • 2
    I took the freedom to replace "What are programming patterns" by a more specific wording, since question which are "shopping for patterns" will usually downvoted, closed and deleted here very quickly. Still, your question does not tell us what kind of prior research you did before asking, what you found and why it did not meet your needs. That is something lots of our community members expect for a good question.
    – Doc Brown
    Aug 9 at 17:00
  • The more I read this the more I think the answer is simply "forms". But I suspect that isn't what you had in mind. Consider an edit that would show me what more you're looking for. Aug 9 at 17:13
  • The answer depends almost entirely on which framework/language you are using, and how familiar you are with it. And it takes a lot of practice to find the perfect spot of abstraction to remove duplicated code without the abstraction becoming unmanageably complex. My advice is go slow and don't beat yourself up with there is some degree of code duplication. Simple non-DRY code with good comments about where the related copies live is far better than complex UI generation frameworks which are very DRY but also very hard to understand and apply edge cases to.
    – GHP
    Aug 14 at 18:24

3 Answers 3

2

I am working regularly on an application where the issue is solved as follows:

  • there is only one form for editing an object (in some database), it is used regardless if you insert a new object or update it

  • for creation of a new object, before the form is opened, a new record with some default values is inserted first into the database, but marked as "not yet finished" by some attribute.

  • then, the related form is opened for editing, so the mandatory attributes of the newly created object can be entered by the user

  • When the user presses "Save", the state will be changed from "not yet finished" to "finished", and the changes will be saved. When the user presses "Cancel", however, the unfinished record will be deleted from the database.

That way, only one form is required for both, editing and creation.

In fact, my above description contains some simplifications:

  • in my real case, the "not yet finished" state is determined by using a negative ID instead of a positive one, but this is an unimportant implementation detail

  • when querying the database for available objects/records of a certain type (in use cases apart from CRUD), one has to sort out the unfinished objects

  • objects usually contain multiple records, a parent record and several child records (in DDD, this would be called an "aggregate"). A form loads them all, and when it comes to saving, the parent record will be updated, the child records are usually deleted and re-inserted again

  • the creation process must take the database constraints into account, or the constraints must be chosen not too restrictive. For example, if you want all objects of a certain type having a unique name in the database which the user has to care for on initial creation, either the creation process has to generate an artifical unique name before doing the first insert (and let the user then replace that name), or one has to allow uniqueness except NULL values for the name, or one uses no database constraint for ensuring uniqueness at all, letting the application handle this.

0

Generally I make all my Add methods "Upsert" unless there is some specific requirement which prevents it.

This way you only need to conditionally change the title and maybe the submit button label of the same page to make Create and Edit UIs.

However, as your app gets more detailed I would expect the Create and Edit use cases to diverge more and more. You will probably end up with two pages eventually whatever you do.

0

For the most basic of CRUD applications, the difference between the "create" page and "edit" page is mostly:

  • Page title.
  • Where the "Cancel" button takes you.
  • An Id of some sort which informs the system which record needs updating.
    • Or the lack of an Id which informs the system this object has not been persisted yet.
    • Or a Boolean flag that indicates whether you are in create or edit mode.
  • Some processing logic when the form is submitted.
    • Which for a purely front end web app might just be a difference in API endpoints.

Just as you said, the form remains largely the same. The trick is to decompose the create and edit pages into a "page" and "form" component.

The page is not reusable. It pertains to a specific use case. The form component would encompass the form fields, basic validations, and some way to retrieve the form values as some structured object that your web API can consume.

Specifically, React has the concept of components, which can be nested inside each other. In your case, the "create page" component could have a "form" component nested inside. Same for the edit page.

This allows you to reuse UI elements and validations between the two use cases.

Reference: Your First Component.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.