SOLID == OOP?

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 object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

, , "" . , , .



"", , "" . , ! , ( ), :



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 ( classhaskell ):



// 
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 , . , !




All Articles