Bagaimana cara berhenti membuang-buang waktu merancang arsitektur [ditutup]


53

Saya baru saja lulus dari universitas dan mulai bekerja sebagai programmer. Saya tidak merasa sulit untuk menyelesaikan masalah "teknis" atau melakukan debugging dengan hal-hal yang saya katakan memiliki 1 solusi.

Tetapi tampaknya ada kelas masalah yang tidak memiliki satu solusi yang jelas - hal-hal seperti arsitektur perangkat lunak. Hal-hal ini membingungkan saya dan menyebabkan saya sangat tertekan.

Saya menghabiskan waktu berjam-jam untuk mencoba memutuskan bagaimana "merancang" program dan sistem saya. Sebagai contoh - apakah saya membagi logika ini menjadi 1 atau 2 kelas, bagaimana saya memberi nama kelas-kelas itu, haruskah saya menjadikan ini privat atau publik, dll. Pertanyaan-pertanyaan semacam ini menyita banyak waktu saya, dan itu membuat saya frustrasi. Saya hanya ingin membuat program - arsitektur terkutuk.

Bagaimana saya bisa melewati fase arsitektur lebih cepat dan ke fase coding dan debugging yang saya nikmati?


61
Dengan melakukan lebih banyak lagi. Anda akan mencari tahu apa yang berhasil dan tidak berhasil. Perhatikan bahwa mengajukan pertanyaan di sini mengikuti tren diskusi yang sama tanpa konteks kode aktual: waktu yang dapat dihabiskan untuk belajar sambil melakukan. Memperdebatkan hal ini menyenangkan, dan pola-pola tertentu secara objektif lebih baik daripada yang lain, tetapi sangat sulit untuk memiliki pendapat yang bermakna tanpa pengalaman (baca: bekas luka).
Jared Smith

5
Merancang adalah tahap perencanaan Anda - lakukan dengan benar dan 90% dari upaya Anda, sisanya adalah pengkodean, debugging, dan penerimaan pengguna. Melompati atau terburu-buru tidak dianjurkan, karena Anda dapat berakhir dengan solusi yang tidak dapat dipertahankan, tidak dapat diperpanjang, jadi jika Anda tidak suka melakukannya maka Anda mungkin perlu orang lain melakukannya untuk Anda ... Penamaan adalah salah satu masalah tersulit dalam pengembangan perangkat lunak, pengembang dapat menderita selama berhari-hari atas nama metode 5 baris. Jadikan semuanya pribadi sampai perlu sesuatu yang lain. Membagi kelas ketika mereka melakukan lebih dari satu hal.
Moo

5
dalam hal OOP, Anda dapat mulai dengan memahami dan menggunakan prinsip-prinsip SOLID . Ini akan membantu menjawab beberapa pertanyaan Anda (seperti apakah ini bersifat pribadi atau publik, membelah atau tidak membagi beberapa logika ...) dengan memberi Anda alasan di balik keputusan yang Anda buat.
njzk2

8
Saya merasa pertanyaannya tidak sebagus nilainya. Pertanyaannya tidak memiliki banyak konteks . Itu juga mengatakan sesuatu tentang bagaimana pemrograman itu (mungkin) salah diajarkan. Ilmu Komputer tidak boleh diajarkan dengan cara yang begineer lumpuh dengan kode.
Basile Starynkevitch

3
"Minggu berkode bisa menghemat banyak waktu dari perencanaan."
mickeyf_supports_Monica

Jawaban:


59

Sempurna adalah musuh kebaikan.

Yang mengatakan, Anda tidak harus mengambil jalan pintas. Desain perangkat lunak akan memiliki dampak yang lebih tahan lama, dan menghemat banyak waktu dan tenaga Anda di masa depan. Butuh waktu lebih lama untuk memperbaikinya. Sebagian besar waktu yang dihabiskan pemrograman tidak memalu pada keyboard, tetapi dengan papan tulis mencari tahu bagaimana menyelesaikan masalah.

Tetapi Anda juga tidak perlu khawatir tentang kesempurnaan. Jika dua desain bertarung dengan jalan buntu, itu berarti mereka memiliki kebaikan yang sama. Pergi saja dengan satu. Ini bukan seolah-olah Anda tidak dapat mengubah hal-hal begitu Anda mengetahui kekurangan dalam desain itu.

(Dan mudah-mudahan itu juga akan membantu setelah Anda mengetahui bahwa tidak hanya ada satu cara untuk debug / memecahkan masalah teknis.)


25
Kelumpuhan dengan Analisis juga muncul dalam pikiran.
mike65535

7
Terkadang wasit terakhir yang sempurna untuk keputusan desain adalah seperempat.
candied_orange

11
YAGNI dan KISS dan GTFO;)
JollyJoker

10
Bagi siapa pun yang membaca jawaban ini - Demi kasih tuhan jangan gunakan "Sempurna adalah musuh kebaikan" untuk membenarkan implementasi yang tidak bersemangat. Maksud dari perkataan ini adalah untuk mencegah Anda melakukan overengineering, untuk tidak mengendur dan menciptakan semacam kekacauan yang dirancang dengan buruk seperti Windows Vista atau Apple III.
T. Sar - Pasang kembali Monica

@ T.Sar: kegagalan Vista sebenarnya adalah 0% kegagalan teknis dan sekitar 100% kegagalan MBA.
whatsisname

39

Untuk program-program sederhana dan kecil (mis. Dengan kurang dari sepuluh ribu baris kode sumber), Anda dapat merancang program tersebut saat menulis kode. Jika Anda mengadopsi pendekatan pengembangan berulang dan bertahap , Anda akan secara progresif membuat keputusan arsitektural sepanjang jalan: jadi tulis beberapa lusin baris kode (tambahkan beberapa fitur mikro), perbaiki mereka sampai tidak ada peringatan yang kembali dari kompiler Anda, ujilah di debugger Anda, dan ulangi.

cara saya membagi logika ini menjadi 1 atau 2 kelas, bagaimana saya memberi nama kelas-kelas itu, haruskah saya menjadikan ini pribadi atau publik, dll. Pertanyaan-pertanyaan semacam ini menghabiskan banyak waktu saya

