# Eclipse Code aufklappen/zuklappen (Code Folding)



## Taneeda (21. Jan 2009)

Hallo zusammen,

Ihr kennt bestimmt von anderen Editoren, z.B. Notepad++, die Fähigkeit den Code (Kommentar, Methode, Schleife, ...) zu- und wieder aufzuklappen... Bei Eclipse ist es nun ja so, das man lediglich die Methoden zu- bzw. aufklappen kann.

Gibt es eine Möglichkeit dies in Eclipse zu erweitern um eine ähnliche Funktionalität wie bei Notepad++ zu erreichen?

Gruß

(edit)
gibt es eine Möglichkeit, dass sich Eclipse wenigstens merkt, was auf- bzw zugeklappt ist?


----------



## Ebenius (21. Jan 2009)

Ich weiß nicht, was es für Möglichkeiten gibt. Aber wenn Du was suchen willst, dann hilft evtl. der Hinweis "Folding" als Suchwort...


----------



## Taneeda (21. Jan 2009)

guter Hinweis, danke die Ebenius, wusste nicht wie man das nennt


----------



## Taneeda (21. Jan 2009)

gesucht, gefunden, danke dir Ebenius...

hier das Plugin: http://www.realjenius.com/platform_support
und ne kurze Einleitung: http://www.bravehartk2.de/index.php?id=35


----------



## byte (21. Jan 2009)

Folding ist so unsinnig ^^


----------



## Taneeda (21. Jan 2009)

also ich empfinde das schon als Erleichterung, gerade bei großen Methoden, wenn man nur das sieht, was man will...

nur optimal isses so nicht, da das Folding nicht gespeichert wird. Wenn das noch gespeichert werden würde, dann wärs perfekt ^^


----------



## byte (21. Jan 2009)

Methoden und Kommentare kann Eclipse per Default folden.


----------



## tfa (21. Jan 2009)

Taneeda hat gesagt.:
			
		

> also ich empfinde das schon als Erleichterung, gerade bei großen Methoden, wenn man nur das sieht, was man will...
> 
> nur optimal isses so nicht, da das Folding nicht gespeichert wird. Wenn das noch gespeichert werden würde, dann wärs perfekt ^^


Wenn du deine Methoden so schreibst, dass man kein Folding braucht, dann wäre es perfekt.
Folding ist neben Spellchecking das erste was rausfliegt, wenn ich mir einen neuen Eclipse-Workspace mache.


----------



## maki (21. Jan 2009)

Taneeda hat gesagt.:
			
		

> also ich empfinde das schon als Erleichterung, gerade bei großen Methoden, wenn man nur das sieht, was man will...
> 
> nur optimal isses so nicht, da das Folding nicht gespeichert wird. Wenn das noch gespeichert werden würde, dann wärs perfekt ^^


"große Methoden" sind ein ziemlich sicheres Zeichen dafür, dass ein Refactoring angebracht wäre, da hilft auch keine IDE bei  "stinkendem" Code


----------



## Ebenius (21. Jan 2009)

tfa hat gesagt.:
			
		

> Wenn du deine Methoden so schreibst, dass man kein Folding braucht, dann wäre es perfekt.



Ich benutze zwar meist kein Code-Folding, weil es mir zu aufwändig ist. Und ich kenne auch so ein paar Faustregeln wie "Eine Klasse mit mehr als 1000 Zeilen ist eigentlich schon ein Fehler", etc. Im allgemeinen stimme ich vielen dieser Regeln zu. Trotzdem gibt es oft Fälle, bei denen man Gründe hat, gegen Faustregeln zu verstoßen. Deswegen nennt man sie ja Regeln und nicht Gesetze.

Ebenius


----------



## maki (21. Jan 2009)

Vorteile davon eine große Methode aufzusplitten sind unter anderem, dass die Aussagekraft/lesbarkeit des Codes zu erhöht wird wenn man die Methodennamen sinnvoll wählt und manchmal um Redundanz zu vermeiden.

Bis jetzt war die Fausregel "lange/große Methoden stinken und sollten aufgesplittet werden" bei mir immer richtig,  imho daher eine gute Sache.


----------



## Ebenius (21. Jan 2009)

maki hat gesagt.:
			
		

