Redundancy, testability and readability are key to building simple and maintainable code. In the fourth extract from his book, Emergent Design: The Evolutionary Nature of Professional Software Development, published by Addison Wesley, Scott Bain tackles the problems and principles involved. We all saw an example of redundancy …
Imperial IntelAIgent Design .... for Massive PreDominantly Passive Systems
That was as cogent and precise a piece of Code revealing the Simple Complexity and Hidden Strength in Transparency and the Power of Text as AI Language as ever I have yet read. Bravo.
With such Skills, Allied to such Thoughts as were Shared, are Dynasties Born and/or Secured, for they are the Core Source Base for Anything with the Potential to Deliver and Build with Future Value.
Heap Powerful Binary Medicine, Kemo Sabe, which can with Simple Words and Real dDeep Understanding, Wipe out and Rebrand Generations of Failure with Nascent Success.
author doesn't understand accessors (set/get methods)
The purpose of accessor methods is to abstract the data in your class. Having a protected bullets counter is only scarcely different from making it private and having getbullets() and setbullets() methods.
The *reason* you abstract the bullets counter into accessor methods is so you don't have to have a bullets counter at all (!)
What if you are building a class of automatic weapons, and you want to implement all firing methods in terms of a burst. Your tommy gun fires a ten-round burst. Your pistol fires a 1-round burst. You want to talk about your bullets in terms of bursts, instead of bullets.
Having a protected bullets counter fixes your implementation in terms of bullets, not bursts. You want to write your data access in terms of bursts and the operations you wish to use on bursts, like burstfire() which consumes a burst and reload() which puts a new magazine in, containing however many bursts it contains.
Now, you might decide that the operations you want to support are firing bullets, not firing bursts. In that case, the operations on bullets are expend() and reload(). Now you aren't counting bullets. You're performing allowed operations on your chosen abstraction. It's not the choice of abstraction that matters, it's the use of abstraction.
Interface/abstract class - not an either/or
Many people (self included) would argue that a better solution to your first example is to keep the interface of Weapon and introduce a parent class to Pistol and TommyGun called AbstractWeapon. That way you get to keep the independence of the interface (any class can implement Weapon without being a subclass of *your* AsbtractWeapon). The best of both worlds.
"lucky enough to know the Template Method pattern"?
I fail to see that anything he has to say has any relvence to the Y2K fiasco.
In the late seventies and early eighties programmaers userd various methods to save storage when storing dates such as two digit years storing the dates as BCD, storing dates in Julian format (YYDDD) etc.
These were perfectly valid design desciaions at the time given the high cost of disk storage approx $100 per MB and the fact that most systems up till then were replaced in less than 10 years.
However upward compatability, better languages, better compilers, and, improved design processes meant that many these systems were still running quite happily thirty years later.
At which point a number of charlatans crawled out of the woodwork and said the sky would fall in everybodies head on January 1st 00 -- unless they handed over a sack of cash in consultancy fees.
If you want evidence of the waste involved there is a nice little story about the Italian government being pressured by the US state department to increase thier very level low Y2K spending, which the Italians politly ignored. On January 1st 2000 the only reported Y2K incident was that the ticket machines for the Milan tram system stopped working. As a result the Milan public transport system lost a days takings (on a very quite day) and the Italian econamy saved itself several billions (well squillions as it was lire).
The simple fact no computer in 1970 could have compiled and run a java program in less than a week. Yes we now have faster machines and can afford to waste cycles on all this OO malarky but they are still trying to master fixed point decimal arithmatic.
As a recently self taught professional (they keep paying me) C++ programmer (and probably not a very good one) I have not written many test and I've certainly not done so in a systematic way. One of the best points of this article is to highlight the correlation between good design and testable code. I must educate myself further on good testing practices.
As by AC above, but also consider: there is a consistent logical path from Requirements to Interfaces to Abstracts to Concretes. Although we can realize short-term gains by skipping one of these steps, keeping all steps provides a useful overview, metadata for the construction of documentation and to help focus testing and debugging, and checks to prevent or minimize the final project drifting from the requirements.
Why do you think your math teacher always told you to show your work?
Personally, I'd build one overclass (Weapon,) and two subclasses (AbstractWeapon and RealWeapon) which you only protect one and build calls to the other in the overclass.
Why? Simple--readability. You only need to call Weapon if you're only gonna fire things externally, not internally. You can even dispense with all three suggested classes into one superclass if you used C++, thanks to its inherent private/protected/public section calls within the class definition.
If you want to understand this stuff better, I'd reccomend building your own GUI handler. It gets tricky up higher, but once you understand what every single element has, it becomes fairly trivial to abstract in function. (The hardest part, IMO, is the textboxes. You try implementing a word-wrap feature into a predefined size for a textbox.)
Gets the Point; Then Drops It
The point is, Keep It Simple, Stupid. Java (and all OO) is inherently a complex way to implement most business applications. Most business objects are already abstractions of reality (money, deadlines, interest rates, taxes). Adding another level of abstraction is about as useful as learning to fart the Warsaw Concerto. Which is why you will always see OO examples of classes as something tangible- guns, fruit or books. Try doing payroll, instead, and COBOL suddenly looks very advanced and useful by comparison. Finally, after 26 years of this, my rule of thumb in code reuse for business applications is that if it doesn't substitute for a system routine (e.g. Date or Time) then it probably isn't worth coding as a separate routine or method. Just put inline.
Properties an "entirely new language feature in .NET" ?!
...only if you were completely ignorant of other languages that had precisely the same language feature for years before .NET was even envisaged, i.e. Delphi and heck, even VB!
It's this sort of technical slip up that fatally undermines the credibility of any technical article, no matter how salient the points may be that it is conveying.
Paris because she delights in making her private parts public.
oh, and some of what Jolyon said.
Reading the article reminded me of the IBM 'buzz word bingo' commercial. Lots of buzz words to say that nothing (except the buzz words) has changed much over the years. Programmers have been using these same concepts for decades, thing is, we just didn't make up fancy names for them.
Oh, and what James Anderson said about the Y2K fiasco (I second that). It really irritates me when people refer to it as a bug or a programming mistake. It was done, on purpose, for some very good business reasons. And, those of us who knew much about computers knew that the century change would be at most an irritation, no airplanes falling out of the sky.
98, 99, ... (text required by Reg comment posting system)
Yes but "those of us who knew much about computers " also knew that
a) the potential scope was, at the time, unknown
b) doing nothing was not an option
Additionally I recall that much robustness improvement came out of the "Y2k" work as a by-product of the reviews and testing work.
Aircraft falling from the sky was not likely, but it was not possible to say how unlikely at the time.
More likely was out-by-one (or worse) errors in flight navigation systems or air traffic control, or counters logging flying hours that scheduled component replacements.
Failure to replace components _could_ have resulted in aircraft loss when the component failed.
- Just TWO climate committee MPs contradict IPCC: The two with SCIENCE degrees
- Apple winks at parents: C'mon, get your kid a tweaked Macbook Pro
- SOULLESS machine-intelligence ROBOT cars to hit Blighty in 2015
- China in MONOPOLY PROBE into Microsoft: Do not pass GO, do not collect 200 yuan
- BuzzGasm! Thirteen Astonishing True Facts You Never Knew About SCREWS