Seharusnya tidak. Dan mereka tidak terlalu penting untuk program kecil (karena program kecil dan sederhana lebih mudah ditingkatkan, misalnya untuk mengubah nama, dll ...). Anda hanya perlu konsisten dan memprioritaskan keterbacaan kode sumber Anda. Anda mungkin menemukan kebutuhan, dari waktu ke waktu, untuk sedikit memperbaiki beberapa bagian kecil dari program Anda (dan itu bukan masalah besar).

Bandingkan ini dengan banyak proyek perangkat lunak gratis (bahkan yang besar seperti kernel Linux). Pengembang tidak menghabiskan banyak upaya "merancang" pada tahap awal. UML hampir tidak pernah digunakan dalam perangkat lunak bebas . Selain itu, Anda akan belajar sedikit dengan mempelajari kode sumber dari beberapa proyek perangkat lunak gratis.

Sebagai pemula, Anda akan bekerja pada proyek perangkat lunak besar dalam sebuah tim, di mana Anda dapat mempercayai pengembang senior (yang membuat keputusan arsitektur), atau Anda akan bekerja sendiri pada proyek-proyek kecil (biasanya, kurang dari beberapa lusin ribu baris kode sumber). Dalam kasus terakhir, Anda akan membuat keputusan arsitektur tambahan, refactoring aplikasi Anda dari waktu ke waktu, setelah itu "desain arsitektur" akan berkembang secara alami.

Bagaimana saya bisa lebih cepat melewati fase arsitektur dan ke fase coding dan debugging, yang saya nikmati?

Untuk proyek perangkat lunak kecil, yang membutuhkan waktu kurang dari satu tahun kerja, sangat mudah: jangan lakukan arsitektur. Luangkan waktu setengah jam untuk bertukar pikiran tentang desain keseluruhan. Kemudian mulailah menulis kode, dengan pendekatan pengembangan berulang dan bertahap : tulis beberapa lusin baris, kompilasi (dengan semua peringatan dan info debug diaktifkan, misalnya g++ -Wall -Wextra -gdengan GCC untuk C ++) hingga Anda tidak mendapatkan peringatan (dan meneruskannya di beberapa sumber statis sederhana) penganalisis kode, jika Anda memilikinya, mis. penganalisis dentang ), uji kode itu dengan debugger , komit ke kontrol versi Anda (mis. git), bilas dan ulangi. Namun, pastikan untuk menghindari utang teknis: ketika sesuatu berbau tidak enak, lakukan pekerjaan (dengan refactoring dan implementasi ulang) untuk memperbaikinya.

Di sisi lain, dalam lingkungan tim, pekerjaan arsitektur memerlukan diskusi awal untuk menentukan tanggung jawab setiap anggota tim. Diskusi itu dipimpin oleh pengembang senior (yang bukan pemula). Baca tentang pengembangan perangkat lunak yang gesit dan The Mythical Man-Month .

Saya hanya ingin membuat program, arsitektur dibendung.

Intuisi luar biasa (setidaknya untuk proyek kecil). Jadi pikirkan beberapa menit tentang program Anda, dan mulai kodekan dengan pendekatan pengembangan iteratif dan tambahan : kode beberapa lusin baris dan pastikan mereka bekerja dengan baik, kemudian ulangi. Sebelum itu, pelajari kode sumber (dan amati arsitekturnya) dari proyek perangkat lunak bebas serupa dan lebih umum lakukan beberapa pekerjaan bibliografi dan penelitian.

Dalam beberapa kasus, pikirkan pendekatan metaprogramming : ada situasi di mana Anda ingin menghasilkan beberapa "file sumber" (contohnya termasuk menggunakan generator parser seperti bison , generator kode lem seperti SWIG , Google protobuf , dan kadang-kadang Anda mungkin ingin menulis skrip sederhana -atau gunakan preprosesor generik seperti GPP - untuk memancarkan beberapa kode C ++ atau Java Anda untuk menghindari pengkodean berulang-ulang).

PS. Saya seorang insinyur penelitian, memiliki gelar PhD dalam ilmu komputer dan pengalaman 40 tahun, dan saya tidak pernah melakukan "arsitektur" seperti yang disarankan oleh pertanyaan Anda, sementara saya telah bekerja dengan sukses pada beberapa proyek berukuran sedang, dan beberapa yang besar (kompiler GCC sendiri ). Bagi saya "arsitektur" hanyalah tahap perencanaan dari pekerjaan beberapa hari atau minggu ke depan (dan saya biasanya melakukannya sambil bermimpi atau tidur dan tentu saja tanpa komputer, dan biasanya tanpa pensil). Juga, ketika menulis hibah penelitian , saya entah bagaimana dan tidak lengkap merancang arsitektur.

NB: beberapa proyek perangkat lunak membutuhkan arsitektur yang lebih banyak daripada yang lain. Misalnya, jika Anda menulis sistem kontrol jantung buatan, atau robot bedah saraf, Anda tidak akan bekerja dengan cara yang sama seperti ketika menulis aplikasi ponsel rata-rata. Lihat juga program Norvig's Teach yourself dalam sepuluh tahun .


1
Begitulah biasanya hal itu datang kepada saya juga. Saya memberikan jumlah waktu yang cukup sebelum memulai program, dan pada saat saya mulai, saya akan memiliki beberapa ide yang jelas tentang bagaimana saya ingin menyusunnya, dan saya tidak benar-benar membuat titik untuk duduk dan memikirkannya. Itu semacam mengalir secara alami ke seseorang yang menangani masalah seperti itu secara teratur.
Neil

1
Mengingat kode sumber GCC, pertumbuhan organik sepenuhnya biasanya bukan sesuatu yang orang akan syukuri. Sebagian besar kontribusi GCC yang saya lihat adalah kasus-kasus mengerikan "buat pekerjaan saya dan keluar dari sini secepat mungkin" karena sisanya sudah seperti itu.
Kafein

1
Klaim saya adalah bahwa setiap basis kode yang cukup besar tumbuh secara organik (lihat hukum Gall ...). Juga, akan sangat bodoh untuk menangani arsitektur proyek perangkat lunak besar bagi seorang pemula
Basile Starynkevitch

Saya berada di tim yang berada di antara dua ukuran yang Anda jelaskan di paruh pertama jawaban Anda. Proyek kami lebih dari sepuluh ribu baris, tetapi tidak cukup besar untuk membutuhkan lebih dari setengah lusin pengembang yang bekerja penuh waktu. Kita berada dalam posisi di mana kita cukup besar untuk perlu merencanakan arsitektur kita dengan hati-hati, namun cukup kecil sehingga kita semua harus dapat membuat keputusan arsitektur sendiri. Saran Anda untuk tumbuh secara organik atau meminta pengembang senior tidak akan bekerja untuk tim saya secara khusus. (Tapi saya kira situasi saya mungkin agak tidak biasa juga.)
Kevin - Reinstate Monica

