In assembly, a design code would be (and here I'm using the Intel 8086 as an example) pass pointers to structures in BX, pointers to strings (or arrays) in SI, CX will contain sizes or limits, DI will point to destinations (say, copying something, or accepting input) with AX and DX used for anything else. Returning data---carry flag clear means success, if set, AX will contain an error code. Other registers may be updated depending upon the function.
That's a design code in Assembly. Move to a Motorola 68000, and well, it changes somewhat---pointers are passed in A0-A5, other data in D0-D7. You can still use the carry flag and say, D0 for error codes.
Move up to C, and the details about passing parameters to a function go away (unless you are mixing Assembly with C, and even then it can be isolated). I just give the parameters to the function and it's up to the compiler to stuff them into proper registers or on the stack or how ever it's done on a particular architecture.
Now, object oriented programming in C---another design pattern. Declare a structure with pointers to functions, and always pass the pointer to the structure to functions called via the function pointers. Again, the programmer is aware of the details. IN C++, the compiler handles those details.