I recently installed the Eclipse Metrics Plugin and have exported the data for one of our projects.
It's all very good having these nice graphs but I'd really like to understand more in depth what they all mean. The definitions of the metrics only go so far to telling you what it really means.
Does anyone know of any good resources, books, websites, etc, that can help me better understand what all the data means and give an understanding of how to improve the code where necessary?
I'm interested in things like Efferent Coupling, and Cyclomatic Complexity, etc, rather than lines of code or lines per method.
I don't think that code metrics (sometimes referred to as software metrics) provide valuable data in terms of where you can improve.
With code metrics it is sort of nice to see how much code you write in an hour etc., but beyond they tell you nada about the quality of the code written, its documentation and code coverage. They are pretty much a week attempt to measure where you cannot really measure.
Code metrics also discriminate the programmers who solve the harder problems because they obviously managed to code less. Yet they solved the hard issues and a junior programmer whipping out lots of crap code looks good.
Another example for using metrics is the very popular Ohloh. They employ metrics to put a price tag on an opensource project (using number of lines, etc.), which in itself is an attempt which is flawed as hell - as you can imagine.
Having said all that the Wikipedia entry provides some overall insight on the topic, sorry to not answer your question in a more supportive way with a really great website or book, but I bet you got the drift that I am not a huge fan. :)
Something to employ to help you improve would be continuous integration and adhering to some sort of standard when it comes to code, documentation and so on. That is how you can improve. Metrics are just eye candy for meetings - "look we coded that much already".
Update
Ok, well my point being efferent coupling or even cyclomatic complexity can indicate something is wrong - it doesn't have to be wrong though. It can be an indicator to refactor a class but there is no rule of thumb that tells you when.
IMHO a rule such as 500+ lines of code, refactor or the DRY principal are more applicable in most cases. Sometimes it's as simple as that.
I give you that much that since cyclomatic complexity is graphed into a flow chart, it can be an eye opener. But again, use carefully.
In my opinion metrics are an excellent way to find pain points in your codebase. They are very useful also to show your manager why you should spend time improving it.
This is a post I wrote about it: http://blog.jorgef.net/2011/12/metrics-in-brownfield-applications.html
I hope it helps
Related
I want to optimize my angularjs frontend application and cleanup the code to provide better code quality.
I thought about bringing in more abstraction, since I implemented a lot of similiar looking, but slightly different controllers.
My question(s) are the following:
Are there common techniques to recognize bad code and optimize it?
How can one determine if code is either good, bad or redundant?
Where should one start, when trying to provide better code quality in
an existing software project?
To answer your questions:
Yes there are: by looking at the code itself experienced programmers can tell if the code has certain characteristics or not. Some metrics exist that could indicate alarm signals in terms of quality like "many dots" in object-oriented languages (same in Javascript) which indicates close coupling. Here is a comprehensive list.
By looking at it or as written before with static code analysis.
As others stated don't optimize or refactor just for the sake to have a good looking code base. When you need to touch existing code again to e.g. add a feature or fix a bug then start to look for code redundancies and many other signals that might indicate to refactor the code. Martin Fowler wrote an excellent book about it with step-by-step examples which IMO is a must-read for every developer. Also a good starting point is Misko's site. He talks about testability but "good" code is well testable.
What's really important before refactoring is to have a strong automated test base to rely on. If not add tests and go really slow to make sure you don't break existing functionality.
The topic is really huge and impossible to work through in a post here but I think it's one of the most important ones that makes an experienced programmer.
If a code is good or bad is your own opinion.
To make the code look better and more efficient I would do something like this:
Don't make the lines to long.
Use variables that make sense.
Use tabs and enter when it is too messy.
There are a whole lot more things to clean up your code, but these are just some examples.
If the code works - don't touch it :)
Then when you work on bug fixes or new features\changes - see if you can also gradually improve pieces of code you are working with. The more you work with the code the better understanding of overall picture you should get and opportunities to improve and optimize should become more obvious. (you should also continue learning from other sources - books, internet, other codebases)
There is now magic "one size fits all" solution :) but yes, you can start with simple style changes as suggested in the other answer.
The process you refer to is commonly known as Refactoring. There are a number of standard techniques for improving code; Martin Fowler's book "Refactoring" has a list, with examples.
Many popular IDEs have refactoring tools built-in.
One of the processes in agile development is known as "red/green/refactor". Red means your code doesn't pass its unit tests; green means it passes (i.e. it does what it's supposed to do), and "refactor" means you make it elegant, maintainable and clean. Because you have a unit test, you know the refactoring doesn't break the code.
Where to start is a tough question - I typically recommend refactoring when you're fixing bugs. You may as well write a unit test to expose the bug, and tidy up the code while fixing the bug. Because that module has a bug, it's likely to be high-risk, so you should improve the code quality.
I am aware that this could be seen as subjective but this is definitely not my intention. I am always on the hunt for techniques that I may have never heard of that help improve both productivity and quality of software engineers.
In particular I am looking for tools, techniques, approaches, tips and tricks, best practices, etc. that helped you to improve both your productivity and quality as a software engineer. This is actually a process related question. So please don't answer with your opinion about which programming language is the best from your perspective.
I expect the answers to be subjective. But that is the beauty of it. Not everything works for everybody. We all have a different set of constraints that we operate under. Therefore it is unavoidable that we make different choices. If the answers are contradictory, that would be perfectly fine!
What were the techniques that were helpful to you specifically? How did they make a difference? What criteria do you use to come to that conclusion?
Ok, here for my subjective answer.
Standard approach for improving quality is unit testing, in my opinion. Of course you can still write crappy code that works and have unit tests that confirm that it works but at least you know that it works. Where unit tests really give you an advantage is when you want to make changes to your code or add additional features. Having unit tests guarantees that your code keeps working.
As for productivity and unit tests it depends whether you look at short-term or long-term productivity. Unit testing takes time so you are less productive writing actual functionality. In the long term I'm absolutely sure you are more productive since your unit tests guarantee that during maintenance all functionality keeps working.
Second productivity and quality enhancing tip is to think each new feature thoroughly through. Once a new feature is shipped, you have to maintain it. Maintenance takes time and decreases productivity. Is the new feature necessary? How many customers actually want this feature? Always try to look at the bigger picture, what is your own vision for your product, does the new feature fit in with this vision.
The less code you have, the less code you have to maintain and the less bugs you have. I always try to keep that in mind.
Delegate to the appropriate party. Then review the assigned task periodically.
Once you know who best to delegate to, who will get tasks done correctly and efficiently, it improves your productivity massively.
It lets you focus on what you want or need to be doing.
Like answering stackoverflow questions for example.
Learning how to use recursion effectively. It's given me a framework to decompose complex problems into understandable code. It's helped me to code tough bits faster with no or very few errors. The book that taught me how to think this way was The Little Schemer by DP Friedman.
The second I'd say was learning Lisp. It's helped me to learn other languages more quickly. I can now classify other languages by the subset of Lisp functionality that they implement.
P.S. I don't use recursion frequently in my software. Most modern languages and frameworks have features and utility functions that allow you to avoid using recursion for simpler problems.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
How do I explain loose coupling and information hiding to a new programmer? I have a programmer who I write designs for, but who can't seem to grasp the concepts of loose coupling and information hiding.
I write designs with everything nicely broken down into classes by function (data access is separate, a class for requests, a controller, about 5 classes total). They come back with a modified design where half the classes inherit from the other half (and there is no "is-a" relationship), and many public variables.
How can I get across the idea that keeping things separate makes it easier to maintain?
Ask him if it's a good idea to let you borrow $10 by giving his wallet to you for a moment and taking the money yourself.
The problem is your expectations, not the developers lack of skill. You talk about loose coupling and information hiding as if these are simple facts or mechanical techniques - they are not. Software development is a craft and the only way to get better at a craft is to practice it and slowly and incrementally improve.
You are looking for a shortcut. You want the developer to experience an "ahah!" moment and suddenly see the wisdom in your design. I say, don't hold your breath.
Adopt the mindset of a mentor. If you want him to improve his design skills, don't "hand" him a design, let him to design it! Then review the design with him. This will give him experience, a deeper sense of ownership and more willingness to listen to your suggestions before he is knee deep in implementation.
An aside - I notice that people look for these shortcuts all the time with abstract skills but not with more "physical" skills. Take tennis for example. If you were a tennis coach and a new player kept hitting his forehands long, you wouldn't just show him a YouTube video of a Roger Federer forehand and expect him to "get it". A great forehand takes YEARS of experience as you learn the feeling and use it in different scenarios - its not your muscles learning, its your brain. It is no different with software design. You get good at it by doing it over and over again. You slowly learn from your mistakes and get better at appreciating the consequences of each individual design decision.
The best way to explain these kinds of concepts is to use analogies. Pick something non-programming related and use that to explain the abstract design concepts.
The following image is pretty good at explaining the need for loose coupling:
Try to come up with stuff like this that will amuse and pertain to your new programmer.
Theory will only get you so far.
Make him try to add new features to code he's written a while ago. Then rework the old code with him so it's loosely coupled and ask him to add the same features.
He will certainly understand the avantages of writing good code.
There's nothing like a physical analogy. Walk out to your car and point out how everything complicated, hot and dangerous is pretty well isolated from the fragile human. Sit in the driver's seat and point out some of the important gauges; for example, the coolant temperature, tachometer and speedometer. Note how the gauges are remarkably similar: they all take a scalar value (from somewhere) and represent it by moving a needle to a position between min and max.
However, if you think about what's being measured, the strong motivation to maintain that isolation (aka loose coupling or information hiding) becomes a lot more obvious.
"How would you like to measure the coolant temperature? By looking at a gauge or by sticking your finger into near-boiling liquid?"
"How would you like to measure the engine rotational speed? By looking at a gauge or by letting a multi-thousand RPM crankshaft rip the flesh from your bones as you try to estimate it by hand?"
"How would you like to measure the car's speed? By looking at a gauge or by dragging your foot on the ground as you're roaring down the highway?"
From there, you can build on the concepts of "your coolant temperature gauge is-a gauge. It isn't-a boiling liquid" and so forth to more complicated concepts.
Loose coupling: The parts of a watch may be replaced by others with out breaking the whole watch. For instance you can remove one hand and it will still work.
Information hiding: The clock hands doesn't know that behind them there's a machinery.
Additional concept
High cohesion: All the elements in the watch "module" are strongly related. In this specific scenario, a battery would belong to another module or namespace.
Show him this presentation. Though it's mainly about DI, it's downright brilliant and up to the point.
I would try sitting down with him and working through a couple of peieces of code with him looking over your sholder and you explaining why you are doing what you are doing as you go along. I've found this is normally the best way to explain things.
Ask him to make a change you know it will be hard because of his design and show him how that would happen using yours.
If he complains, tell him the truth: business will ask more bizarre changes, it's a matter of time he will see that.
Just don't talk to him. That should teach him about information hiding. ;-)
I like a credit card for an example.
You have a credit card.
A credit card represents your credit history. It has a balance and a APR. It has permissions and an entire financial state. It has a id, an expiration date, and a security code. The magnetic strip summarizes all of this.
When you go to your local credit-card-accepting establishment, they don't need to know that. They don't want to know that, and it is often very dangerous if they do know that. What they need to "know" is that there is a magnetic strip which will take care of all of this, and (sometimes) that the person holding the card has id to match the name printed on the card.
Giving them more information is either (in the best case) useless, or (in the worst case) dangerous. Requiring them to know which bank to check with, making sure they know how to calculate your particular APR, or allowing them to check your balance is simply silly at that point.
If he's misinterpreting your designs, perhaps a couple pair-programming sessions will be enough to get them on track. I do have to agree with #ThomasD and will expand upon it -- the encapsulation going on here could be you. It could be a simple case of misinterpretation instead of them not understanding the concepts.
I think that OO concepts really need to be learnt practically. One really needs to do these things to understand. I go to school (engineering) and most of my peers don't really get the concept. They know in general that loose coupling is 'good' but not why. They also don't know how to achieve loose coupling. I am working on my final year project now and I got through to them by making them part of the design process. (It helped that they really did understand how and why and had an inkling of its importance)
Given your situation, here is what I would suggest:
1. Make them follow your design exactly (at least for a couple of weeks). If they want to deviate, have them discuss what and why with you. [Time constraints may not permit this].
2. Sit with them on whichever part of the design you are doing next and explain some o0f your design choices to them, with examples. Somethings that are obvious to you may need to be pointed out to them.
3. Be on the lookout for examples, both of good design and bad design and show them how that works better.
The most important task here is of delegation. You have to show them what good code looks like, maybe train them for a couple of hours. Then you agree on when to review and how you can help them (whithin your limited free time (?)) do the task well. The main thing is to get them to identify with and understand good design. Doing these things will help them 'buy-in' to the design. Once they feel it is their design, I am sure they will do better work.
Overall, I think you need to put your foot down and get them to code it right, without stifling their creativity.
I don't really have too much experience in the area. I am just giving my opinion on the subject, based on what worked for me. I hope this helps.
Note
I'd like to add that OO concepts can be learnt from books, while their application can be learnt only by practice. I have added this note in response to a comment by Christopher W. Allen-Poole.
Well if you have to explain it to them then I'm forced to ask: are they really a programmer?
Tell them they need a "college do over"?
That's a hard one because it's such a basic concept. Personally I wouldn't want to handle it because it's like someone is getting paid to learn stuff they should already know but life isn't always ideal.
I'd approach it by finding a problem that's simple enough to solved relatively simple. Public variables are usually handled best by trying to find the source of a problem when you can't see what's changin gthe variables. You can design a scenario for that.
The over-inheritance may not be their fault. They may have learnt in a course designed in the 90s that's trapped in the idea that "everything must inherit". I remember the old examples of Manager extends Employee. It's just BAD. Thing is people get taught this nonsense. Still.
For C++ the Scott Meyer Effective C++ series is probably worth poniting them to (assuming they can be bothered to read something). For Java, Josh Bloch's Effective Java ("favor composition") is along the same lines. Not sure about C#.
These sorts of books give a better approach to inheritance vs composition and also give some good examples of why inheritance is (as Josh Bloch puts it) an "implementation detail". I've also heard it described as "inheritance breaks encapsulation".
I saw a good example once of inheritance vs composition with extending the capabilities of a List in Java and how inheritance required you to know implementation details of the parent to do correct whereas composition didn't. I'll see if I can find it.
If you do Unit Testing, explain it in terms of test-writing. Alternatively, Abstract Classes and Interfaces both use loose coupling and information hiding to great effect. If you explain it to him in terms of other concepts he may already have a handle on, he'll be more likely to appreciate the concept quickly.
Programs are systems of interacting parts.
For a system of interacting parts to work together requires connections between these parts.
The more connections, the more costly the program.
For a fixed number of parts, a system whose parts are unnecessarily connected is more costly than a system whose parts are necessarily connected.
Unneccessary connections can only be formed in a system whose parts are unnecessarily exposed to connections from other parts.
Minimising unneccessary exposure of parts to connection from other parts is fundamental to cost-effective program development.
Loose coupling and information hiding are the fundamentals of connection-exposure minimisation.
This is not optional knowledge for a programmer.
This is fundamental.
You cannot be a cost-conscious programmer without this knowledge.
Asking how to explain loose coupling and information hiding to a new programmer is like asking how to explain surgery to a new surgeon? Or to explain architecture to a new architect? Or how to explain flying to a pilot.
If your, 'New programmers,' don't know loose coupling and information hiding, then they are not, 'New programmers;' they are potential programmers.
Curiously, it probably won't help to tell them to read the original two papers:
i)Loose coupling: 'Structured design,' by W.P. Stevens, G.J. Myers and L.L. Constantine.
ii)Information hiding: http://www.cs.umd.edu/class/spring2003/cmsc838p/Design/criteria.pdf
Just like the move from 16 bit to 32 bit windows applications where processes were given their own address space. This stopped any other process from being able to kill your application when it "accidently" walked over your data.
Moving processes to different address spaces was like treating each process as a class, and hiding the memory internally and decoupling the processes by forcing interprocess communication to only happen via an expected interface ( eg Windows Messages ).
loose coupling means the external code should use the object of derived non abstract class through abstract base class. if any change occur in set of class on which it depend then not neccessory to change in external code i.e. external code really exhibit loose coupling.
So no doubt that building a domain model is something that I think happens best when you approach it as as team. Even going so far as to involve someone who is not technical and a member of the 'business' in the modeling sessions. So much can get done quickly when you put the right people in a room and hammer out things on a whiteboard. But what about the times that you don't have that luxury? What about when you have to build a complex domain model alone? I have been doing this for the past month or so and have done the following:
Start off by Noun Idendtification, then use Class-Role-Collaborations to analyze relationships
Look for analysis patterns that can be used to refine the model, Party, etc..
As soon as I have a handle on the basics, I'll bust out an IDE and start writing XUnit tests to show that the model let's me do the things that I want
While these techniques have worked well, I'm not sure they are as efficient as a truely collaborative effort. I think it is easy to get carried away with a concept only to realize later that it violates x or y requirement. What techniques have you used when working in isolation to ensure that your object/domain model is on target?
Everyone does it differently, I think, but...
I almost always start with a Class diagram (usually UML-like and on paper), paying special attention to relationships between classes and their arity. Validation at this stage is mostly trying to understand if the high-level semantics of the entities make sense together.
Then start sketching in the key functions, especially those involved in collaborations. Make sure objects in a collaboration can reach each other through the relationships. At this stage I'll be using a drawing tool (StarUML).
Then come the gedanken experiments. I mentally walk through the trickiest use cases I can think of and see if I can envision a way to address them with the given design. This isn't psuedocode, just stepping through each of the major tasks/functions and following the lines of the diagram to make sure I'm not missing callbacks, circular dependencies, etc.
I think one key is to not get too married to any particular aspect of the design until you've satisfied yourself that it will probably work reasonably well. In my mind, if you can't step through a design mentally to evaluate/validate it you either lack some understanding of the problem, or the design on paper isn't complete enough...
Then, time permitting, set that one aside and see if you can come up with something really different...
If you're building it all on your own, just make sure it's adaptable, because there's no way you'll think of everything on the first shot.
Get some big paper. Draw everything out, and be messy. Don't worry about making it perfect. Put everything down that you think of, cross out stuff as it proves to not be useful. The paper will look like your mind threw up pieces of an object model all over the place. As you think of things that have already been written down, make those things stand out. At the end of this process, you'll have a mess, but for sure you'll have a lot of good ideas. At this point, I would recommend showing this to people, but since you said that's out of the question, we'll move on.
Now sit down in front of a computer with a UML tool and map out something that resembles the highlights of your brain dump. Think of the major pieces of the object model and then think of the more minor things that enable those pieces to work together. Once you have settled on something, turn that UML into code and go about writing some tests to see if it works. Rinse and repeat.
I've been quite used to working on small projects which I coded with 1,000 lines or less (pong, tetris, simple 3d games, etc). However as my abilities in programming are increasing, my organization isn't. I seem to be making everything dependent on one one another, so it's very hard for me to change the implementation of something.
Any ideas for keeping my code organized and being able to tackle large projects?
whiteboards are your best friends
prototype designs (not necessarily working prototypes, use notecards or other methods)
plan first! dont code until you know your requirements/goals
Sketch out an architectural design ahead of time. It doesn't have to be too detailed, but imagine how you want things to fit together in general terms.
Read into refactoring first (made famous by Martin Fowler).
By learning refactoring, you can learn how to write code which is easy to change, readable, and simplified.
I would suggest not to learn design patterns until you understand refactoring first. With refactoring, you can understand the themes of clean and readable code. Once you understand refactoring, read on to design patterns. Design patterns is very useful when you need to write more complex designs.
Use of design patterns is a good first step.
Also, spend a little time writing good documentation regarding system architecture and requirements for the application.
Using source control will help if you are not already doing this.
Look for libraries that may do want you want before you decide to roll your own.