9

Ada tiga motto yang ingin saya ingat.

  • "Segala sesuatu harus dibuat sesederhana mungkin, tetapi tidak sederhana"

    Untuk mengambil contoh "satu atau dua kelas?", Saya akan bertanya, "solusi mana yang lebih sederhana?"

  • "Tidak ada bug yang jelas" versus "Jelas tidak ada bug"

    Yang terakhir lebih disukai!

    Dan itulah alasan mengapa itu harus sederhana, yaitu sehingga Anda dapat alasan tentang itu. Satu kelas besar mungkin (atau mungkin menjadi) terlalu besar dan terlalu rumit untuk dipikirkan, dalam hal ini Anda membaginya menjadi beberapa kelas yang lebih kecil, di mana Anda dapat mengatakan "Setiap kelas kecil dan melakukan apa yang dikatakannya akan dilakukan - dan antarmuka mereka sederhana, dan mereka bergabung dengan cara yang benar. "

    1. Kode harus dijalankan secara teori (yaitu di kepala Anda).
    2. Kemudian jika itu tidak berhasil dalam praktek Anda dapat men-debug itu sampai latihan sesuai dengan teorinya.

    Seorang pemula kadang-kadang tidak peduli dengan langkah 1, yaitu menjalankannya di kepala Anda (misalnya karena terlalu rumit) - tetapi dalam kasus itu hanya menjalankan "secara tidak sengaja" daripada "dalam teori", mungkin karena Anda belum t mengujinya cukup untuk menemukan bug yang tidak jelas.

  • Hukum Gall

    Ini alias "refactor".

    Dalam praktiknya ini berarti:

    1. Mulailah dengan [ny] sistem sederhana yang berfungsi
    2. Sekarang saatnya untuk menambahkan fitur baru
    3. Perbaiki sistem yang ada sehingga (yaitu sampai) fitur baru mudah ditambahkan
    4. Tambahkan fitur baru

    5. ... dan ulangi seperti di atas

    Ini cocok dengan motto seperti YAGNI yaitu jangan refactor (khawatir tentang arsitektur) sebelum Anda perlu ... tetapi buat arsitektur yang tepat tepat pada waktunya yaitu ketika Anda membutuhkannya untuk tujuan tertentu.


6

Yang dapat Anda lakukan adalah mulai dengan jumlah minimal abstraksi yang Anda butuhkan. Misalnya, kelas Person dalam satu file. Sekarang saat Anda terus menambahkan kode dan fitur, Anda mulai melihat hal-hal yang perlu dipindahkan ke abstraksi yang berbeda. Misalnya prinsip tanggung jawab tunggal (S SOLID) memberitahu Anda untuk tidak memiliki metode yang terkait dengan penguraian alamat dalam kelas Person. Jadi sekarang Anda tahu bahwa Anda memerlukan kelas Alamat.

Tetapi selalu baik untuk meluangkan waktu untuk berpikir tentang apa yang tampak seperti "jumlah minimal abstraksi" untuk sistem Anda. Mulai dari arsitektur yang cukup baik dan tingkatkan seiring Anda.

sunting: @Basile answer memberikan contoh tentang bagaimana Anda dapat mengulang dan meningkatkan arsitektur minimal Anda.


4
Saya tidak setuju. Mencoba menggunakan jumlah abstraksi yang minimal tidak seharusnya menjadi tujuannya. Membangun struktur yang layak untuk jangka panjang adalah yang lebih penting. Jangan hanya memikirkan waktu minimum yang diperlukan, tetapi pikirkan tentang membangun kode sehingga orang lain dapat menanganinya juga di masa depan yang jauh. Jika abstraksi membuat kode lebih mudah dibaca dan bisa diterapkan, itu adalah perbaikan yang jelas. Saya lebih suka menyarankan untuk menulis kode modular yang dapat digunakan kembali. Yang mengatakan, itu masalah pengalaman untuk bisa menilai itu.
Pertempuran

@Battle Maksud Anda adalah bahwa pemeriksaan di masa depan sama pentingnya, apakah saya benar? Saya setuju dengan ini, meskipun saya kira idealnya adalah membuat program dengan jumlah abstraksi yang minimal juga dengan mempertimbangkan pengembangan di masa depan. Saya berpendapat bahwa abstraksi sewenang-wenang tanpa manfaat di saat ini dan di masa depan hanya membuat program Anda lebih buruk, tidak lebih baik.
Neil

2
Dalam dunia nyata Anda akan memiliki banyak konteks seputar penggunaan perangkat lunak sehingga arsitektur minimal Anda akan mencakup banyak kasus penggunaan yang saat ini dikenal. Saya pikir itu memberi Anda titik awal yang layak. Modularitas dan penggunaan kembali adalah persyaratan non-fungsional sebagian besar waktu. Jika mereka menghalangi, tidak masalah untuk mengabaikan dan memalu keyboard Anda. Tapi ya, abstraksi minimum seharusnya tidak menjadi tujuan akhir. Tapi itu bisa menjadi titik awal.
sul4bh

@ Neil - Ya, saya sedang berbicara tentang pemeriksaan masa depan, dan saya pikir itu ada hubungannya dengan penataan kode dan dengan abstraksi sebagai bagian dari itu. Tapi saya tidak berbicara tentang abstraksi sewenang-wenang, tetapi tentang tujuan untuk meminimalkan mereka, seolah-olah mereka akan menjadi sesuatu yang buruk secara inheren. Mereka jahat ketika mereka berbuat jahat.
Pertempuran

3
@ Sapi: menambahkan struktur sebelumnya "berjaga-jaga" adalah apa yang dengan mudah mengarah ke rekayasa ulang. Menurut pengalaman saya, hanya selalu memiliki jumlah abstraksi yang diperlukan untuk ukuran basis kode saat ini "adalah tujuan yang sangat bagus - tidak kurang, tidak lebih. Abstraksi harus ditambahkan ketika basis kode tumbuh, bukan sebelumnya. Itu adalah bagaimana saya membaca jawaban ini, tetapi mungkin kata-kata "jumlah minimal abstraksi" dapat disalahartikan
Doc Brown