> Bis jetzt war die Fausregel "lange/große Methoden stinken und sollten aufgesplittet werden" bei mir immer richtig,  imho daher eine gute Sache.



Wie gesagt: Meistens stimmt das. Leider nicht immer.


----------



## Taneeda (21. Jan 2009)

all den genannten Regeln kann ich ebenfalls nur zustimmen, jedoch ist es auch so, dass man, wie auch schon erwähnt, man in dem einen oder anderen Fall doch nich ganz um eine riesige bzw. große Methode nicht herum kommt...

Beispiel, eine Methode, die eine XML Datei ausließt... Diese muss Elemente, Attribute, Werte, Zeichen, etc. verarbeiten, auf verschiene Möglichkeiten regieren, weiterverarbeiten, etc. ... dann gibts noch den ein oder anderen Kommentar, damit man nicht vergisst was da passiert, dann natürlich noch etliche Exception handlings und ähnliches, etc. ... also da kommen schnell ein paar hundert Zeilen Code zusammen, vor allem wenn die XML Datei größer is...

Also zumindest kenne ich keine andere Möglichkeit diese zu verarbeiten, aber wenn mir jemand eine bessere Methode zeigen kann, bin ich sehr dankbar, finde das schließlich auch nicht toll so große Methoden zu schreiben, alle schon wegen den Scroll-Aufwand


----------



## maki (21. Jan 2009)

zeig doch mal die große Methode


----------



## Ebenius (21. Jan 2009)

maki hat gesagt.:
			
		

> zeig doch mal die große Methode


Jetzt wirste fies. :-D


----------



## maki (21. Jan 2009)

Wollte nicht fies sein 

Manchmal ist es schneller gezeigt als zerredet bzw. dann sehe ich einen Irrtum schneller ein.

Könnte ja doch noch zustimmen dass es sich um eine Aussnahme handelt 

Die tatsache das es Kommentare im Quelltext gibt ist übrigens noch ein Indiz dass Refactoring zumindest versucht werden sollte.


----------



## Taneeda (21. Jan 2009)

trau mich nich 

(edit)
also hier die Methode... also ernsthaft, is bestimmt nicht gut gelöst, aber mit meiner bescheidenen Erfahrung fiel mir keine andere Möglichkeit ein...

das geht bestimmt besser, also lasst mich bitte nicht dumm sterben ^^


