3 ms·
Yup, I heard a lot about objects and object oriented programming (OOP). On some selected toy problems it seemed to have some advantages. Okay. It's good to r
by graycat 11y ago
Yup, I heard a lot about objects and object oriented programming (OOP). On some selected toy problems it seemed to have some advantages. Okay.
It's good to read from the OP and in this thread yet more explanations of what OOP was supposed to be about. Okay.
So, in my current project, I make a lot of use of the classes in .NET and have defined some classes with some methods, etc. Okay -- the encapsulation seems to help make the code easier to understand and debug.
I have made some use of polymorphism, and mostly I like it. So, I use interfaces, and, really, those are a lot like, but much less powerful than, what I used to do in languages where I passed as an argument to a subroutine or function the name of a subroutine or function the subroutine or function could call. E.g., in solving an initial value problem for an ordinary differential equation, have a function that does that and pass to the function a function that will evaluate the differential equation. For finding the minimum value of a function X, have a function Y that is a general purpose function minimizer and pass X to Y and let Y do the work of finding the minimum value of X.
For inheritance, .NET seems to use a lot of it, at least in their documentation, but so far in the code I've written I've never used any of inheritance. I love hierarchical file systems and the idea of inheritances of capabilities and access control lists (ACLs), but I don't really like the idea of inheritance among OOP classes. Sorry 'bout that.
If I want to build an outhouse, then I don't want to inherit a small house and add a toilet -- instead, I just want an outhouse.
For passing messages, sure, I saw that in Smalltalk but never thought to use it among objects in one program.
My server farm architecture and software does have some message passing among some of the back end servers. For a case of that, sure, OOP helps: For the data to be passed, I define a class, allocate an instance, put data into the members of the instance, serialize the instance to a byte string, send the byte string via just old TCP/IP sockets, wait for the response, a byte string, deserialize the byte string to an instance of the class that is supposed to get the returned data, and continue on. If there is an error, then the code writes a message to the Web site log file and returns a notification of an error to the user. Works fine.
For immutable state, no thanks -- e.g., in software about a car, the current state is position and velocity, and as the car moves that state changes and is not immutable. The speedometer of the car does not have immutable state, either, nor the steering, throttle setting, transmission gear, etc. Sure, could define an immutable state separately for each instance of time, but I guess that speedometer makers didn't think of that. If I put some raw meat in the oven and cook it, what comes out should be a good roast, and not something immutable. I think of state as changing, not as immutable.
Some of what the OP describes that is supposed to be real OOP, I was never tempted! No thanks! I never tried that and never would. To me, those rules were obviously nonsense, like programming standing on my head. Able to do it? Yes. Want to do it? No. A good idea anyway? Nope. Good to read that author of the OP now agrees!
But that de/serialization to/from a byte string, I like that! The .NET classes, sure, they are very nice to have. For sending data from one server to another, sure, define a class, allocate an instance, assign values to the members, and send the data -- terrific, easy to understand, works great. E.g, the data I send might be fairly complicated, but classes usually have enough generality that can define good places for all the complicated data.
And, can have arrays of object instances -- terrific! And one of the members of a class can be an instance of another class -- I do some of that.
And the methods have some name scoping, and I very much like that -- I wish that scope of names was much more finely grained, as in Algol and PL/I.
Otherwise I program much like I always have back through lots of various programming languages.
How to make the code easy to understand? By far the most important way is documentation, clearly written in English. Think of a freshman text in calculus or physics: The equations are like the code, and the text is like the documentation of the code. Math is written in complete sentences; there is never any attempt to make the symbols and expressions understandable by themselves. And my code is understandable mostly only due to the documentation. Between the documentation and the code, the documentation is the more important. I make essentially no attempt to write self documenting code, no more than a calculus text author tried to write self-explanatory equations.
For more, sure, I have a lot of functions. A function does something easy to document with logic easy to understand. It helps if each function is short and has relatively few arguments. The documentation for the function describes what the function does -- this is what you give to the function, this is what the function does, and this is what comes back from the function. If that's all nice and clear, then that's usually good enough for well written code.
Sure, in simple terms, a program has four steps:
(1) Get input data.
(2) Process the input data.
(3) Send output data.
(4) Return to (1).
Step (2) is essentially
a function. It reads its argument, processes that data, and returns its results to the arguments and/or the function value. To do this, this function does its version of (1)-(3).
A server? It does (1)-(4).
I call all of this, SCSONUPS -- simple, common sense, obvious, nearly universal programming style. No, no, no, don't thank me. Don't make me famous. No, I won't be writing any books or giving any seminars. I have nothing on Github. If this style is not obviously simple, then I apologize.
I'm not writing code for anyone else. Instead, I own my own business and am writing code for my own business. So, I'm reporting only to myself and am free to write the code anyway I want to. The code I have, I like. With all the documentation, the code is relatively easy to understand and change.
Really the code is organized much like usual work, say, in cooking, lawn maintenance, car maintenance, washing dishes, etc., and the documentation is much like descriptions for how to do such work.
Enough with programming style!
- terminalcommand 11y agoI think you just invented Realism in programming. The programs are written by programmers not academics. There is no perfect way to code something. We should stop the dogma fetishism. Structural/OO/Functional programming theories have all their pros/cons but it can't be proven that one is better than the other. So instead of committing ourselves to the one true cause, we should focus on writing code that achieves its purpose. Why shouldn't we use goto statements at all? PS: I wanted to write "programming is not sacred", but I couldn't. I only use emacs and open source software. I love computers religiously and think that there is something magical about them. So I admit to a certain extent of hypocrisy. We computer geeks are obsessive people.
- graycat 11y agoTerrific! You named it -- Realistic Programming! Now you will be as famous as Dijkstra, Wirth, Knuth, Stroustrup, etc.! Yes, I saw some sense in some of the criticism of the GOTO statement, but, yes, I still use the GOTO statement. Main usage: In a function, some bad situation is detected. Okay, that code might write to a log file and should set a return code value. Then that code just does GOTO OUT which means, time to give and just get out'a here, ASAP, where OUT is a statement label of some code that does whatever general clean up is needed and just returns. There's another cute use of nearly a GOTO: For a loop, have something like DO FOREVER and in the code of the loop, maybe several places, decide when to get out'a the loop and then, do so with a statement LEAVE or some such which is really a GOTO the next statement after the end of the loop. It's essentially a GOTO and in some languages is implemented with an actual GOTO. But there was a totally sweetheart use of a GOTO in PL/I: In some code could have a statement ON FUBAR where FUBAR was a condition that could be raised, and this statement ON was followed by some code to be executed if condition FUBAR was raised. The ON statement made the condition FUBAR enabled and established what to do if the condition was raised. The code of the ON statement could have a GOTO. So, the code of function A has such an ON statement. Function A is called and the execution comes to the ON statement. Now the condition FUBAR is enabled and that ON unit is established for condition FUBAR should it be raised. If the code of function A returns, then that ON condition is no longer established. Function A calls function B which raises condition FUBAR. Then the code immediately jumps to the code of ON FUBAR. If that code executes a GOTO to a label in the code of function A, then all the code in the stack of active code from function A and lower is ended (e.g., storage automatically allocated is freed), and execution continues. So, look, Ma, a way to handle exceptional conditions that is easy to code and understand and does the usual, obvious stuff to clean up the mess for, e.g., no memory leaks. And could do GOTO X, and the X could be a statement label in any code so far called but not yet returned, and the label in the code most recently called but not yet returned would be the target of the GOTO. Again would get stack cleanup. Nice. Ah, Dijkstra would roll over, screaming. GOTOs are a common part of life: If get a flat tire, then raise an exceptional condition, cancel a lot of plans and work in progress, and go to the shop of the towing service and call a cab. If the computer processor fan stops and the processor overheats, then something similar. Lots of common situations in life.