5

Waktu yang dihabiskan untuk memikirkan arsitektur suatu sistem bukanlah waktu yang terbuang.

Saya percaya pertanyaan Anda dapat diulangi sebagai "bagaimana saya bisa lebih efisien dengan mengambil keputusan arsitektur?".

Jawaban singkat saya adalah: Anda perlu menemukan prinsip-prinsip inti yang akan memungkinkan Anda untuk mengambil keputusan secara andal dan efisien dan kemudian Anda harus benar-benar keluar dan membentuk perangkat lunak dunia nyata. Ini akan menjadi perjalanan panjang mencari pengetahuan, coba-coba dan pengembangan pribadi.

-

Dan untuk jawaban yang lebih panjang ...

Pertama-tama saya harus mengklarifikasi konsep-konsep: Saya menggunakan kata arsitektur untuk menggambarkan struktur sistem perangkat lunak yang kompleks ketika saya bekerja dengan proses, layanan, API dan database. Saya menggunakan desain kata untuk menggambarkan struktur hanya satu bagian dari sistem yang lebih kompleks, ketika saya bekerja dengan kelas, fungsi dan perpustakaan. Ini adalah definisi saya, beberapa orang memiliki definisi yang berbeda. Namun dalam konteks ini, saya percaya Anda berbicara tentang desain .

Saya pikir ada 3 hal penting yang perlu diingat ketika membahas topik ini:

  • arsitektur dan desain ada tanpa secara eksplisit dijelaskan melalui diagram atau dokumentasi, juga tanpa dikelola oleh tim atau orang ( arsitek ). Setiap sistem memiliki arsitektur intrinsik dan desain intrinsik yang dapat dijelaskan setelah fakta.

  • pengembangan perangkat lunak bukan pemrograman, itu pemrograman dari waktu ke waktu. Saya membuat perbedaan ini karena saya pikir ini adalah salah satu titik buta terbesar bagi orang-orang yang datang dalam industri ini (termasuk saya, pada satu titik waktu). Artinya, dibandingkan dengan proyek universitas atau proyek sampingan pribadi, bekerja pada sistem perangkat lunak dunia nyata secara eksponensial lebih kompleks, karena setiap keputusan arsitektur akan memiliki dampak besar pada pengembangan sistem, seiring waktu. Keputusan Anda sekarang akan kembali menghantui Anda, dijamin.

  • karena arsitektur dan desain ada secara instrinsik dan karena basis kode adalah makhluk hidup yang berevolusi dengan waktu, arsitektur dan desain juga perlu berevolusi. Mereka akan berkembang secara terkendali melalui keputusan sadar yang diambil pada waktu yang tepat, atau mereka akan berkembang secara kacau, didorong oleh pengkodean. Ini penting untuk dipahami, karena itu berarti pendekatan tradisional "arsitek pertama dan tulis kode kedua" cacat. Tentu saja, ketika memulai proyek dari awal, beberapa pekerjaan arsitektur dan desain harus dilakukan di muka. Namun selain itu, akan ada banyak keputusan arsitektur dan desain yang masih harus dibuat saat mengembangkan sistem.

Untuk menyaring lebih lanjut di atas, sangat penting untuk menyadari fakta bahwa Anda akan membuat keputusan desain saat menulis kode, baik secara sadar atau tidak. Anda harus berusaha keras untuk membuat sebanyak mungkin keputusan itu secara sadar dan kritis, karena setiap keputusan yang diambil dengan ringan dapat berdampak besar pada pekerjaan di masa mendatang (dampak ini biasanya memanifestasikan dirinya dalam basis kode menjadi sangat sulit diubah untuk memperbaiki bug atau mengimplementasikan fitur). Robert C. Martin menggambarkan ini dengan indah, dengan data, dalam bukunya "Arsitektur Bersih" (yang saya sangat sarankan).

Jadi, sekarang kita tahu mengapa arsitektur dan desain itu penting, apa prinsip-prinsip inti yang dapat memberi kita kerangka kerja yang tepat untuk pengambilan keputusan yang baik? Saya memiliki pertanyaan ini sebelumnya dalam karir saya, saya merasa ada sesuatu yang hilang dalam perangkat saya tetapi tidak tahu apa, tidak tahu bagaimana menggambarkannya atau mencari itu. Saya akan membagikan beberapa prinsip ini yang saya temukan seiring waktu dan saya berharap itu akan membuat hidup Anda sedikit lebih mudah:

  • serangkaian trik pengkodean yang sangat sederhana namun kuat dapat diambil dengan membaca buku Martin Fowler "Refactoring: Meningkatkan Desain Kode yang Ada". Ada terlalu banyak untuk dicantumkan di sini, tetapi ini adalah keputusan tingkat waktu pengkodean yang sangat rendah yang dapat Anda buat untuk sangat meningkatkan struktur kode Anda dan membantu Anda mengambil keputusan desain. Buku ini juga cocok untuk mengintegrasikan pengujian unit ke dalam alur kerja pribadi Anda dan cara menulis kode yang dapat diuji.

  • khusus untuk OOP, Anda harus melihat prinsip-prinsip SOLID . Mereka agak abstrak dan sulit untuk membungkus pikiran Anda pada awalnya, tetapi sangat kuat. Saya sarankan Anda mulai dengan 2 pertama untuk mendapatkan manfaat paling cepat:

Prinsip tanggung jawab tunggal : suatu kelas hanya boleh memiliki satu tanggung jawab tunggal (yaitu hanya perubahan pada satu bagian dari spesifikasi perangkat lunak yang dapat memengaruhi spesifikasi kelas).

Prinsip terbuka / tertutup : "entitas perangkat lunak ... harus terbuka untuk ekstensi, tetapi ditutup untuk modifikasi."

  • konsep komposisi lebih dari warisan

    prinsip bahwa kelas harus mencapai perilaku polimorfik dan penggunaan kembali kode oleh komposisi mereka (dengan memuat contoh kelas lain yang mengimplementasikan fungsionalitas yang diinginkan) alih-alih warisan dari kelas dasar atau induk.

  • konsep perangkai ("tingkat saling ketergantungan antara modul perangkat lunak") dan kohesi ("sejauh mana unsur-unsur di dalam modul menjadi satu.")
  • konsep KERING (Jangan Ulangi Diri Sendiri)
  • yang konsep pemisahan perintah / permintaan ( "setiap metode harus berupa perintah yang melakukan tindakan, atau query yang kembali data ke pemanggil, tetapi tidak keduanya")
  • konsep sistem stateful versus stateless (aturan praktis saya adalah: hindari menangani negara; membangun sistem stateless sebanyak mungkin).