```
/**
	 * This method loads and processes the xml configuration file of this
	 * test case.
	 * 
	 * @return void
	 */
	public void load()
	{
		log.info("Loading test case from project [" + 
			xmlpp.getInfoProject().getProjectName() + "]");
		
		BufferedReader in = null;
		try 
		{
			in = new BufferedReader(new FileReader(tcConfigFile));
		} 
		catch (FileNotFoundException e)
		{
			log.warning("File [" + tcConfigFile.toString() + 
				"] not found...");
			
			FailureMessage.printFailureMessage(MainClass.getController(), 
				"File [" + tcConfigFile.toString() + "] not found...");
		}
		
		XMLInputFactory factory = XMLInputFactory.newInstance();
		try 
		{
			XMLStreamReader parser = factory.createXMLStreamReader(in);
			
			while(true) 
			{
			    int event = parser.next();
			    
			    /**
			     * End of the Document
			     */
			    if(event == XMLStreamConstants.END_DOCUMENT) 
			    {
			    	parser.close();
			    	break;
			    }
			    
			    /**
			     * a new Elements starts
			     */
			    if(event == XMLStreamConstants.START_ELEMENT) 
			    {
			    	log.finest("XMLStreamConstants.START_ELEMENT: " +
				    	parser.getLocalName());
			    	
			    	if(parser.getLocalName().equals("tc"))
			    	{
			    		for(int i=0; i<parser.getAttributeCount(); i++)
			    		{
			    			log.finest("Reading xml attribute: (" +
					        	parser.getAttributeLocalName(i) + "=" +
					        	parser.getAttributeValue(i) + ")");
			    			
			    			if(parser.getAttributeLocalName(i).equals
			    				("name"))
			    			{
			    				infoTestCase.setTCName(parser.
			    					getAttributeValue(i));
			    				
			    				tcFolder = parser.getAttributeValue(i);
			    			}
			    			else
			        		{
			        			log.config("Unsupported attribute (" +
			        				parser.getAttributeLocalName(i) + "=" +
			        				parser.getAttributeValue(i) + ")");
			        			
			        			FailureMessage.printFailureMessage(
			        				MainClass.getController(),
			        				"Unsupported attribute (" +
			        				parser.getAttributeLocalName(i) + "=" +
			        				parser.getAttributeValue(i) + ")");
			        		}
			    		}
			    	}
			    	else if(parser.getLocalName().equals("redirection"))
			    	{
			    		for(int i=0; i<parser.getAttributeCount(); i++)
			    		{
			    			log.finest("Reading xml attribute: (" +
						       	parser.getAttributeLocalName(i) + "=" +
						       	parser.getAttributeValue(i) + ")");
			    			
			    			if(parser.getAttributeLocalName(i).equals
			    				("mode"))
			    			{
			    				if(parser.getAttributeValue(i).equals
			    					("enabled"))
			    				{
			    					log.config("Redirection [enabled] for" +
			    						" test case [" + infoTestCase.
			    						getTCName() + "]");
			    					
			    					infoTestCase.setTCRedirection(true);
			    				}
			    				else if(parser.getAttributeValue(i).equals
			    					("disabled"))
			    				{
			    					log.config("Redirection [disabled] " +
			    						"for test case [" + infoTestCase.
			    						getTCName() + "]");
			    					
			    					infoTestCase.setTCRedirection(false);
			    				}
			    				else
			    				{
			    					log.warning("Wrong redirection " +
			    						"configuration [" + parser.
			    						getAttributeLocalName(i) + "=" +
			    						parser.getAttributeValue(i) + "]");
			    					
			    					FailureMessage.printFailureMessage(
			    						MainClass.getController(),
			    						"Wrong redirection " +
			    						"configuration [" + parser.
			    						getAttributeLocalName(i) + "=" +
			    						parser.getAttributeValue(i) + "]");
			    				}
			    			}
			    			else
			        		{
			        			log.config("Unsupported attribute (" +
			        				parser.getAttributeLocalName(i) + "=" +
			        				parser.getAttributeValue(i) + ")");
			        			
			        			FailureMessage.printFailureMessage(
			        				MainClass.getController(),
			        				"Unsupported attribute (" +
			        				parser.getAttributeLocalName(i) + "=" +
			        				parser.getAttributeValue(i) + ")");
			        		}
			    		}
			    	}
			    	
			    	/**
			    	 * Steps in this test case...
			    	 */
			    	if(RegexPatterns.findStepInTestCase(
			    		parser.getLocalName()))
			    	{
			    		numSteps = new Integer(numSteps.intValue() + 1);
			    		
			    		TCStep tcs = new TCStep();
			    		tcs.setNumStep(numSteps.intValue());
			    		infoTestCase.setTCName(tcFolder);
			    		
			    		/**
			    		 * processes all attributes of the current step.
			    		 */
			    		for(int i=0; i<parser.getAttributeCount(); i++)
			    		{
			    			log.finest("Reading xml attribute: (" +
			    				parser.getAttributeLocalName(i) + "=" +
			    				parser.getAttributeValue(i) + ")");
			    			
			    			/**
			    			 * Determines how many times the request should
			    			 * repeated. 
			    			 */
			    			if(parser.getAttributeLocalName(i).equals
			    				("num"))
			    			{
			    				log.config("Repeating request " + 
			    					parser.getAttributeValue(i) + " times");
			    				
			    				numRequestRepeats = new Integer(
			    					parser.getAttributeValue(i));
			    			}
			    			/**
			    			 * What should be done.
			    			 */
			    			else if(parser.getAttributeLocalName(i).equals
			    				("action"))
			    			{
			    				tcs.setAction(parser.getAttributeValue(i));
			    				
			    				if(parser.getAttributeValue(i).
			    					equals("sendRequest"))
			    				{
			    					if(parser.getAttributeLocalName(i+1).
			    						equals("file"))
			    					{
			    						tcs.setFile(parser.
			    							getAttributeValue(i+1).
			    							replace("%projectFolder%", 
			    								xmlpp.getProjectFolder()).
			    							replace("%tc%", tcFolder));
			    						
		    							/**
			    						 * Create message pair to process.
			    						 */
			    						
		    							tcs.setHmp
		    							(
		    								loadRequestFromFile(new File
		    								(
					    						parser.getAttributeValue(i+1).
					    							replace
					    							(
					    								"%projectFolder%",
					    								xmlpp.getProjectFolder()
					    							).replace
					    							(
					    								"%tc%", tcFolder
					    							)
					    					)),
					    					new Response(
					    						MainClass.
					    							getOutputModeResponse())
					    				);
			    					}
			    					else
			    					{
			    						log.info("If you want to" +
			    							" send a request, you must" +
			    							" define the request file!");
			    						
			    						FailureMessage.printFailureMessage
			    							(controller, "If you want to" +
			    							" send a request, you must" +
			    							" define the request file!");
			    					}
			    				}
			    				else
			    				{
			    					log.warning("Unknown action" +
			    						" in test case step [" + i + "];" +
			    						parser.getAttributeValue(i));
			    					
			    					FailureMessage.printFailureMessage
			    						(controller, "Unknown action" +
			    						" in test case step [" + i + "];" +
			    						parser.getAttributeValue(i));
			    				}
			    			}
			    			else if(parser.getAttributeLocalName(i).
		    					equals("file"))
		    				{
		    					/**
		    					 * Do nothing. This attribute is parsed
		    					 * above during sendRequest detection.
		    					 * This is only to prevent failure
		    					 * message.
		    					 */
		    				}
			    			/**
			    			 * The expected status code of the response.
			    			 */
			    			else if(parser.getAttributeLocalName(i).equals
			    				("expStatusCode"))
			    			{
			    				log.config("expStatusCode (" + tcFolder +
			    					") = " + parser.getAttributeValue(i));
			    				
			    				/**
			    				 * Set the expected status code of the
			    				 * received response.
			    				 */
			    				tcs.getErd().setResponseStatusCode(
			    					new Integer(parser.
			    					getAttributeValue(i)));
			    			}
			    			/**
			    			 * The expected header which the response should
			    			 * contain.
			    			 */
			    			else if(parser.getAttributeLocalName(i).equals
			    				("expHeader"))
			    			{
			    				log.config("expHeader (" + tcFolder +
				    				") = " + parser.getAttributeValue(i));
			    				
			    				if(parser.getAttributeValue(i).contains
			    					("|"))
			    				{
				    				/**
				    				 * The headers with values...
				    				 * [name]:[value]
				    				 */
				    				String[] splitHeader = parser.
				    					getAttributeValue(i).split("[|]");
				    				for(int h=0; h<splitHeader.length; h++)
				    				{
				    					String[] hpSplit = splitHeader[h].
				    						split(":");
				    					
				    					tcs.getErd().getHeaders().add(
				    						new HeaderPair<String, String>(
				    						//     name   ,   value
				    							hpSplit[0], hpSplit[1])
				    						);
				    				}
			    				}
			    				else
			    				{
			    					String[] hpSplit = parser.
			    						getAttributeValue(i).split(":");
			    					
			    					tcs.getErd().getHeaders().add(
			    						new HeaderPair<String, String>(
			    						//     name   ,   value
			    							hpSplit[0], hpSplit[1])
			    						);
			    				}
			    			}
			    			/**
			    			 * The expected string which the response data
			    			 * should contains (only usable if the response
			    			 * data is text data).
			    			 */
			    			else if(parser.getAttributeLocalName(i).equals
			    				("expStringsData"))
			    			{
			    				log.config("expStringsData (" + tcFolder +
				    				") = " + parser.getAttributeValue(i));
			    				
			    				if(parser.getAttributeValue(i).contains
			    					("|"))
			    				{
				    				/**
				    				 * The strings...
				    				 */
				    				String[] split = parser.
			    						getAttributeValue(i).split("|");
				    				
				    				for(int s=0; s<split.length; s++)
				    				{
				    					tcs.getErd().getDataString().add(
				    						split[s]);
				    				}
			    				}
			    				else
			    				{
			    					tcs.getErd().getDataString().add(parser.
			    						getAttributeValue(i));
			    				}
			    			}
			    			else
			        		{
			        			log.config("Unsupported attribute (" +
			        				parser.getAttributeLocalName(i) + "=" +
			        				parser.getAttributeValue(i) + ")");
			        			
			        			FailureMessage.printFailureMessage(
			        				MainClass.getController(),
			        				"Unsupported attribute (" +
			        				parser.getAttributeLocalName(i) + "=" +
			        				parser.getAttributeValue(i) + ")");
			        		}
			    		}
			    		
				    	/**
						 * adds the request num times to the
						 * message pair array. num is
						 * defined in stepX element in test
						 * case configuration file
						 */
						for(int num=0; num<numRequestRepeats; 
							num++)
						{														
							/**
							 * The first request num.
							 */
							if(num == 0)
							{
								log.info("Adding request first time.");
								
								/** 
								 * because in step to compare or anything like
								 * this, the message pair IS null!!!
								 */
								if(tcs.getHmp() != null)
								{
									/**
									 * panel for this test case.
									 */
									tcs.setPip(true);
									
									/**
									 * Sets the number of the message pair.
									 */
									tcs.getHmp().setNum(num);
								
									/**
									 * Set the object with the expected response
									 * data to the http message pair.
									 */
									tcs.getHmp().setExpResponseData(
										tcs.getErd());
									
									/**
						    		 * Add the new message pair for the actual 
						    		 * step to the <code>msgPairs</code> vector.
						    		 */
						    		msgPairs.add(tcs.getHmp());
						    		
						    		/**
					    			 * One <code>ProcessInfoPanel</code> for each 
					    			 * step.
					    			 */
									tcs.getPip().getJLabelName().setText(
										"tc" + num);
									
					    			GuiProgressPanel.getInstance().
										addProcessInfoPanel(tcs.getPip());
					    			tcs.getPip().setVisible(true);
					    			
					    			/**
					    			 * Add test case step to vector.
					    			 */
					    			infoTestCase.getTCSteps().add(tcs);
								}
							}
							/**
							 * Repeating the same request.
							 */
							else if(num > 0)
							{
								log.info("Adding request (repeat)");
								
								TCStep tcStep = new TCStep();
								
								/** 
								 * because in step to compare or anything 
								 * like this, the message pair IS null!!!
								 */
								if(tcs.getHmp() != null)
								{
									tcStep.setNumStep(tcs.getNumStep());
									tcStep.setAction(tcs.getAction());
									tcStep.setFile(tcs.getFile());
									tcStep.setReapeating(num+1);
									
									/**
									 * A new TCStep for each request
									 * repeating.
									 */
									tcStep.setHmp(tcs.getHmp().getRequest(),
										tcs.getHmp().getResponse());
									
									/**
									 * panel for this test case.
									 */
									tcStep.setPip(true);
									
									/**
									 * Sets the number of the message pair.
									 */
									tcStep.getHmp().setNum(num);
								
									/**
									 * Set the object with the expected 
									 * response data to the http message 
									 * pair.
									 */
									tcStep.getHmp().setExpResponseData(
										tcs.getErd());
									
									/**
						    		 * Add the new message pair for the actual 
						    		 * step to the <code>msgPairs</code> vector.
						    		 */
						    		msgPairs.add(tcStep.getHmp());
						    		
						    		/**
					    			 * One <code>ProcessInfoPanel</code> for each 
					    			 * step.
					    			 */
						    		tcStep.getPip().getJLabelName().setText(
										"tc" + num);
									
					    			GuiProgressPanel.getInstance().
										addProcessInfoPanel(tcStep.getPip());
					    			tcStep.getPip().setVisible(true);
					    			
					    			/**
					    			 * Add test case step to vector.
					    			 */
					    			infoTestCase.getTCSteps().add(tcStep);
								}
							}
						}
			    	}
			    }
			    
			    /**
			     * A String, e.g. ISA Server between <proxy> </proxy> Tags
			     */
			    if(event == XMLStreamConstants.CHARACTERS)
			    {}
			}
			
			log.info("Loading test case finished");
			
			/**
			 * panel for compare progress.
			 */
			log.fine("");
			GuiProgressPanel.getInstance().addComparePanel(
				new CompareInfoPanel());
			
			ProcessInfoPanel reportPanel = new ProcessInfoPanel(false);
			reportPanel.getJLabelName().setText("report");
			GuiProgressPanel.getInstance().addProcessInfoPanel(reportPanel);
		}
		catch (XMLStreamException e) 
		{
			log.warning("XMLStreamException in XMLTestCaseProcessor;" +
				e.getMessage() + ";" + e.getCause() + ";" +
				e.getLocation());
			
			FailureMessage.printFailureMessage(MainClass.getController(), 
				"XMLStreamException in XMLTestCaseProcessor;" +
				e.getMessage() + ";" + e.getCause() + ";" +
				e.getLocation());
		}
	}
```

