Skip to content

Commit 73b212a

Browse files
authored
Merge pull request #5042 from luishendrix92/main
#30 - OCaml
2 parents 5a219d0 + 3a5cac5 commit 73b212a

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
open Printf
2+
3+
(******************************************************************************)
4+
(* *)
5+
(* Dependency Inversion Principle *)
6+
(* *)
7+
(* DIP is the strategy of depending upon interfaes or abstract functions *)
8+
(* and classes rather than upon concrete functions and classes. A good rule *)
9+
(* to apply is that higher-level components should not depend on a lower *)
10+
(* level component, and they should also work in isolation. DIP tells us *)
11+
(* that every dependency in the design should target an interface or an *)
12+
(* abstract class. Furthermore, a dependency should not target a concrete *)
13+
(* class. It's also worth noting that {e Dependency Injection} is just a *)
14+
(* vehicle to achieve the inversion of control. *)
15+
(* *)
16+
(******************************************************************************)
17+
18+
module LowLevelModule = struct
19+
let do_something () = print_endline "LLM Doing something..."
20+
end
21+
22+
module HighLevelModule = struct
23+
(** [LowLevelSubModule] is tightly coupled with the high-level module.
24+
This breaks the DIP and should be abstracted with a functor instead. *)
25+
module LowLevelSubModule = LowLevelModule
26+
27+
let say_hello () =
28+
print_endline "Hello from HLM, submodule does something:";
29+
LowLevelModule.do_something ()
30+
;;
31+
end
32+
33+
let _ = HighLevelModule.say_hello ()
34+
35+
module type AbstractModule = sig
36+
val do_something : unit -> unit
37+
end
38+
39+
module ConcreteModule : AbstractModule = struct
40+
let do_something () = print_endline "ConcreteModule does something..."
41+
end
42+
43+
module DIP_HLM_Functor (AM : AbstractModule) : sig
44+
val say_hello : unit -> unit
45+
end = struct
46+
(** [ASM] is an injected dependency module that implements the
47+
[AbstractModule] pseudointerface.*)
48+
module ASM = AM
49+
50+
let say_hello () =
51+
print_endline "Hello from a DIP-complied HLM!";
52+
print_endline "The abstract submodule does something:";
53+
ASM.do_something ()
54+
;;
55+
end
56+
57+
module DIP_Compliant = DIP_HLM_Functor (ConcreteModule)
58+
59+
let _ =
60+
print_newline ();
61+
(* Sealing [DIP_Compliant] with a module signature allows us to make the
62+
abstract submodule (dependency) private, just like in OOP. *)
63+
DIP_Compliant.say_hello ()
64+
;;
65+
66+
(* Here's how it's done with classes in OCaml. *)
67+
68+
class type abstraction = object
69+
method operation : unit
70+
end
71+
72+
class low_level_class : abstraction =
73+
object
74+
method operation = print_endline "Low-level class operation/method"
75+
end
76+
77+
class high_level_class (dependency' : abstraction) =
78+
object
79+
val dependency = dependency'
80+
81+
method use_dependency =
82+
print_endline "High level class uses its injected dependency:";
83+
dependency#operation
84+
end
85+
86+
let _ =
87+
let hlo = new high_level_class (new low_level_class) in
88+
print_newline ();
89+
hlo#use_dependency
90+
;;
91+
92+
(*
93+
DIFICULTAD EXTRA (opcional):
94+
Crea un sistema de notificaciones.
95+
Requisitos:
96+
1. El sistema puede enviar Email, PUSH y SMS (implementaciones específicas).
97+
2. El sistema de notificaciones no puede depender de las implementaciones específicas.
98+
Instrucciones:
99+
1. Crea la interfaz o clase abstracta.
100+
2. Desarrolla las implementaciones específicas.
101+
3. Crea el sistema de notificaciones usando el DIP.
102+
3. Desarrolla un código que compruebe que se cumple el principio.
103+
*)
104+
105+
module type Notifier = sig
106+
val id : string
107+
val notify : string -> string -> unit
108+
end
109+
110+
module EmailService : Notifier = struct
111+
let address = "[email protected]"
112+
let id = "EMAILER"
113+
114+
let notify msg destination =
115+
print_endline "Email sent:\n--------------------------";
116+
printf "From: %s\n" address;
117+
printf "To: %s\n" destination;
118+
print_endline msg
119+
;;
120+
end
121+
122+
module NotificationManager (N : Notifier) : sig
123+
val create_and_send : string -> string -> unit
124+
end = struct
125+
module NotificationService = N
126+
127+
let create_and_send msg destination =
128+
printf
129+
"Sending [%s] to [%s] via %s...\n"
130+
msg
131+
destination
132+
NotificationService.id;
133+
NotificationService.notify msg destination
134+
;;
135+
end
136+
137+
(* We can inject an existing module that satisfies the interface: *)
138+
module EmailNotificationManager = NotificationManager (EmailService)
139+
140+
(* OR... we can also inject anonymous modules in-line: *)
141+
module SMSNotificationManager = NotificationManager (struct
142+
let id = "TelcelSMS"
143+
let phone_number = "664-563-7778"
144+
145+
let notify msg destination =
146+
print_endline "SMS sent:\n--------------------------";
147+
printf "To: [[ %s ]]\n" destination;
148+
printf "Text message: %s\n" msg;
149+
printf "From: [[ %s ]]\n" phone_number
150+
;;
151+
end)
152+
153+
module UbuntuNotificationCenter = NotificationManager (struct
154+
let id = "UbuntuNotifications"
155+
156+
let notify msg destination =
157+
printf "Application: %s\n" destination;
158+
print_endline msg
159+
;;
160+
end)
161+
162+
let _ =
163+
print_newline ();
164+
EmailNotificationManager.create_and_send
165+
"Hello, how are you? Let's meet soon"
166+
167+
print_newline ();
168+
SMSNotificationManager.create_and_send "Did you buy milk?" "664-121-4442";
169+
print_newline ();
170+
UbuntuNotificationCenter.create_and_send
171+
"Currently playing: Los Lobos - La Bamba"
172+
"Spotify"
173+
;;

0 commit comments

Comments
 (0)