Tentu saja, ini hanya konsep, bukan aturan. Langkah pertama adalah memahami mereka dan menyadarinya. Berikutnya datang benar-benar menggunakannya dalam praktik dan membangun pengalaman tentang kapan Anda harus mengikuti mereka dan kapan Anda seharusnya tidak. Dan kemudian ada proses terus menerus untuk menyempurnakan pemahaman Anda tentang konsep-konsep ini, sisi negatifnya dan interaksi kompleksnya satu sama lain.

Saya pikir saran paling berharga yang bisa saya berikan adalah: bersabarlah dengan diri sendiri. Anda baru saja memulai jalan yang panjang tapi memuaskan. Teruslah berlatih dan bereksperimen, catat apa yang berhasil dan yang tidak dan Anda hanya akan menjadi lebih baik dengan waktu.


Ini adalah sesuatu yang harus dipelajari dengan pengalaman. Itu setengah dari pekerjaan Anda, dan melakukannya dengan buruk memiliki biaya yang sangat besar, tetapi itu tidak diajarkan di sekolah karena Ilmu Komputer dan pengembangan perangkat lunak hampir semuanya berbeda.
No U

1

Sebagian besar dari apa yang Anda gambarkan sebenarnya bukan arsitektur (penting) - penamaan yang baik dan desain kelas yang baik adalah sesuatu yang harus menjadi kebiasaan Anda. Ini hanya akan menjadi lebih baik semakin banyak kode Anda. Yang paling membantu untuk masalah semacam itu biasanya pemrograman berpasangan - ini membantu untuk mengklarifikasi masalah seperti itu dan membantu Anda mempelajari cara ini secara efisien.

Di mana arsitektur diperlukan adalah SEBELUM proyek:

  1. Kumpulkan persyaratan yang tepat dan persyaratan nonfungsional (berapa banyak permintaan / detik yang harus saya dukung?). Kesalahan missmatch dalam fase ini akan mengarah ke pengkodean neraka - mengintegrasikan ide yang terlewatkan setelah faktanya memakan waktu, menyebalkan dan kadang-kadang tidak mungkin. Saya tahu ini tidak menyenangkan sebagai pengkodean, tetapi mencoba untuk mendapatkan kode untuk melakukan sesuatu yang tidak dirancang untuk itu bahkan kurang menyenangkan.

  2. Jika sesuai, tentukan konteks terbatas sistem Anda dan pastikan Anda memiliki kosakata yang benar, mis. Jika bisnis berbicara tentang "Frobbels" pastikan Anda menyebutkan kelas / antarmuka dll dengan "*** Frobbels". Kedengarannya sepele, tetapi jika Anda berbicara tentang alur kerja, sementara bisnis berbicara tentang operasi, menerjemahkan menjadi sangat cepat menyebalkan.

  3. Jika Anda bekerja dengan banyak orang / tim, uraikan antarmuka Anda lebih awal dan pastikan semua asumsi dan masalah dipahami oleh semua orang - jika Anda tidak memiliki konteks bersama, integrasi akan menjadi "menyenangkan". Misalnya Anda membuat generator gambar pisang, tetapi frontend-dev Anda membutuhkan generator gambar apel. Atau Anda membangun sesuatu yang dapat menjawab 100 permintaan / detik, tetapi 10.000 r / detik diperlukan.

Catatan: ini sangat dipengaruhi oleh pekerjaan saya pada arsitektur layanan mikro. Bagaimana melayani dibangun secara internal, BISA juga dirancang - tetapi sebagian besar waktu itu jauh lebih penting daripada mendapatkan gambaran besar dengan benar.


1

Saya tidak akan melemparkan banyak istilah dan singkatan pada Anda (yang sebagian besar hampir tidak disetujui oleh mayoritas coders / insinyur perangkat lunak). Sebagai gantinya, pertimbangkan hal berikut:

  1. Anda belajar - Anda tidak membuang waktu, Anda mencoba berbagai pendekatan dan mempelajari apa yang berhasil. Anda dapat melakukan ini tanpa banyak perencanaan sebelumnya, dengan menyelami masalah dengan solusi pertama yang muncul di benak Anda dan mengubahnya jika atau ketika itu tidak berhasil. Jika berhasil, bagus! Anda telah menemukan solusi sederhana untuk suatu masalah. Solusi sederhana baik-baik saja jika mereka bekerja dengan baik, dan kadang-kadang cukup baik .

  2. Semuanya adalah tradeoff - Anda dapat merancang sistem yang sama dengan berbagai cara, menukar waktu dan ruang, kompleksitas dan fleksibilitas, abstraksi dan keterbacaan, atau salah satu dari banyak tradeoff yang mungkin. Tidak ada solusi yang sempurna dalam segala hal dan tidak ada aturan tanpa pengecualian dalam rekayasa perangkat lunak. Siapa pun yang memberi tahu Anda sebaliknya adalah naif atau menjual sesuatu.

  3. Sebagai lulusan baru-baru ini, pengkodean dan debugging bisa sangat menarik, tetapi ini akan hilang seiring waktu, dan keterampilan yang Anda pelajari sekarang akan membantu Anda dengan baik saat melakukannya.

  4. Saya berpendapat bahwa membangun perangkat lunak lebih merupakan seni / kerajinan daripada rekayasa. Seni yang hebat bukan hanya tentang sapuan kuas individu, tetapi juga tentang keputusan tingkat tinggi dan pengorbanan yang dibuat oleh seniman / pengrajin.


1

Saya akan mencoba menjawab pertanyaan ini yang berasal dari sudut pandang pengembangan web (artinya: berasal dari bidang di mana banyak orang menderita karena arsitektur). Saya akan mulai dengan menjelaskan mengapa orang-orang peduli tentang arsitektur dan kemudian akan menguraikan cara untuk melewati bagian arsitektur lebih cepat.

Arsitektur melakukan dua hal untuk kode Anda:

  1. Ini membuatnya lebih mudah untuk memahami kode Anda untuk Anda dan orang lain.
  2. Ini membantu menyusun kode Anda dengan cara yang membuatnya lebih mudah untuk memperluas dan mengintegrasikannya.

