Thoughts on How to Develop

 ・ 9 min

A broken laptop computer sitting on top of a table

Development Dilemma#

Lately, I've been thinking a lot about how to develop in a more structured way. I want to build a feature, but I keep questioning what order to build it in and whether what I'm doing is right — and because of that, I'm not actually writing much code.

Rather than typing away, I keep thinking "there must be a better way to do this..." and I'm starting to wonder whether this question even has an answer, or if I'm just chasing some fantasy because I don't want to start. I asked ChatGPT a similar question, and the answers were things I already knew, but it made me reflect on whether I've actually been doing them.

GPT told me to approach it through development processes, architecture, collaboration methods, and tool selection. Let me share what AI had to say. Of course, GPT's answers didn't solve my dilemma. What I really wanted to know was the order in which to build features.


Question#

I've learned programming languages, but I'm always struggling with how to develop. I never feel like I'm developing in an efficient and correct way. Use all the knowledge you have to tell me the most efficient development approach for building app/web services.

GPT's Answer#

1. Requirements Definition and Planning#

  • Goal Setting: Clearly define the app's purpose and key features. Set specific goals for solving user problems.
  • User Stories: Write user stories thinking about what actions users will take in the service. This helps concretize requirements functionally.
  • MVP (Minimum Viable Product) Definition: Implementing all features at once is inefficient. Define a minimum viable product with only core features and use it to quickly get user feedback.

2. Architecture Design#

  • Modularization: Design each feature as an independent module. This increases code reusability and maintainability.
  • Clean Architecture: Adopting clean architecture (or layered architecture) clearly separates business logic, UI, and data access, making code management easier.
  • API Design: Design RESTful or GraphQL APIs so that the frontend and backend can communicate clearly. API documentation is essential.

3. Technology Stack Selection#

  • Frontend: Choose one of frameworks like React, Vue.js, or Angular. Each framework has different learning curves, performance, and community support, so choose based on your project's nature.
  • Backend: Choose a backend framework like Node.js, Django, Ruby on Rails, or Spring based on the performance and scalability you need.
  • Database: Choose between relational databases (MySQL, PostgreSQL) and NoSQL databases (MongoDB, Firebase) based on your requirements.
  • Cloud Services: Use cloud platforms like AWS, Google Cloud, or Azure to automate infrastructure and easily manage deployments.

4. Version Control and Collaboration Tools#

  • Git: Use Git for version control. Strengthen collaboration through GitHub, GitLab, Bitbucket, etc.
  • CI/CD: Build CI/CD pipelines with tools like Jenkins, GitLab CI, or CircleCI to set up automated testing and deployment.
  • Project Management: Use tools like Jira, Trello, or Asana to manage tasks and maximize team productivity.

5. Testing#

  • Unit Tests: Verify that each feature works as intended through unit tests. Use testing frameworks like Jest, Mocha, or JUnit.
  • Integration Tests: Test interactions between modules. Use Postman, Newman, etc. for API testing.
  • Automated Tests: Automate repetitive tests using tools like Selenium or Cypress.

6. Deployment and Operations#

  • Deployment Automation: Automate deployment through CI/CD pipelines, aiming for zero-downtime deployment.
  • Monitoring: Monitor application status in real-time using monitoring tools like New Relic, Datadog, or Prometheus to quickly identify issues.
  • Logging: Manage and analyze logs using tools like Logstash, Kibana, or Grafana.

7. Continuous Improvement#

  • Incorporate User Feedback: After deploying the MVP or initial version, actively incorporate user feedback to improve features.
  • Code Refactoring: Periodically refactor code to improve maintainability and reduce technical debt.
  • Performance Optimization: Continuously monitor application performance and optimize databases, caching, and code as needed.

I didn't want to create files and type simple repetitive code, so I looked into code generation packages like freezed and json_serializable, and also tried VS Code snippets. There's also something called Macros being developed for Flutter, which I think could make things even more convenient.

I need to have a lot of conversations with myself, but I think this is what I want:

  • I want to build a service, but I'm in a situation where I have to build everything myself
  • For app release and continuous operation, what to do first: planning, design, development
  • I want to make quick decisions on each item and move forward
  • I want to be productive in development, which has a lot to do
  • I'm looking into folder structures, Flutter development architectures, state management, and useful packages to boost development productivity
  • I want to improve code quality by combining development architecture and state management

I chose Flutter for app development. But while developing with Flutter, I started looking for something like the MVC pattern I used during Spring development. Flutter has several development architectures, and among them, I liked the Feature-First architecture that can be connected with Riverpod. I'm not great at using this architecture yet, but I thought I'd try applying it.

But every time I build something, I obsessively wonder whether I'm following the architecture correctly. This made me think there must be an order for building features while following this architecture properly. Should I build the UI first, or build the Model first and then the features separated from UI, and finally build the UI last? With these thoughts, I also asked GPT about the approach below.


