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__



--
Marco Antoniotti, Associate Professor         tel. +39 - 02 64 48 79 01
DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it
Viale Sarca 336
I-20126 Milan (MI) ITALY