Gaya kode memudahkan Anda membaca bagian tertentu dari kode, dengan memberi Anda konvensi yang dapat Anda kenali dan gunakan untuk menavigasi kode itu. Demikian juga arsitektur yang baik membantu Anda mengidentifikasi di mana Anda benar-benar akan menemukan kode yang menangani fitur tertentu. Sebagai contoh, di sebagian besar proyek web arsitektur erat kaitannya dengan bagaimana folder dan file diurutkan. Pada flipside, arsitektur yang baik seharusnya benar-benar membantu Anda berpikir lebih sedikit tentang kode, karena semuanya harus memiliki tempat yang intuitif di mana ada bagian dari kode.

Selain itu, arsitektur yang baik memberikan cara cepat untuk menghindari banyak jebakan yang dapat menjaga kode Anda agar tidak digunakan dengan mudah. Sekali lagi, jika Anda membuat keputusan arsitektur, itu harus membuat konvensi yang membantu Anda berpikir lebih sedikit tentang cara menulis kode.

Sekarang bagian di mana Anda sebenarnya berada di sini:

Apa yang dapat Anda lakukan melalui bagian arsitektur lebih cepat:

  1. Jangan lakukan itu

Seperti yang sudah ditunjukkan oleh banyak jawaban. Pertama, tanyakan pada diri Anda apakah Anda benar-benar membutuhkan arsitektur. Jika Anda tidak memiliki banyak kode (dan Anda dapat yakin bahwa proyek tersebut tidak akan tumbuh dalam waktu dekat), Anda dapat melewati bagian arsitektur dan mengeruk bersama sesuatu yang hanya berfungsi. NAMUN, jika Anda berada di awal karir Anda, saya akan menggunakan kesempatan untuk berlatih kapan pun Anda bisa. Pada titik tertentu Anda akan melakukan proyek yang lebih besar, dan pada titik itu mungkin terlambat untuk belajar.

Dengan itu, apa yang dapat Anda lakukan untuk membuat arsitektur tidak begitu menyakitkan:

  1. Lakukan lebih awal
  2. Mencuri
  3. Belajar / Tetap berpegang pada itu
  4. Jangan berlebihan

Memutuskan arsitektur harus menjadi bagian awal dari proses perencanaan. Segera setelah Anda memiliki gagasan tentang aplikasi / program / situs web apa yang akan Anda buat, Anda harus berpikir tentang jenis arsitektur apa yang akan mendukung ini.

Pada titik ini saatnya untuk mencuri tanpa malu-malu. Ada banyak literatur di luar sana tentang cara mengatur arsitektur program dengan benar, dan jumlah kasus penggunaan yang mencengangkan dicakup oleh prototipe arsitektur yang ada. Anda harus mempelajari gambaran umum kasar tentang jenis arsitektur apa yang ada di sana, bahkan jika Anda tidak tahu bagaimana menerapkannya.

Jika Anda telah memilih jenis arsitektur, maka patuhi itu. Untuk sebagian besar, keputusan arsitektur harus intuitif dan hanya perlu beberapa detik setelah pengaturan awal. Banyak dari ini berujung pada pengalaman.

Terakhir, jangan terlalu banyak berpikir. Anda memberikan contoh apakah sesuatu harus publik atau pribadi, dan kenyataannya adalah, bahwa mungkin tidak masalah jika Anda membuat semuanya publik. Ya, Anda seharusnya tidak melakukannya dengan cara ini, dan banyak kesalahan kecil ini akan menumpuk setelah beberapa waktu, tetapi pada akhirnya mungkin juga tidak akan membunuh proyek Anda. Pertama dan terpenting, buat perangkat lunak yang berfungsi!

(PS: Kalimat terakhir itu bukan alasan untuk malas. Memprioritaskan perangkat lunak yang berfungsi tidak berarti Anda tidak harus belajar pengkodean yang baik suatu hari nanti.)


1

Jawabannya sangat sederhana,

  • Buat prototipe (Kotak waktu)
  • Refactor (menghabiskan waktu sebanyak yang Anda inginkan atau didasarkan pada berbagai faktor)

Ketika Anda membuat prototipe fokusnya harus pada Produk yang layak Minimal, dan ketika Anda refactoring, fokus harus pada membuat proyek atau solusi Anda dapat diskalakan.


1

Bagaimana saya bisa lebih cepat melewati fase arsitektur dan ke fase coding dan debugging, yang saya nikmati?

Dengan mengalihkan tugas ini ke (atau meminta bantuan dari) rekan kerja Anda yang lebih berpengalaman.

Anda tidak memiliki pengalaman yang diperlukan untuk mengambil keputusan dengan cepat. Uni memberi Anda latar belakang teoretis yang bagus, tetapi itu hanya membuat Anda sampai pada garis awal. Tidak ada cara lain untuk menilai arsitektur yang diberikan dalam situasi tertentu selain dengan mengetahui bagaimana arsitektur serupa berperilaku dalam situasi yang sama di masa lalu.

Bekerja dengan orang-orang yang lebih baik dalam pekerjaan daripada Anda adalah cara tercepat untuk mempelajari berbagai hal. Jika Anda tidak memiliki siapa pun yang lebih senior untuk beralih ke, Anda membutuhkan pekerjaan yang lebih baik. "Lebih baik" seperti dalam "menyesuaikan kebutuhan Anda dengan lebih baik". Kebutuhan pengetahuan dan pengalaman adalah kebutuhan Anda yang paling mengerikan saat ini, sebagaimana dibuktikan oleh dilema Anda. Anda menikmati fase pengkodean dan debugging? Kedengarannya seperti junior yang sempurna. Tetapi seorang junior membutuhkan bimbingan senior. Itulah inti dari deskripsi pekerjaan itu. Orang asing di internet hanya dapat membantu Anda sejauh ini, Anda memerlukan seorang mentor.


Saya pikir ini adalah jawaban yang baik tetapi saya akan menyarankan untuk mengubah "Bekerja dengan orang-orang yang lebih baik dari Anda" menjadi "Bekerja dengan orang-orang yang lebih berpengalaman daripada Anda". 'Lebih baik' dapat diartikan dalam banyak cara berbeda seperti yang Anda tunjukkan dalam kalimat berikutnya.
JimmyJames

