Saya kira saya tidak akan salah jika saya mengatakan bahwa paling sering orang bertanya tentang prinsip-prinsip SOLID selama wawancara. Teknologi, bahasa, dan kerangka kerja berbeda, tetapi prinsip-prinsip pengkodean umumnya serupa: SOLID, KISS, DRY, YAGNI, GRASP, dan sejenisnya patut diketahui untuk semua orang.
Dalam industri modern, paradigma OOP telah mendominasi selama beberapa dekade, dan banyak pengembang memiliki kesan bahwa itu adalah yang terbaik atau bahkan lebih buruk - satu-satunya. Ada video yang bagus tentang topik ini. Mengapa Pemrograman Norma Tidak Berfungsi? tentang perkembangan bahasa / paradigma dan akar popularitas mereka.
SOLID pada awalnya dijelaskan oleh Robert Martin untuk OOP dan dianggap oleh banyak orang sebagai merujuk hanya untuk OOP, bahkan wikipedia memberitahu kita tentang hal itu, mari kita lihat apakah prinsip-prinsip ini sangat terkait dengan OOP?
Tanggung jawab tunggal
Mari nikmati wawasan Paman Bob tentang SOLID :
Prinsip ini dijelaskan dalam karya Tom DeMarco dan Meilir Page-Jones. Mereka menyebutnya kohesi. Mereka mendefinisikan kohesi sebagai keterkaitan fungsional unsur-unsur modul. Dalam bab ini kita akan menggeser makna itu sedikit, dan menghubungkan kohesi dengan kekuatan yang menyebabkan modul, atau kelas, berubah.
Setiap modul harus memiliki satu alasan untuk perubahan (dan sama sekali tidak melakukan satu hal, sebanyak jawaban) dan seperti yang dijelaskan penulis sendiri di salah satu video, ini berarti bahwa perubahan harus berasal dari satu kelompok / peran orang, misalnya, modul hanya boleh berubah sesuai dengan analis bisnis, perancang, spesialis DBA, akuntan, atau permintaan pengacara.
Harap dicatat bahwa prinsip ini berlaku untuk modul, yang dalam OOP adalah kelas. Ada modul di hampir semua bahasa, jadi prinsip ini tidak terbatas pada OOP.
Buka Ditutup
SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.) SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR MODIFICATION
Bertrand Meyer
- , — , ( ) .
( , ). , . map
, filter
, reduce
, . , foldLeft
!
def map(xs: Seq[Int], f: Int => Int) =
xs.foldLeft(Seq.empty) { (acc, x) => acc :+ f(x) }
def filter(xs: Seq[Int], f: Int => Boolean) =
xs.foldLeft(Seq.empty) { (acc, x) => if (f(x)) acc :+ x else acc }
def reduce(xs: Seq[Int], init: Int, f: (Int, Int) => Int) =
xs.foldLeft(init) { (acc, x) => f(acc, x) }
, , — .
Liskov Substitution
If for each objecto1
of typeS
there is an objecto2
of typeT
such that for all programsP
defined in terms ofT
, the behavior ofP
is unchanged wheno1
is substituted foro2
thenS
is a subtype ofT
.
, , "" . , , .
"", , "" . , ! , ( ), :
static <T> T increment(T number) {
if (number instanceof Integer) return (T) (Object) (((Integer) number) + 1);
if (number instanceof Double) return (T) (Object) (((Double) number) + 1);
throw new IllegalArgumentException("Unexpected value "+ number);
}
, T
, , "" (.. ), , — .
, , "" , , . , , ( ), , (ad hoc) . .
Interface Segregation
, , , .
, , "" ! , (type classes), .
Comparable
Java
type class Ord
haskell
( class
— haskell
):
//
class Ord a where
compare :: a -> a -> Ordering
"", , , compare
( Comparable
). .
Dependency Inversion
Depend on abstractions, not on concretions.
Dependency Injection, — , :
int first(ArrayList<Integer> xs) // ArrayList ->
int first(Collection<Integer> xs) // Collection ->
<T> T first(Collection<T> xs) //
: ( ):
def sum[F[_]: Monad](xs: Seq[F[Int]]): F[Int] =
if (xs.isEmpty) 0.pure
else for (head <- xs.head; tail <- all(xs.tail)) yield head + tail
sum[Id](Seq(1, 2, 3)) -> 6
sum[Future](Seq(queryService1(), queryService2())) -> Future(6)
, , .
SOLID , . , SOLID , . , !