OK.
procedure foo is x : Integer := 42; begin ... end
Now foo depends on the hardwired '42' (as is should, one may argue :) ). And we are not even talking about "classes" or Lisp here.
Have I boiled down to the essentials? How do you do the rolling eyes emoticon?
All the best
Marco
On Sat, Feb 6, 2021 at 10:50 PM Pascal Bourguignon pjb@informatimago.com wrote:
Le 06/02/2021 à 22:37, Manfred Bergmann a écrit :
You have a class. This class uses some other class. But by using or creating an instance of this other class directly you
create a dependency on something concrete.
That’s not what you want, because you might want to replace this with
something else if required. For example with a mock or fake implementation in a test.
‚Dependency injection‘ allows you to declare this dependency with just
an interface/protocol and have some other facility (the dependency injection framework) ‚inject‘ a concrete object at run-time.
A similar thing could certainly be done by just using a constructor
parameter (strategy pattern).
But I think the important part here is the dependency on just an
interface and not on a concrete implementation. For flexibility.
With some code:
;;;------------------------------------------------------------
(defclass used () ())
(defmethod used-stuff ((self used)) 'stuff)
;;; ---
(defclass user () ((used :reader used)))
(defmethod initialize-instance :after ((self user) &key &allow-other-keys) (setf (slot-value self 'used) (make-instance 'used #|OOPS, Dependency!|#)))
(defmethod user-stuff ((self user)) ;; Not a real dependency on the used class, ;; it's a dependency on the used-stuff generic function (interface). (used-stuff (used self)))
;;; ---
(defclass client () ())
(defmethod create-user ((self client)) ;; The class client depends directly on the user class, ;; and indirectly on the used class. (make-instance 'user))
;;;------------------------------------------------------------
(defclass used () ())
(defmethod used-stuff ((self used)) 'stuff)
;;; ---
(defclass user () ((used :initarg :used :reader used)))
;; The user class has no more any dependency on the used class.
(defmethod user-stuff ((self user)) ;; Not a real dependency on the used class, ;; it's a dependency on the used-stuff generic function (interface). (used-stuff (used self)))
;;; ---
(defclass client () ())
(defmethod create-user ((self client)) ;; The class client depends explicitely on the user and used classes. ;; But now, the class user doesn't depend directly on the used class; ;; this dependency is injected by the client into the user classe: (make-instance 'user :used (make-instance 'used)))
;;;------------------------------------------------------------
;; Notably if the client wants the user to use another used class:
(defclass variant-used (used) ()) (defmethod used-stuff ((self variant-used)) 'variant-stuff)
(defmethod create-user ((self client)) ;; only the client needs to be changed; the user class won't know ;; the difference: (make-instance 'user :used (make-instance 'variant-used)))
-- __Pascal Bourguignon__