@JimmyJames Saya telah berubah menjadi "lebih baik di pekerjaan". Karena pengalaman itu hanya sebagian saja.
Agent_L

Saya tidak setuju dengan itu secara umum dan justru itulah alasan saya berpikir 'lebih baik' belum tentu kata yang tepat di sini. Saya pikir untuk OP, mereka berputar-putar karena mereka tidak memiliki konteks proses desain. Bahkan desainer / arsitek yang buruk dapat membantu dengan itu dan secara teknis 'lebih baik' daripada OP. Tetapi begitu OP memahami pekerjaan itu, mereka mungkin 'lebih baik' daripada mentor. Jadi bukan karena jawaban Anda salah, hanya ada banyak nuansa yang tidak jelas dari penggunaan istilah 'lebih baik'.
JimmyJames

1

Saya melihat beberapa masalah serius dengan pertanyaan ini. Ayo mulai.

Bagaimana berhenti membuang-buang waktu mendesain arsitektur

Pertanyaan ini agak dimuat. Juga, Anda tidak merancang arsitektur. Anda arsitek . Arsitektur dan desain adalah kegiatan yang saling melengkapi dan terkait, tetapi tidak sama, bahkan jika mereka tumpang tindih.

Demikian pula, dengan cara yang sama dimungkinkan untuk membuang waktu melakukan arsitektur (dengan over-architecting), Anda juga dapat membuang waktu over-desain dan over-coding (dengan mengkodekan hal-hal dengan cara yang jauh lebih kompleks daripada yang diperlukan, atau dengan gagal untuk kode untuk hal-hal yang diperlukan.)

Arsitektur yang tepat bertujuan untuk mencegah pemborosan dalam pengkodean. Ia melakukannya dengan membatasi, mempersempit, dan mendokumentasikan cara-cara yang mungkin dilakukan oleh sistem yang kompleks 1) dirancang, 2) dikodekan dan diuji, 3) dikirim, 4) dipelihara, 5) pulih dari kegagalan, dan 6) akhirnya dinonaktifkan.

Pengalaman saya adalah bahwa orang-orang yang hanya menikmati pengkodean, mereka hanya kode tanpa memikirkan bagaimana sistem untuk beroperasi dan dipelihara dalam jangka panjang, pindah ke kentang panas berikutnya meninggalkan beberapa jiwa miskin untuk mempertahankan golem jelek.

Tapi saya ngelantur ...

Ini masalahnya: Untuk sistem yang cukup sederhana, arsitektur sudah terbukti dengan sendirinya dan berasal dari desain dan praktik implementasi yang baik.

Ini hanya untuk sistem besar yang melibatkan sejumlah besar orang atau perangkat lunak tingkat sistem yang melakukan hal-hal yang sangat kompleks yang memerlukan arsitektur eksplisit.

Saya baru saja lulus dari universitas dan mulai bekerja sebagai programmer. Saya tidak merasa sulit untuk menyelesaikan masalah "teknis" atau melakukan debugging, hal-hal yang saya katakan memiliki 1 solusi.

Itu adalah persyaratan minimum untuk profesi ini, dan saya senang Anda tidak memiliki masalah dalam melakukannya (saya akan khawatir jika melakukannya.)

Tetapi tampaknya ada kelas masalah yang tidak memiliki satu solusi

Itu adalah roti dan mentega dari profesi kita, jenis masalah di mana majikan bersedia membayar gaji kita (biasanya) jauh di atas rata-rata.

Faktanya, masalah yang layak dipecahkan adalah masalah yang dapat memiliki lebih dari satu solusi. Masalah dunia nyata, mereka memang seperti itu. Dan dunia membutuhkan keahlian kita, sebagai pengembang perangkat lunak, untuk menghasilkan pertukaran yang dapat diterima.

- hal-hal seperti arsitektur perangkat lunak.

Arsitektur benda adalah karakteristik sistem kompleks yang tak terhindarkan, baik itu virtual / perangkat lunak atau di dunia nyata. Setiap sistem yang beroperasi, yang mengambil input dan menghasilkan output, itu akan kompleks dan akan memiliki arsitektur.

Ketika kami mengembangkan perangkat lunak untuk sistem seperti itu (sistem perbankan, sistem pemantauan daya, sistem penjualan tiket, dll), kami bertujuan untuk menghasilkan perangkat lunak yang meniru fungsi dan persyaratan sistem tersebut.

Kami hanya tidak bisa hanya sayap dan kode itu gaya koboi. Kami membutuhkan semacam arsitektur. Ini terutama benar jika proyek tersebut membutuhkan lusinan insinyur, jika tidak lebih.

Hal-hal ini membingungkan saya dan menyebabkan saya sangat tertekan.

Itu tidak apa-apa. Ini bukan pelajaran yang mudah dipelajari atau diajarkan, bukan tanpa banyak latihan.

Saya menghabiskan waktu berjam-jam untuk mencoba memutuskan bagaimana "merancang" program dan sistem saya. Sebagai contoh, apakah saya membagi logika ini menjadi 1 atau 2 kelas, bagaimana saya memberi nama kelas-kelas tersebut, apakah saya harus menjadikan ini privat atau publik, dll. Pertanyaan-pertanyaan semacam ini menghabiskan banyak waktu saya, dan itu membuat saya frustrasi. Saya hanya ingin membuat program, arsitektur terkutuk.

Sayangnya, itu bukan arsitektur perangkat lunak.

Ini bahkan bukan desain, tetapi hanya coding. Saya akan memberikan beberapa saran di bagian bawah posting ini.

Bagaimana saya bisa lebih cepat melewati fase arsitektur dan ke fase coding dan debugging, yang saya nikmati ?

Saya mengalami kesulitan menemukan cara untuk menjawab ini, karena itu agak emosional.

Apakah kita sedang berusaha menyelesaikan pekerjaan, atau kita hanya mencoba untuk menikmati latihan? Sangat bagus ketika keduanya satu dan sama, tetapi dalam kehidupan nyata, sering kali mereka tidak sama.

Sangat bagus untuk melakukan hal-hal yang kita nikmati, tetapi dalam profesi yang kompleks seperti kita, untuk fokus hanya pada apa yang kita nikmati, itu tidak konduktif untuk memiliki karier yang bermanfaat.

Anda tidak akan maju, Anda tidak akan dewasa atau mendapatkan pengetahuan baru.

Ada pepatah di Angkatan Darat, "merangkul payah."

