|
Prev: English to UML
Next: clean code vs dirty code smack down! (was: Simples Rules make creating Big Balls of Mud impossible.)
From: topmind on 26 Jan 2007 19:12 Robert Martin wrote: > On 2007-01-25 22:53:48 -0600, "topmind" <topmind(a)technologist.com> said: > > > > > Robert Martin wrote: > >> On 2007-01-24 01:35:40 -0600, frebe73(a)gmail.com said: > > > >> Consider this: > >> > >> Select employee_number from employee where date_of_birth < 1952 and sex > >> = F and employment_type = EXEMPT OR emloyment_type = SPECIAL and salary > >> > 90000; > >> > >> I'd like to hide this behind: > >> > >> find_all_employees_eligible_for_early_retirement(); > >> > >> Firstly, it makes the program easier to understand. > > > > Do you think that those who disagree WANT hard-to-understand programs? > > No. What does that have to do with my statement? You are implying that we don't know the difference between "easy to understand" and "hard to understand", and that is why we don't wrap more. I know pretty well after all these years what trips me up and what doesn't. What I cannot do is heavily extrapolate that to everybody else because brains are too different. > > Perhaps SQL trips you up, > > No. > > > but you have to be > > careful which psychology of yours you extrapolate to other human > > beings. > > You are completely missing the point. The Select statment above is > loaded with detail. (DOB, salary, emloyee type etc). The function > simply named the policy. Hiding that detail behind the policy name is > a good, and very old, engineering discipline. Not every damned detail under the sun. This sounds similar to a debate that raged on C2 a few years ago: http://c2.com/cgi/wiki?HeadlinesTechnique http://c2.com/cgi/wiki?LongFunctionsDiscussion > >> Secondly, it > >> isolates the policy from the implementation. I can change the > >> implementaiton of the SQL statement without affecting the functions > >> that call find_all_employees... > > > > But you fail to consider simplicity. If such a statement is only used > > *once*, then wrapping it in a function/method creates more code and > > more red tape. That creates confusion and slower productivity in > > itself. It is not a free lunch. > > 1. That's a big if. > 2. Putting a select statement into a function requires a negligible > amount of code that has a one-time negligible cost. It adds code, interface maitaining layers, and fill up the "function space". > 3. Giving the select statement a name reduces confusion and increases > productivity every time the statement is read. Not specific enough. Too much clutter slows me down, and superfulous chunk-a-tizing creates clutter. > > > I agree that if it is used several times, then it makes sense to put it > > into a shared function. But you seem to want to wrap ever last one. > > In general I do. For any number of different reasons. > > 1. It's clearer. By what metric? You again seem to be extrapolating your personal preferences to others. > 2. It's easier to test since I can replace the function implementations > with canned data. I see no reason to test at such a small level. Testing an SQL statement outside of the context of the app is of marginal use anyhow. Do you wrap every math formula and reg-ex also? // RCM lampoon code .... x = addThreeNumbers(a, b, c); .... function addThreeNumbers(a, b, c) { return(a + b + c); } > 3. I can deploy the business rules that call the functions separately > from the SQL that implements the functions. (This is a big deal for > most medium to large systems, and even has significant impact on > smaller systems) Please clarify. > > > -- > Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com -T-
From: Robert Martin on 29 Jan 2007 18:15 On 2007-01-26 18:12:29 -0600, "topmind" <topmind(a)technologist.com> said: > You are implying that we don't know the difference between "easy to > understand" and "hard to understand", and that is why we don't wrap > more. I know pretty well after all these years what trips me up and > what doesn't. What I cannot do is heavily extrapolate that to everybody > else because brains are too different. Consider this: Select employee_number from employee where date_of_birth < 1952 and sex = F and employment_type = EXEMPT OR emloyment_type = SPECIAL and salary > 90000; I'd like to hide this behind: find_all_employees_eligible_for_early_retirement(); It seems to me that the first exposes implementation and the second exposes intent. Generally, when programs expose intent, they are easier to understand. -- Robert C. Martin (Uncle Bob)��| email: unclebob(a)objectmentor.com Object Mentor Inc.� � � � � ��| blog:��www.butunclebob.com The Agile Transition Experts��| web:���www.objectmentor.com 800-338-6716� � � � � � � � ��|
From: topmind on 29 Jan 2007 18:35 Robert Martin wrote: > On 2007-01-26 18:12:29 -0600, "topmind" <topmind(a)technologist.com> said: > > > You are implying that we don't know the difference between "easy to > > understand" and "hard to understand", and that is why we don't wrap > > more. I know pretty well after all these years what trips me up and > > what doesn't. What I cannot do is heavily extrapolate that to everybody > > else because brains are too different. > > Consider this: > > Select employee_number from employee where date_of_birth < 1952 and sex > = F and employment_type = EXEMPT OR emloyment_type = SPECIAL and salary > [greater than] 90000; [greater than symbols throw off indenter so I replaced it.] > > I'd like to hide this behind: > > find_all_employees_eligible_for_early_retirement(); > > It seems to me that the first exposes implementation and the second > exposes intent. Generally, when programs expose intent, they are > easier to understand. Do this: // find employees elegible for ealy retirement rs = query(std, "SELECT emp_no FROM employees WHERE..."); It is unnecessary to create a function/method JUST to name something. And if there are parameters (usually the case), then there is the extra effort of maintaining the interface parameters. Further, it clogs up the function space with names like: find_all_good_ employees_eligible_for_early_retirement(); find_all_bad_ employees_eligible_for_early_retirement(); find_all_employees_eligible_for_raises(); find_all_employees_who_didnt_pay_their_parking_permit(); find_all_employees_who_dont_have_parking_permits(); find_employees_who_lost_a_pink_sweater_last_friday(); find_employees_who_think_oop_is_the_pits(); The big-picture functions get lost in the dandruff of SQL wrapping. Large function spaces decrease the speed of me finding functions and groking the app. I know that is a fact for me. It is a truism for me. If you have a magic memory or are a speed-reader, congratulations for being a superior being. But I am not a speed reader such that your assumptions about what throws you off do not necessarily apply to me. I KNOW WHAT SLOWS ME DOWN better than anybody because I am stuck with my body and my brain (for good or bad) and have been for many many decades. You wouldn't do this I assume: x = sumFourNumbers(a,b,c,d); .... function sumFourNumbers(a,b,c,d) { return(a + b + c + d); } If you *wouldn't* do it for math, then why would you do it for queries? When such functions/methods are single-use, you are crossing the line between hiding implimentation and making an e-beurocracy out of code. K.I.S.S. is an important factor in easy maintanence. > -- > Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com -T-
From: Robert Martin on 29 Jan 2007 22:41 On 2007-01-29 17:35:39 -0600, "topmind" <topmind(a)technologist.com> said: > > Robert Martin wrote: >> On 2007-01-26 18:12:29 -0600, "topmind" <topmind(a)technologist.com> said: >> >>> You are implying that we don't know the difference between "easy to >>> understand" and "hard to understand", and that is why we don't wrap >>> more. I know pretty well after all these years what trips me up and >>> what doesn't. What I cannot do is heavily extrapolate that to everybody >>> else because brains are too different. >> >> Consider this: >> >> Select employee_number from employee where date_of_birth < 1952 and sex >> = F and employment_type = EXEMPT OR emloyment_type = SPECIAL and salary >> [greater than] 90000; > > [greater than symbols throw off indenter so I replaced it.] > >> >> I'd like to hide this behind: >> >> find_all_employees_eligible_for_early_retirement(); >> >> It seems to me that the first exposes implementation and the second >> exposes intent. Generally, when programs expose intent, they are >> easier to understand. > > Do this: > > // find employees elegible for ealy retirement > rs = query(std, "SELECT emp_no FROM employees WHERE..."); Why? All that does is add detail to what would otherwise be a nice clear program. Why would you prefer: // DO A akwlke;rlkj;wlekmrw;lekjrwe welrkjwe;lkrjw;lekjrw;lkejr lwje;lkrjw;eiruw;elkrnw;leknrp;owie we;lkrjw;eoijrw;lekr wekljrwpeoijrw[oeirjw;elkrnj l;wker;owijer;lkwejmrpoijw // DO B w;lekjr;wlkmnef[owiejf;lwkejnf welkjwe;lrkjw;elkrjw;eiorjw;elrknjwer welkjrwo;eklrjw;elirjWer;lkwjer;lkj wejklrw;eijo wer;lkjwe;riljwe we;lrkjweporiwerpoiu to just: DO_A(); DO_B(); Oh, and then there's the problem of comments that don't actually describe what's going on because they don't get maintained. Yes, I know we shouldn't do that, but... > > It is unnecessary to create a function/method JUST to name something. It may not be necessary, but it is remarkably beneficial. > And if there are parameters (usually the case), then there is the extra > effort of maintaining the interface parameters. Again, we like to make sure the parameters have meaning, so that the code reads well. > > Further, it clogs up the function space with names like: > > find_all_good_ employees_eligible_for_early_retirement(); > find_all_bad_ employees_eligible_for_early_retirement(); > find_all_employees_eligible_for_raises(); > find_all_employees_who_didnt_pay_their_parking_permit(); > find_all_employees_who_dont_have_parking_permits(); > find_employees_who_lost_a_pink_sweater_last_friday(); > find_employees_who_think_oop_is_the_pits(); So what? The functions space is big. > The big-picture functions get lost in the dandruff of SQL wrapping. That's just silly. Lesser theorems do not get lost in the dandruff of larger theorems. Go back to geometry and prove that the sum of angles in a triangle is 180 using nothing but postulates and no sub theorems. > Large function spaces decrease the speed of me finding functions and > groking the app. Quite to the contrary. > I know that is a fact for me. It is a truism for me. If you have a > magic memory or are a speed-reader, congratulations for being a > superior being. I have an IDE. > But I am not a speed reader such that your assumptions about what > throws you off do not necessarily apply to me. I KNOW WHAT SLOWS ME > DOWN better than anybody because I am stuck with my body and my brain > (for good or bad) and have been for many many decades. I don't doubt that you do. However, you tend to make assumptions for everyone. e.g. OOP_IS_MAD. > You wouldn't do this I assume: > > x = sumFourNumbers(a,b,c,d); > ... > function sumFourNumbers(a,b,c,d) { > return(a + b + c + d); > } No, but I would very likely do this: function computeInitialRentPayment(securityDeposit, monthlyRate) { return securityDeposit + monthlyRate; } > > If you *wouldn't* do it for math, then why would you do it for queries? Because queries have an intent that is not communicated by their syntax. > When such functions/methods are single-use, you are crossing the line > between hiding implimentation and making an e-beurocracy out of code. > K.I.S.S. is an important factor in easy maintanence. K.I.S.S. does not mean: "hide intent". -- Robert C. Martin (Uncle Bob)��| email: unclebob(a)objectmentor.com Object Mentor Inc.� � � � � ��| blog:��www.butunclebob.com The Agile Transition Experts��| web:���www.objectmentor.com 800-338-6716� � � � � � � � ��|
From: topmind on 30 Jan 2007 18:05
Robert Martin wrote: > On 2007-01-29 17:35:39 -0600, "topmind" <topmind(a)technologist.com> said: > > > > > Robert Martin wrote: > >> On 2007-01-26 18:12:29 -0600, "topmind" <topmind(a)technologist.com> said: > >> > >>> You are implying that we don't know the difference between "easy to > >>> understand" and "hard to understand", and that is why we don't wrap > >>> more. I know pretty well after all these years what trips me up and > >>> what doesn't. What I cannot do is heavily extrapolate that to everybody > >>> else because brains are too different. > >> > >> Consider this: > >> > >> Select employee_number from employee where date_of_birth < 1952 and sex > >> = F and employment_type = EXEMPT OR emloyment_type = SPECIAL and salary > >> [greater than] 90000; > > > > [greater than symbols throw off indenter so I replaced it.] > > > >> > >> I'd like to hide this behind: > >> > >> find_all_employees_eligible_for_early_retirement(); > >> > >> It seems to me that the first exposes implementation and the second > >> exposes intent. Generally, when programs expose intent, they are > >> easier to understand. > > > > Do this: > > > > // find employees elegible for ealy retirement > > rs = query(std, "SELECT emp_no FROM employees WHERE..."); > > Why? All that does is add detail to what would otherwise be a nice > clear program. Why would you prefer: > > // DO A > akwlke;rlkj;wlekmrw;lekjrwe > welrkjwe;lkrjw;lekjrw;lkejr > lwje;lkrjw;eiruw;elkrnw;leknrp;owie > we;lkrjw;eoijrw;lekr > wekljrwpeoijrw[oeirjw;elkrnj > l;wker;owijer;lkwejmrpoijw > > // DO B > w;lekjr;wlkmnef[owiejf;lwkejnf > welkjwe;lrkjw;elkrjw;eiorjw;elrknjwer > welkjrwo;eklrjw;elirjWer;lkwjer;lkj > wejklrw;eijo > wer;lkjwe;riljwe > we;lrkjweporiwerpoiu > > to just: > > DO_A(); > DO_B(); > Often I do. It reduces "jumping around" to inspect details, and reduces the maintenence of interfaces/parameters. I've tried to get out of the business of telling people what their eyes and brains *should* like. I've found out the hard way that people think differently. Some have fast eyes and slow brains, and visa versa, and compensate in different ways. I don't insist that my pet tools are objectively better, but rather now try to focus on why they fit my mental work processes (personal psychology). There are times where I think my pet tech objectively favors the change pattern frequencies I observe, but we disagree on these frequencies also. One can show that something is better for given change frequencies, but the actual values of such frequencies are merely anecdotal at this stage. Note that I prefer dashes for larger blocks: // ------ Do B w;lekjr;wlkmnef[owiejf;lwkejnf welkjwe;lrkjw;elkrjw;eiorjw;elrknjwer welkjrwo;eklrjw;elirjWer;lkwjer;lkj wejklrw;eijo // ------- Do C w;lekjr;wlkmnef[owiejf;lwkejnf welkjwe;lrkjw;elkrjw;eiorjw;elrknjwer wsdfsf... > Oh, and then there's the problem of comments that don't actually > describe what's going on because they don't get maintained. Yes, I > know we shouldn't do that, but... Same applies to function/method names. A program can still work even though the function/method name has grown obsolete. Thus, there is no immediate incentive to fix it, just like comments. > > > > It is unnecessary to create a function/method JUST to name something. > > It may not be necessary, but it is remarkably beneficial. I disagree in many cases. > > > And if there are parameters (usually the case), then there is the extra > > effort of maintaining the interface parameters. > > Again, we like to make sure the parameters have meaning, so that the > code reads well. Often they just feed something with a name into something else with a similar name. Wasting code going in and out and in and out and up and down. Mamma's got a squeaze-box... > > > > Further, it clogs up the function space with names like: > > > > find_all_good_ employees_eligible_for_early_retirement(); > > find_all_bad_ employees_eligible_for_early_retirement(); > > find_all_employees_eligible_for_raises(); > > find_all_employees_who_didnt_pay_their_parking_permit(); > > find_all_employees_who_dont_have_parking_permits(); > > find_employees_who_lost_a_pink_sweater_last_friday(); > > find_employees_who_think_oop_is_the_pits(); > > So what? The functions space is big. But human brains and eyes have limits. It is the people who we are catering to here, not so much the machines. > > > The big-picture functions get lost in the dandruff of SQL wrapping. > > That's just silly. Lesser theorems do not get lost in the dandruff of > larger theorems. Go back to geometry and prove that the sum of angles > in a triangle is 180 using nothing but postulates and no sub theorems. Sub-theorems are fine. Sub-Sub-Sub-Theorems are overkill in my opinion. > > > Large function spaces decrease the speed of me finding functions and > > groking the app. > > Quite to the contrary. Please re-read this. I don't think you realized what you just objected to. > > > I know that is a fact for me. It is a truism for me. If you have a > > magic memory or are a speed-reader, congratulations for being a > > superior being. > > I have an IDE. Still it produces more candidate matches to visually sift thru. Plus, if you print out code for paper-based inspection, one may not have an IDE. Further, one can tune an IDE to work around many of the problems you claim exist in p/r code. > > > But I am not a speed reader such that your assumptions about what > > throws you off do not necessarily apply to me. I KNOW WHAT SLOWS ME > > DOWN better than anybody because I am stuck with my body and my brain > > (for good or bad) and have been for many many decades. > > I don't doubt that you do. However, you tend to make assumptions for > everyone. e.g. OOP_IS_MAD. "Mad" is not necessarily a technical term. See above regarding my anti- OO rants. Your book is written as if your design decisions are a mathematical truism, not a subjective preference. I object to the industry implication that OO is a slam-dunk sureshot. If it is a subjective personal proference, they should clearly tell the readers. > > > You wouldn't do this I assume: > > > > x = sumFourNumbers(a,b,c,d); > > ... > > function sumFourNumbers(a,b,c,d) { > > return(a + b + c + d); > > } > > No, but I would very likely do this: > > function computeInitialRentPayment(securityDeposit, monthlyRate) { > return securityDeposit + monthlyRate; > } You're kidding, right? I think our differences are far beyond OO versus p/r. > > > > > If you *wouldn't* do it for math, then why would you do it for queries? > > Because queries have an intent that is not communicated by their syntax. That is why we have comments. Plus, often there is only one SQL statement per task such that the task name describes what it does. > > > When such functions/methods are single-use, you are crossing the line > > between hiding implimentation and making an e-beurocracy out of code. > > K.I.S.S. is an important factor in easy maintanence. > > K.I.S.S. does not mean: "hide intent". It does not mean wrap every piece of dust either. > > > -- > Robert C. Martin (Uncle Bob) | email: unclebob(a)objectmentor.com > Object Mentor Inc. | blog: www.butunclebob.com > The Agile Transition Experts | web: www.objectmentor.com > 800-338-6716 | -T- |