Question#

Development architecture requires creating a lot of files and folders. Tell me the order for building a Feature-First Architecture.

GPT's Answer#

In Feature-First Architecture, having many files and folders is natural, but to manage them efficiently, the order of setting up the structure and adding features is important. By following this order, you can reduce project complexity and expand gradually. Below is a step-by-step order to consider when building a Feature-First Architecture.

1. Setting Up the Basic Folder Structure#

First, you need to establish the overall project structure. This clarifies where code will be located within the project.

lib/
├── features/
   ├── feature_name/
   ├── data/
   ├── domain/
   └── presentation/
├── core/
   ├── common_widgets/
   ├── exceptions/
   ├── network/
   └── theme/
└── main.dart

At this stage, it's important to set up the folders for each feature and the core folder. As features are added, create the appropriate subfolders for each feature.

2. Feature Development Order#

When adding individual features, create and implement the necessary files and folders at each step. The order for adding features is as follows:

  1. Feature Requirements Analysis and Planning
    • Define the role and requirements of the feature.
    • Identify key use cases and user flows to determine what data and logic are needed.
  2. Implement the Domain Layer
    • Entities: Define the main entities (business models) used in the feature.
      • Example: lib/features/login/domain/entities/user.dart
    • Use Cases: Write use cases that handle business logic.
      • Example: lib/features/login/domain/use_cases/login_use_case.dart
        The reason to implement the domain layer first is that you can design the data and presentation layers around the core logic of the feature.
  3. Implement the Data Layer
    • Repositories: Implement the interfaces defined in the domain layer to manage data sources.
      • Example: lib/features/login/data/repositories/auth_repository_impl.dart
    • Data Providers: Implement classes responsible for API calls or local database access.
      • Example: lib/features/login/data/providers/auth_api_provider.dart
    • Models: Define models for data used from APIs or local data.
      • Example: lib/features/login/data/models/user_model.dart
        At this stage, connect data sources with the domain layer so the feature actually works.
  4. Implement the Presentation Layer
    • State Management: Implement state management using Riverpod. Define the necessary state and state notifiers containing business logic.
      • Example: lib/features/login/presentation/state/login_state.dart
    • Screens: Implement the screens (UI) for the feature. Define how the UI changes based on state.
      • Example: lib/features/login/presentation/screens/login_screen.dart
    • Widgets: Implement reusable widgets for the feature.
      • Example: lib/features/login/presentation/widgets/login_form.dart
        The presentation layer is where you implement the screens and interactions that the user ultimately sees.
  5. Write Unit Tests
    • Write unit tests for each layer. Prioritize tests for the domain and data layers.
    • Example: lib/features/login/domain/use_cases/login_use_case_test.dart
    • Example: lib/features/login/data/repositories/auth_repository_impl_test.dart
      This process ensures that each layer's functionality works correctly independently.
  6. Feature Integration and Review
    • Verify that the domain, data, and presentation layers are well integrated, and validate through unit tests and integration tests.
    • Start with small feature units initially, and iteratively review and improve the overall structure and design.

3. Common Code and Refactoring#

As features are added, commonly used code will increase. For this, refactor common logic, utilities, widgets, etc. into the core folder to modularize them.

  • Common Widgets: Place widgets usable across multiple features in core/common_widgets/.
  • Network Management: Modularize API call logic in core/network/.
  • Exception Handling: Manage common exception handling in core/exceptions/, and utilize it from each feature.

4. Project Expansion and Maintenance#

  • When adding new features, repeat the order described above to gradually expand the project.
  • If issues or improvements are found in existing features, improve them through refactoring.

5. Automation and Deployment#

  • CI/CD Setup: Automate testing and building on code push to manage the project reliably.
  • Release Management: Manage through version control to ensure new features are properly released.

It's important to start with key features, expand gradually, and maintain project quality through testing and refactoring.


Wrapping Up#

I recently read a development-related post on Threads, and this line really hit me hard. I'm also working on something solo and it's true that things are falling behind.

Startups with beautiful code go bankrupt.

Overthinking for too long seems like a shortcut to poor results. I need to fix this habit that I don't consider to be a good one.

Having high code quality is great, but I need to prioritize getting the work (business) done first.


Treat people as if they were what they ought to be, and you help them to become what they are capable of being.

— Johann Wolfgang von Goethe


Other posts
Hongong Computer Architecture & OS - Week 6 Study Group Homework 커버 이미지
 ・ 4 min

Hongong Computer Architecture & OS - Week 6 Study Group Homework

The U.S. Constitution 커버 이미지
 ・ 18 min

The U.S. Constitution

Creating Custom Snippets in VS Code 커버 이미지
 ・ 3 min

Creating Custom Snippets in VS Code