also ich für meinen Teil brauch da schon einige Kommentare, wenn ich das mal ein paar Wochen nich sehe, dann vergess ich ja die Hälfte wieder ^^


----------



## maki (21. Jan 2009)

Würde ich bestimmt auch nicht 

Sehr empfehlenswertes Buch von Martin Fowler: Refactoring: Improving the Design of Existing Code


----------



## Taneeda (21. Jan 2009)

danke für den Buchtipp, werde ich wenn ich mal Zeit dazu finde gerne durcharbeiten ^^


----------



## SlaterB (21. Jan 2009)

die Verwendung von Unter-Methoden bietet sich in dem Beispiel schon allein aufgrund der Einrückung an,
daduch dass du nur 50% der Zeile nutzen kannst, bekommst du viele zweizeilige Befehle, was die Methode noch länger macht

wenn du so weiter einrückst,
dann steht da bald ganz rechts ganz eng

/** 
                            * A new TCStep 
for each request 
                            * repeating. 
                            */ 
                           tcStep.setHmp(
tcs.getHmp().
getRequest(), 
                              tcs.getHmp().
getResponse()); 

                           /** 
                            * panel for this 
test case. 
                            */ 
                           tcStep.setPip(true); 

                           /** 
                            * Sets the number 
of the message pair. 
                            */ 
                           tcStep.getHmp().