Frasa lain memiliki saran serupa. "Jika tidak mengisap, itu tidak layak" dan favorit saya, "Jika itu menyebalkan (dan ini penting), lakukan sampai berhenti mengisap."

Rekomendasi saya:

Sepertinya saya bahwa Anda masih berjuang untuk memahami perbedaan di antara keduanya

  1. pengkodean (cara membuat kode kelas, modul atau tidak, konvensi penamaan, visibilitas akses, ruang lingkup, dll),

  2. desain (berapa banyak tingkatan, front-end / back-end / db, bagaimana masing-masing berkomunikasi, apa yang terjadi di mana) dan keputusan arsitektur implisit yang berasal dari desain sistem sederhana,

  3. arsitektur (seperti yang ditemukan dalam sistem kompleks yang membutuhkan ribuan, jika tidak ratusan ribu jam kerja)

Jadi saya sarankan Anda mempelajari secara mendalam subjek pertama (pengkodean) untuk membawanya ke tingkat berikutnya.

Kode Bersih

Robert "Paman Bob" "Kode Bersih " Martin adalah tempat yang baik untuk memulai.

Kohesi Perangkat Lunak

Selain itu, saya sarankan Anda membiasakan diri dengan metrik perangkat lunak Berorientasi Objek yang disebut LCOM atau lebih tepatnya LCOM4.

Ini bisa menjadi agak matematis dan bukan anti peluru, tetapi tujuan Anda harus memahami dan mendeteksi secara empiris (atau bola mata jika Anda mau) jika suatu kelas kohesif atau jika tidak memiliki kohesi.

http://www.aivosto.com/project/help/pm-oo-cohesion.html#LCOM4 https://www.computing.dcu.ie/~renaat/ca421/LCOM.html

Prinsip Perangkat Lunak

Ini terkait erat dengan "Prinsip Tanggung Jawab Tunggal" atau SRY yang harus kita ketahui bersama. SRY adalah salah satu dari 5 "SOLID" yang harus kita ketahui jika kita ingin menjadi ahli dalam pengkodean.

Ketika kita bergerak melalui prinsip-prinsip SOLID, kita juga perlu membiasakan diri dengan prinsip-prinsip "GRASP" , yang mengatur, atau lebih tepatnya membimbing bagaimana kita mengkode kelas.

Buku tambahan

Terakhir, saya juga menyarankan yang berikut:

  • "Refactoring" oleh Martin Fowler dan Ken Beck akan menjadi buku berikutnya yang saya baca dalam daftar ini.

  • "Desain oleh Kontrak, dengan Contoh" oleh Richard Mitchell, Jim McKim dan Bertrand Meyer (kemudian ketenaran Eiffel.) Buku ini tidak dicetak, tetapi Anda dapat menemukan salinan yang murah dan bekas di Amazon.

Dengan ini, Anda harus memahami cara memulai pengkodean dan desain, dan dengan latihan, untuk memindahkan dan menguasai (atau setidaknya memahami) arsitektur perangkat lunak.

Saya yakin akan ada profesional lain yang akan menambah, mengurangi, atau menolak saran ini. Mereka akan datang dengan saran lain, kemungkinan divalidasi oleh pengalaman mereka sendiri.

Yang bisa saya katakan adalah ini - tidak ada jalan pintas.

Semua yang terbaik.


1

Ada banyak informasi di sini dan terus terang TL; DR. Ada satu hal utama yang saya pikir orang salah ketika mencoba mempelajari cara mendesain sistem: mereka mencoba memikirkannya dalam urutan bahwa pekerjaan akan dilakukan. Sebaliknya, Anda harus bekerja mundur. Maksudnya, tujuan utama desain / arsitektur adalah untuk menentukan seperti apa hasil akhirnya.

Sebagai analogi, pertimbangkan arsitektur rumah. Seorang arsitek tidak mulai bertanya pada diri sendiri pertanyaan-pertanyaan seperti: "berapa banyak jendela yang harus dimiliki rumah ini?", "Di mana batu bata pertama harus ditempatkan?". Detail implementasi tersebut bukan desain, mereka berasal dari desain. Arsitektur dimulai dengan sebuah visi, mungkin sebuah sketsa tentang bagaimana rumah yang sudah jadi kelihatan. Apakah ini rumah keluarga tunggal, dupleks? Apakah ini rumah mewah atau rumah yang mudah terjangkau? Demikian juga, apakah variabel bersifat pribadi dan apakah Anda membagi kelas tidak ada hubungannya dengan arsitektur.

Mulailah terlebih dahulu dengan mencari tahu apa tujuan desain Anda. Misalnya, apakah ini solusi satu kali? Apakah akan diperluas dan direvisi dan dipelihara selama beberapa dekade? Jawabannya akan menunjukkan desain yang sangat berbeda dan itulah titik arsitekturnya. Setelah Anda mengetahui apa yang perlu Anda lakukan, detail desain akan mengikuti secara alami. Bukan karena rincian ini jelas atau mudah tetapi itu adalah rencana tingkat tinggi yang menjadi dasar pilihan ini.


0

Cara menilai berapa banyak waktu yang harus Anda curahkan untuk merancang perangkat lunak apa pun sebelum mendapatkan loop semacam penulisan-kompilasi semacam ini cukup mudah: informasi yang cukup untuk dimuat di kepala Anda, dan tidak lebih dari itu. Kecuali jika proyek yang sedang Anda kerjakan mengamanatkan metodologi yang lebih ketat. Dalam hal ini sebagai pemula kemungkinan besar Anda harus membaca dokumen arsitektur, bukan menulisnya.

Mengenai hal penamaan, bagi saya itu adalah bagian dari "menulis" tetapi tidak diragukan lagi itu adalah bagian yang sangat penting dari pemrograman: jangan ragu untuk berpikir keras tentang bagaimana Anda menyebutkan sesuatu, dan untuk berpikir lebih keras semakin besar cakupan nama.

Menemukan nama yang tepat, arsitektur yang tepat, modularitas yang tepat, dan abstraksi yang tepat adalah bagian dari pengalaman yang akan Anda peroleh dengan membuat kesalahan. Selama bertahun-tahun saya telah menulis sebuah program melakukan hal yang sama sekitar lima kali dan kode itu sangat berbeda setiap kali karena setiap iterasi masa lalu memberi saya petunjuk pada desain yang lebih baik.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.