Hari ke-15/200: Membangun Aplikasi Full-Stack β Perjalanan dan Pembelajaran
Selamat datang kembali ke perjalanan 200 hari saya menuju penguasaan full-stack! Hari ke-15 merupakan tonggak penting dalam eksplorasi teknologi dan pengembangan web. Dalam postingan ini, saya akan membagikan apa yang saya pelajari, tantangan yang saya hadapi, dan solusi yang saya temukan. Saya juga akan membahas beberapa praktik terbaik yang saya adopsi untuk memastikan kode yang bersih, efisien, dan mudah dipelihara.
Daftar Isi
- Pengantar: Mengapa Full-Stack?
- Tinjauan Proyek: Apa yang Sedang Dibangun
- Teknologi yang Digunakan (Stack Pilihan)
- Pembaruan Kemajuan: Apa yang Sudah Selesai
- Tantangan dan Solusi: Memecahkan Masalah
- Kode Hari Ini: Contoh Implementasi
- Pembelajaran Utama: Wawasan Baru dan Konsep yang Dipahami
- Praktik Terbaik: Kode Bersih dan Pemeliharaan
- Sumber Daya yang Digunakan: Tautan dan Referensi Bermanfaat
- Langkah Selanjutnya: Rencana untuk Hari ke-16
- Kesimpulan: Refleksi dan Motivasi
1. Pengantar: Mengapa Full-Stack?
Sebelum kita masuk ke detail teknis, mari kita tinjau mengapa saya memilih jalur full-stack. Menjadi pengembang full-stack memberi Anda kemampuan untuk memahami dan berkontribusi pada setiap lapisan aplikasi, dari front-end yang dihadapi pengguna hingga back-end yang mengelola data dan logika bisnis. Ini memungkinkan untuk:
- Kemandirian: Mampu membangun fitur lengkap sendiri.
- Pemecahan Masalah Holistik: Memahami bagaimana berbagai bagian aplikasi berinteraksi dan dengan demikian memecahkan masalah lebih efektif.
- Fleksibilitas Karir: Pilihan karir yang lebih luas dan kemampuan untuk beradaptasi dengan berbagai peran dalam tim pengembangan.
Dengan menguasai full-stack, saya bertujuan untuk membangun aplikasi yang komprehensif, mudah digunakan, dan efisien. Ini adalah investasi jangka panjang yang akan menuai hasil yang signifikan dalam karir saya.
2. Tinjauan Proyek: Apa yang Sedang Dibangun
Proyek yang saya kerjakan adalah aplikasi TODO List sederhana. Tujuannya bukan hanya membuat aplikasi yang berfungsi, tetapi juga untuk mengaplikasikan prinsip-prinsip pengembangan yang baik, praktik terbaik, dan arsitektur yang scalable. Fitur utama yang direncanakan adalah:
- Membuat Tugas: Pengguna dapat menambahkan tugas baru dengan judul dan deskripsi.
- Menampilkan Tugas: Semua tugas akan ditampilkan dalam daftar yang terorganisir.
- Menandai Tugas Selesai: Pengguna dapat menandai tugas sebagai selesai.
- Menghapus Tugas: Pengguna dapat menghapus tugas yang tidak lagi dibutuhkan.
- Mengedit Tugas: Pengguna dapat memperbarui judul dan deskripsi tugas.
Proyek ini dirancang untuk menjadi landasan yang kuat untuk proyek-proyek yang lebih kompleks di masa depan.
3. Teknologi yang Digunakan (Stack Pilihan)
Untuk proyek ini, saya menggunakan stack teknologi berikut:
- Front-end: React.js (untuk UI yang interaktif dan komponen reusable).
- Back-end: Node.js dengan Express.js (untuk membangun API yang kuat dan scalable).
- Database: MongoDB (database NoSQL yang fleksibel dan mudah diskalakan).
- Version Control: Git (untuk melacak perubahan kode dan berkolaborasi dengan pengembang lain).
- Hosting: Heroku (untuk deployment yang mudah dan manajemen aplikasi).
Alasan pemilihan stack ini adalah karena popularitas, komunitas yang besar, dan ketersediaan sumber daya pembelajaran yang melimpah. Stack ini juga sangat cocok untuk membangun aplikasi web modern dan scalable.
4. Pembaruan Kemajuan: Apa yang Sudah Selesai
Pada hari ke-15, saya fokus pada implementasi fitur dasar untuk membuat, membaca, memperbarui, dan menghapus (CRUD) tugas. Berikut adalah rinciannya:
- Back-end API:
- Membuat endpoint untuk membuat tugas baru: API menerima data tugas (judul, deskripsi) dan menyimpannya ke database MongoDB.
- Membuat endpoint untuk mengambil semua tugas: API mengambil semua tugas dari database dan mengembalikannya dalam format JSON.
- Membuat endpoint untuk memperbarui tugas berdasarkan ID: API menerima ID tugas dan data yang diperbarui, lalu memperbarui tugas yang sesuai dalam database.
- Membuat endpoint untuk menghapus tugas berdasarkan ID: API menerima ID tugas dan menghapusnya dari database.
- Front-end (React):
- Membuat komponen untuk menampilkan daftar tugas: Komponen ini mengambil data tugas dari API dan menampilkannya dalam daftar yang terorganisir.
- Membuat komponen untuk menambahkan tugas baru: Komponen ini memungkinkan pengguna untuk memasukkan judul dan deskripsi tugas, lalu mengirimkan data ke API untuk membuat tugas baru.
Meskipun masih banyak pekerjaan yang harus dilakukan, fondasinya sudah kuat dan saya merasa percaya diri untuk melanjutkan ke fitur-fitur yang lebih kompleks.
5. Tantangan dan Solusi: Memecahkan Masalah
Sepanjang hari ini, saya menghadapi beberapa tantangan, dan berikut adalah bagaimana saya mengatasinya:
- Masalah CORS:
- Masalah: Saat mencoba mengirim permintaan dari front-end (React) ke back-end (Node.js), saya mengalami kesalahan CORS (Cross-Origin Resource Sharing).
- Solusi: Saya menginstal dan mengkonfigurasi middleware `cors` di server Node.js. Ini memungkinkan permintaan lintas domain dari front-end saya.
npm install cors
Kemudian, di server.js:
const cors = require('cors');
app.use(cors()); - Koneksi Database MongoDB:
- Masalah: Awalnya, aplikasi tidak dapat terhubung ke database MongoDB.
- Solusi: Saya memastikan bahwa string koneksi MongoDB sudah benar dan bahwa server MongoDB sedang berjalan. Saya juga memeriksa firewall untuk memastikan bahwa tidak memblokir koneksi.
mongoose.connect('mongodb://localhost:27017/todoapp', {
useNewUrlParser: true,
useUnifiedTopology: true,
}) - State Management di React:
- Masalah: Mengelola state aplikasi (daftar tugas) di React menjadi rumit.
- Solusi: Saya mulai menggunakan `useState` hook untuk mengelola state komponen dan mengimplementasikan fungsi untuk memperbarui state saat tugas ditambahkan, dihapus, atau diperbarui.
Memecahkan masalah ini membantu saya memahami lebih dalam tentang bagaimana berbagai teknologi berinteraksi dan bagaimana mengatasinya dengan efektif.
6. Kode Hari Ini: Contoh Implementasi
Berikut adalah contoh kode untuk endpoint pembuatan tugas di back-end (Node.js/Express.js):
server.js (Node.js/Express.js)
“`javascript
const express = require(‘express’);
const mongoose = require(‘mongoose’);
const cors = require(‘cors’);
const app = express();
const port = 5000;
app.use(cors());
app.use(express.json());
mongoose.connect(‘mongodb://localhost:27017/todoapp’, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log(‘Terhubung ke MongoDB’))
.catch(err => console.error(‘Gagal terhubung ke MongoDB:’, err));
const todoSchema = new mongoose.Schema({
title: String,
description: String,
completed: { type: Boolean, default: false },
});
const Todo = mongoose.model(‘Todo’, todoSchema);
// Membuat Tugas
app.post(‘/todos’, async (req, res) => {
try {
const newTodo = new Todo(req.body);
const savedTodo = await newTodo.save();
res.status(201).json(savedTodo);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
// Mendapatkan Semua Tugas
app.get(‘/todos’, async (req, res) => {
try {
const todos = await Todo.find();
res.json(todos);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
// Mendapatkan Tugas Berdasarkan ID
app.get(‘/todos/:id’, async (req, res) => {
try {
const todo = await Todo.findById(req.params.id);
if (!todo) {
return res.status(404).json({ message: ‘Tugas tidak ditemukan’ });
}
res.json(todo);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
// Memperbarui Tugas
app.put(‘/todos/:id’, async (req, res) => {
try {
const updatedTodo = await Todo.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!updatedTodo) {
return res.status(404).json({ message: ‘Tugas tidak ditemukan’ });
}
res.json(updatedTodo);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
// Menghapus Tugas
app.delete(‘/todos/:id’, async (req, res) => {
try {
const deletedTodo = await Todo.findByIdAndDelete(req.params.id);
if (!deletedTodo) {
return res.status(404).json({ message: ‘Tugas tidak ditemukan’ });
}
res.json({ message: ‘Tugas berhasil dihapus’ });
} catch (err) {
res.status(500).json({ message: err.message });
}
});
app.listen(port, () => {
console.log(`Server berjalan di http://localhost:${port}`);
});
“`
Berikut adalah contoh kode untuk komponen React yang menambahkan tugas baru:
src/components/AddTodo.js (React)
“`javascript
import React, { useState } from ‘react’;
import axios from ‘axios’;
function AddTodo({ onAdd }) {
const [title, setTitle] = useState(”);
const [description, setDescription] = useState(”);
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await axios.post(‘http://localhost:5000/todos’, {
title,
description,
});
onAdd(response.data);
setTitle(”);
setDescription(”);
} catch (error) {
console.error(‘Error adding todo:’, error);
}
};
return (
);
}
export default AddTodo;
“`
Kode ini hanyalah contoh sederhana, tetapi memberikan gambaran tentang bagaimana back-end dan front-end berinteraksi untuk membuat tugas baru.
7. Pembelajaran Utama: Wawasan Baru dan Konsep yang Dipahami
Hari ke-15 memberikan beberapa wawasan berharga:
- Pentingnya Middleware: Memahami bagaimana middleware dapat digunakan untuk memecahkan masalah seperti CORS dan menambahkan fungsionalitas ke server.
- Database Schema Design: Belajar bagaimana merancang skema database yang efektif untuk menyimpan data aplikasi.
- Penggunaan `useState` Hook di React: Memperdalam pemahaman tentang bagaimana mengelola state komponen menggunakan hook.
- Penanganan Error: Pentingnya menangani kesalahan dengan benar di back-end dan front-end untuk memberikan pengalaman pengguna yang baik.
Wawasan ini tidak hanya membantu saya menyelesaikan masalah hari ini, tetapi juga akan bermanfaat di masa depan.
8. Praktik Terbaik: Kode Bersih dan Pemeliharaan
Saya selalu berusaha untuk mengikuti praktik terbaik untuk kode yang bersih dan mudah dipelihara:
- Konsisten Naming Conventions: Menggunakan nama variabel dan fungsi yang deskriptif dan konsisten.
- Komentar Kode: Menambahkan komentar untuk menjelaskan logika kompleks dan memberikan konteks.
- Modularisasi Kode: Memecah kode menjadi modul yang lebih kecil dan reusable.
- Penanganan Error yang Komprehensif: Menangani semua potensi kesalahan dan memberikan pesan error yang informatif.
- Menggunakan Linter dan Formatter: Menggunakan alat seperti ESLint dan Prettier untuk memastikan kode yang konsisten dan bebas kesalahan.
Dengan mengikuti praktik ini, saya memastikan bahwa kode saya mudah dibaca, dimengerti, dan dipelihara oleh saya dan orang lain.
9. Sumber Daya yang Digunakan: Tautan dan Referensi Bermanfaat
Berikut adalah beberapa sumber daya yang saya temukan sangat membantu:
- Dokumentasi React: https://reactjs.org/
- Dokumentasi Node.js: https://nodejs.org/en/
- Dokumentasi Express.js: https://expressjs.com/
- Dokumentasi MongoDB: https://www.mongodb.com/
- MDN Web Docs (untuk CORS): https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Sumber daya ini memberikan informasi yang mendalam dan contoh kode yang membantu saya memahami konsep-konsep dan mengatasi tantangan.
10. Langkah Selanjutnya: Rencana untuk Hari ke-16
Untuk hari ke-16, saya berencana untuk fokus pada:
- Mengimplementasikan fitur untuk menandai tugas sebagai selesai.
- Mengimplementasikan fitur untuk mengedit tugas.
- Meningkatkan UI untuk memberikan pengalaman pengguna yang lebih baik.
- Menambahkan validasi data pada back-end dan front-end.
Saya sangat antusias untuk terus membangun aplikasi ini dan belajar lebih banyak tentang pengembangan full-stack.
11. Kesimpulan: Refleksi dan Motivasi
Hari ke-15 merupakan hari yang produktif dan penuh pembelajaran. Saya berhasil mengimplementasikan fitur CRUD dasar untuk aplikasi TODO List saya, mengatasi beberapa tantangan, dan mendapatkan wawasan berharga tentang pengembangan full-stack. Saya merasa termotivasi untuk terus belajar dan mengembangkan keterampilan saya, dan saya yakin bahwa dengan kerja keras dan dedikasi, saya akan mencapai tujuan saya menjadi pengembang full-stack yang kompeten.
Terima kasih telah mengikuti perjalanan saya! Sampai jumpa di hari ke-16!
“`