setNum(num); 

                           /** 
                            * Set the object 
with the expected 
                            * response data to 
the http message 
                            * pair. 
                            */ 
                           tcStep.getHmp().
setExpResponseData( 
                              tcs.getErd());



so in der Art jedenfalls

-> 

 /** 
                    * processes all attributes of the current step. 
                    */ 
                   for(int i=0; i<parser.getAttributeCount(); i++) 
                   { 
and dieser Stelle z.B. den Schleifeninhalt in eine Methode auslagern,
selbst wenn du 8 Parameter übergeben musst und in der Methode nochmal 5 weitere Daten aus anderen neu herausholen musst,
das lohnt sich dennnoch

später kann man dann überlegen, wie die Parameter-Anzahl optimiert werden kann


----------



## maki (21. Jan 2009)

Taneeda hat gesagt.:
			
		

> danke für den Buchtipp, werde ich wenn ich mal Zeit dazu finde gerne durcharbeiten ^^


Unbedingt, das Buch gehört zu den besten die ich über SW Entwicklung gelesen habe.


----------



## Taneeda (21. Jan 2009)

also ich glaub wenn ich da oben die Methoden aufruf, dann dürfts ja schon fast länger als jetz werden ^^


----------



## Ebenius (21. Jan 2009)

Taneeda hat gesagt.:
			
		

> also ich glaub wenn ich da oben die Methoden aufruf, dann dürfts ja schon fast länger als jetz werden ^^



Möglich. Aber übersichtlicher, sofern die Methoden gute Namen haben.


----------



## Taneeda (21. Jan 2009)

Ebenius hat gesagt.:
			
		

> Möglich. Aber übersichtlicher, sofern die Methoden gute Namen haben.



da hast allerdings recht ^^


----------



## Wildcard (21. Jan 2009)

Folding ist Blödsinn. Wenn man gerne auf das wesentliche reduziert wird, dann Focused UI von Mylyn aktivieren (nichts für mich, aber wer's mag...)


----------



## Taneeda (22. Jan 2009)

naja, jeder wie ers will


----------



## bbnvacx (6. Feb 2009)

In Eclipse 3.4 ist Folding eingebaut.

Ich habe es so gemacht:

Window>Preferences dann in der Seitenleiste Java>Editor>Folding und dann einfach alles aktivieren  :wink:


----------

